// // WSHtpc04 // // Description a fullscreen now-playing script for foo_uie_wsh_panel // Author ojdo // Version 0.2.0 // Last change 2011-11-26 // -------------------------------------------------------------------------------------- // CONFIGURATION ////////////////////////////////////// // faux "associative arrays" for settings var tf = new Object(); // titleformating strings var ft = new Object(); // fonts var col = new Object(); // colours var geo = new Object(); // sizes var pref = new Object(); // preferences // TEXTS tf["title"] = "%title%"; tf["album"] = "[%album%]"; tf["artist"] = "[%artist%]"; tf["grid"] = Array( // simply add, change or remove entries to change grid layout Array("Genre:", "[%genre%]"), Array(":", "[%%]"), Array("Year:", "[%date%]"), Array(":", "[%%]"), Array("Track:", "$if(%tracknumber%,$num(%tracknumber%,1)$if(%totaltracks%,/$replace($num(%totaltracks%,1),0,₀,1,₁,2,₂,3,₃,4,₄,5,₅,6,₆,7,₇,8,₈,9,₉)))$ifgreater(%totaldiscs%,1, CD %discnumber%/$replace($num(%totaldiscs%,1),0,₀,1,₁,2,₂,3,₃,4,₄,5,₅,6,₆,7,₇,8,₈,9,₉),)"), Array("Rating", "$repeat(IIIII ,%rating%)"), Array("Mood", "$repeat(IIIII ,%mood%)") ); // TIMING pref["t_start"] = 10000; // seconds to display tag grid after track change pref["t_tag"] = 5; // seconds to display tag grid on tag change // GLOB PICTURES pref["aa_glob"] = false; // true: use glob, false: use albumart reader (front only) pref["aa_glob_shuffle"] = false; // true: random order, false: ordered like found by glob_paths pref["t_aa_glob"] = 10000; // seconds per image tf["glob_paths"] = Array( // simply add, change or re-order entries "$replace(%path%,%filename_ext%,)folder*", "$replace(%path%,%filename_ext%,)*.jpg", "$replace(%path%,%filename_ext%,)*.png", "$replace(%path%,%directoryname%\\%filename_ext%,)folder.jpg" ); // FONTS ft["title"] = gdi.Font("Calibri",36,0); ft["album"] = gdi.Font("Calibri",24,0); ft["artist"] = gdi.Font("Calibri",18,0); ft["grd_key"] = gdi.Font("Calibri",16,0); ft["grd_val"] = gdi.Font("Calibri",16,0); ft["lower_bar"] = gdi.Font("Calibri",18,0); // COLOURS col["title"] = RGB(255,255,255); col["album"] = RGB(255,255,255); col["artist"] = RGB(255,255,255); col["grd_key"] = RGB(090,090,090); col["grd_val"] = RGB(192,192,192); col["btm_key"] = RGB(090,090,090); col["btm_val"] = RGB(192,192,192); col["bg"] = RGB(000,000,000); col["rating"] = RGB(255,128,000); col["mood"] = RGB(000,128,255); col["prgrss_fill"] = RGB(255,215,0); col["prgrss_line"] = RGBA(255,255,255,050); // ALBUM ART DISPLAY PROPERTIES col["aa_border"] = RGBA(060,060,060,128); col["aa_shadow"] = RGBA(000,000,000,255); geo["aa_shadow"] = 22; // size of albumart shadow // BACKGROUND IMAGE pref["bg_image"] = fb.ProfilePath+"images/WSHtpc04/bg.jpg"; // END OF CONFIGURATION ///////////////////////////////// // INIT // ALBUM ART var albumart = null; // albumart image var albumart_size = new Array(0,0,0,0); // position (big image) var aa_size = new Array(0,0,0,0); // position (small image) var image_bg = gdi.Image(pref["bg_image"]); // background image var textrender = gdi.CreateStyleTextRender(); // anti-aliased text var str = new Object(); var img = new Object(); var pbtext = new Array("Default", "Repeat (Playlist)", "Repeat (Track)", "Random", "Shuffle (tracks)", "Shuffle (albums)", "Shuffle (folders)"); var metadb_handle = null; // watch db for tag changes var timer; // 40ms repaint of progress bar // TIMER & STATUS var ww = 0, wh = 0; // size of panel var start_timer = 0; // timer for panel layout after track change var glob_timer = 0; // timer for glob albumart cycle var tag_timer = 0; // timer for panel layout after tag change var pb_timer = 0; // timer for playback_order text var last_pb; // saves last playback order var g_drag = 0; // status variable for clickable progress bar var aa_list = new Array(); var aa_k = 0; // Function: Remove duplicates from array Array.prototype.myUnique = function(){ var r = new Array(); o:for(var i = 0; i < this.length; i++) { for(var x = 0; x < r.length; x++) { if(r[x]==this[i]) { continue o; } } r[r.length] = this[i]; } return r; }; // Call initialization function on_init(); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function on_paint(gr) { gr.SetTextRenderingHint(5); gr.SetSmoothingMode(4); //gr.SetInterpolationMode(7); // Background gr.FillSolidRect(-1,-1,ww+2,wh+2,col["bg"]); gr.DrawImage(image_bg, 0,0,ww,wh-geo["lower_bar_h"]-1, 0,0,image_bg.Width,image_bg.Height-geo["lower_bar_h"]-1); if (ww > 600 && ((tag_timer < pref["t_tag"]*25) || (start_timer < pref["t_start"]*25))) { // TAG GRID & ALBUMART // Small albumart on the right if (albumart) { shadow_image && gr.DrawImage(shadow_image, aa_size[0]-geo["aa_shadow"],aa_size[1]-geo["aa_shadow"],aa_size[2]+2*geo["aa_shadow"],aa_size[3]+2*geo["aa_shadow"],0,0,shadow_image.Width,shadow_image.Height); gr.DrawImage(albumart, aa_size[0], aa_size[1], aa_size[2], aa_size[3], 0, 0, albumart.Width, albumart.Height); gr.DrawRect(aa_size[0]-1,aa_size[1]-1,aa_size[2]+1,aa_size[3]+1,1,col["aa_border"]); if (fb.IsPaused) { gr.FillSolidRect(aa_size[0],aa_size[1],aa_size[2],aa_size[3],RGBA(0,0,0,150)); } } // Artist album & title textrender.EnableShadow(true); textrender.ResetShadow(); textrender.GlowText(col["title"], col["bg"], 6); if(str["title"]) { textrender.RenderStringRect(gr, str["title"], ft["title"], 0.025*ww, 0.175*wh, 0.5*ww, 36, StringFormat(0,0,4)); } textrender.GlowText(col["album"], col["bg"], 6); if(str["album"]) { textrender.RenderStringRect(gr, str["album"], ft["album"], 0.025*ww, 0.175*wh+50, 0.5*ww, 24, StringFormat(0,0,4)); } textrender.GlowText(col["artist"], col["bg"], 6); if(str["artist"]) { textrender.RenderStringRect(gr, str["artist"], ft["artist"], 0.025*ww, 0.175*wh+87, 0.5*ww, 18, StringFormat(0,0,4)); } // Tag grid for (k=0; k 780) { cell_width = (ww <= 1080) ? 0.5*ww-80 : 0.25*ww-80; textrender.GlowText(col["grd_key"], col["bg"], 3); textrender.RenderStringRect(gr, key, ft["grd_key"], 0.025*ww + (k%2)*0.25*ww, 0.45*wh+Math.floor(k/2)*30+3, cell_width, 20, StringFormat(0,0,4)); switch (key) { case "Rating": textrender.GlowText(col["rating"], col["bg"], 3); break; case "Mood": textrender.GlowText(col["mood"], col["bg"], 3); break; default: textrender.GlowText(col["grd_val"], col["bg"], 3); } textrender.RenderStringRect(gr, value, ft["grd_val"], 0.025*ww+80 + (k%2)*0.25*ww, 0.45*wh+Math.floor(k/2)*30, cell_width, 20, StringFormat(0,0,4)); } } } } else { // BIG ALBUMART if (albumart) { shadow_image && gr.DrawImage(shadow_image, albumart_size[0]-geo["aa_shadow"],albumart_size[1]-geo["aa_shadow"],albumart_size[2]+2*geo["aa_shadow"],albumart_size[3]+2*geo["aa_shadow"],0,0,shadow_image.Width,shadow_image.Height); gr.DrawImage(albumart, albumart_size[0], albumart_size[1], albumart_size[2], albumart_size[3], 0, 0, albumart.Width, albumart.Height); gr.DrawRect(albumart_size[0]-1,albumart_size[1]-1,albumart_size[2]+1,albumart_size[3]+1,1,col["aa_border"]); if (fb.IsPaused) { gr.FillSolidRect(albumart_size[0],albumart_size[1],albumart_size[2],albumart_size[3],RGBA(0,0,0,150)); } } } // LOWER BAR // Title & artist // Playback order if(pb_timer < 5*25 && ww > 600) { gr.DrawString(pbtext[fb.PlaybackOrder]+" "+str["time"]+" "+str["length"],ft["lower_bar"],col["btm_key"],0.575*ww,wh-geo["lower_bar_h"],0.4*ww,0.5*geo["lower_bar_h"],StringFormat(2,0)); } // Progress bar gr.DrawRect( 0.025*ww,wh-0.5*geo["lower_bar_h"],0.95*ww,4,1,col["prgrss_line"]); if(fb.PlaybackLength > 0) { if (ww > 600) { gr.DrawString(str["time"]+" "+str["length"],ft["lower_bar"],col["btm_key"],0.725*ww,wh-geo["lower_bar_h"],0.25*ww,0.5*geo["lower_bar_h"],StringFormat(2,0)); gr.DrawString( str["length"],ft["lower_bar"],col["btm_val"],0.725*ww,wh-geo["lower_bar_h"],0.25*ww,0.5*geo["lower_bar_h"],StringFormat(2,0)); } gr.FillSolidRect(0.025*ww,wh-0.5*geo["lower_bar_h"],0.95*ww*(fb.PlaybackTime / fb.PlaybackLength),4,col["prgrss_fill"]); } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ----------------------------------------------------------------------- // CALLBACKS // ----------------------------------------------------------------------- // custom initialisation function, called once after variable declarations function on_init() { on_size(); geo["lower_bar_h"] = 60; str["title"] = ""; str["album"] = ""; str["artist"] = ""; str["grid"] = new Array(); last_pb = fb.PlaybackOrder; var bg_scale = Math.max(1,(wh-geo["lower_bar_h"]-1) / image_bg.Height); image_bg = image_bg.Resize(image_bg.Width*bg_scale,image_bg.Height*bg_scale); on_playback_new_track(fb.GetNowPlaying()); } // window size changed function on_size() { ww = window.Width; wh = window.Height; if(albumart) { // Size for big albumart var album_scale = Math.min(0.95*ww / albumart.Width, 0.9*(wh-geo["lower_bar_h"]) / albumart.Height); albumart_size[2] = albumart.Width * album_scale; albumart_size[3] = albumart.Height * album_scale; albumart_size[0] = 0.5*ww-0.5*albumart_size[2]; albumart_size[1] = 0.5*(wh-geo["lower_bar_h"])-0.5*albumart_size[3]; // Size for small var aa_scale = Math.min(0.45*ww / albumart.Width, 0.7*(wh-geo["lower_bar_h"]) / albumart.Height); aa_size[2] = albumart.Width * aa_scale; aa_size[3] = albumart.Height * aa_scale; aa_size[0] = 0.75*ww-0.5*aa_size[2]; aa_size[1] = 0.5*wh-0.5*aa_size[3]; } else { albumart_size = Array(0,0,0,0); } } // new track function on_playback_new_track(metadb) { start_timer = 0; pb_timer = 0; glob_timer = 0; timer = window.CreateTimerInterval(40); // Fetch new albumart aa_list = []; for(k = 0;k 0) { aa_list = eliminateDuplicates(aa_list); // remove duplicates pref["aa_glob_shuffle"] && fisherYates(aa_list); // shuffle list aa_k = 0; glob_image(aa_k); // display first image } } // enable "watch for tag changes" on new track if (metadb_handle) {window.UnwatchMetadb();} metadb_handle = fb.GetNowPlaying(); if (metadb_handle) { on_metadb_changed(); // refresh panel window.WatchMetadb(metadb_handle); } on_playback_time(); } // tag content changed function on_metadb_changed() { title = fb.TitleFormat(tf["title"]).Eval(); album = fb.TitleFormat(tf["album"]).Eval(); artist = fb.TitleFormat(tf["artist"]).Eval(); str["title"] = title; str["album"] = album; str["artist"] = artist; h = Math.floor(fb.PlaybackLength/3600); m = Math.floor(fb.PlaybackLength%3600/60); s = Math.floor(fb.PlaybackLength%60); str["length"] = (h > 0 ? h+":"+(m < 10 ? "0":"")+m : m) + ":" + (s < 10 ? "0":"") + s; for (k=0; k wh-geo["lower_bar_h"]) { g_drag = 1; } } function on_mouse_lbtn_up(x, y) { on_mouse_move(x, y); g_drag = 0; // Play or pause on album cover if (ww > 600 && ((tag_timer < pref["t_tag"]*25) || (start_timer < pref["t_start"]*25))) { // small album art if ( aa_size[0] <= x && aa_size[1] <= y && aa_size[0]+aa_size[2] >= x && aa_size[1]+aa_size[3] >= y) { fb.PlayOrPause(); } } else { // big album art if ( albumart_size[0] <= x && albumart_size[1] <= y && albumart_size[0]+aa_size[2] >= x && albumart_size[1]+aa_size[3] >= y) { fb.PlayOrPause(); } } if (x < 0.01*ww) { fb.Prev(); } if (x > 0.99*ww) { fb.Next(); } } function on_mouse_lbtn_dblclk() { tag_timer = -1; on_timer(); } function on_mouse_move(x, y) { if (g_drag) { var v = (x-0.025*ww) / (0.95*ww); v = (v < 0) ? 0 : (v < 1) ? v : 1; if (fb.PlaybackTime != v*fb.PlaybackLength) fb.PlaybackTime = v*fb.PlaybackLength; } } // Timed events function on_playback_time(){ // Repaint seekbar and playback times this_time = fb.PlaybackTime; pb_length = fb.PlaybackLength; h = Math.floor(this_time/3600); m = Math.floor(this_time%3600/60); s = Math.floor(this_time%60); str["time"] = (h > 0 ? h+":"+(m < 10 ? "0":"")+m : m) + ":" + (s < 10 ? "0":"")+ s; } function on_timer(id){ start_timer = start_timer + 1; tag_timer = tag_timer + 1; pb_timer = pb_timer + 1; glob_timer = glob_timer + 1; if (glob_timer == pref["t_aa_glob"]*25) { aa_k = (aa_k + 1) % aa_list.length; glob_image(aa_k); glob_timer = 0; } if ((tag_timer == pref["t_tag"]*25) || (tag_timer <= 0) || (start_timer == pref["t_start"]*25) || (glob_timer == 0)) { window.Repaint(); } else { window.RepaintRect(0,wh-geo["lower_bar_h"],ww,geo["lower_bar_h"]); } } function on_playback_pause() { // Draws grey shadow on album art window.RepaintRect(albumart_size[0],albumart_size[1],albumart_size[2],albumart_size[3]); window.RepaintRect(aa_size[0],aa_size[1],aa_size[2],aa_size[3]); } function on_playback_stop(reason) { if(reason != 2) { // starting_another // clear all variables and repaint albumart = null; artistart = null; str["grid"] = Array(); window.Repaint(); } timer && window.KillTimer(timer); } // album art retrieved function on_get_album_art_done(metadb, art_id, image) { // only use album art reader if globbing is disabled if (!pref["aa_glob"]) { switch(art_id) { case 0: // front if(image) { albumart = image; } else { albumart = null; } break; } on_size(); // recalculate image positions createDropShadow(); // recreate shadow image window.Repaint(); // calls on_paint() } } // 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)); } function drawStar(gr, x, y) { // gr = Drawing Object handle // x,y = position of center // color = array of colors for filling and border // size = radius // n = number of peaks // phi = rotation var size=16, n=5, phi=Math.PI/2, color=Array(RGB(210,170,0),RGB(255,255,0)), innerSize=.5; switch(arguments.length) { // fall-through case 8: innerSize = arguments[7]; case 7: phi = arguments[6]; case 6: n = arguments[5]; case 5: size = arguments[4]; case 4: color = arguments[3]; } var points = new Array(4*n); for(var k=0;k