First a big thank you T.P Wang for releasing and developing this component. I ignored it for too long. Now that foo_uie_trackinfo_mod became problematic, I finally took the challenge and tried to master the mysteries of callbacks and repaint functions. It was to my best; I managed not only to mimic all functionality of my old trackinfo_mod trackinfo display, there is still much to come.
Here is my current "test" now playing WSH panel:
Maybe the code is for use to someone:
// -----------------------------------------------------------------------
// WSH-test-nowplaying
// a WSH panel script by ojdo
// last modified: 2009-12-04
// -----------------------------------------------------------------------
// HELPER FUNCTIONS
function StringFormat() {
var h_align = 0, v_align = 0, trimming = 0, flags = 0;
switch (arguments.length)
{
// fall-through
case 4: flags = arguments[3];
case 3: trimming = arguments[2];
case 2: v_align = arguments[1];
case 1: h_align = arguments[0]; break;
default: return 0;
}
return ((h_align << 28) | (v_align << 24) | (trimming << 20) | flags);
}
function RGB(r, g, b) { return (0xff000000 | (r << 16) | (g << 8) | (b)); }
function RGBA(r, g, b, a) { return ((a << 24) | (r << 16) | (g << 8) | (b)); }
// INITIALIZATION
var g_albumart = null, g_albumart_rot = null;
var g_artistart = null, g_artistart_rot = null;
var g_font_title = gdi.Font("Calibri", 40, 0);
var g_font_artist = gdi.Font("Calibri", 26, 0);
var g_fontsmall = gdi.Font("Calibri", 14, 0);
var g_stringformat = StringFormat(1, 0);
var ww = 0, wh = 0; // Window width, height
var g_handle = null; // metadb handle variable for watching the currently played track
AlbumArtId = { front: 0, back: 1, disc: 2, icon: 3, artist: 4 };
// evoke callback function to initially paint the window
on_playback_new_track(fb.GetNowPlaying());
// -----------------------------------------------------------------------
// DRAW CANVAS CONTENT
function on_paint(gr) {
gr.SetTextRenderingHint(5); // enable cleartype font rendering
// Background
gr.FillSolidRect(0, 0, ww, wh, RGB(0,0,0));
gr.FillGradRect(0, 3*wh/4, ww, 20, 90,RGBA(128,128,128,64), RGBA(128,128,128,0));
// Reflected albumart
if(g_albumart) {
var scale_w = 0.9*ww / g_albumart.Width;
var scale_h = 0.9*(0.75*wh+20) / g_albumart.Height;
var scale = Math.min(scale_w, scale_h);
var pos_x = (ww - g_albumart.Width * scale) / 2;
var pos_y = 0.75*wh+20- g_albumart.height * scale;
var img_w = g_albumart.Width * scale;
var img_h = g_albumart.Height * scale;
gr.DrawImage(g_albumart_rot, pos_x, pos_y+img_h, img_w, img_h, 0, 0, g_albumart.Width, g_albumart.Height);
gr.DrawRect(pos_x+1,pos_y+img_h+1,img_w-2, wh-pos_y-img_h-2, 1.0,RGBA(128,128,128,64));
gr.FillGradRect(pos_x,pos_y+img_h,img_w,wh/5, 90, RGBA(0,0,0,128), RGB(0,0,0,255));
gr.FillSolidRect(pos_x,pos_y+img_h+wh/5,img_w,4*wh/5, RGBA(0,0,0,255));
}
// Rating and Mood
gr.FillGradRect(0, wh-40, rating*30, 10, 90, RGB(255,128,0), RGB(255,128,0));
gr.FillGradRect(ww-mood*30, wh-40, mood*30, 10, 90, RGB(0, 255, 0), RGB(0, 255, 0));
gr.DrawString(rating, g_fontsmall, RGB(255,255,255), rating*30+5, wh-45, 20, 20, StringFormat(0,0));
gr.DrawString(mood, g_fontsmall, RGB(255,255,255), ww-mood*30-25, wh-45, 20, 20, StringFormat(2,0));
// Artist & Title
gr.DrawString(title, g_font_title, RGB(255, 255, 255), 0, 0.83*wh, ww, 50, g_stringformat);
gr.DrawString(artist, g_font_artist, RGB(255, 255, 255), 0, 0.83*wh+40, ww, 30, g_stringformat);
// Progressbar
switch(fb.PlaybackOrder) { // change color of progressbar according to playback order
case 0: pbcolor = RGB(0,128,255); break; // Default
case 1: // RepeatPlaylist
case 2: pbcolor = RGB(255,255,0); break; // RepeatTrack
case 3: pbcolor = RGB(64,64,255); break; // Random
case 4: pbcolor = RGB(128,64,192); break; // ShuffleTracks
case 5: // ShuffleAlbums
case 6: pbcolor = RGB(64,64,255); break; // ShuffleFolders
default: pbcolor = RGB(255,0,0); break; // should not happen
}
if (fb.PlaybackLength>0) {
gr.FillSolidRect(0,wh-20, fb.PlaybackTime/fb.PlaybackLength*ww, 10, pbcolor);
}
gr.DrawString(fb.TitleFormat("%playback_time%").Eval(), g_fontsmall, RGB(255,255,255), fb.PlaybackTime/fb.PlaybackLength*ww+5, wh-25, 80, 20, StringFormat(0,0));
// Albumart
if (g_albumart) {
gr.DrawImage(g_albumart, pos_x, pos_y, img_w, img_h, 0, 0, g_albumart.Width, g_albumart.Height);
gr.DrawRect(pos_x+1,pos_y+1,img_w-2, img_h-2, 1.0,RGBA(128,128,128,32));
}
}
// -----------------------------------------------------------------------
// CALLBACKS
// -----------------------------------------------------------------------
// window size changed
function on_size() {
ww = window.Width;
wh = window.Height;
}
// new track
function on_playback_new_track(metadb) {
if (metadb) {
utils.GetAlbumArtAsync(window.ID, metadb, AlbumArtId.front);
utils.GetAlbumArtAsync(window.ID, metadb, AlbumArtId.artist);
}
g_albumart = null;
g_albumart_rot = null;
g_artistart = null;
g_artistart_rot = null;
if (g_handle) {window.UnwatchMetadb();}
g_handle = fb.GetNowPlaying();
if (g_handle) {
on_metadb_changed(); // calls on_metadb_changed()
window.WatchMetadb(g_handle);
}
}
// tag content changed
function on_metadb_changed() {
rating = fb.TitleFormat("%rating%").Eval(); if(rating == "?") rating=-1;
mood = fb.TitleFormat("%mood%").Eval(); if(mood == "?") mood=-1;
title = fb.TitleFormat("%title%").Eval();
artist = fb.TitleFormat("%artist%").Eval();
albumartist = fb.TitleFormat("%album artist%").Eval();
trackartist = fb.TitleFormat("%track artist").Eval();
album = fb.TitleFormat("%album%").Eval();
date = fb.TitleFormat("%date%").Eval();
window.RepaintRect(0,wh-40,ww,10); // calls on_paint()
}
// time (each second) and on seeking
function on_playback_time(time) { window.RepaintRect(0,wh-25,ww,20); }
function on_playback_seek(time) { window.RepaintRect(0,wh-25, ww, 20); }
// playback order changed
function on_playback_order_changed(new_order_index) { window.RepaintRect(0,wh-25, ww, 20); }
// album art retrieved
function on_get_album_art_done(metadb, art_id, image) {
switch(art_id) {
case AlbumArtId.front:
g_albumart = image;
g_albumart_rot = g_albumart.Clone(0, 0, g_albumart.Width, g_albumart.Height);
g_albumart_rot.RotateFlip(6);
window.Repaint(); // calls on_paint()
break;
case AlbumArtId.artist:
g_artistart = image;
g_artistart_rot = g_artistart.Clone(0, 0, g_artistart.Width, g_artistart.Height);
g_artistart_rot.RotateFlip(6);
window.Repaint(); // calls on_paint()
break;
}
}
// EOF
Next I plan to finally write a full replacement for my former fullscreen HTPC trackinfo displays.