Skip to main content

Topic: WSH Panel Mod script discussion/help (Read 842179 times) previous topic - next topic

0 Members and 1 Guest are viewing this topic.
  • Falstaff
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #375
Help required :

i want to use the SendKeys method to write in a dialog box somthing, and first, opening this dialog Box

in a WSH panel, i call this on left mouse button up :

var WshShell = new ActiveXObject("WScript.Shell");
WshShell.SendKeys("(^P)");

it should open Preferences window, but it does nothing ... i think that the focus is on the WSH panel hosting this command, so maybe i should send a {TAB} key to swap to another panel of the foobar window BEFORE trying to send Ctrl+P (^ = Ctrl key) :

WshShell.SendKeys("{TAB}");


any idea ?

  • mastema
  • [*]
WSH Panel Mod script discussion/help
Reply #376
@marc2003

Issue 1: still having issues with the "now playing" script. All others work and safe mode is turned off.

Whenever I turn auto download off it shows no artist pictures, not even from the tags. As soon as I stop playing a track without an artist pic the panel goes into SCRIPT ERROR. Starts working again after right click -> configure -> apply, but still without tag images. Foobar can't be closed before I do this step because art.exe stalls it. I have to manually end art.exe from the task manager and then close foobar.

Note I use your scripts from: 4/26/2010 11:47 AM.

Issue 2: a while back (page 12. posts 285, 286), I asked you if there was a way for "now playing" to display cover art instead of artist pic (swap them). You then posted the code for this on pastebin (and it worked great, many thanks), but when I checked again today, the code was gone. Would you mind re-uploading it?

Issue 3: this is probably easy, but since I'm not a coder, I only mix and match to get a result; can't quite create something new. Is it possible for "now playing" to have a three color gradient?
  • Last Edit: 26 April, 2010, 02:40:44 PM by mastema

  • marc2003
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #377
i have no idea why you're getting an error. check the console, see which line it is and then post what it is. auto-download is turned off by default and it's the setting i always use. you shouldn't have any problems if there are no images, it just looks like this...



did you overwrite all files when downloading the zip. there was a problem with art.exe hanging if artists weren't found on last.fm. i've since re-compiled it to fix that. (note i didn't write that program but the author (paradog) published the source code. the reason it hung is that it was waiting for user input but i hide the program so that wasn't possible. i just commented out one line of code so it exits by itself)

i suppose i can modify it not to use last.fm and the artreader instead. i'll do that later.

and no, you can't have a 3 colour gradient.

edit: i lied. you can have 3 colours if you spilt the panel. i'll post how to do that later as well.
  • Last Edit: 26 April, 2010, 03:12:57 PM by marc2003

  • mastema
  • [*]
WSH Panel Mod script discussion/help
Reply #378
did you overwrite all files when downloading the zip. there was a problem with art.exe hanging if artists weren't found on last.fm. i've since re-compiled it to fix that. (note i didn't write that program but the author (paradog) published the source code. the reason it hung is that it was waiting for user input but i hide the program so that wasn't possible. i just commented out one line of code so it exits by itself)


I deleted everything related and redownloaded: seems to be working fine now, but I don't know why, since it's exactly what I did an hour before (I did a new portable install today due to getting a new hard drive). Well, if it works...

In any case, I took a short screencast (1min.) for reference if you should need it in the future. The error was:
Quote
Error: WSH Panel Mod (GUID: BA3A201A-5E28-425F-9B01-A3245A424D5F): Microsoft JScript runtime error:
Object required
Ln: 269, Col: 2


I'll wait patiently for your other info and "thanks" in advance.

  • marc2003
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #379
i'm sure i told pastebin to keep it forever last time but here it is again.

http://pastebin.com/zHQxxwns

there are 3 variables at the top of the script to set 3 colours top_c, mid_c and bot_c

as for the error, i can only assume you were using a new script with an old version of the scripts folder in your foobar directory??

EDIT: link updated due to a small error. 
  • Last Edit: 26 April, 2010, 04:46:03 PM by marc2003

  • mastema
  • [*]
WSH Panel Mod script discussion/help
Reply #380
Superb! I won't have time to fiddle with it now since it's midnight for me, but I'll be sure to post tomorrow if something comes up.

As for the error, yeah I guess it's possible. Since I did a fresh Windows install today I had folders and files scattered all over the desktop for me take a look at; something could have snuck by. In any case, thanks a lot for the prompt response.

  • laite
  • [*][*]
WSH Panel Mod script discussion/help
Reply #381
I'm not really sure if this is the right place to ask, but since I'm scripting with WSH Panel mod.. Is there a way to find out the possible position of text 'live' (case insensitive) within string. For example, if I have "Song2 (live)" function would return 7 (as first character is 0).

  • marc2003
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #382
var title = fb.TitleFormat("%title%").EvalWithMetadb(g_metadb);
var pos = title.toLowerCase().indexOf("live");

  • Maf
  • [*]
