Skip to main content
Topic: JScript Panel script discussion/help (Read 62509 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

Re: JScript Panel script discussion/help

Reply #725
Apparently I was on a very old version 1.3.0 and decided to update just now. Unfortunately a ton of scripts in my skin broke. I fixed some errors regarding fb.trace and getcolorcui replacements but this one I can't beat:
Those scripts have been updated by marc. The one you want is located in: %appdata%\foobar2000\user-components\foo_jscript_panel\samples\complete\js\panel.js

Use that instead of the one you have installed to that location.
Thanks, I had an old path. Managed to salvage all but one panel.
I also moved to a JS version of smooth playlist (was using WSH), does anyone know how to alight text to the middle of the row vertically?

Re: JScript Panel script discussion/help

Reply #726
You'll need to find the DrawString call for those texts, and set the last parameter to be: StringFormat(0, 1)

I've found it's easier to set up objects to make handling those StringFormat calls easier, so I have this in my code:
Code: [Select]
var StringAlignment = {Near: 0, Center: 1, Far: 2};
// then you can use it like
gr.DrawString("blah", font, color, x, y, w, h, StringFormat(StringAlignment.Near, StringAlignment.Center));

// or
var leftCenter = StringFormat(StringAlignment.Near, StringAlignment.Center);
gr.DrawString("blah", font, color, x, y, w, h, leftCenter);
You'll also need to make sure the height for the text is the entire height of the row, and not just tall enough for the text.

Re: JScript Panel script discussion/help

Reply #727
You'll need to find the DrawString call for those texts, and set the last parameter to be: StringFormat(0, 1)

I've found it's easier to set up objects to make handling those StringFormat calls easier, so I have this in my code:
Code: [Select]
var StringAlignment = {Near: 0, Center: 1, Far: 2};
// then you can use it like
gr.DrawString("blah", font, color, x, y, w, h, StringFormat(StringAlignment.Near, StringAlignment.Center));

// or
var leftCenter = StringFormat(StringAlignment.Near, StringAlignment.Center);
gr.DrawString("blah", font, color, x, y, w, h, leftCenter);
You'll also need to make sure the height for the text is the entire height of the row, and not just tall enough for the text.
Thanks but I couldn't get it to work :P All I managed was to move heart icon via WSHplaylist.js :D

Re: JScript Panel script discussion/help

Reply #728
Another question, is there another option apart from fb.GetFocusItem() and fb.GetNowPlaying()?
I want to add tracks to queue with a single MMB click, fb.RunContextCommandWithMetadb("Add to playback queue",fb.GetFocusItem()) needs 2 clicks, first one to select the track with LMB and only then MMB to add to queue.

Re: JScript Panel script discussion/help

Reply #729
Hi,

I hope one of you kind folk can help. I'm a complete coding novice, but have been making small changes to the fantastic work done by others. Thing is, there's something i want to add but have hit a brick wall.

I'd like to add different images to the left of time elapsed on the seekbar depending on the codec of the track playing. So an image for MP3, a different one for FLAC etc etc, you get the picture. Along with that, another image that appears to the left of that only if the track is greater than 16-bit. I've found scripts that do similar, but i can't get my head around what is required from them to achieve this. I've even attempted merging them into my existing edits, but have had nothing but inevitable errors  ::) A lot of Googling and some headaches later, i've decided to admit defeat and ask those that know best!

So if anyone wouldn't mind a bit of hand-holding with a complete newb it'd be very very much appreciated...just assume you're talking to a child  :)) I'm here to learn and improve my knowledge.

Code below and screenshot attached and again, thanks for any assistance guys.

Code: [Select]
// ==PREPROCESSOR==
// @name "Track Info + Seekbar + Buttons"
// @author "marc2003"
// @import "%fb2k_component_path%samples\complete\js\lodash.min.js"
// @import "%fb2k_component_path%samples\complete\js\helpers.js"
// @import "%fb2k_component_path%samples\complete\js\panel.js"
// @import "%fb2k_component_path%samples\complete\js\seekbar.js"
// ==/PREPROCESSOR==

