Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: Spider Monkey Panel (foo_spider_monkey_panel) (Read 348831 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #600
I feel that you are talking past each other =)
So, I'll try to sum up all the things that @snotlicker said.

@regor , as it was mentioned above, in quite a few programming languages (and even in RegExp and windows command line) `\` character is used as an escape character or to form a control character. For example, `\n` is a control character for a new line, `\"` - escape the quote character.
Values that can be seen in property dialog have all the escape chars and control chars parsed.

So, in JS (and SMP) it will work like this:
Code: [Select]
window.SetProperty("escape_1", "\"");
console.log(window.GetProperty("escape_1"));  // Logged and displayed in Property dialog as `"`

window.SetProperty("escape_2", "\\");
console.log(window.GetProperty("escape_2"));  // Logged and displayed as `\`

window.SetProperty("path_1", "path\\to\\file.ext");
console.log(window.GetProperty("path_1")); // Logged and displayed as `path\to\file.ext`

window.SetProperty("path_2", "path/to/file.ext");
console.log(window.GetProperty("path_2")); // Logged and displayed as `path/to/file.ext`

window.SetProperty("control_1", "line_1\nline_2");
console.log(window.GetProperty("control_1"));
// Logged as:
// `line_1
// line_2`
// displayed as:
// `line_1line_2`

Thus, path strings in JS code should be either like this `path/to/file.ext` or like this `path\\to\\file.ext` .
Was a bug on my installation. New foobar profile worked right, I reinstalled everything and now works as expected. Have no idea what was going on.. since same lines of code behaved differently on different profiles.

Btw, I have one more doubt. I'm trying to create a playlist manager, like the autoplaylist list on samples but for standard playlists.
Right now I got it like this: There is a monitored folder, the UI loads all files within that folder (playlists), I can open them and they are loaded within foobar, update the file (i.e. save foobar playlist to binded file), rebind playlist and rename (renaming playlist on manager, renames the file itself and the playlist on foobar). All that is working. I only have a problem, I can delete the files using this function from helpers .
Code: [Select]
let app = new ActiveXObject('Shell.Application');
function _recycleFile(file) {
if (_isFile(file)) {
app.NameSpace(10).MoveHere(file);
}
}
But restoring the file becomes a problem. I can not find a way to move files from the bin to the original folder.  I use the Move method with this, something like this
Code: [Select]
let fso = new ActiveXObject('Scripting.FileSystemObject');
let recyclePath = "c:\\$RECYCLE.BIN\\" + app.NameSpace(10) + "\\" + file.FILENAME;
let restorePath = file.PATH;
fso.MoveFile(recyclePath , restorePath );
But files are never moved from the bin. I have tried with that recyclePath which does indeed work on explorer, but not using the move function. So as far as I understand, the path should be right since it works on explorer (?)
"c:\$RECYCLE.BIN\" points to the physical folder, and  "c:\$RECYCLE.BIN\" + app.NameSpace(10) to the virtual one containing all files from any HDD

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #601
I've tried looking through the documentation but I'm not getting any wiser so I thought I'd ask here.

I want to make a button that switches between shuffle track and default playback that works like how the play/pause button in the sample "playback buttons", anyone have any suggestions on how to make it work?

Code: [Select]
			if (plman.PlaybackOrder === 4){
fb.RunMainMenuCommand("Playback/Order/Default");
} else {
fb.RunMainMenuCommand("Playback/Order/Shuffle (tracks)");
}
That code worked to switch, thanks a lot.
I have to ask for more help though, sadly. I want to swap icon based on which order is active, how do I add that?

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #602
That code worked to switch, thanks a lot.
I have to ask for more help though, sadly. I want to swap icon based on which order is active, how do I add that?

Well, you can use the plman.PlaybackOrder property to write a conditional statement for that, too, much in the same way as above. To keep it simple, if you are using actual images:
Code: [Select]
function on_paint(gr){
let img_path;
if (plman.PlaybackOrder === 4){
img_path = //path to the default icon image
} else {
img_path = //path to the shuffle icon image
}
let img = gdi.Image(img_path)
gr.GdiDrawBitmap(img.CreateRawBitmap(), dstX, dstY, dstW, dstH, srcX, srcY, srcW, srcH)
}