WSH Panel Mod script discussion/help
Reply #383
There is a script for viewing album covers on the panel has buttons to switch Folder\CD\Artist\etc. Please help make switch tracks for this buttons Previous\Play\Pause\Next.
Code: [Select]
function RGBA(r,g,b,a){
var res = 0xff000000|(r<<16)|(g<<8)|(b);
if (a!=undefined) res = (res & 0x00ffffff) | (a << 24)
return res;
}
//====================================================
// Properties Object =======================================
/* All settings store here */
var Properties = new function (){
this.Panel = {
// 0: Never, 1: When not playing, 2: Always.
FollowCursor: window.GetProperty("Panel.FollowCursor", 1),
// Where the images folders in.
WorkDirectory: fb.FoobarPath+fb.TitleFormat(window.GetProperty("Panel.WorkDirectory", "Images\\EIKO\\WSH Cover\\")).Eval(true),
// "cn": Chinese, "en": English, "auto": Auto choose, base on foobar2000 core language.
lang: window.GetProperty("Panel.Language", "auto").toLowerCase(), // Language
// Separate with comma, like "255,255,255"
BackGroundColor: window.GetProperty("Panel.BackGroundColor", ""),
Tooltip: window.CreateTooltip() // Create button's tooltip
};

if (typeof(this.Panel.FollowCursor)!="number")
this.Panel.FollowCursor = 1;
else if (this.Panel.FollowCursor<0)
this.Panel.FollowCursor = 0;
else if (this.Panel.FollowCursor>2)
this.Panel.FollowCursor = 2;

if (this.Panel.lang != "cn" && this.Panel.lang != "en")
this.Panel.lang = (fb.TitleFormat("$meta()").Eval(true)=="[未知函数]") ? "cn" : "en";

try {
this.Panel.FSO = new ActiveXObject("Scripting.FileSystemObject");
} catch(e) {
// Impossible to work without FSO.
fb.ShowPopupMessage(this.Panel.lang=="cn" ? "无法创建FSO对象, WSH Cover面板无法工作." : "Can not create File System Object (FSO), WSH Cover Panel can't work.", "WSH Cover Panel", 1);
new ActiveXObject("Scripting.FileSystemObject"); // End scripts running.
}

if (!this.Panel.FSO.FolderExists(this.Panel.WorkDirectory))
fb.ShowPopupMessage(this.Panel.lang=="cn" ? "无效的工作路径." : "Invalid work directory.", "WSH Cover Panel", 1);

if (this.Panel.BackGroundColor) {
this.Panel.BackGroundColor = this.Panel.BackGroundColor.replace(/ | /g, "");
this.Panel.BackGroundColor = this.Panel.BackGroundColor.split(",");
for (var i in this.Panel.BackGroundColor) {
if (this.Panel.BackGroundColor[i]<0)
this.Panel.BackGroundColor[i] = 0;
else if (this.Panel.BackGroundColor[i]>255)
this.Panel.BackGroundColor[i] = 255;
}
if (this.Panel.BackGroundColor.length<4)
this.Panel.BackGroundColor.length = 4;
}

//---------------------------------------------------------------------
this.Cycle = {
// Enable image cycle.
Enable: window.GetProperty("Cycle.Enable", true),
// Interval period.
Period: window.GetProperty("Cycle.Period", 10000),
// Cycle all the wildcard match files in image SourceFormat.
CycleInWildCard: window.GetProperty("Cycle.CycleInWildCard", true),
// Pause images cycle automatic when following cursor.
AutoPauseWhenFollowCursor: window.GetProperty("Cycle.AutoPauseWhenFollowCursor", true),
// Animations on image's changing. Not only in image cycle, but also in track switching.
Animation: {
Enable: window.GetProperty("Cycle.Animation.Enable", true),
RefreshInterval: window.GetProperty("Cycle.Animation.RefreshInterval", 50),
Duration: window.GetProperty("Cycle.Animation.Duration", 400)
}
};

if (typeof(this.Cycle.Period)!="number")
this.Cycle.Period = 7000;
else if (this.Cycle.Period<100)
this.Cycle.Period = 100;

if (typeof(this.Cycle.Animation.RefreshInterval)!="number")
this.Cycle.Animation.RefreshInterval = 50;
else if (this.Cycle.Animation.RefreshInterval<10)
this.Cycle.Animation.RefreshInterval = 10;

if (typeof(this.Cycle.Animation.Duration)!="number")
this.Cycle.Animation.Duration = 300;
else if (this.Cycle.Animation.Duration<10)
this.Cycle.Animation.Duration = 10;

//---------------------------------------------------------------------
this.Image = {
// Separate paths by "||"; use "|||" to separate default images and other images, only can be used once; "<embed>" means embed cover, must be a individual path in sourceformat.
SourceFormat: window.GetProperty("Image.SourceFormat", "<embed>||$directory_path(%path%)\\cover.*||$directory_path(%path%)\\folder.*"),
// In same group, if SourceFormat not changed, panel will not check any new files, and the images cycle will not be reset.
GroupFormat: window.GetProperty("Image.GroupFormat", "%album%"),
// Default image path.
DefaultImagePath: fb.TitleFormat(window.GetProperty("Image.DefaultImagePath", "Images\\EIKO\\Default.jpg")).Eval(true),
// File larger than this value will not be loaded. <=0 means no limit.
MaxFileSize: window.GetProperty("Image.MaxFileSize", 2097152),
// Keep images aspect ratio.
KeepAspectRatio: window.GetProperty("Image.KeepAspectRatio", true),
// Stretch images to fit panel.
Stretch: window.GetProperty("Image.Stretch", false),
// Images is stored after resize, so you can set this value larger if your panel size is not very large.
ImageCacheCapacity: window.GetProperty("Image.ImageCacheCapacity", 10),
// This panel also stores path search result, only stores the strings.
PathCacheCapacity: window.GetProperty("Image.PathCacheCapacity", 20),
// Only these types of files can be displayed. Not necessary to modify this at most times.
SupportTypes: new Array("jpg", "jpeg", "png", "gif", "bmp"),
// Image smoothing mode.
SmoothingMode: window.GetProperty("Image.SmoothingMode", 0),
// Image interpolation mode in resizing.
InterpolationMode: window.GetProperty("Image.InterpolationMode", 0)
};

if (typeof(this.Image.MaxFileSize)!="number")
this.Image.MaxFileSize = 2097152;
else if (this.Image.MaxFileSize<0)
this.Image.MaxFileSize = 0;

if (typeof(this.Image.ImageCacheCapacity)!="number")
this.Image.ImageCacheCapacity = 10;
else if (this.Image.ImageCacheCapacity<0)
this.Image.ImageCacheCapacity = 0;

if (typeof(this.Image.PathCacheCapacity)!="number")
this.Image.PathCacheCapacity = 20;
else if (this.Image.PathCacheCapacity<0)
this.Image.PathCacheCapacity = 0;

if (typeof(this.Image.SmoothingMode)!="number")
this.Image.SmoothingMode = 0;
else if (this.Image.SmoothingMode<-1)
this.Image.SmoothingMode = -1;
else if (this.Image.SmoothingMode>4)
this.Image.SmoothingMode = 4;

if (typeof(this.Image.InterpolationMode)!="number")
this.Image.InterpolationMode = 0;
else if (this.Image.InterpolationMode<-1)
this.Image.InterpolationMode = -1;
else if (this.Image.InterpolationMode>7)
this.Image.InterpolationMode = 7;

//---------------------------------------------------------------------
this.Buttons = {
// Whether display the control buttons.
Display: window.GetProperty("Buttons.Display", true),
// 0: topleft, 1:topright, 2:bottomleft, 3:bottomright
Position: window.GetProperty("Buttons.Position", "4")
};

if (typeof(this.Buttons.Position)!="number")
this.Buttons.Position = 4;
else if (this.Buttons.Position<0)
this.Buttons.Position = 0;
else if (this.Buttons.Position>5)
this.Buttons.Position = 5;

}();


//====================================================
// Three funtions ==========================================

//---------------------------------------------------------------------------------------------
/* Calculate image's new size and offsets in new width and height range.
Use panel's default settings of stretch and ratio if they are not specified */
function CalcNewImgSize (img, dstW, dstH, srcW,srcH, strch, kar) {
if (!img) return;
if (!srcW) srcW = img.width;
if (!srcH) srcH = img.height;
if (strch==undefined) strch = Properties.Image.Stretch;
if (kar==undefined) kar = Properties.Image.KeepAspectRatio;

var size;
if (strch) {
size = {x:0, y:0, width:dstW, height:dstH};
if (kar) {
size.width = Math.ceil(srcW*dstH/srcH);
if (size.width>dstW) {
size.width = dstW;
size.height = Math.ceil(srcH*dstW/srcW);
}
}
} else {
size = {x:0, y:0, width:srcW, height:srcH};
if (kar) {
if (srcH>dstH) {
size.height = dstH;
size.width = Math.ceil(srcW*dstH/srcH);
}
if (size.width>dstW) {
size.width = dstW;
size.height = Math.ceil(srcH*dstW/srcW);
}
} else {
size.width = Math.min(srcW, dstW);
size.height = Math.min(srcH, dstH);
}
}
size.x = Math.floor((dstW-size.width)/2);
size.y = Math.floor((dstH-size.height)/2);
return size;
}

//---------------------------------------------------------------------------------------------
/* Reisze image to new width and height */
function ResizeImg (img, dstW, dstH) {
if (!img || !dstW || !dstH) return img;
if (img.width==dstW && img.height==dstH) return img;

var newimg = gdi.CreateImage(dstW, dstH);
var g = newimg.GetGraphics();
g.DrawImage(img, 0, 0, dstW, dstH, 0, 0, img.width, img.height);
newimg.ReleaseGraphics(g);
CollectGarbage(); // Release memory.
return newimg;
}

//---------------------------------------------------------------------------------------------
/* Remove an element from "this" array, return the removed element */
function RemoveFromArray (index) {
if (index==0)
return this.shift();
else if (index==this.length-1)
return this.pop();
var c = this[index];
var rest = this.slice(index+1);
this.length = index;
this.push.apply(this, rest);
return c;
}