var colours = {
background : _.RGB(30, 30, 30),
title : _.RGB(255, 255, 255),
artist : _.RGB(240, 240, 240),
    codec : _.RGB(180, 180, 180),
album : _.RGB(180, 180, 180),
time : _.RGB(240, 240, 240),
seekbar_background : _.RGB(160, 160, 160),
seekbar_progress : _.RGB(255, 255, 255),
seekbar_knob : _.RGB(0, 120, 215)
};

var tfo = {
artist : fb.TitleFormat('%artist%'),
title : fb.TitleFormat('%title%'),
    codec : fb.TitleFormat('%codec%'),
album : fb.TitleFormat('%album%'),
playback_time : fb.TitleFormat('%playback_time%  '),
length : fb.TitleFormat('  %length%')
};

//////////////////////////////////////////////////////////////

var panel = new _.panel();
var seekbar = new _.seekbar(0, 0, 0, 0);
var buttons = new _.buttons();
var img = null;
var bs = _.scale(30);
on_playback_new_track(fb.GetNowPlaying());

buttons.update = function () {
var y = Math.round((panel.h - bs) / 1.7);
this.buttons.stop = new _.button(panel.w - LM - (bs * 13.0), y, bs, bs, {normal : 'buttons\\stop_grey_min.png'}, function () { fb.Stop(); }, 'Stop');
this.buttons.previous = new _.button(panel.w - LM - (bs * 11.7), y, bs, bs, {normal : 'buttons\\back_grey_min.png'}, function () { fb.Prev(); }, 'Previous');
this.buttons.play = new _.button(panel.w - LM - (bs * 10.4), y, bs, bs, {normal : !fb.IsPlaying || fb.IsPaused ? 'buttons\\play_grey_min.png' : 'buttons\\pause_grey_min.png'}, function () { fb.PlayOrPause(); }, !fb.IsPlaying || fb.IsPaused ? 'Play' : 'Pause');
this.buttons.next = new _.button(panel.w - LM - (bs * 9.1), y, bs, bs, {normal : 'buttons\\next_grey_min.png'}, function () { fb.Next(); }, 'Next');
this.buttons.random = new _.button(panel.w - LM - (bs * 4.9), y, bs, bs, {normal : 'buttons\\shuffle_grey_min.png'}, function () { fb.Random(); }, 'Random');
this.buttons.console = new _.button(panel.w - LM - (bs * 3.6), y, bs, bs, {normal : 'buttons\\console_grey_min.png'}, function () { fb.ShowConsole(); }, 'Console');
this.buttons.search = new _.button(panel.w - LM - (bs * 2.3), y, bs, bs, {normal : 'buttons\\search_grey_min.png'}, function () { fb.RunMainMenuCommand('Library/Search'); }, 'Library Search');
this.buttons.preferences = new _.button(panel.w - LM - bs, y, bs, bs, {normal : 'buttons\\settings_grey_min.png'}, function () { fb.ShowPreferences(); }, 'Preferences');
   
}

function on_size() {
panel.size();
seekbar.x = Math.round(panel.w * 0.32);
seekbar.w = panel.w - seekbar.x - _.scale(500);
seekbar.h = _.scale(12);
seekbar.y = (panel.h - seekbar.h) / 2;
buttons.update();
}