If you are using font icon characters the principle is the same.
I'm late

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #603
That code worked to switch, thanks a lot.
I have to ask for more help though, sadly. I want to swap icon based on which order is active, how do I add that?

Well, you can use the plman.PlaybackOrder property to write a conditional statement for that, too, much in the same way as above. To keep it simple, if you are using actual images:
Code: [Select]
function on_paint(gr){
let img_path;
if (plman.PlaybackOrder === 4){
img_path = //path to the default icon image
} else {
img_path = //path to the shuffle icon image
}
let img = gdi.Image(img_path)
gr.GdiDrawBitmap(img.CreateRawBitmap(), dstX, dstY, dstW, dstH, srcX, srcY, srcW, srcH)
}

If you are using font icon characters the principle is the same.

I think I'm too dumb for this, the current thing I use is this:
Code: [Select]
buttons.buttons.shuffle = new _button(2, 2, 32, 32, {normal : 'buttons\\Menu.png'}, (x, y) => { if (plman.PlaybackOrder === 4){ fb.RunMainMenuCommand("Playback/Order/Default"); } else { fb.RunMainMenuCommand("Playback/Order/Shuffle (tracks)"); } }, 'Shuffle');

Maybe I should just look for another skin that has this function and see how they did it because I can't figure this out. When I add the function I get image is null.

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #604
I think I'm too dumb for this, the current thing I use is this:
Code: [Select]
buttons.buttons.shuffle = new _button(2, 2, 32, 32, {normal : 'buttons\\Menu.png'}, (x, y) => { if (plman.PlaybackOrder === 4){ fb.RunMainMenuCommand("Playback/Order/Default"); } else { fb.RunMainMenuCommand("Playback/Order/Shuffle (tracks)"); } }, 'Shuffle');

Maybe I should just look for another skin that has this function and see how they did it because I can't figure this out. When I add the function I get image is null.

I see, you're editing marc's script! I thought you were writing your own code. That makes it a little more complicated because you need to look at the code of at least three different scripts to understand where and how to edit (playback buttons, helpers and panel I think). I don't use it and I'm not familiar with it, but in that line of code you posted, the button image is likely passed by the fith argument of the _button() function, which is an object:
Code: [Select]
{normal : 'buttons\\Menu.png'}
So first of all you need to have the required image files in the buttons folder and than you could try replacing "menu" with a variable and assign that variable the appropriate value with the conditional statement I suggested in the previous post. You could write the conditional statement in the on_playback_order_changed() callback, for example. But really, I would need to have a better look at the scripts before suggesting anything.
I'm late

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #605
I think I'm too dumb for this, the current thing I use is this:
Code: [Select]
buttons.buttons.shuffle = new _button(2, 2, 32, 32, {normal : 'buttons\\Menu.png'}, (x, y) => { if (plman.PlaybackOrder === 4){ fb.RunMainMenuCommand("Playback/Order/Default"); } else { fb.RunMainMenuCommand("Playback/Order/Shuffle (tracks)"); } }, 'Shuffle');

Maybe I should just look for another skin that has this function and see how they did it because I can't figure this out. When I add the function I get image is null.

I see, you're editing marc's script! I thought you were writing your own code. That makes it a little more complicated because you need to look at the code of at least three different scripts to understand where and how to edit (playback buttons, helpers and panel I think). I don't use it and I'm not familiar with it, but in that line of code you posted, the button image is likely passed by the fith argument of the _button() function, which is an object:
Code: [Select]
{normal : 'buttons\\Menu.png'}
So first of all you need to have the required image files in the buttons folder and than you could try replacing "menu" with a variable and assign that variable the appropriate value with the conditional statement I suggested in the previous post. You could write the conditional statement in the on_playback_order_changed() callback, for example. But really, I would need to have a better look at the scripts before suggesting anything.
So you recommend I start from scratch instead?

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #606
So you recommend I start from scratch instead?