//====================================================
// Define Image Loader ====================================
/* Loader image file from specified path. It contains a image cache.
Primarily provides the "GetImg()" method */
var ImageLoader = new function (Prop) {
var ImgCacheCapacity = Prop.Image.ImageCacheCapacity;

if (ImgCacheCapacity) {
// Cache array is always sorted, sort by last accessed.
// Array's length never change.
// No empty element, only empty "cacheitem".
// No item will really be deleted, only be deassigned.
var ImgsCache = new Array;
// Admissible size error in cache reading.
ImgsCache.ImgSizeError1 = 10; // For enlarge.
ImgsCache.ImgSizeError2 = 50; // For shrink.

// Class of the items in cache.
ImgsCache.cacheItem = function (path, imgobj) {
this.Path = path; // String.
this.ImgObj = imgobj; // Object, gdi.image() object, or empty.
this.srcW = 0; // Source width.
this.srcH = 0; // Source height
};

// Fill the cache array with empty cacheitems.
for (var i=0; i<ImgCacheCapacity-1; i++)
ImgsCache.push(new ImgsCache.cacheItem(null, null));

// Remove element from cache array, return the removed element.
ImgsCache.remove = RemoveFromArray;

// Store item in the beginning of the cache array. Duplicate item's "ImgObj" will be overwritten.
ImgsCache.Store = function (path, imgobj, srcW, srcH) {
var c;
if (this.SearchFor(path)) {
c = this[0]; // This is the one just found.
c.ImgObj = imgobj;
if (srcW) c.srcW = srcW;
if (srcH) c.srcH = srcH;
} else if (c = this.pop()) {
c.Path = path;
c.ImgObj = imgobj;
c.srcW = srcW ? srcW : (imgobj ? imgobj.width : 0); // Store source width.
c.srcH = srcH ? srcH : (imgobj ? imgobj.height : 0); // Store source height.
this.unshift©;
}
};

// Search in cache, find the image object.
// Resize "ImgObj" to "dst" size, if current size is not enough, and the source size is closer, remove this item and return nothing.
// Or, move it to the beginning of the cache array, then resize image, then return this cache item.
// If no result found, return nothing.
ImgsCache.SearchFor = function (path, dstW, dstH) {
var i = 0;
for (i; i<this.length; i++) // Find it.
if (this[i].Path==path)
break;

if (i<this.length) {
var c = this.remove(i);
var img = c.ImgObj;
// For resizing------------------------
if (img && dstW && dstH) {
var size = CalcNewImgSize(img, dstW, dstH, c.srcW, c.srcH);
// If image should be enlarged and it still can be enlarged...
if ((size.width>img.width && img.width<c.srcW) || (size.height>img.height && img.height<c.srcH)) {
// If the dst size is not too large...
if (size.width-img.width<this.ImgSizeError1 && size.width<c.srcW && size.height-img.height<this.ImgSizeError1 && size.height<c.srcH)
img = ResizeImg(img, size.width, size.height); // Only resize, no cache.
else {
// Return to reload image file.
this.push©;
return;
}
// If it's shrinking...
} else if (size.width<img.width || size.height<img.height) {
// If the dst size is too small...
if (img.width-size.width>this.ImgSizeError2 || img.height-size.height>this.ImgSizeError2) {
img = ResizeImg(img, size.width, size.height); // Resize and cache.
c.ImgObj = img;
} else
img = ResizeImg(img, size.width, size.height); // Resize and don't cache.
} else {
size = CalcNewImgSize(img, dstW, dstH);
img = ResizeImg(img, size.width, size.height);
c.ImgObj = img;
}
}
//------------------------------------
this.unshift©;
return (img || true); // If path was found, return something "true" at all times.
}
};

// Clear cache, only reset all cache items indeed.
ImgsCache.Clear = function () {
for (var i=0; i<this.length-1; i++) {
this[i].Path = null;
this[i].ImgObj = null;
this[i].srcW = 0;
this[i].srcH = 0;
}
};
}

// Load image file from specified path, generate gdi.image() object, resize it, cache it, then return it.
// If path invalid or file corrupt, return nothing.
this.GetImg = function (path, dstW, dstH, NoCache) {
if (!path) return;
var imgobj;
if (!NoCache && ImgsCache)
imgobj = ImgsCache.SearchFor(path, dstW, dstH);

if (imgobj) {
if (typeof(imgobj)!="object") imgobj = null; // Maybe it's a boolean value.
} else {
if (path.charAt(0)=="<") // Embed image.
imgobj = utils.GetAlbumArtEmbedded(path.substring(1, path.length-1), 0);
else
imgobj = gdi.image(path);

var srcW, srcH;
if (imgobj) {
srcW = imgobj.width;
srcH = imgobj.height;
if (dstW && dstH) {
var size = CalcNewImgSize(imgobj, dstW, dstH);
imgobj = ResizeImg(imgobj, size.width, size.height);
}
}
// Store every path, even no valid image exists.
ImgsCache && ImgsCache.Store(path, imgobj, srcW, srcH);
}

if (imgobj)
return imgobj;
};

this.ClearCache = function () {
ImgsCache && ImgsCache.Clear();
};

} (Properties);

var GetImg = ImageLoader.GetImg;