function on_paint(gr) {
gr.FillSolidRect(0, 0, panel.w, panel.h, colours.background);
buttons.paint(gr);
gr.FillSolidRect(seekbar.x, seekbar.y, seekbar.w + _.scale(6), seekbar.h, colours.seekbar_background);
if (fb.IsPlaying) {
if (img) {
_.drawImage(gr, img, 0, 0, panel.h, panel.h, image.centre);
}
gr.GdiDrawText(tfo.title.Eval(), panel.fonts.title, colours.title, panel.h + 10, 0, seekbar.x - panel.h - _.scale(60), panel.h * 0.4, LEFT);
gr.GdiDrawText(tfo.artist.Eval(), panel.fonts.normal, colours.artist, panel.h + 10, panel.h * 0.3, seekbar.x - panel.h - _.scale(60), panel.h * 0.4, LEFT);
gr.GdiDrawText(tfo.album.Eval(), panel.fonts.normal, colours.album, panel.h + 10, panel.h * 0.3, seekbar.x - panel.h - _.scale(60), panel.h * 1.0, LEFT);
        gr.GdiDrawText(tfo.codec.Eval(), panel.fonts.normal, colours.codec, panel.h + 500, panel.h * 0.3, seekbar.x - panel.h - _.scale(60), panel.h * 0.4, LEFT);
gr.SetSmoothingMode(2);
if (fb.PlaybackLength > 0) {
var pos = seekbar.pos();
gr.FillSolidRect(seekbar.x, seekbar.y, pos, seekbar.h, colours.seekbar_progress);
gr.FillSolidRect(seekbar.x + pos, seekbar.y, _.scale(6), seekbar.h, colours.seekbar_knob);
gr.GdiDrawText(tfo.playback_time.Eval(), panel.fonts.normal, colours.time, seekbar.x - _.scale(45), 0, _.scale(45), panel.h, RIGHT);
gr.GdiDrawText(tfo.length.Eval(), panel.fonts.normal, colours.time, seekbar.x + seekbar.w + _.scale(6), 0, _.scale(45), panel.h, LEFT);
}
}
gr.DrawRect(seekbar.x, seekbar.y, seekbar.w + _.scale(6), seekbar.h, 1, colours.seekbar_progress);
}

function on_playback_new_track(metadb) {
if (!metadb) {
return;
}
_.dispose(img);
img = utils.GetAlbumArtV2(metadb, 0);
window.Repaint();
}

function on_playback_edited() {
window.Repaint();
}

function on_playback_seek() {
seekbar.playback_seek();
}

function on_playback_stop() {
buttons.update();
window.Repaint();
}

function on_playback_pause() {
buttons.update();
window.Repaint();
}

function on_playback_starting() {
buttons.update();
window.Repaint();
}

function on_mouse_wheel(s) {
if (seekbar.wheel(s)) {
return;
}
if (s == 1) {
fb.VolumeUp();
} else {
fb.VolumeDown();
}
}

function on_mouse_move(x, y) {
if (buttons.move(x, y)) {
return;
}
seekbar.move(x, y);
}

function on_mouse_leave() {
buttons.leave();
}

function on_mouse_lbtn_down(x, y) {
seekbar.lbtn_down(x, y);
}

function on_mouse_lbtn_up(x, y) {
if (buttons.lbtn_up(x, y)) {
return;
}
if (seekbar.lbtn_up(x, y)) {
return;
}
fb.RunMainMenuCommand('View/Show now playing in playlist');
}

function on_mouse_rbtn_up(x, y) {
return panel.rbtn_up(x, y);

}

Re: JScript Panel script discussion/help

Reply #730
Hi again,
So in the end, you didn't manage to find a way to remove this rectangle, or replace it with something which would make more sense ? Generating a gdi.Image for each drag and drop is completely fine, then it's up to the coder to do something which look nice/is useful in term of UI.
I kinda forgot about it =)
I will work on it a bit later, when I catch up with some IRL stuff...

(About the drag and drop inside a panel / outside a panel, i managed to install your catrox theme, and yes, your code do what i'm trying to achieve in term of behavior, so i'm convinced now : ) i need to clean up my drag and drop code to make it work like yours.)
Glad that it worked out ;)

You are doing god's work, my friend. Thank you so much.
You are welcome ;)