I encourage anyone to write their own rather than hacking other people's scripts, unless they are fairly simple and straightforward standalone scripts. But good coders usually don't have standalone scripts, but more complex systems which are hard to edit without breaking something. Nevertheless, meanwhile I had a look at the scripts and something easy you could try is editing the line of code you posted as follows:

Code: [Select]
buttons.buttons.shuffle = new _button(2, 2, 32, 32, {normal : plman.PlaybackOrder === 4 ? 'buttons\\deafult.png' : 'buttons\\shuffle.png'}, (x, y) => { if (plman.PlaybackOrder === 4){ fb.RunMainMenuCommand("Playback/Order/Default"); } else { fb.RunMainMenuCommand("Playback/Order/Shuffle (tracks)"); } }, 'Shuffle');

Than add the following:
Code: [Select]
function on_playback_order_changed(){
buttons.update();
window.Repaint();
}

Of course this works if you have a "shuffle.png" and "default.png" file in the buttons folder.

I'm late

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #607
P.S.
While we are at it, you can use the ternary operator ('?' and ':') for the conditional statement of the command as well:

Code: [Select]
buttons.buttons.shuffle = new _button(2, 2, 32, 32, {normal : plman.PlaybackOrder === 4 ? 'buttons\\deafult.png' : 'buttons\\shuffle.png'}, (x, y) => plman.PlaybackOrder === 4 ? fb.RunMainMenuCommand("Playback/Order/Default") : fb.RunMainMenuCommand("Playback/Order/Shuffle (tracks)"), 'shuffle');
I'm late

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #608
P.S.
While we are at it, you can use the ternary operator ('?' and ':') for the conditional statement of the command as well:

Code: [Select]
buttons.buttons.shuffle = new _button(2, 2, 32, 32, {normal : plman.PlaybackOrder === 4 ? 'buttons\\deafult.png' : 'buttons\\shuffle.png'}, (x, y) => plman.PlaybackOrder === 4 ? fb.RunMainMenuCommand("Playback/Order/Default") : fb.RunMainMenuCommand("Playback/Order/Shuffle (tracks)"), 'shuffle');

Works just the way I want it, thanks for your help :)

This is how I made it look, top right corner, greyed out when not enabled:

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #609
@Qwertiest
I've added some info. on issue 'ActiveXObject error when dealing with exotic filename encodings #54' on github. Hope this helped. If you need further info. please let me know.

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #610
Check if the path ends with .cue or use title formatting for embedded cuesheets %__cue_embedded% equals yes
If cue is external (i.e. not embedded), you may also try checking FbMetadbHandle.SubSong, it seems to be above zero only when it's a multi-track file.
Not necessarily. If you are using mtags with one file for each track, the subsong index is always 1.

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #611
How do you save a playlist to a path? I found nothing about that on the documentation only SavePlaylist() and using a main menu command I can not add the path.

Quote
But restoring the file becomes a problem. I can not find a way to move files from the bin to the original folder.  I use the Move method with this, something like this
Any help there would be appreciated too.

Thanks!

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #612
How do you save a playlist to a path? I found nothing about that on the documentation only SavePlaylist() and using a main menu command I can not add the path.
marc2k3 just aded that functionality btw.

Quote
But restoring the file becomes a problem. I can not find a way to move files from the bin to the original folder.  I use the Move method with this, something like this
Any help there would be appreciated too.

Thanks!
Well just found the problem is the (physical) name gets changed by the SO after sending a file to the Recycle Bin, so "a.txt" is changed to "$K4354A.txt" or things like that, while the explorer displays the original (virtual) name. I have now to list all files on the bin and identify the one I deleted, will report if that works for restoring purposes.

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #613
Also, is there some method to create a simple yes/no popupBox without using HTML?

popupBox(window_id, prompt, okString, cancelString)  -> return true/false

Obviously InputBox() could be used along try/catch to emulate that functionality but it looks weird (since the window expects a text input).

X

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #614
Well just found the problem is the (physical) name gets changed by the SO after sending a file to the Recycle Bin, so "a.txt" is changed to "$K4354A.txt" or things like that, while the explorer displays the original (virtual) name. I have now to list all files on the bin and identify the one I deleted, will report if that works for restoring purposes.
You can get original filename by using the following code:
Code: [Select]
let dir = app.NameSpace(10);
let items = dir.Items();