//====================================================
// Define Path Checker =====================================
/* Find matches image files in directorys. It contains a paths cache.
Primarily provides the "GetImgPaths()" method */
var PathChecker = new function (Prop, ImgLoader) {
var FSO = Prop.Panel.FSO;
var ImgSrcFmt = Prop.Image.SourceFormat;
var ImgSrcStr = "";
var SupportTypes = Prop.Image.SupportTypes;
var MaxFileSize = Prop.Image.MaxFileSize;
var CycleInWildCard = Prop.Cycle.CycleInWildCard;
var GetEmbedImg = ImgLoader;
var FoundFiles = new Array;
var PathsArray;
var PathCacheCapacity = Prop.Image.PathCacheCapacity;

if (PathCacheCapacity) {
// This cache array is similar to the images cache array.
var PathsCache = new Array;
PathsCache.FSO = FSO;

PathsCache.cacheItem = function (path, files) {
this.Path = path; // String.
this.MatchFiles = files; // Must an array, path array.
};

for (var i=0; i<PathCacheCapacity-1; i++)
PathsCache.push(new PathsCache.cacheItem(null, null))

PathsCache.remove = RemoveFromArray;

// Duplicate item will be overwritten.
PathsCache.Store = function (path, files) {
var c;
if (this.SearchFor(path))
this[0].MatchFiles = files;
else if (c = this.pop()) {
c.Path = path;
c.MatchFiles = files;
this.unshift©;
}
};

// Search in cache, returns the search result, and move it to the beginning of the cache array.
// All files in result array will be checked before return, if one or more files doesn't exist, remove this item and return nothing.
// If no result found, return nothing.
PathsCache.SearchFor = function (path) {
var i = 0;
for (i; i<this.length; i++)
if (this[i].Path==path)
break;

if (i<this.length) {
var c = this.remove(i);
var rslt = c.MatchFiles;

for (var j=0; j<rslt.length; j++) // Check whether all the files are exist.
if (!this.FSO.FileExists(rslt[j])) {
c.Path = null;
this.push©;
return;
}

this.unshift©;
return rslt;
}
};

PathsCache.Clear = function () {
for (var i=0; i<this.length-1; i++) {
this[i].Path = null;
this[i].MatchFiles = null;
}
};
}

// Union Array2 into Array1.
var unionArray = function (Array1, Array2 ) {
var seen = {};
for (var i=0; i<Array1.length; i++)
seen[Array1[i]] = true;
for (var i=0; i<Array2.length; i++)
if (!seen[Array2[i]])
Array1.push(Array2[i]);
};

// Calculate ImageSourceFormat, and replace <embed> with <rawpath>.
var CalcPathFmt = function (pathfmt, metadb) {
if (metadb)
var paths =  fb.TitleFormat(ImgSrcFmt).EvalWithMetadb(metadb)
else
var paths =  fb.TitleFormat(ImgSrcFmt).Eval();
paths = paths.replace(/<embed>/gi, "<"+metadb.RawPath+">");
return paths;
};

// Check file type and file size.
var IsFilePropOK = function (file) {
var ext = FSO.GetExtensionName(file).toLowerCase();
for (var i=0; i<SupportTypes.length; i++) {
if (ext==SupportTypes[i] && (MaxFileSize<=0 || file.Size<=MaxFileSize))
return true;
}
return false;
};

// Find matches image files in "ImgSrc", cache relational paths, return the valid paths array.
// If "ImgSrc" has nothing changed, return the previous array directly.
// If no valid path found, return an empty array.
this.GetImgPaths = function (metadb) {
var newsrc = CalcPathFmt(ImgSrcFmt, metadb);
if (newsrc==ImgSrcStr)
return FoundFiles; // If the source format has nothing changed, return the previous results directly.
else
ImgSrcStr = newsrc;

PathsArray = ImgSrcStr.split("||");
var NewFoundFiles = new Array;

for (var i=0; i<PathsArray.length; i++) {
var Path = PathsArray[i];
var SearchResults = PathsCache ? PathsCache.SearchFor(Path) : null;
if (!SearchResults) {
SearchResults = new Array;
var EmbedPath = Path.match(/<.*>/);
if (EmbedPath) { // Check embed cover.
EmbedPath = EmbedPath.toString();
if (GetEmbedImg(EmbedPath))
SearchResults.push(EmbedPath);
} else if (Path.indexOf("*")==-1 && Path.indexOf("?")==-1) { // If not wildcard exist.
if (!FSO.FileExists(Path)) continue;
SearchResults.push(Path);
} else { // Search in wildcard.
var foldername = FSO.GetParentFolderName(Path);
if (!FSO.FolderExists(foldername)) continue;

if (CycleInWildCard) {
// Check file type and size first -----------------
var ValidFiles = PathsCache ? PathsCache.SearchFor(foldername+"\\*") : null; // Search in cache first.
if (!ValidFiles) {
ValidFiles = new Array;
var e = new Enumerator(FSO.GetFolder(foldername).Files);
for (; !e.atEnd(); e.moveNext()) {
var file = e.item();
if (IsFilePropOK(file))
ValidFiles.push(file.Path);
}
PathsCache && PathsCache.Store(foldername+"\\*", ValidFiles); // Store this step's result in cache.
}
// Then match wildcard ------------------
var exp = FSO.GetFileName(Path);
if (exp!="*" && exp!="*.*") {
for (var j=0; j<ValidFiles.length; j++) {
if (utils.PathWildcardMatch(exp, FSO.GetFileName(ValidFiles[j])))
SearchResults.push(ValidFiles[j]);
}
} else
SearchResults = ValidFiles;

} else {
var exp = FSO.GetFileName(Path);
var e = new Enumerator(FSO.GetFolder(foldername).Files);
for (; !e.atEnd(); e.moveNext()) {
var file = e.item();
if (IsFilePropOK(file) && utils.PathWildcardMatch(exp, file.Name)) {
SearchResults.push(file.Path);
break; // One file per path is enough.
}
}
}
}
PathsCache && PathsCache.Store(Path, SearchResults); // Store search results for this path.
}
// Merge these files of this path into the final results, duplicate files will only keep one.
unionArray(NewFoundFiles, SearchResults);
}

if (NewFoundFiles.join()!=FoundFiles.join()) // If the result has nothing changed, return the previous results directly.
FoundFiles = NewFoundFiles;
CollectGarbage(); // Release memory.
return FoundFiles;
};

this.ClearCache = function () {
PathsCache && PathsCache.Clear();
ImgSrcStr = "";
};

} (Properties, GetImg);

var GetImgPaths = PathChecker.GetImgPaths;


//====================================================
// Define Display Style =====================================
/* Define style, display image and animation.
Primarily provides the "ChangeImage()" method */
var Display = new function (Prop, ImgLoader) {
this.margin = {top: 0, left: 0, bottom: 0, right: 0};
this.x = this.margin.left;
this.y = this.margin.top;
this.width;
this.height;
var FSO = Prop.Panel.FSO;
var EnableFading = Prop.Cycle.Animation.Enable;
var RefreshInterval = Prop.Cycle.Animation.RefreshInterval;
var step = Math.min(Math.ceil(255*RefreshInterval/Prop.Cycle.Animation.Duration),255);
var DefaultImg = gdi.image(Prop.Image.DefaultImagePath);
var ext = FSO.GetExtensionName(Prop.Image.DefaultImagePath).toLowerCase();
var DefaultRaw = null;
if (DefaultImg && ext!="png" && ext!="gif")
DefaultRaw = DefaultImg.CreateRawBitmap();
var ImgPath = null;
var CurImage = DefaultImg;
var CurRaw = DefaultRaw;
var CurSize = null;
var NewImage = null;
var NewSize = null;
var CanBeCreateRaw = true;
var opacity = 255;
var timer = null;

if (ImgLoader)
var GetImg = ImgLoader;
else
var GetImg = function () {
return gdi.image(path);
};

// Change now displaying image to the new one.
// "path" is a string object, or empty.
// When "path" is empty, means change to style default image (DefaultImg).
// "GroupChanged" means "GroupFormat" calculate result changes.
this.ChangeImage = function (path, GroupChanged) {
if (path==ImgPath) return;
ImgPath = path;
var newimg;
if (ImgPath) {
newimg = GetImg(ImgPath, this.width, this.height);
var ext = FSO.GetExtensionName(ImgPath).toLowerCase();
CanBeCreateRaw = ext!="png" && ext!="gif";
} else
newimg = DefaultImg;

if (EnableFading) {
if (NewImage) {
CurImage = NewImage;
//CurRaw = NewImage==DefaultImg ? DefaultRaw : (CanBeCreateRaw ? CurImage.CreateRawBitmap() : null);
CurSize = NewSize;
opacity = 255;
}
NewImage = newimg;
NewSize = CalcNewImgSize(NewImage, this.width, this.height);
if (!timer) timer = window.CreateTimerInterval(RefreshInterval);
} else {
CurImage = newimg;
CurRaw = ImgPath ? (CanBeCreateRaw ? CurImage.CreateRawBitmap() : null) : DefaultRaw;
CurSize = CalcNewImgSize(CurImage, this.width, this.height);
window.RepaintRect(this.x, this.y, this.width, this.height);
}
};

this.Refresh = function () {
if (ImgPath) {
CurImage = GetImg(ImgPath, this.width, this.height, true); // Get image bypass cache.
if (CurRaw) CurRaw = CurImage.CreateRawBitmap();
} else {
DefaultImg = gdi.image(Prop.Image.DefaultImagePath);
DefaultRaw = DefaultImg.CreateRawBitmap();
CurImage = DefaultImg;
CurRaw = DefaultRaw;
}
if (CurImage)
CurSize = CalcNewImgSize(CurImage, this.width, this.height);
if (NewImage)
NewSize = CalcNewImgSize(NewImage, this.width, this.height);
window.Repaint();
};

this.OnPaint = function (gr) {
var Img, size;
if (Img = CurImage) {
size = CurSize;
if (opacity==255 && CurRaw)
// This funtion is much more faster.
gr.GdiDrawBitmap(CurRaw, this.x+size.x, this.y+size.y, size.width, size.height, 0, 0, Img.width, Img.height);
else
gr.DrawImage(Img, this.x+size.x, this.y+size.y, size.width, size.height, 0, 0, Img.width, Img.height, 0, opacity);
}
if (Img = NewImage) {
size = NewSize;
gr.DrawImage(Img, this.x+size.x, this.y+size.y, size.width, size.height, 0, 0, Img.width, Img.height, 0, 255-opacity);
}
};

this.OnTimer = function (id) {
if (timer && id==timer.ID) {
if (opacity>0) {
opacity = Math.max(opacity-step,0);
window.RepaintRect(this.x, this.y, this.width, this.height);
} else {
CurImage = NewImage;
CurRaw = ImgPath ? (CanBeCreateRaw ? CurImage.CreateRawBitmap() : null) : DefaultRaw;
CurSize = NewSize;
NewImage = null;
NewSize = null;
opacity = 255;
timer && window.KillTimer(timer);
timer = null;
CollectGarbage(); // Release memory.
//window.RepaintRect(this.x, this.y, this.width, this.height);
}
}
};

this.OnResize = function (ww, wh) {
this.width = ww-this.margin.left-this.margin.right;
this.height = wh-this.margin.top-this.margin.bottom;

if (ImgPath) {
CurImage = GetImg(ImgPath, this.width, this.height);
if (CurRaw) CurRaw = CurImage.CreateRawBitmap();
}
if (CurImage)
CurSize = CalcNewImgSize(CurImage, this.width, this.height);
if (NewImage)
NewSize = CalcNewImgSize(NewImage, this.width, this.height);
};

} (Properties, GetImg);