Another question, is there another option apart from fb.GetFocusItem() and fb.GetNowPlaying()?
I want to add tracks to queue with a single MMB click, fb.RunContextCommandWithMetadb("Add to playback queue",fb.GetFocusItem()) needs 2 clicks, first one to select the track with LMB and only then MMB to add to queue.
Not entirely sure what's the problem, you can do all of this in one call. Smth like this:
Code: [Select]
function on_mouse_mbtn_down(x,y,m) {
    var item_idx;   
    ...
    // Calculate item index
    ...
    plman.SetPlaylistFocusItem(plman.ActivePlaylist, item_idx);
    plman.AddPlaylistItemToPlaybackQueue(plman.ActivePlaylist, item_idx);
}

Re: JScript Panel script discussion/help

Reply #731
I'd like to add different images to the left of time elapsed on the seekbar depending on the codec of the track playing. So an image for MP3, a different one for FLAC etc etc, you get the picture. Along with that, another image that appears to the left of that only if the track is greater than 16-bit. I've found scripts that do similar, but i can't get my head around what is required from them to achieve this. I've even attempted merging them into my existing edits, but have had nothing but inevitable errors  ::) A lot of Googling and some headaches later, i've decided to admit defeat and ask those that know best!
I'm not going to do all the heavy lifting for you, but I'll show you what I've done to accomplish something similar. Some of this code was written years ago, and the style may not be great, so change it as needed.

First off I'm assuming you have the images you want to display already in a folder somewhere. Let's call it /images/codecs

At the top of your file where you setup your globals:
Code: [Select]
var mediaTypeImg = null;
var pref = {};

pref.codec_base = fb.ProfilePath + 'images/codecs';

Code: [Select]
// gets the correct image
function LoadMediaTypeImage() {
_.dispose(mediaTypeImg);
if (pref.show_codec_img) {
codec = fb.TitleFormat("[%codec%]").Eval();
switch (codec) {
case "DTS":
mediaTypeImg = gdi.Image(pref.codec_base+"DTS.png");
break;
case "ATSC A/52":
mediaTypeImg = gdi.Image(pref.codec_base+"Dolby Digital.png");
break;
case "FLAC":
mediaTypeImg = gdi.Image(pref.codec_base+"FLAC.png");
break;
case "Vorbis":
mediaTypeImg = gdi.Image(pref.codec_base+"Ogg.png");
break;
case "MP3":
mediaTypeImg = gdi.Image(pref.codec_base+"mp3.png");
break;
case "default":
console.log("Unknown codec: "+codec);
break;
}
}
return;
}

Then in your on_playback_new_track before window.Repaint(); call LoadMediaTypeImage(), and dispose the mediaTypeImg in on_playback_stop()

Now all you need to do is add the code to display the image in your on_paint callback which should be fairly trivial. Just do an:
Code: [Select]
// you'll need to figure out what the x, y, w, and h should be
if (mediaTypeImg) {
    gr.DrawImage(mediaTypeImg, x, y, w, h, 0, 0, mediaTypeImg.Width, mediaTypeImg.Height, 0);
}
If you want to check for 24-bit or whatever you can also do that in the LoadMediaTypeImg function and only set that image if bit-depth > 16.

Hope that helps.

Re: JScript Panel script discussion/help

Reply #732
Another question, is there another option apart from fb.GetFocusItem() and fb.GetNowPlaying()?
I want to add tracks to queue with a single MMB click, fb.RunContextCommandWithMetadb("Add to playback queue",fb.GetFocusItem()) needs 2 clicks, first one to select the track with LMB and only then MMB to add to queue.
Not entirely sure what's the problem, you can do all of this in one call. Smth like this:
Code: [Select]
function on_mouse_mbtn_down(x,y,m) {
    var item_idx;   
    ...
    // Calculate item index
    ...
    plman.SetPlaylistFocusItem(plman.ActivePlaylist, item_idx);
    plman.AddPlaylistItemToPlaybackQueue(plman.ActivePlaylist, item_idx);
}
Thanks for your reply! It adds track #1 of current playlist to the queue no matter which track I click on though.