// Regretfully, `dir.Items()` is not enumerable, so it must be traversed manually
for (let i = 0; i < items.Count; ++i) {
   console.log(items.Item(i).Name); // original name
   console.log(items.Item(i).Path); // full path in recycle bin
}

How do you save a playlist to a path? I found nothing about that on the documentation only SavePlaylist() and using a main menu command I can not add the path.
Not sure I want to add this method, but I will put it on the maybe list in case I change my mind (it does happen =)).

Also, is there some method to create a simple yes/no popupBox without using HTML?
Not currently, but I'll see if it can be done.

@Qwertiest
I've added some info. on issue 'ActiveXObject error when dealing with exotic filename encodings #54' on github. Hope this helped. If you need further info. please let me know.
Thanks, I'll take a look.

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #615
Simple popups are already possible and have been in my samples for years.

Code: [Select]
let WshShell = new ActiveXObject('WScript.Shell');

let popup = {
ok : 0,
yes_no : 4,
yes : 6,
no : 7,
stop : 16,
question : 32,
info : 64
};

let prompt = ...
let caption = ...

if (WshShell.Popup(prompt, 0, caption, popup.question + popup.yes_no) == popup.yes) {
//do something
}

edit: see here for other button combos I've not included

https://www.devguru.com/content/technologies/wsh/wshshell-popup.html

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #616
Yep I did the same and finally got it working.  Thanks :) For reference, if anyone needs to do the same (it's just an improvement to marc's helpers):

Code: [Select]
const fso = new ActiveXObject('Scripting.FileSystemObject');
const app = new ActiveXObject('Shell.Application');

function _isFile(file) {
return _.isString(file) ? fso.FileExists(file) : false;
}

function _isFolder(folder) {
return _.isString(folder) ? fso.FolderExists(folder) : false;
}

function _createFolder(folder) {
if (!_isFolder(folder)) {
try {
fso.CreateFolder(folder);
} catch (e) {
return false;
}
return _isFolder(folder);
}
return false;
}

function _deleteFile(file) {
if (_isFile(file)) {
try {
fso.DeleteFile(file);
} catch (e) {
return false;
}
return !(_isFile(file));
}
return false;
}