//====================================================
// Define Main Controler ====================================
/* Main controler of the panel,
controls images loading, changing, cycle, and paths checking */
var Controler = new function (Prop, GetImgPaths, Dsp) {
var CycleEnabled = Prop.Cycle.Enable;
this.CycleActivated = false;
var CyclePeriod = Prop.Cycle.Period;
var GroupFmt = Prop.Image.GroupFormat;
var GroupStr = null;
var ImgPaths = null;
this.CurImgPath = null;
var CurImgIdx = 0;
this.Paused = window.GetProperty("Cycle.Paused", !CycleEnabled);
var timer = null;
var _this = this;

var ChangeImg = function (arg, GroupChanged) {
switch (arg) {
case 2: // Last
CurImgIdx = ImgPaths.length-1;
break;
case 1: // Next
CurImgIdx = CurImgIdx+1<ImgPaths.length ? CurImgIdx+1 : 0;
break;
case -1: // Previous
CurImgIdx = CurImgIdx-1>=0 ? CurImgIdx-1 : ImgPaths.length-1;
break;
case -2: // First
CurImgIdx = 0;
break;
default: // Default
arg = 0;
}
var path = arg ? ImgPaths[CurImgIdx] : null;
toDefault(path ? false : true);

if (!GroupChanged && path==_this.CurImgPath)
return;
else
_this.CurImgPath = path;

Dsp.ChangeImage(_this.CurImgPath, GroupChanged);
};

var ResetTimer = function () {
if (!timer) return;
window.KillTimer(timer);
timer = window.CreateTimerInterval(CyclePeriod);
CollectGarbage(); // Release memory.
};

this.Play = function () {
this.Paused = false;
window.SetProperty("Cycle.Paused", this.Paused);
if (!this.CycleActivated) return;
if (!timer) timer = window.CreateTimerInterval(CyclePeriod);
};

this.Pause = function (p) {
if (!p) {
this.Paused = true;
window.SetProperty("Cycle.Paused", this.Paused);
}
if (!this.CycleActivated) return;
if (timer) {
window.KillTimer(timer);
timer = null;
CollectGarbage(); // Release memory.
}
};

this.Next = function () {
if (!this.CycleActivated) return;
ResetTimer();
ChangeImg(1);
};

this.Previous = function () {
if (!this.CycleActivated) return;
ResetTimer();
ChangeImg(-1);
};

this.First = function () {
if (!this.CycleActivated) return;
ResetTimer();
ChangeImg(-2);
};

this.Last = function () {
if (!this.CycleActivated) return;
ResetTimer();
ChangeImg(2);
};

this.OnNewTrack = function (metadb, followcur) {
var NewImgPaths = GetImgPaths(metadb);
if (metadb)
var groupstr = fb.TitleFormat(GroupFmt).EvalWithMetadb(metadb)
else
var groupstr = fb.TitleFormat(GroupFmt).Eval();

if (GroupStr!=groupstr) {
GroupStr = groupstr;
var IsNewGroup = true;
} else
var IsNewGroup = false;

if (ImgPaths!=NewImgPaths || IsNewGroup) {
ImgPaths = NewImgPaths;
if (ImgPaths.length<=1)
SetCycleStatus(false);
else
SetCycleStatus(CycleEnabled);
ResetTimer();
ChangeImg(-2, IsNewGroup);
}

if (followcur && Prop.Cycle.AutoPauseWhenFollowCursor) {
this.Pause(true);
if (CurImgIdx!=0)
ChangeImg(-2);
} else
!this.Paused && this.Play();
};

this.OnStop = function (reason) {
timer && window.KillTimer(timer);
if (reason<=1)
ChangeImg();
if (reason!=2) {
this.Pause(true);
SetCycleStatus(false);
ImgPaths = null;
this.CurImgPath = null;
CurImgIdx = 0;
GroupStr = null;
}
};

this.OnTimer = function (id) {
if (timer && id==timer.ID)
this.Next();
};

} (Properties, GetImgPaths, Display);