Re: JScript Panel script discussion/help

Reply #734
I'd like to add different images to the left of time elapsed on the seekbar depending on the codec of the track playing. So an image for MP3, a different one for FLAC etc etc, you get the picture. Along with that, another image that appears to the left of that only if the track is greater than 16-bit. I've found scripts that do similar, but i can't get my head around what is required from them to achieve this. I've even attempted merging them into my existing edits, but have had nothing but inevitable errors  ::) A lot of Googling and some headaches later, i've decided to admit defeat and ask those that know best!
I'm not going to do all the heavy lifting for you, but I'll show you what I've done to accomplish something similar. Some of this code was written years ago, and the style may not be great, so change it as needed.

First off I'm assuming you have the images you want to display already in a folder somewhere. Let's call it /images/codecs

At the top of your file where you setup your globals:
Code: [Select]
var mediaTypeImg = null;
var pref = {};

pref.codec_base = fb.ProfilePath + 'images/codecs';

Code: [Select]
// gets the correct image
function LoadMediaTypeImage() {
_.dispose(mediaTypeImg);
if (pref.show_codec_img) {
codec = fb.TitleFormat("[%codec%]").Eval();
switch (codec) {
case "DTS":
mediaTypeImg = gdi.Image(pref.codec_base+"DTS.png");
break;
case "ATSC A/52":
mediaTypeImg = gdi.Image(pref.codec_base+"Dolby Digital.png");
break;
case "FLAC":
mediaTypeImg = gdi.Image(pref.codec_base+"FLAC.png");
break;
case "Vorbis":
mediaTypeImg = gdi.Image(pref.codec_base+"Ogg.png");
break;
case "MP3":
mediaTypeImg = gdi.Image(pref.codec_base+"mp3.png");
break;
case "default":
console.log("Unknown codec: "+codec);
break;
}
}
return;
}

Then in your on_playback_new_track before window.Repaint(); call LoadMediaTypeImage(), and dispose the mediaTypeImg in on_playback_stop()

Now all you need to do is add the code to display the image in your on_paint callback which should be fairly trivial. Just do an:
Code: [Select]
// you'll need to figure out what the x, y, w, and h should be
if (mediaTypeImg) {
    gr.DrawImage(mediaTypeImg, x, y, w, h, 0, 0, mediaTypeImg.Width, mediaTypeImg.Height, 0);
}
If you want to check for 24-bit or whatever you can also do that in the LoadMediaTypeImg function and only set that image if bit-depth > 16.

Hope that helps.

Thanks so much for taking the time to give some advice and reply Mordred, and yes I'd certainly rather do the bulk of it myself. How else will I learn!? I will have a proper go at getting it to work at the weekend once I have the time (can see it taking a while!)

I may ask some seemingly stupid questions though...I hope that's ok? (total novice remember).

So the variables can be added below the existing ones in my code? (i.e. before the buttons.update) The code layout is split into sections yes?

Then in your on_playback_new_track before window.Repaint(); call LoadMediaTypeImage(), and dispose the mediaTypeImg in on_playback_stop() I'm sure this probably is easy, but it has thrown me a bit!

Thanks, and again sorry for the probably ridiculously obvious questions. Its very difficult to find much online about how these work though.

Appreciate it Mordred


Jamie

Re: JScript Panel script discussion/help

Reply #735
Thanks so much for taking the time to give some advice and reply Mordred, and yes I'd certainly rather do the bulk of it myself. How else will I learn!? I will have a proper go at getting it to work at the weekend once I have the time (can see it taking a while!)

I may ask some seemingly stupid questions though...I hope that's ok? (total novice remember).