function _renameFile(file, newFilePath) {
if (!_isFile(newFilePath) {
if (_isFile(file)) {
try {
fso.MoveFile(file, newFilePath);
} catch (e) {
return false;
}
return _isFile(newFilePath);
}
return false;
}
return false;
}

function _recycleFile(file) {
if (_isFile(file)) {
try {
app.NameSpace(10).MoveHere(file);
} catch (e) {
return false;
}
return !(_isFile(file));
}
return false;
}

function _restoreFile(file) {
if (!_isFile(file)) {
const arr = utils.FileTest(file, "split");
const OriginalFileName = arr[1];
const items = app.NameSpace(10).Items();
const numItems = items.Count;
for (let i = 0; i < numItems; i++) {
if (items.Item(i).Name == OriginalFileName) {
_renameFile(items.Item(i).Path, file);
break;
}
}
let bFound = _isFile(file);
if (!bFound){console.log('_restoreFile(): Can not restore file, "' + OriginalFileName + '" was not found at the bin.');}
return bFound;
} else {
console.log('_restoreFile(): Can not restore file to "' + file + '" since there is already another file at the same path.');
return false;
}
}



Btw utils.FileTest() seems to have a bug.

Code: [Select]
let arr = utils.FileTest("D:\\Somedir\\Somefile.txt", "split")
// arr[1] <= "Somefile.txt" extension included (?)

Not sure if that's intended, but the documentation says otherwise:

Code: [Select]
let arr = utils.FileTest("D:\\Somedir\\Somefile.txt", "split");
// arr[0] <= "D:\\Somedir\\" (always includes backslash at the end)
// arr[1] <= "Somefile"
// arr[2] <= ".txt"

PD: For reference, if that behaviour get's fixed, then the scripts at top should reflect that change too.

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #617
Simple popups are already possible and have been in my samples for years.

Code: [Select]
let WshShell = new ActiveXObject('WScript.Shell');

let popup = {
ok : 0,
yes_no : 4,
yes : 6,
no : 7,
stop : 16,
question : 32,
info : 64
};

let prompt = ...
let caption = ...

if (WshShell.Popup(prompt, 0, caption, popup.question + popup.yes_no) == popup.yes) {
//do something
}

edit: see here for other button combos I've not included

https://www.devguru.com/content/technologies/wsh/wshshell-popup.html

Oh that... yes. That's why I asked, I was sure I have been seeing them somewhere! I would prefer to not use ActiveXobjects but it's good enough. Thanks!

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #618
I can see the bug with utils.FileTest here...

https://github.com/TheQwertiest/foo_spider_monkey_panel/blob/150e49cdc072762b1a6b6a90d7e5be1158bbba50/foo_spider_monkey_panel/js_objects/utils.cpp#L298

It should use stem(), not filename().

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #619
Finally got all working on the playlist manager, and managed to get playlist size (#tracks) by using m3u directives and/or counting lines if they are missing. But I have a limitation, I can easily read/write m3u, m3u8 files and create schemes for them but I have no way to read fpl files.

If I want to know the number of tracks from a fpl playlist, is there any other way other than loading the playlist within foobar, and using plman.PlaylistItemCount(index)t?
I mean, is there a way to bypass playlist loading into the UI? fpl -> Handle list

EDIT: since addLocations(playlistIndex, paths, selectopt)  is async and there is no other method to load a playlist, the mentioned method doesn't work since PlaylistItemCount returns 0 because the playlist loading is not done yet when called. And having in mind all this involves playlist being temporarily shown on the UI, I think I should avoid using promises for creating/count/deleting temp playlists.


Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #621
Another bug:

I have folder with these files:
Code: [Select]
c:\Users\XXX\AppData\Roaming\foobar2000\playlist_manager\Lucia Emotivas.fpl
c:\Users\XXX\AppData\Roaming\foobar2000\playlist_manager\Post-Britpop.m3u8
c:\Users\XXX\AppData\Roaming\foobar2000\playlist_manager\World.m3u

Code: [Select]
utils.Glob(folderPath + '*.m3u').concat(utils.Glob(folderPath + '*.m3u8')).concat(utils.Glob(folderPath + '*.fpl')).concat(utils.Glob(folderPath + '*.pls'));

On console, win 7, there are 4 files:
[15:11:36] ["C:\Users\XXX\AppData\Roaming\foobar2000\playlist_manager\Post-Britpop.m3u8", "C:\Users\XXX\AppData\Roaming\foobar2000\playlist_manager\World.m3u", "C:\Users\XXX\AppData\Roaming\foobar2000\playlist_manager\Post-Britpop.m3u8", "C:\Users\XXX\AppData\Roaming\foobar2000\playlist_manager\Lucia Emotivas.fpl"]

Same script on win 10: 3 files
Code: [Select]
[15:11:36] ["C:\Users\XXX\AppData\Roaming\foobar2000\playlist_manager\World.m3u", "C:\Users\XXX\AppData\Roaming\foobar2000\playlist_manager\Post-Britpop.m3u8", "C:\Users\XXX\AppData\Roaming\foobar2000\playlist_manager\Lucia Emotivas.fpl"]

utils.Glob(folderPath + '*.m3u') matches '*.m3u8' too on win 7.

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #622
Seems like its not a component bug but a windows API issue.

But you can just use *.* and filter by extension yourself.

Code: [Select]
const allowed = ["m3u", "m3u8", "pls", "fpl"];
let files = utils.Glob("z:\\*.*").filter((item) => {
return allowed.includes(item.split('.').pop().toLowerCase());
});

Re: Spider Monkey Panel (foo_spider_monkey_panel)

Reply #623
Yep, I did something similar.
@TheQwertiest  Also check PathWildcardMatch(), since being a bug with the API it probably has the same behavior. If you need testing on win 7 just let me know, I use both.