//====================================================
// Define Control Buttons ===================================
/* All button's funtions are calls of Controler's method */
if (Properties.Buttons.Display && Properties.Cycle.Enable) {
var Buttons = new function (Prop, Ctrl) {
var BtnDir = Prop.Panel.WorkDirectory + "Buttons\\";
var lang = Prop.Panel.lang;
var Position = Prop.Buttons.Position;
this.x = 0;
this.y = 0;
this.width = 0;
this.height = 0;
var opacity = 0;
var defaultOp = 150;
var hbtn = null;
var dbtn = null;
var timer = null;
var RefreshInterval = 50;
var step = 40;
var dstOp = 0;
var _this = this;
this.BtnsArray = new Array();

// Define button class ------------------------------------------------
var Button = function (x, y, img, OnClick, tiptext) {
this.x = x;
this.y = y;
this.width = img.width/4;
this.height = img.height;
this.Img = img;
this.tiptext = tiptext;
this.state = 3; // 0=normal, 1=hover, 2=down, 3=disabled
this.enabled = false;
this.OnClick = OnClick;
var Tooltip = Prop.Panel.Tooltip;

this.isXYinBtn = function (x, y) {
if (!this.enabled) return false;
return (x >= this.x && y >= this.y && x<= this.x + this.width && y <= this.y + this.height) ? true : false;
};

this.Draw = function (gr, op) {
if (!opacity) return;
gr.DrawImage(this.Img, this.x, this.y, this.width, this.height, this.state*this.Img.width/4, 0, this.width, this.height, 0, opacity);
};

this.ChangeState = function (s, enabled) {
//if (!this.enabled && !enabled) return;
if (enabled===undefined) {
if (s==this.state)
return;
else
this.state = s;
} else {
this.enabled = enabled;
this.state = enabled ? 0 : 3;
}
if (s==1) {
Tooltip.Text =  this.tiptext;
Tooltip.Activate();
} else
Tooltip.Deactivate();
if (opacity)
window.RepaintRect(this.x, this.y, this.width, this.height);
};
};

// Create buttons --------------------------------
var img_play = gdi.image(BtnDir+"Play.png");
var img_pause = gdi.image(BtnDir+"Pause.png");
var img_next = gdi.image(BtnDir+"Next.png");
var img_prev = gdi.image(BtnDir+"Prev.png");
var xOffset = this.x;
this.BtnsArray.push(new Button(xOffset, this.y, img_prev, function(){Ctrl.Previous();}, lang=="cn" ? "上一张图片" : "Previous Image"));
xOffset += this.BtnsArray[this.BtnsArray.length-1].width;
this.BtnsArray.push(PlayBtn = new Button(xOffset, this.y, img_play, function(){SetPauseStatus(Ctrl.Paused)}, ""));
xOffset += this.BtnsArray[this.BtnsArray.length-1].width;
this.BtnsArray.push(new Button(xOffset, this.y, img_next, function(){Ctrl.Next();}, lang=="cn" ? "下一张图片" : "Next Image"));
xOffset += this.BtnsArray[this.BtnsArray.length-1].width;

PlayBtn.tiptext_play = lang=="cn" ? "循环封面" : "Cycle Covers";
PlayBtn.tiptext_pause = lang=="cn" ? "暂停循环" : "Pause Cycle";
PlayBtn.tiptext = Ctrl.Paused ? PlayBtn.tiptext_play : PlayBtn.tiptext_pause;
PlayBtn.img_pause = img_pause;
PlayBtn.img_play = img_play;
PlayBtn.Img = Ctrl.Paused ? PlayBtn.img_play : PlayBtn.img_pause;
PlayBtn.ChangeState(null, true);
this.PlayBtn = PlayBtn;

this.width = xOffset-this.x;
this.height = PlayBtn.height;
//---------------------------------------
this.SetCycleStatus = function (s) {
this.BtnsArray[0].ChangeState(null, s);
this.BtnsArray[2].ChangeState(null, s);
};

this.SetPauseStatus = function (s) {
if (s) {
PlayBtn.Img = PlayBtn.img_pause;
PlayBtn.tiptext = PlayBtn.tiptext_pause;
} else {
PlayBtn.Img = PlayBtn.img_play;
PlayBtn.tiptext = PlayBtn.tiptext_play;
}
};

var isXYinBtns = function (x, y) {
return (x >= _this.x && y >= _this.y && x<= _this.x + _this.width && y <= _this.y + _this.height) ? true : false;
};

var Fading = function (dstop) {
if (dstOp==dstop) return;
dstOp = dstop;
if (!timer) timer = window.CreateTimerInterval(RefreshInterval);
};

this.OnPaint = function (gr) {
if (!opacity) return;
for (var i=0; i<this.BtnsArray.length; i++)
this.BtnsArray[i].Draw(gr, opacity);
};

this.OnMouseMove = function (x, y) {
if (isXYinBtns(x, y)) {
if (opacity!=255) {
dstOp = 255;
opacity = 255;
window.RepaintRect(this.x, this.y, this.width, this.height);
}
} else if (opacity!=defaultOp)
Fading(defaultOp);

if (dbtn) {
if (dbtn.isXYinBtn(x, y))
dbtn.ChangeState(2);
else
dbtn.ChangeState(1);
} else {
for (var i=0; i < this.BtnsArray.length ; i++)
if (this.BtnsArray[i].isXYinBtn(x,y)) {
if (hbtn!=this.BtnsArray[i]) {
if(hbtn) hbtn.ChangeState(0);
hbtn = this.BtnsArray[i];
hbtn.ChangeState(1);
}
break;
}
if (i==this.BtnsArray.length) {
if (hbtn) {
hbtn.ChangeState(0);
hbtn = null;
}
}
}
};

this.OnLbtnDown = function (x, y) {
if (hbtn) {
dbtn = hbtn;
dbtn.ChangeState(2);
}
};

this.OnLbtnUp = function (x, y) {
if (dbtn) {
if (dbtn.state==2) {
dbtn.OnClick();
dbtn.ChangeState(1);
}
dbtn = null;
this.OnMouseMove(x, y);
}
};

this.OnMouseLeave = function () {
Fading(0);
if (hbtn) {
hbtn.ChangeState(0);
hbtn = null;
}
};

this.OnTimer = function (id) {
if (timer && id==timer.ID) {
if (opacity==dstOp) {
timer && window.KillTimer(timer);
timer = null;
CollectGarbage(); // Release memory.
//window.RepaintRect(this.x, this.y, this.width, this.height);
} else {
if (opacity<dstOp)
opacity = Math.min(opacity+step, dstOp);
else
opacity = Math.max(opacity-step, dstOp);
window.RepaintRect(this.x, this.y, this.width, this.height);
}
}
};

this.OnResize = function (ww, wh) {
if (Position==1 || Position==4)
this.x = (ww-this.width)/2;
else if (Position==2 || Position==5)
this.x = ww-this.width;

if (Position>2)
this.y = wh-this.height;

var x = this.x;
for (var i=0; i<this.BtnsArray.length; i++) {
this.BtnsArray[i].x = x;
x += this.BtnsArray[i].width;
this.BtnsArray[i].y = this.y;
};
this.width = x-this.x;
};

} (Properties, Controler);

} else
var Buttons = {};