So the variables can be added below the existing ones in my code? (i.e. before the buttons.update) The code layout is split into sections yes?
There are other variables declared in you script, you can just add them there. I'm confused what you mean by code being split into sections. It's split into functions. I know you said you're new to all of this, so it might be worthwhile checking out a super basic javascript tutorial just so you understand a little bit more about how all this works.

Quote
Then in your on_playback_new_track before window.Repaint(); call LoadMediaTypeImage(), and dispose the mediaTypeImg in on_playback_stop() I'm sure this probably is easy, but it has thrown me a bit!
i.e. just do:
Code: [Select]
function on_playback_new_track(metadb) {
if (!metadb) {
return;
}
_.dispose(img);
img = utils.GetAlbumArtV2(metadb, 0);
LoadMediaTypeImage();
window.Repaint();
}
And just toss a _.dispose(mediaTypeImg);  into your on_playback_stop() function.

Re: JScript Panel script discussion/help

Reply #736
I've got a playlist in my theme (based on CatRox) and I had a crazy idea that I'm not sure is possible. What I'd like is to turn certain strings in the playlist into buttons (I know how to do this part), which when clicked on will populate a playlist. I.e. Where I list the Artist in the playlist if you clicked on the artist name, it would populate a playlist with all songs from that artist, and set it to active. It'd be like playlist hyperlinks.

Is it possible to create/populate a playlist based on strings from jscript? I confess I haven't really looked into this, just hoping someone can save me some time and trial/error here.

Re: JScript Panel script discussion/help

Reply #737
You could create an autoplaylist
  plman.CreateAutoPlaylist  , using the string in the query and then switch to that playlist.
You can find a sample in marc2003 samples,  autoplaylist.txt and the code in list.js


Re: JScript Panel script discussion/help

Reply #739
One thing though: autoplaylists are read-only, so you'll have to copy it, if you want to have ability to edit it afterwords.
I'm assuming you mean I can't edit it from jscript. Can I at least delete the auto-playlist? I'd hate to have dozens of these things clogging up my playlists dropdown.

Re: JScript Panel script discussion/help

Reply #740
I'm assuming you mean I can't edit it from jscript. Can I at least delete the auto-playlist? I'd hate to have dozens of these things clogging up my playlists dropdown.
Autoplaylists are not editable in fb2k in general, not just in JScript =)
You can modify playlist itself (move\delete\rename etc), but you can't modify it's contents.

Re: JScript Panel script discussion/help

Reply #741
fb.GetQueryItems(handle_list, query); (IFbMetadbHandleList) is another possibility

Gives handle list that can add to playlist etc, e.g.

var b = fb.GetQueryItems(fb.GetLibraryItems(), "artist IS Madonna");
Results are unsorted.
NOTE: Use try/catch to handle invalid queries. An empty handle list will be returned if the query is valid but there are no results.

Re: JScript Panel script discussion/help

Reply #742
Autoplaylists are not editable in fb2k in general, not just in JScript =)
You can modify playlist itself (move\delete\rename etc), but you can't modify it's contents.
Haha, I thought you were trying to say you couldn't modify the query. Yes I realize you can't delete the contents.

var b = fb.GetQueryItems(fb.GetLibraryItems(), "artist IS Madonna");
Results are unsorted.
NOTE: Use try/catch to handle invalid queries. An empty handle list will be returned if the query is valid but there are no results.
Yeah, I was going through interfaces.txt and literally just saw that.

But then with that it looks like I can do:
plman.FindOrCreatePlaylist <- get my special "selected object" playlist
plman.ClearPlaylist
plman.InsertPlaylistItems <- insert that handle_list into the playlist
plman.SortByFormatV2

Boom, done. Thanks guys! This will be a fun project tonight.

Re: JScript Panel script discussion/help

Reply #743
foo_jscript_panel\samples\complete\last.fm bio.txt
Some characters cannot be displayed properly.
e.g. "Lou Reed & Metallica" will show "Lou Reed _Metallica".

 

 
SimplePortal 1.0.0 RC1 © 2008-2018