//====================================================
// Functions Menu ========================================
var FuncMenu = new function (Prop, Ctrl, Dsp, Btns, ImgLoader, ImgFinder) {
// Flags ----------
var MF_SEPARATOR = 0x00000800;
var MF_ENABLED = 0x00000000;
var MF_GRAYED = 0x00000001;
var MF_DISABLED = 0x00000002;
var MF_UNCHECKED = 0x00000000;
var MF_CHECKED = 0x00000008;
var MF_STRING = 0x00000000;
var MF_POPUP = 0x00000010;
var MF_RIGHTJUSTIFY = 0x00004000;

var lang = Prop.Panel.lang;
var ItemList = {};
var ItemID = 1;

var BuildMenu = function (items) {
var menu = window.CreatePopupMenu();
var mf, id, radio;
for (var i=0; i<items.length; i++) {
mf =  items[i].Flag || MF_STRING;
id = items[i].ID || ItemID++;
menu.AppendMenuItem(mf, id, items[i].Caption);
if (i==items.Radio)
radio = id;
ItemList[id] = items[i];
}
radio && menu.CheckMenuRadioItem(1, items.length, radio);
return menu;
};

// Submenu: Follow Cursor -------------------------
var Menu_FC_Items = new Array(
{
Caption: lang=="cn" ? "仅在非播放时" : "Only when not playing",
Func: function(){
if (Prop.Panel.FollowCursor==1) return;
Prop.Panel.FollowCursor = 1;
window.SetProperty("Panel.FollowCursor", 1);
Menu_FC_Items.Radio = 0;
if (fb.IsPlaying)
on_playback_new_track(fb.GetNowPlaying());
else
on_item_focus_change(fb.GetFocusItem());
RebuildMenu();
}
},
{
Caption: lang=="cn" ? "总是" : "Always",
Func: function(){
if (Prop.Panel.FollowCursor==2) return;
Prop.Panel.FollowCursor = 2;
window.SetProperty("Panel.FollowCursor", 2);
Menu_FC_Items.Radio = 1;
on_item_focus_change(fb.GetFocusItem());
RebuildMenu();
}
},
{
Caption: lang=="cn" ? "从不" : "Never",
Func: function(){
if (Prop.Panel.FollowCursor==0) return;
Prop.Panel.FollowCursor = 0;
window.SetProperty("Panel.FollowCursor", 0);
Menu_FC_Items.Radio = 2;
if (fb.IsPlaying)
on_playback_new_track(fb.GetNowPlaying());
else
on_playback_stop(0);
RebuildMenu();
}
}
);
var fc = Prop.Panel.FollowCursor;
Menu_FC_Items.Radio = fc==1 ? 0 : fc==2 ? 1 : fc==0 ? 2 : null;
var Menu_SubItem_FC = {
Flag: MF_POPUP,
Caption: lang=="cn" ? "光标跟随模式" : "Follow Cursor",
ID: null
}

// Submenu: Image Stretching ----------------------
var Menu_IS_Items = new Array(
{
Flag: Prop.Image.Stretch ? MF_CHECKED : MF_UNCHECKED,
Caption: lang=="cn" ? "拉伸图像" : "Stretch Image",
Func: function(){
Prop.Image.Stretch = !Prop.Image.Stretch;
window.SetProperty("Image.Stretch", Prop.Image.Stretch);
this.Flag = Prop.Image.Stretch ? MF_CHECKED : MF_UNCHECKED;
Dsp && Dsp.Refresh();
RebuildMenu();
}
},
{
Flag: Prop.Image.KeepAspectRatio ? MF_CHECKED : MF_UNCHECKED,
Caption: lang=="cn" ? "保持比例" : "Keep Aspect Ratio",
Func: function(){
Prop.Image.KeepAspectRatio = !Prop.Image.KeepAspectRatio;
window.SetProperty("Image.KeepAspectRatio", Prop.Image.KeepAspectRatio);
this.Flag = Prop.Image.KeepAspectRatio ? MF_CHECKED : MF_UNCHECKED;
Dsp && Dsp.Refresh();
RebuildMenu();
}
}
);
var Menu_SubItem_IS = {
Flag: MF_POPUP,
Caption: lang=="cn" ? "图像拉伸" : "Image Stretching",
ID: null
}

// Main menu --------------------------------
var Item_cycle = {
Flag: MF_ENABLED,
cap_play: lang=="cn" ? "继续循环" : "Resume Cycle",
cap_pause: lang=="cn" ? "暂停循环" : "Pause Cycle",
Caption: null,
Func: function () {Ctrl && SetPauseStatus(Ctrl.Paused);}
};
Item_cycle.Caption = Ctrl.Paused ? Item_cycle.cap_play : Item_cycle.cap_pause;

var Item_VWEV, Item_OIF;
var Menu_Items = new Array (
Item_cycle,
{
Flag: MF_GRAYED,
Caption: lang=="cn" ? "上一张图片" : "Previous Image",
Func: function(){Ctrl & Ctrl.Previous();}
},
{
Flag: MF_GRAYED,
Caption: lang=="cn" ? "下一张图片" : "Next Image",
Func: function(){Ctrl && Ctrl.Next();}
},
{
Flag: MF_GRAYED,
Caption: lang=="cn" ? "第一张图片" : "First Image",
Func: function(){Ctrl && Ctrl.First();}
},
{
Flag: MF_GRAYED,
Caption: lang=="cn" ? "最后一张图片" : "Last Image",
Func: function(){Ctrl && Ctrl.Last();}
},
//--------------------------------------------------------------
Item_VWEV = {
Flag: MF_GRAYED,
Caption: lang=="cn" ? "在外部查看器中查看" : "View With External Viewer",
Func: function(){
var path = Ctrl.CurImgPath;
if (!path) return;
if (path.charAt(0)=="<") {
fb.ShowPopupMessage(lang=="cn" ? "当前图片为内嵌图片,无法用外部查看器显示" : "This image is embed image, can't be displayed in external viewer", "WSH Cover Panel", 1);
return;
}
if (!Prop.Panel.ShellObj)
Prop.Panel.ShellObj= new ActiveXObject("Shell.Application");
Prop.Panel.ShellObj.ShellExecute('"' + path + '"', "", "", "open", 1);
}
},
Item_OIF = {
Flag: MF_GRAYED,
Caption: lang=="cn" ? "打开图片所在目录" : "Open Containing Folder",
Func: function(){
var path = Ctrl.CurImgPath;
if (!path) return;
if (path.charAt(0)=="<")
path = path.substring(1, path.length-1);
if (!Prop.Panel.ShellObj)
Prop.Panel.ShellObj= new ActiveXObject("Shell.Application");
Prop.Panel.ShellObj.ShellExecute("explorer", '/select,\"' + path + '"', "", "open", 1);
}
},
{
Flag: MF_SEPARATOR // Insert separator.
},
Menu_SubItem_IS // Insert "Image Stretching" submenu.
,
Menu_SubItem_FC // Insert "Follow Cursor" submenu.
,
{
Flag: MF_SEPARATOR
},
{
Caption: lang=="cn" ? "刷新图片" : "Refresh Image",
Func: function(){Dsp && Dsp.Refresh();}
},
{
Flag: (Prop.Image.ImageCacheCapacity || Prop.Image.PathCacheCapacity) ? MF_ENABLED : MF_GRAYED,
Caption: lang=="cn" ? "清除缓存" : "Clear Cache",
Func: function () {
ImgLoader && ImgLoader.ClearCache();
ImgFinder && ImgFinder.ClearCache();
CollectGarbage(); // Release memory.
}
},
{
Flag: MF_SEPARATOR
},
{
Caption: lang=="cn" ? "WSH Cover 参数设置..." : "WSH Cover Properties...",
Func: function(){window.ShowProperties();}
},
{
Caption: lang=="cn" ? "帮助..." : "Help...",
Func: function(){
var HelpFile = Prop.Panel.WorkDirectory + "WSH_Cover_Properties_Help.txt";
if (!Prop.Panel.FSO.FileExists(HelpFile)) {
fb.ShowPopupMessage(Prop.Panel.lang=="cn" ? "找不到 "+HelpFile+" 文件." : "Can not find file "+HelpFile+" .", "WSH Cover Panel", 1);
return;
}
var file = Prop.Panel.FSO.OpenTextFile(HelpFile, 1);
var txt = file.ReadAll();
fb.ShowPopupMessage(txt, "WSH Cover Panel", 2);
file.Close();
}
}
);

this.ViewWithExternalViewer = Item_VWEV.Func;
this.Menu_Items = Menu_Items;
var Menu, Menu_FC;

var RebuildMenu = function(){
ItemList = {};
ItemID = 1;
Menu_FC = BuildMenu(Menu_FC_Items);
Menu_SubItem_FC.ID = Menu_FC.ID;
Menu_IS = BuildMenu(Menu_IS_Items);
Menu_SubItem_IS.ID = Menu_IS.ID;
Menu = BuildMenu(Menu_Items);
};

this.RebuildMenu = RebuildMenu;
RebuildMenu();

this.Show = function (x, y) {
var ret = Menu.TrackPopupMenu(x, y);
if (ret!=0)
ItemList[ret].Func();
};

this.SetCycleStatus = function (s) {
for (var i=1; i<5; i++)
Menu_Items[i].Flag = s ? MF_ENABLED : MF_GRAYED;
RebuildMenu();
};

this.SetPauseStatus = function (s) {
if (s)
Item_cycle.Caption = Item_cycle.cap_pause;
else
Item_cycle.Caption = Item_cycle.cap_play;
RebuildMenu();
};

var IsDefaultImg = true;
this.toDefault = function (s) {
if (s==IsDefaultImg) return;
IsDefaultImg = s;
Item_VWEV.Flag = s ? MF_GRAYED : MF_ENABLED;
Item_OIF.Flag = s ? MF_GRAYED : MF_ENABLED;
RebuildMenu();
};

} (Properties, Controler, Display, Buttons, ImageLoader, PathChecker);


//====================================================
function SetCycleStatus (s) {
Controler.CycleActivated = s;
Buttons.SetCycleStatus && Buttons.SetCycleStatus(s);
FuncMenu && FuncMenu.SetCycleStatus(s);
};

function SetPauseStatus (s) {
if (s)
Controler.Play();
else
Controler.Pause();
Buttons.SetPauseStatus && Buttons.SetPauseStatus(s);
FuncMenu && FuncMenu.SetPauseStatus(s);
};

function toDefault (s) {
FuncMenu && FuncMenu.toDefault(s);
};


//====================================================
// BackGround ===========================================
var bgcolor = Properties.Panel.BackGroundColor;
if (bgcolor)
bgcolor = RGBA(bgcolor[0], bgcolor[1], bgcolor[2], bgcolor[3]);


//====================================================
//====================================================
function on_paint(gr){
gr.SetSmoothingMode(Properties.Image.SmoothingMode);
gr.SetInterpolationMode(Properties.Image.InterpolationMode);

if (bgcolor)
gr.FillSolidRect(0, 0, ww, wh, bgcolor);

Display.OnPaint && Display.OnPaint(gr);
Buttons.OnPaint && Buttons.OnPaint(gr);
}
function on_size(){
if (!window.Width || !window.Height) return;
ww = window.Width;
wh = window.Height;
Display.OnResize && Display.OnResize(ww, wh);
Buttons.OnResize && Buttons.OnResize(ww, wh);
}
// Track events ---------------------------------------------
function on_item_focus_change(){
if (fb.GetFocusItem() && (Properties.Panel.FollowCursor==2 || (Properties.Panel.FollowCursor==1 && !fb.IsPlaying)))
Controler.OnNewTrack && Controler.OnNewTrack(fb.GetFocusItem(), true);
}
function on_playback_new_track(metadb){
if (Properties.Panel.FollowCursor<=1)
Controler.OnNewTrack && Controler.OnNewTrack(metadb);
}
function on_playback_stop(reason){
var metadb = fb.GetFocusItem();
if (Properties.Panel.FollowCursor==0 || !metadb)
Controler.OnStop && Controler.OnStop(reason);
else if (Properties.Panel.FollowCursor==1 && reason!=2)
Controler.OnNewTrack && Controler.OnNewTrack(metadb, true);
}
// Mouse events --------------------------------------------
var rbtnDown, ShiftDown, mbtnDown;
function on_mouse_move(x,y){
Buttons.OnMouseMove && Buttons.OnMouseMove(x, y);
}
function on_mouse_lbtn_down(x,y){
Buttons.OnLbtnDown && Buttons.OnLbtnDown(x, y);
}
function on_mouse_lbtn_up(x,y){
Buttons.OnLbtnUp && Buttons.OnLbtnUp(x, y);
}
function on_mouse_leave(){
Buttons.OnMouseLeave && Buttons.OnMouseLeave();
}
function on_mouse_rbtn_down(x, y, vkey){
rbtnDown = true;
ShiftDown = vkey==6 ? true : false;
}
function on_mouse_rbtn_up(x, y, vkey){
if (!rbtnDown) return true;
rbtnDown = false;
if (ShiftDown)
return; // If shift key was pressed down, show default right click menu.
else {
FuncMenu.Show(x,y); // Show customize menu.
return true; // Disable default right click menu.
}
}
function on_mouse_mbtn_down(x, y, mask) {
mbtnDown = true;
}
function on_mouse_mbtn_up(x, y, mask) {
if (!mbtnDown) return;
FuncMenu.ViewWithExternalViewer();
mbtnDown = false;
}
function on_mouse_wheel(delta){
if (delta>0)
Controler && Controler.Previous();
else
Controler && Controler.Next();
}
//---------------------------------------------------------
function on_timer(id){
Controler.OnTimer && Controler.OnTimer(id);
Display.OnTimer && Display.OnTimer(id);
Buttons.OnTimer && Buttons.OnTimer(id);
}
http://maf.freedom-vrn.ru/Images.zip

WSH Panel Mod script discussion/help
Reply #384
I have used Songbird before and they have a add-on called MashTape.  I like the plugin and was wondering if there was a WSH script to get some similar functionality.

What I really like is the reviews.  Has anyone developed a script to pull down reviews from say AMG or something?

Thanks!

  • icedtea
  • [*][*]
WSH Panel Mod script discussion/help
Reply #385
marc2003 an idea for a panel
Using http://www.youtube.com/rssls to display popular videos (links to) in a panel.

  • laite
  • [*][*]
WSH Panel Mod script discussion/help
Reply #386
Marc2003: I'm using your Now Playing - panel but it seems that autodownload doesn't work with artists with "&" in their names (like Emerson, Lake & Palmer). Is there any way to make this work besides copying the images manually from last.fm?

  • marc2003
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #387
there shouldn't be any problem with & in the artist name - i have plenty of images downloaded just fine.

i'm unable to test that artist because i'm running linux at the moment and WSH panel mod doesn't work in it.

  • laite
  • [*][*]
WSH Panel Mod script discussion/help
Reply #388
there shouldn't be any problem with & in the artist name - i have plenty of images downloaded just fine.

i'm unable to test that artist because i'm running linux at the moment and WSH panel mod doesn't work in it.


I tried this with different artists, and it seems to retrieve anything before "&", for example "B.B. King & Eric Clapton" gets images from "B.B. King", "Echo & the bunnymen" downloads images from artist called "Echo" etc.

  • marc2003
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #389
i see. i'll take another look when i'm back on windows again.

  • marc2003
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #390
it was an old version of art.exe not handling the & that was the problem. but the author (paradog) has fixed it ages ago.

as before, you can't use that version as it will hang waiting for user input when the artist doesn't exist. so you'll need my modified version. i've updated my samples with it....

http://cid-649d3bfeaf541fbb.skydrive.live....ide/samples.zip

  • laite
  • [*][*]
WSH Panel Mod script discussion/help
Reply #391
as before, you can't use that version as it will hang waiting for user input when the artist doesn't exist. so you'll need my modified version. i've updated my samples with it....


Much appreciated, works fine now.

  • Joe30
  • [*]
WSH Panel Mod script discussion/help
Reply #392
@marc2003: I just discovered your "now playing.txt" script. It is exactly what I was looking for:
- automatic artist images download
- and cycle them
- display the song infos on top of that

==> THANK YOU!

WSH Panel Mod script discussion/help
Reply #393
How would I make a "text button," as in display a string that acts like a hyperlink button? I want to do something like this:

Quote
Now playing: Title by Artist


Where the Title is a text button for Quicksearch for Same / Title, and the Artist text button for Quicksearch for Same / Artist

WSH Panel Mod script discussion/help
Reply #394
Is it possible with WSH Panel Mod to change the active tab in CUI? I want to switch to my Now Playing Tab when playback starts.
  • Last Edit: 15 May, 2010, 03:34:13 PM by phunkydizco

WSH Panel Mod script discussion/help
Reply #395
I have two questions:

Is there a way to drop a shadow in real-time, without additional graphics?

How can I make the reflection effect seen in CUI playlist viewer?

I use gr.GdiDrawBitmap for displaying album art at the moment.

WSH Panel Mod script discussion/help
Reply #396
i'm having problems with the rating script in marc2003's sample package.
it shows my track ratings just fine, but i can't set them. clicking on stars has no effect.
i have foo_playcount installed...

any thoughts?

  • marc2003
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #397
check "playback statistics" is enabled on your context menu.

WSH Panel Mod script discussion/help
Reply #398
that fixes it, thanks!

WSH Panel Mod script discussion/help
Reply #399
another question for you, marc2003

in this post you put up a script for a button that tags tracks with %love%
http://www.hydrogenaudio.org/forums/index....st&p=685807

but it uses foo_customdb. is there a way to have a Love button like this that actually writes to the tag?

i use quick tagger right now to set %love% to 1 or 0 with keyboard shortcuts, but would like to have a button too.

thanks