Advertisement
Guest User

Lyrics Reader - For Xch4nge

a guest
Aug 17th, 2013
1,658
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==PREPROCESSOR==
  2. // @name "Lyrics Reader"
  3. // @version "2.1"
  4. // @author "Br3tt(Changed by Mire777)"
  5. // @feature "dragdrop"
  6. // @import "%fb2k_profile_path%skins\xc4\scripts\Common.js"
  7. // @import "%fb2k_profile_path%skins\xc4\scripts\Codepages.js"
  8. // ==/PREPROCESSOR==
  9.  
  10.  
  11. // Paths
  12. var lyrics_dir1 = fb.Titleformat("$replace($replace(%path%,%filename_ext%,),\,\\)");
  13. var fbfolder = (fb.ProfilePath + "lyrics");
  14. var Lyrics_path = window.GetProperty("Lyrics folder", fbfolder);
  15. var lyrics_dir2 =(Lyrics_path + "\\");
  16.  
  17.  
  18.  
  19.  
  20. /*
  21. ===========================================================================================================
  22. Lyrics 2.0 (build 20110507.1850) - a WSH lyrics module by Br3tt
  23. - This WSH script get lyrics from TAG first then from local file in Music folder then in foobar2000\lyrics\ and it displays them (scrolling+sync)
  24. - It handles TXT and LRC format (sync handled), but not the LRC Enhanced format (translated to simple LRC format)
  25. - exotics timestamps are now handled (like [9:99], [99:99.999], [9:99.999], [99:99:999] ...)
  26. - filenames supported are : <%artist%> -<%title%>.lrc (or .txt)  AND <%artist%> - <%title%>.lrc (or .txt)
  27. - Comments, Blank lines (no timestamp) and Info lines (ar:, ti, ...) are ignored.
  28. - Manual Scrolling possible with the mousewheel (double click on the panel to re-center on the active line)
  29. - Requirements :
  30.   1) foobar2000
  31.   2) WSH Panel Mod component 1.4.2+
  32.   3) this javascript in a WSH panel mod instance
  33.   4) Optional: a lyrics grabber component (i.e: Lyrics Show Panel by hidding the panel, foo_lyricsDB, ...)
  34. - Some settings are available by using the panel Properties (right click on WSH panel -> Properties)
  35. - This script don't make any changes to your files and write nothing on your system, except the creation of the folder foobar2000/lyrics if not found
  36. ===========================================================================================================
  37. */
  38.  
  39. // ================================================== CUI Colours
  40.  
  41. var g_instancetype = window.InstanceType;
  42. var c01, c02, c03, c04, c05, c06;
  43. var TXT_GLOW_COLOUR;
  44. var BG_FOCUS_COLOUR;
  45. var TXT_NORMAL_COLOUR;
  46. var TXT_FOCUS_COLOUR;
  47. function get_colors() {
  48.     if (g_instancetype == 0) { // CUI
  49.         c01 = window.GetColorCUI(ColorTypeCUI.background);
  50.         c02 = window.GetColorCUI(ColorTypeCUI.selection_background);
  51.         c03 = window.GetColorCUI(ColorTypeCUI.text);
  52.         c04 = window.GetColorCUI(ColorTypeCUI.selection_text);
  53.         c05 = window.GetColorCUI(ColorTypeCUI.inactive_selection_text);
  54.         c06 = window.GetColorCUI(ColorTypeCUI.inactive_selection_background);
  55.         TXT_GLOW_COLOUR = c01;
  56.         BG_FOCUS_COLOUR = c01;
  57.         TXT_NORMAL_COLOUR = c03;
  58.         TXT_FOCUS_COLOUR = c05;
  59.     }
  60. }
  61. get_colors();
  62. function on_colors_changed() {
  63.     get_colors();
  64.     on_init();
  65. }
  66. // ================================================== CUI Colours
  67.  
  68. var cpt=0;
  69.  
  70. // ================================================/ Properties
  71. var FONT_NAME = window.GetProperty("Font name", "segoe ui");
  72. var FONT_SIZE = window.GetProperty("Font size", 12);
  73. var FONT_STYLE = window.GetProperty("Font style", 3);
  74. var LINE_HEIGHT = window.GetProperty("Default Line height", 24);
  75. var SCROLL_STEP = window.GetProperty("Scrolling speed [01:10]", 8);
  76. var TEXT_SHADOW = window.GetProperty("Show Text shadow", true);
  77. var TEXT_GLOW = window.GetProperty("Glow Text enabled", false);
  78. //var BG_DRAW = window.GetProperty("Background enabled", false);
  79. var BG_DRAW = false;
  80. //var BG_DEFAULT_COLOUR = window.GetProperty("Background colour", "RGB(0, 0, 0);");
  81. var BG_DEFAULT_COLOUR = RGB(0, 0, 0);
  82. //var DITHER = window.GetProperty("Show Borders Shadow", true);
  83. var DITHER = true;
  84. var H_PADDING = window.GetProperty("Horizontal padding", 15);
  85. var TXT_ALIGN = window.GetProperty("Text alignment (left/center/right)", "center");
  86. var IMG_TYPE = window.GetProperty("Image Type [0:1]", 0);
  87. var ALBUM_IMG_ASPECT = window.GetProperty("Album Image Aspect [0:2]", 2);
  88. var ARTIST_IMG_ASPECT = window.GetProperty("Artist Image Aspect [0:2]", 1);
  89. //var GET_ENCODING = window.GetProperty("Get Encoding enabled", true);
  90. var GET_ENCODING = true;
  91. var DEBUG = false;
  92. var DEFAULT_OFFSET = 29;
  93.  
  94. //=================================================// Read Options
  95.  
  96. var opt_show_lyrics = true;
  97. var REFLECT_HEIGHT = 0;
  98.  
  99. //=================================================// Images
  100.  
  101. var icon_artist_img;
  102. var icon_album_img;
  103.  
  104. // ================================================/ Constants
  105.  
  106. var PLAYTIMER_VALUE = 10;  // do not modify this value
  107.  
  108.  
  109.  
  110. //{{
  111. // new objects
  112. sentence = function () {
  113.     this.timer = 0;
  114.     this.text = "";
  115.     this.total_lines = 0;
  116.     this.ante_lines = 0;
  117. }
  118. //}}
  119.  
  120. function get_Cx(delay) {
  121.     var k = g_panelopt_left + Math.floor(g_panelopt_scale_w/2);
  122.     var i = delay/20;
  123.     var x = k + i;
  124.     return x;
  125. }
  126.    
  127. function get_delay(x) {
  128.     var k = g_panelopt_left + Math.floor(g_panelopt_scale_w/2);
  129.     var delay = x<k ? (k-x)*-1 : x-k;
  130.     return delay*20;
  131. }
  132.  
  133. // ================================================/ TF
  134. var len = fb.Titleformat("%length%");
  135. var elap = fb.TitleFormat("%playback_time%");
  136. var remain = fb.TitleFormat("%playback_time_remaining%");
  137. var len_seconds = fb.Titleformat("%length_seconds%");
  138. var elap_seconds = fb.TitleFormat("%playback_time_seconds%");
  139. var remain_seconds = fb.Titleformat("%playback_time_remaining_seconds%");
  140. var artist = fb.Titleformat("$if2(%artist%,$if2(%band%,'N/A'))");
  141. var title = fb.Titleformat("%title%");
  142. var artist2 = fb.Titleformat("$replace($if2(%artist%,$if2(%band%,'N/A')),:,_,;,_)");
  143. var title2 = fb.Titleformat("$replace(%title%,:,_,;,_)");
  144. var lyrics = fb.TitleFormat("$replace([$if2(%LYRICS%,$if2(%LYRIC%,$if2(%UNSYNCED LYRICS%,%UNSYNCED LYRIC%)))],&nbsp;,,&nbsp,)");
  145. var tf_path = fb.TitleFormat("$left(%_path_raw%,4)");
  146.  
  147. // ================================================/ Globals
  148. var mybutton = Array(new button, new button, new button, new button, new button);
  149.  
  150. var mouse_x = -1;
  151. var mouse_y = -1;
  152.  
  153. var g_font = gdi.Font(FONT_NAME, FONT_SIZE, FONT_STYLE);
  154. var g_font_small = gdi.Font("segoe ui", 9, 0);
  155. var g_panelopt_font = gdi.Font("segoe ui", 10, 0);
  156. var g_playtimer;
  157. var g_panelopt_delay=0;
  158. var Cx;
  159. var Cdrag=false;
  160. var Cdrag_x;
  161. var g_panelopt_timer;
  162. var g_panelopt_waiter;
  163. var g_panelopt_sens;
  164. var g_panelopt_h = 42;
  165. var g_panelopt_y = -42;
  166. var g_panelopt_left = 48;
  167. var g_panelopt_right = 44;
  168. var g_panelopt_scale_w;
  169. var g_timer_abs;
  170. var g_metadb;
  171. var ww = 0, wh = 0;
  172.  
  173. var g_fso = new ActiveXObject("Scripting.FileSystemObject");
  174. var g_file = null;
  175. var g_tab = Array();
  176. var g_codepage;
  177. var g_scroll=0;
  178. var g_lyrics_path;
  179. var g_lyrics_filename;
  180. var g_lyrics_status;
  181. var focus=0;
  182. var focus_next=0;
  183. var g_bg_colour;
  184. var g_ovbg_highlightcolour;
  185. var g_txt_normalcolour;
  186. var g_txt_highlightcolour;
  187. var g_txt_shadowcolour;
  188. var g_txt_glowcolour;
  189. var g_dither_shadowcolour;
  190. var centiemes = 0;
  191. var g_is_scrolling = false;
  192. var g_multi_balise = false;
  193. var g_balise_total;
  194. var g_balise_char_offset = 10;
  195. var g_tab_length;
  196. var g_txt_align;
  197. var midpoint;
  198. var pos;
  199. var g_track_type;
  200. var g_path;
  201.  
  202. // front cover
  203. var is_art;
  204. var is_embedded;
  205. var is_stream;
  206. var frontcover;
  207. var cover_inner_padding = 0;
  208. var img_info = {orient: 0, cut: 0, cut_offset: 0, ratio: 0, x: 0, y: 0, w: 0, h: 0};
  209.  
  210. // START
  211. function on_init() {
  212.     ww = window.Width;
  213.     wh = window.Height;
  214.    
  215.     refresh_images();
  216.    
  217.     g_panelopt_scale_w = ww - g_panelopt_left - g_panelopt_right;
  218.    
  219.     on_item_focus_change();
  220.    
  221.     midpoint = (wh-REFLECT_HEIGHT) / 2 - LINE_HEIGHT / 2;
  222.     // colour definitions
  223.     g_bg_colour = eval(BG_DEFAULT_COLOUR);
  224.     g_ovbg_highlightcolour = eval(BG_FOCUS_COLOUR);
  225.     g_txt_normalcolour = eval(TXT_NORMAL_COLOUR);
  226.     g_txt_highlightcolour = eval(TXT_FOCUS_COLOUR);
  227.     g_txt_shadowcolour = c01&0x66ffffff;
  228.     g_txt_glowcolour = eval(TXT_GLOW_COLOUR);
  229.     g_dither_shadowcolour = RGBA(000, 000, 000, 200);
  230. }
  231. on_init();
  232.  
  233. function on_size() {
  234.    
  235.     window.MinWidth = 80;
  236.     window.MinHeight = 40;
  237.    
  238.     ww = window.Width;
  239.     wh = window.Height;
  240.    
  241.     g_panelopt_scale_w = ww - g_panelopt_left - g_panelopt_right;
  242.     midpoint = (wh-REFLECT_HEIGHT) / 2 - LINE_HEIGHT / 2;
  243.     reset_lyrics();
  244. }
  245.  
  246. function reset_lyrics() {
  247.     var k, delta;
  248.    
  249.     midpoint = (wh-REFLECT_HEIGHT) / 2 - LINE_HEIGHT / 2;
  250.  
  251.     g_playtimer && window.KillTimer(g_playtimer);
  252.  
  253.     if(fb.IsPlaying||fb.IsPaused) {
  254.         g_scroll=0;
  255.         g_is_scrolling = false;
  256.         get_lyrics();
  257.         change_focus();
  258.         k = g_tab[focus].ante_lines * LINE_HEIGHT;
  259.         if(g_lyrics_status>0) {
  260.             pos = midpoint - k;
  261.             g_playtimer = window.CreateTimerInterval(PLAYTIMER_VALUE);
  262.             g_timer_abs = 4;
  263.         } else {
  264.             delta = (g_tab[g_tab.length-1].ante_lines + g_tab[g_tab.length-1].total_lines);
  265.             pos = Math.round(((wh-REFLECT_HEIGHT) / 2) - (delta * LINE_HEIGHT / 2));
  266.         }
  267.     }
  268. }
  269.  
  270. function on_paint(gr) {
  271.     var i, j;
  272.     var aspect;
  273.    
  274.     if(REFLECT_HEIGHT>=0) {
  275.         var main_img = gdi.CreateImage(ww, wh-REFLECT_HEIGHT);
  276.         var gp = main_img.GetGraphics();
  277.  
  278.         if(opt_show_lyrics) {
  279.             //gp.FillSolidRect(0, 0, ww, ww, RGBA(0,0,0,075));
  280.         } else {
  281.             //gp.FillSolidRect(0, 0, ww, ww, RGBA(0,0,0,020));
  282.         }
  283.  
  284.         if(fb.IsPlaying||fb.IsPaused) {
  285.             gp.SetTextRenderingHint(3);
  286.             opt_show_lyrics && show_lyrics(gp, g_tab, pos);
  287.         }
  288.         main_img.ReleaseGraphics(gp);
  289.         gr.DrawImage(main_img, 0, 0, main_img.Width, main_img.Height, 0, 0, main_img.Width, main_img.Height, 0, 255);
  290.         //gr.DrawImage(main_img, main_img.Width, (wh-REFLECT_HEIGHT)+1, -1*main_img.Width, main_img.Height*95/100, 0, 0, main_img.Width, main_img.Height,180,245);
  291.         //gr.FillGradRect(0, wh-REFLECT_HEIGHT+1, ww, REFLECT_HEIGHT+1, 90, RGBA(15,15,15,080), RGBA(0,0,0,255));
  292.         CollectGarbage();
  293.     } else {
  294.         if(fb.IsPlaying||fb.IsPaused) {
  295.             gr.SetTextRenderingHint(3);
  296.             opt_show_lyrics && show_lyrics(gr, g_tab, pos);
  297.         }
  298.     }
  299.    
  300.     // panel option (offset adjust)
  301.     // ============================
  302.     if(opt_show_lyrics) {
  303.         if(fb.IsPlaying||fb.IsPaused) {
  304.             var y_offset = 0;
  305.         } else {
  306.             var y_offset = 18;
  307.         }
  308.     } else {
  309.         var y_offset = 18;
  310.     }
  311.     if(g_track_type!=3 && g_panelopt_y+y_offset>g_panelopt_h*-1) {
  312.         gr.SetSmoothingMode(2);
  313.         gr.SetTextRenderingHint(3);
  314.         gr.FillRoundRect(5, g_panelopt_y-10, ww-10, g_panelopt_h+9, 5, 5, RGBA(10, 010, 010, 210));
  315.         gr.DrawRoundRect(6, g_panelopt_y-10, ww-12, g_panelopt_h+8, 5, 5, 1.0, RGBA(255, 255, 255, 040));
  316.         gr.DrawRoundRect(5, g_panelopt_y-10, ww-10, g_panelopt_h+9, 5, 5, 1.0, RGBA(0, 0, 0, 230));
  317.         // drawing the scale for offset adjustement
  318.         switch(g_lyrics_status) {
  319.             case 0:
  320.                 gr.gdiDrawText("> NO LYRICS FOUND FOR THIS TRACK", g_panelopt_font, RGBA(200, 200, 200, 255), 12, g_panelopt_y+3-y_offset, ww-10, 16, DT_LEFT | DT_TOP);
  321.                 break;
  322.             case 1:
  323.                 gr.gdiDrawText("OFFSET", g_panelopt_font, RGBA(200, 200, 200, 255), 12, g_panelopt_y+3-y_offset, ww-10, 16, DT_LEFT | DT_TOP);
  324.                 gr.SetSmoothingMode(0);
  325.                 gr.DrawLine(g_panelopt_left+2, g_panelopt_y+9-y_offset, ww-g_panelopt_right+2, g_panelopt_y+9-y_offset, 1.0, RGBA(150, 150, 150, 255));
  326.                 gr.DrawLine(g_panelopt_left+2, g_panelopt_y+6-y_offset, g_panelopt_left+2, g_panelopt_y+12-y_offset, 1.0, RGBA(150, 150, 150, 255));
  327.                 gr.DrawLine(g_panelopt_left+2+g_panelopt_scale_w/2, g_panelopt_y+6-y_offset, g_panelopt_left+2+g_panelopt_scale_w/2, g_panelopt_y+12-y_offset, 1.0, RGBA(150, 150, 150, 255));
  328.                 gr.DrawLine(ww-g_panelopt_right+2, g_panelopt_y+6-y_offset, ww-g_panelopt_right+2, g_panelopt_y+12-y_offset, 1.0, RGBA(150, 150, 150, 255));
  329.                 Cx = get_Cx(g_panelopt_delay);
  330.                 gr.DrawLine(Cx+2, g_panelopt_y+5-y_offset, Cx+2, g_panelopt_y+14-y_offset, 3.0, Cdrag?RGBA(255, 255, 255, 255):RGBA(230, 230, 230, 255));
  331.                 gr.gdiDrawText(g_panelopt_delay/100+" s", g_panelopt_font, RGBA(200, 200, 200, 255), ww-g_panelopt_right+3, g_panelopt_y+3-y_offset, g_panelopt_right-14, 16, DT_RIGHT | DT_TOP);
  332.                 break;
  333.             case 2:
  334.                 gr.gdiDrawText("> UNSYNCED LYRICS", g_panelopt_font, RGBA(200, 200, 200, 255), 12, g_panelopt_y+3-y_offset, ww-10, 16, DT_LEFT | DT_TOP);
  335.                 break;
  336.         }
  337.         gr.SetSmoothingMode(0);
  338.         gr.FillSolidRect(12, g_panelopt_y+18-y_offset, ww-24, 1, RGBA(255,255,255,40));
  339.         gr.FillSolidRect(12, g_panelopt_y+17-y_offset, ww-24, 1, RGBA(0,0,0,170));
  340.         // draw buttons (option panel only)
  341.         if(IMG_TYPE==0) {
  342.             aspect = ALBUM_IMG_ASPECT;
  343.         } else {
  344.             aspect = ARTIST_IMG_ASPECT;  
  345.         }
  346.         for (i = 0; i < mybutton.length; i++) {
  347.             switch (i) {
  348.                 case 0:
  349.                     // panelopt album icon
  350.                     mybutton[i].draw(gr, 0, g_panelopt_y+22-y_offset, IMG_TYPE==0?000:255, "");
  351.                     break;
  352.                 case 1:
  353.                     // panelopt artist icon
  354.                     mybutton[i].draw(gr, 30, g_panelopt_y+22-y_offset, IMG_TYPE!=0?000:255, "");
  355.                     break;
  356.                 case 2:
  357.                     // panelopt aspect icon : crop
  358.                     mybutton[i].draw(gr, ww-65, g_panelopt_y+23-y_offset, aspect==0?000:255, "");
  359.                     break;
  360.                 case 3:
  361.                     // panelopt aspect icon : center
  362.                     mybutton[i].draw(gr, ww-44, g_panelopt_y+23-y_offset, aspect==1?000:255, "");
  363.                     break;
  364.                 case 4:
  365.                     // panelopt aspect icon : fill
  366.                     mybutton[i].draw(gr, ww-25, g_panelopt_y+23-y_offset, aspect==2?000:255, "");
  367.                     break;
  368.             }
  369.         }
  370.     }
  371.     // encoding used
  372.     if(opt_show_lyrics) {
  373.         gr.SetTextRenderingHint(3);
  374.         if(GET_ENCODING && g_lyrics_status>0 && g_codepage!=0) {
  375.             gr.DrawString("codepage: "+g_codepage, g_font_small, RGBA(000,000,000,100), 2, wh-14, ww, 12, lc_stringformat);
  376.         }
  377.     }
  378. }
  379.  
  380. function on_mouse_lbtn_dblclk(x, y, mask) {
  381.     // reset position
  382.     reset_lyrics();
  383. }
  384.  
  385. function on_mouse_lbtn_down(x, y) {
  386.     var i;
  387.    
  388.     if(x>g_panelopt_left && x<ww-g_panelopt_right && y>0 && y<18) {
  389.         Cdrag = true;
  390.         Cx=x;
  391.         g_panelopt_delay = get_delay(Cx);
  392.         window.RepaintRect(0, 0, ww, g_panelopt_h+g_panelopt_y+3);
  393.     } else {
  394.         Cdrag = false;
  395.     }
  396.  
  397.     // buttons
  398.     for (i = 0; i < mybutton.length; i++) {
  399.         mybutton[i].checkstate("down", x, y, i);
  400.     }
  401. }
  402.  
  403. function on_mouse_lbtn_up(x, y) {
  404.     var i;
  405.    
  406.     if(Cdrag) reset_lyrics();
  407.     Cdrag = false;
  408.  
  409.     // buttons
  410.     for (i = 0; i < mybutton.length; i++) {
  411.         switch (i) {
  412.             case 0:
  413.                 if (mybutton[i].checkstate("up", x, y)== mybutton[i].ButtonStates.hover) {
  414.                     IMG_TYPE = 0;
  415.                     window.SetProperty("Image Type [0:1]", 0);
  416.                 }
  417.                 break;
  418.             case 1:
  419.                 if (mybutton[i].checkstate("up", x, y)== mybutton[i].ButtonStates.hover) {
  420.                     IMG_TYPE = 1;
  421.                     window.SetProperty("Image Type [0:1]", 1);
  422.                 }
  423.                 break;
  424.             case 2:
  425.                 if (mybutton[i].checkstate("up", x, y)== mybutton[i].ButtonStates.hover) {
  426.                     if(IMG_TYPE==0) {
  427.                         ALBUM_IMG_ASPECT = 0;
  428.                         window.SetProperty("Album Image Aspect [0:2]", 0);
  429.                     } else {
  430.                         ARTIST_IMG_ASPECT = 0;
  431.                         window.SetProperty("Artist Image Aspect [0:2]", 0);
  432.                     }
  433.                 }
  434.                 break;
  435.             case 3:
  436.                 if (mybutton[i].checkstate("up", x, y)== mybutton[i].ButtonStates.hover) {
  437.                     if(IMG_TYPE==0) {
  438.                         ALBUM_IMG_ASPECT = 1;
  439.                         window.SetProperty("Album Image Aspect [0:2]", 1);
  440.                     } else {
  441.                         ARTIST_IMG_ASPECT = 1;
  442.                         window.SetProperty("Artist Image Aspect [0:2]", 1);
  443.                     }
  444.                 }
  445.                 break;
  446.             case 4:
  447.                 if (mybutton[i].checkstate("up", x, y)== mybutton[i].ButtonStates.hover) {
  448.                     if(IMG_TYPE==0) {
  449.                         ALBUM_IMG_ASPECT = 2;
  450.                         window.SetProperty("Album Image Aspect [0:2]", 2);
  451.                     } else {
  452.                         ARTIST_IMG_ASPECT = 2;
  453.                         window.SetProperty("Artist Image Aspect [0:2]", 2);
  454.                     }
  455.                 }
  456.                 break;
  457.         }
  458.     }
  459.  
  460. }
  461.  
  462. function on_mouse_move(x, y) {
  463.     mouse_x = x;
  464.     mouse_y = y;
  465.    
  466.     // Option panel (adjust offset) animation
  467.     /*
  468.     if(y<=g_panelopt_h) {
  469.         if(g_panelopt_y==(g_panelopt_h * -1)) {
  470.             if(!g_panelopt_waiter) {
  471.                 g_panelopt_waiter = window.CreateTimerInterval(500);
  472.             }
  473.         } else {
  474.             if(!g_panelopt_waiter) {
  475.                 g_panelopt_waiter = window.CreateTimerInterval(1);
  476.             }
  477.         }
  478.     } else if (y>g_panelopt_h && g_panelopt_y>g_panelopt_h * -1){
  479.         g_panelopt_sens = -1;
  480.         if(!g_panelopt_timer) {
  481.             g_panelopt_timer = window.CreateTimerInterval(40);
  482.         }
  483.     }
  484.     // offset cursor dragging
  485.     if(Cdrag) {
  486.         if(x>g_panelopt_left && x<ww-g_panelopt_right && y<18) {
  487.             Cx=x;
  488.             g_panelopt_delay = get_delay(Cx);
  489.             window.RepaintRect(0, 0, ww, g_panelopt_h+g_panelopt_y+3);
  490.         }
  491.     } else if (g_panelopt_y>g_panelopt_h * -1) {
  492.         window.RepaintRect(0, 0, ww, g_panelopt_h+g_panelopt_y+3);
  493.     }
  494.     */
  495.  
  496.  
  497.     // buttons
  498.     hand=false;
  499.     for(i=0;i<mybutton.length;i++) {
  500.         mybutton[i].checkstate("move", x, y, i);
  501.         if(mybutton[i].is_hover) hand=true;
  502.     }
  503.  
  504.     // Mouse Cursor
  505.     window.SetCursor(hand? IDC_HAND : IDC_ARROW);
  506. }
  507.  
  508. function on_mouse_wheel(delta) {
  509.     if(opt_show_lyrics && g_lyrics_status>0) {
  510.         if(delta>0) {
  511.             pos = (pos>=midpoint)?pos:pos + LINE_HEIGHT;
  512.         } else {
  513.             pos = (pos<=(wh/2 - g_tab_length*LINE_HEIGHT))?pos:pos - LINE_HEIGHT;
  514.         }
  515.         window.Repaint();
  516.     }
  517. }
  518.  
  519. function on_mouse_leave() {
  520.     var i;
  521.  
  522.     mouse_x = -1;
  523.     mouse_y = -1;
  524.  
  525.     if (g_panelopt_y>g_panelopt_h * -1) {
  526.         g_panelopt_sens = -1;
  527.         if(!g_panelopt_timer) {
  528.             g_panelopt_timer = window.CreateTimerInterval(40);
  529.         }
  530.     }
  531.  
  532.     // buttons    
  533.     for (i = 0; i < mybutton.length; i++) {
  534.         mybutton[i].checkstate("leave", 0, 0, i);
  535.     }
  536. }
  537.  
  538. function on_focus(is_focused) {
  539.     if(!is_focused){
  540.         mouse_x = -1;
  541.         mouse_y = -1;
  542.         if (g_panelopt_y>g_panelopt_h * -1) {
  543.             g_panelopt_sens = -1;
  544.             if(!g_panelopt_timer) {
  545.                 g_panelopt_timer = window.CreateTimerInterval(40);
  546.             }
  547.         }
  548.     }
  549. }
  550.  
  551. function on_playback_time(time) {
  552.  
  553. //******************************Mire777 Script -(Force SAVE OPTION!)********************
  554.      {        
  555.      //Check if lyric has been found
  556.      if(g_lyrics_status==0)
  557.      if( fb.TitleFormat( "%lyric_exists%" ).Eval() )
  558.      
  559.      //If Lyrics found, save it!
  560.      fb.RunMainMenuCommand("View/Lyrics Show 3/Save");
  561.      else
  562.      {
  563.               }
  564. }
  565. //**************************************************************************************    
  566.  
  567. // at each new seconde, centiemes is reset to 0 (Increment on timer every 100ms)
  568.     centiemes = 0;
  569.     if(g_lyrics_status==0) {
  570.         //next line add wait option for display lyrics, else show lyrics NOW!..
  571.         //if(elap_seconds.Eval()==7)
  572.         {
  573.             reset_lyrics();
  574.             window.Repaint();
  575.         }
  576.         }
  577.  
  578.     if (g_panelopt_y>g_panelopt_h * -1) {
  579.         g_panelopt_sens = -1;
  580.         if(!g_panelopt_timer) {
  581.             g_panelopt_timer = window.CreateTimerInterval(40);
  582.         }
  583.     }
  584. }
  585.  
  586. function on_playback_new_track(info) {
  587.     g_panelopt_delay=0;
  588.     g_playtimer && window.KillTimer(g_playtimer);
  589.     pos=0;
  590.     g_scroll = 0;
  591.     g_is_scrolling = false;
  592.     on_item_focus_change();
  593.     change_focus();
  594.     if(g_lyrics_status>0) {
  595.         g_playtimer = window.CreateTimerInterval(PLAYTIMER_VALUE);
  596.         g_timer_abs = 4;
  597.     }
  598. }
  599.  
  600. function on_playback_seek(time) {
  601.     var k;
  602.     if(g_lyrics_status>0) {
  603.         reset_lyrics();
  604.     }
  605. }
  606.  
  607. function on_playback_stop(reason) {
  608.     g_playtimer && window.KillTimer(g_playtimer);
  609.     g_playtimer = false;
  610.     if(reason==0) {
  611.         // user Stop
  612.         on_item_focus_change();
  613.     }
  614. }
  615.  
  616. function on_timer(id) {
  617.     var i;
  618.     var t1 = elap_seconds.Eval() * 100 + centiemes;
  619.     var t2 = len_seconds.Eval() * 100;
  620.     var p1, p2;
  621.  
  622.     // buttons
  623.     for (i = 0; i < mybutton.length; i++) {
  624.         mybutton[i].ontimer(id);
  625.     }
  626.    
  627.     if(g_panelopt_waiter) {
  628.         if(g_panelopt_waiter.ID == id) {
  629.             if(mouse_y>0 && mouse_y<g_panelopt_h) {
  630.                 g_panelopt_sens = 1;
  631.                 if(!g_panelopt_timer && g_panelopt_y<0) {
  632.                     g_panelopt_timer = window.CreateTimerInterval(40);
  633.                 }
  634.                 if(opt_show_lyrics) {
  635.                     if(fb.IsPlaying||fb.IsPaused) {
  636.                         g_panelopt_h = 42;
  637.                     } else {
  638.                         g_panelopt_h = 42 - 18;
  639.                     }
  640.                 } else {
  641.                     g_panelopt_h = 42 - 18;
  642.                 }
  643.             }
  644.             window.KillTimer(g_panelopt_waiter);
  645.             g_panelopt_waiter = false;
  646.         }
  647.     }
  648.    
  649.     if(t1>t2-100) {
  650.         g_playtimer && window.KillTimer(g_playtimer);
  651.     }
  652.  
  653.     if(g_panelopt_timer) {
  654.         if(g_panelopt_timer.ID == id) {
  655.             var po_step = 3;
  656.             if(g_panelopt_sens>0) {
  657.                 if(g_panelopt_y<0) {
  658.                     g_panelopt_y = g_panelopt_y<=po_step*-1?g_panelopt_y+po_step:0;
  659.                 } else {
  660.                     window.KillTimer(g_panelopt_timer);
  661.                     g_panelopt_timer = false;
  662.                 }
  663.             } else {
  664.                 if(g_panelopt_y>g_panelopt_h * -1) {
  665.                     g_panelopt_y = g_panelopt_y>=(g_panelopt_h*-1)+po_step?g_panelopt_y-po_step:(g_panelopt_h*-1);
  666.                 } else {
  667.                     window.KillTimer(g_panelopt_timer);
  668.                     g_panelopt_timer = false;
  669.                 }
  670.             }
  671.             window.RepaintRect(0, 0, ww, g_panelopt_h+g_panelopt_y+3);
  672.         }
  673.     } else {
  674.    
  675.         if(g_playtimer && g_lyrics_status>0) {
  676.             if(g_playtimer.ID == id) {
  677.                 if(!g_is_scrolling && t1>=g_tab[focus_next].timer) {
  678.                     p1 = g_tab[focus].ante_lines*LINE_HEIGHT;
  679.                     p2 = g_tab[focus_next].ante_lines*LINE_HEIGHT;
  680.                     g_scroll = (p2 - p1);
  681.                     change_focus();
  682.                     g_is_scrolling = true;
  683.                 }
  684.                 g_timer_abs--;
  685.                 if (g_scroll>0) {
  686.                     pos -= g_scroll<SCROLL_STEP/10?g_scroll:SCROLL_STEP/10;
  687.                     g_scroll -= g_scroll<SCROLL_STEP/10?g_scroll:SCROLL_STEP/10;
  688.                     if(g_timer_abs<=1) {
  689.                         g_timer_abs = 4;
  690.                         if(opt_show_lyrics) window.Repaint();
  691.                     }
  692.                 } else {
  693.                     g_timer_abs = 4;
  694.                     g_is_scrolling = false;
  695.                 }
  696.                 centiemes = (centiemes>98)?0:(centiemes+1);
  697.             }
  698.         }
  699.        
  700.     }
  701. }
  702.  
  703. function show_lyrics(gr, tab, posy) {
  704.     var i, k, text_colour;
  705.    
  706.     switch(TXT_ALIGN.toUpperCase()) {
  707.         case "LEFT":
  708.             g_txt_align = lc_stringformat;
  709.             break;
  710.         case "CENTER":
  711.             g_txt_align = cc_stringformat;
  712.             break;
  713.         case "RIGHT":
  714.             g_txt_align = rc_stringformat;
  715.             break;
  716.         default:
  717.             g_txt_align = cc_stringformat;
  718.     }
  719.  
  720.     for(i=0;i<tab.length;i++) {
  721.         if(Math.round(posy)>=(LINE_HEIGHT*-4) && Math.round(posy)<wh) {
  722.             if(i==focus && g_lyrics_status==1) {
  723.                 text_colour = g_txt_highlightcolour;
  724.                 shadow_colour = c06;
  725.             } else {
  726.                 if(g_lyrics_status==1) {
  727.                     text_colour = g_txt_normalcolour;
  728.                     shadow_colour = c01;
  729.                 } else {
  730.                     text_colour = g_txt_highlightcolour;
  731.                     shadow_colour = c06;
  732.                 }
  733.             }
  734.             if(g_lyrics_status>0) {
  735.                 if(i==focus && tab[i].text.length>2 && g_lyrics_status==1) {
  736.                     gr.FillGradRect(0, Math.floor(posy), ww, (tab[i].total_lines*LINE_HEIGHT), 00, RGBA(0,0,0,10), RGBA(0,0,0,90), 0.5);
  737.                 }
  738.             }
  739.             TEXT_SHADOW && gr.DrawString(tab[i].text, g_font, shadow_colour&0x66ffffff, H_PADDING+0, Math.floor(posy)-1+1, ww-H_PADDING*2, (tab[i].total_lines*LINE_HEIGHT), g_txt_align);
  740.             TEXT_GLOW && gr.DrawString(tab[i].text, g_font, g_txt_glowcolour, H_PADDING-1, Math.floor(posy)-1, ww-H_PADDING*2, (tab[i].total_lines*LINE_HEIGHT), g_txt_align);
  741.             TEXT_GLOW && gr.DrawString(tab[i].text, g_font, g_txt_glowcolour, H_PADDING+1, Math.floor(posy)-1, ww-H_PADDING*2, (tab[i].total_lines*LINE_HEIGHT), g_txt_align);
  742.             TEXT_GLOW && gr.DrawString(tab[i].text, g_font, g_txt_glowcolour, H_PADDING, Math.floor(posy)-1-1, ww-H_PADDING*2, (tab[i].total_lines*LINE_HEIGHT), g_txt_align);
  743.             TEXT_GLOW && gr.DrawString(tab[i].text, g_font, g_txt_glowcolour, H_PADDING, Math.floor(posy)-1+1, ww-H_PADDING*2, (tab[i].total_lines*LINE_HEIGHT), g_txt_align);
  744.             gr.DrawString(tab[i].text, g_font, text_colour, H_PADDING, Math.floor(posy)-1, ww-H_PADDING*2, (tab[i].total_lines*LINE_HEIGHT), g_txt_align);
  745.         }
  746.         posy = Math.floor(posy+LINE_HEIGHT+((tab[i].total_lines-1)*LINE_HEIGHT));
  747.     }
  748. }
  749.  
  750. function grab_timer(t_tab) {
  751.     var tminutes, tsecondes, tcentiemes;
  752.     var i, k, f_sentence, b, c, delta, repeat_text;
  753.     var tab = Array();
  754.     for(i=0;i<t_tab.length;i++) {
  755.         if(g_lyrics_status==1) {
  756.             // -----------
  757.             // sync lyrics
  758.             // -----------
  759.             if(IsTimestamped(t_tab[i])) {
  760.                 b = 0;
  761.                 while(t_tab[i].substring(b*10, b*10+1)=="[") {
  762.                     b++;
  763.                 }
  764.                 c = b;
  765.                 repeat_text = remove_enhanced_balises(t_tab[i].substring(c*10, t_tab[i].length));
  766.                 if(repeat_text.length==0) repeat_text = repeat_text + " ";
  767.                 for(b=0;b<c;b++) {
  768.                     f_sentence = new sentence;
  769.                     tminutes = t_tab[i].substring(1+(b*10), 3+(b*10));
  770.                     tsecondes = t_tab[i].substring(4+(b*10), 6+(b*10));
  771.                     tcentiemes = t_tab[i].substring(7+(b*10), 9+(b*10));
  772.                     f_sentence.timer = Math.round(tminutes)*60*100 + Math.round(tsecondes)*100 + Math.round(tcentiemes) - DEFAULT_OFFSET - g_panelopt_delay;
  773.                     if(f_sentence.timer<0) f_sentence.timer=0;
  774.                     f_sentence.text = repeat_text;
  775.                     tab.push(f_sentence);
  776.                 }
  777.             }
  778.         } else {
  779.             // -------------
  780.             // unsync lyrics
  781.             // -------------
  782.             if(IsTimestamped(t_tab[i])) {
  783.                 // if sync line in unsync lyrics, i remove timestamps in this line
  784.                 b = 0;
  785.                 while(IsTimestamped(t_tab[i].substring(b*10, b*10+10))) {
  786.                     b++;
  787.                 }
  788.                 t_tab[i] = t_tab[i].substring(b*10, t_tab[i].length);
  789.             }
  790.             f_sentence = new sentence;
  791.             f_sentence.timer = 0;
  792.             f_sentence.text = t_tab[i];
  793.             tab.push(f_sentence);
  794.         }
  795.     }
  796.     if(tab.length==0) {
  797.         g_lyrics_status = 0;
  798.         tab = load_track_info();
  799.         delta = (tab[tab.length-1].ante_lines + tab[tab.length-1].total_lines);
  800.         pos = (wh / 2) - (delta * LINE_HEIGHT / 2);
  801.     } else {
  802.         f_sentence = new sentence;
  803.         f_sentence.timer = 9999999;
  804.         f_sentence.text = "---";
  805.         tab.push(f_sentence);
  806.     }
  807.     CollectGarbage();
  808.     return calc_lines(sort_tab(tab));
  809. }
  810.  
  811. function load_txt_file(filePath, fileName, codepage) {
  812.     var str;
  813.     if(GET_ENCODING) {
  814.         str = utils.ReadTextFile(filePath + fileName, codepage);
  815.     } else {
  816.         str = utils.ReadTextFile(filePath + fileName, convertCharsetToCodepage("default"));
  817.     }
  818.     return str;    
  819. }
  820.  
  821. function load_file(filePath, fileName) {
  822.     var i;
  823.     var t_tab = Array();
  824.     var str;
  825.     g_file = open_file(filePath, fileName, ForReading);
  826.     while(!g_file.AtEndOfStream) {
  827.         str = g_file.ReadLine();
  828.         // blank lines are ignored
  829.         if(str.length>0) t_tab.push(str);
  830.     }
  831.     close_file(g_file);
  832.     return grab_timer(check_lyrics_type(t_tab));
  833. }
  834.  
  835. function get_encoding(filePath, fileName) {
  836.     var i;
  837.     var found = false;
  838.     var str, str_light;
  839.     var charset="";
  840.     g_file = open_file(filePath, fileName, ForReading);
  841.     while(!g_file.AtEndOfStream && !found) {
  842.         str = g_file.ReadLine().toLowerCase();
  843.         str_light = str.replace(' ','');
  844.         str_light = str_light.replace('[','');
  845.         str_light = str_light.replace(']','');
  846.         if(str_light.substring(0,9) == "encoding:") {
  847.             i = 9;
  848.             while(str_light.substring(i,i+1)!="]" && str.charCodeAt(i)!=10 && i<str_light.length) {
  849.                 charset = charset + str_light.substring(i,i+1);
  850.                 i += 1;
  851.             }
  852.             found = true;
  853.         }
  854.     }
  855.     close_file(g_file);
  856.     if(found) {
  857.         return convertCharsetToCodepage(charset);
  858.     } else {
  859.         return 0;
  860.     }
  861. }
  862.  
  863. function check_lyrics_type(t_tab) {
  864.     var i;
  865.     var count = 0;
  866.     var ts_percent;
  867.     var tab = Array();
  868.     for(i=0;i<t_tab.length;i++) {
  869.         if(IsTimestamped(t_tab[i])) {
  870.             // format timestamps to default syntax : [99:99.99]
  871.             tab.push(ts_analyzer(t_tab[i]));
  872.             // count # of sync lines
  873.             count++;
  874.         } else {
  875.             if(t_tab[i].length>1) tab.push(t_tab[i]);
  876.         }
  877.     }
  878.     // calc percent of sync lines, if more than 50% of the total filled lines, it's sync lyrics, else, unsync lyrics!
  879.     ts_percent = Math.round(count/tab.length*100);
  880.     if(ts_percent>30) {
  881.         // sync lyrics
  882.         g_lyrics_status = 1;
  883.     } else {
  884.         // unsync lyrics
  885.         g_lyrics_status = 2;
  886.     }
  887.     return tab;
  888. }
  889.  
  890. function parse_tag(tag, delimiter) {
  891.     var t_tab = Array();
  892.     var i, j;
  893.     j = 0;
  894.     for(i=0;i<tag.length;i++) {
  895.         if(i==tag.length-1 || tag.charCodeAt(i)==10 || (i>0 && (i<tag.length-5) && (tag.substring(i, i+1)==delimiter) && (tag.substring(i-1, i)!="]"))) {
  896.             if(i==tag.length-1) {
  897.                 t_tab.push(tag.substring(j, i+1));
  898.             } else {
  899.                 t_tab.push(tag.substring(j, i));
  900.             }
  901.             if(tag.charCodeAt(i)!=10) {
  902.                 j = i;
  903.             } else {
  904.                 j = i+1;
  905.             }
  906.         }
  907.     }
  908.     return grab_timer(check_lyrics_type(t_tab));
  909. }
  910.  
  911. function load_track_info() {
  912.     var tab = Array(new sentence, new sentence, new sentence, new sentence);
  913.     var count = 0;
  914.     tab[count].text = artist.Eval();
  915.     count++;
  916.     tab[count].text = title.Eval();
  917.     count++;
  918.     tab[count].text = "(no lyric)";
  919.     count++;
  920.     return calc_lines(tab);
  921. }
  922.  
  923. function open_file(filePath, fileName, ioMode) {
  924.     var fileInst = null;
  925.     var bool = file_exists(filePath + fileName);
  926.     if(bool) {
  927.         fileInst = g_fso.OpenTextFile(filePath + fileName, ioMode);
  928.     }
  929.     return fileInst;
  930. }
  931.  
  932. function close_file(fileInst) {
  933.         fileInst.Close();
  934. }
  935.  
  936. function read_file(fileInst) {
  937.     var line = fileInst.ReadLine();
  938.     return line;
  939. }
  940.  
  941. function folder_exists(folderPath) {
  942.     var fso, bool;
  943.     fso = new ActiveXObject("Scripting.FileSystemObject");
  944.     bool = fso.FolderExists(folderPath);
  945.     return bool;
  946. }
  947.  
  948. function file_exists(filePath) {
  949.     var fso, bool;
  950.     fso = new ActiveXObject("Scripting.FileSystemObject");
  951.     bool = fso.Fileexists(filePath);
  952.     return bool;
  953. }
  954.  
  955. function lyrics_folder_exists(folder_name) {
  956.     var fso;
  957.     var bool=1;
  958.     fso = new ActiveXObject("Scripting.FileSystemObject");
  959.     if (folder_exists(fb.ProfilePath + folder_name) == false) {
  960.         fso.CreateFolder(fb.ProfilePath + folder_name);
  961.         bool=0;
  962.     }
  963.     return bool;
  964. }
  965.  
  966. function change_focus() {
  967.     var i, j, t1;
  968.     t1 = elap_seconds.Eval()*100+centiemes;
  969.     if(g_lyrics_status>0) {
  970.         // search line index just after actual timer
  971.         for(i=focus;i<g_tab.length;i++) {
  972.             if(g_tab[i].timer>t1) break;
  973.         }
  974.         focus_next=i;
  975.         focus = (i>0)?i-1:0;
  976.         // now i check if there are more than one line with the same timer as focus one & if found, i take it as new focus 'cause it's the first (not a blank line)
  977.         if(focus>0) {
  978.             for(i=0;i<focus;i++) {
  979.                 if(g_tab[i].timer==g_tab[focus].timer) {
  980.                     focus = i;
  981.                     break;
  982.                 }
  983.             }
  984.         }
  985.     }
  986. }
  987.  
  988. function calc_lines(ctab) {
  989.     var i, j;
  990.     var padx = 0;
  991.     var tmp_img;
  992.     var gp;
  993.     var lineh;
  994.     g_tab_length = 0;
  995.     if(ww==0) return ctab; // test to avoid errors if panel is hidden (ww=0)
  996.     tmp_img = gdi.CreateImage(ww-(H_PADDING*2)-padx, 100);
  997.     gp = tmp_img.GetGraphics();
  998.     for(i=0;i<ctab.length;i++) {
  999.         // calc sentence #lines to display / window.width
  1000.         lineh = gp.MeasureString(ctab[i].text, g_font, 0, 0, ww-(H_PADDING*2)-padx, wh).Height;
  1001.         ctab[i].total_lines = (lineh/LINE_HEIGHT) > Math.floor(lineh/LINE_HEIGHT) ? Math.floor(lineh/LINE_HEIGHT) + 1 : Math.floor(lineh/LINE_HEIGHT)  ;
  1002.         ctab[i].ante_lines = 0;
  1003.         for(j=0;j<i;j++) {
  1004.             ctab[i].ante_lines += ctab[j].total_lines;
  1005.         }
  1006.         g_tab_length += ctab[i].total_lines;
  1007.     }
  1008.     CollectGarbage();
  1009.     return ctab;
  1010. }
  1011.  
  1012. function sort_tab(tab2sort) {
  1013.     var tab = Array();
  1014.     var i, j;
  1015.     var tmp = new sentence;
  1016.     var smallest = 0;
  1017.     for(i=0;i<tab2sort.length;i++) {
  1018.         for(j=i;j<tab2sort.length;j++) {
  1019.             if(tab2sort[i].timer > tab2sort[j].timer) {
  1020.                 tmp = tab2sort[i];
  1021.                 tab2sort[i] = tab2sort[j];
  1022.                 tab2sort[j] = tmp;
  1023.             }
  1024.         }
  1025.         tab.push(tab2sort[i]);
  1026.     }
  1027.     return tab;
  1028. }
  1029.  
  1030. function remove_enhanced_balises(str) {
  1031.     var i;
  1032.     var chr1, chr2;
  1033.     var new_str="";
  1034.     for(i=0;i<str.length;i++) {
  1035.         chr1 = str.substring(i, i+1);
  1036.         if(i+10<=str.length) chr2 = str.substring(i+9, i+10); else chr2=null;
  1037.         if(chr1=="<" && chr2==">") {
  1038.             i = i + 10 - 1;
  1039.         } else {
  1040.             new_str = new_str + chr1;
  1041.         }
  1042.     }
  1043.     return new_str;
  1044. }
  1045.  
  1046. function ts_analyzer(str) {
  1047.     var i, j, ch,  ts_len;
  1048.     var str2 = "";
  1049.     var state=0;
  1050.     var deb = -1;
  1051.     var fin = -1;
  1052.     var sep1 = -1;
  1053.     var sep2 = -1;
  1054.     var suite=0;
  1055.     for(i=0;i<str.length;i++) {
  1056.         ch = str.substring(i, i+1);
  1057.         switch(state) {
  1058.         case 0:            
  1059.             if(ch=="[" && IsNumeric(str.substring(i+1, i+2))) {
  1060.                 state=1;
  1061.                 deb=i;
  1062.                 fin=-1;
  1063.             }
  1064.             break;
  1065.         case 1:
  1066.             if(deb>=0 && ch==":") {
  1067.                 state=2;
  1068.                 sep1=i;
  1069.             }
  1070.             if(i>deb+3) {
  1071.                 deb=-1;
  1072.                 fin=-1;
  1073.                 sep1=-1;
  1074.                 sep2=-1;
  1075.                 state=0;
  1076.             }
  1077.             break;
  1078.         case 2:
  1079.             if(sep1>=0 && (ch==":" || ch==".")) {
  1080.                 state=3;
  1081.                 sep2=i;
  1082.             }
  1083.             if(sep1>=0 && sep2==-1 && ch=="]") {
  1084.                 state=4;
  1085.                 fin=i;
  1086.             }
  1087.             if(i>sep1+3) {
  1088.                 deb=-1;
  1089.                 fin=-1;
  1090.                 sep1=-1;
  1091.                 sep2=-1;
  1092.                 state=0;
  1093.             }
  1094.             break;
  1095.         case 3:
  1096.             if(deb>=0 && ch=="]") {
  1097.                 state=4;
  1098.                 if(i==str.length-1) {
  1099.                     str=str+" ";
  1100.                 }
  1101.                 fin=i;
  1102.             }
  1103.             if(i>deb+10) {
  1104.                 deb=-1;
  1105.                 fin=-1;
  1106.                 sep1=-1;
  1107.                 sep2=-1;
  1108.                 state=0;
  1109.             }
  1110.             break;
  1111.         case 4:
  1112.             ts_len=fin-deb+1;
  1113.             switch(ts_len) {
  1114.                 case 6:
  1115.                     str2 = str2 + "[0" + str.substring(deb+1,deb+2) + ":" + str.substring(deb+3, deb+5) + ".00]";
  1116.                     break;
  1117.                 case 7:
  1118.                     str2 = str2 + str.substring(deb,deb+6) + ".00]";
  1119.                     break;
  1120.                 case 9:
  1121.                     str2 = str2 + "[0" + str.substring(deb+1,deb+2) + ":" + str.substring(deb+3, deb+5) + "." + str.substring(deb+6, deb+8) + "]";
  1122.                     break;
  1123.                 case 10:
  1124.                     if(sep1==deb+2) {
  1125.                         str2 = str2 + "[0" + str.substring(deb+1,deb+2) + ":" + str.substring(deb+3, deb+5) + "." + str.substring(deb+6, deb+8) + "]";
  1126.                     } else {
  1127.                         str2 = str2 + str.substring(deb,deb+10);
  1128.                     }
  1129.                     break;
  1130.                 case 11:
  1131.                     str2 = str2 + str.substring(deb,deb+9) + "]";
  1132.                     break;
  1133.             }
  1134.             j += 10;
  1135.             if(str.substring(fin+1,fin+2)=="[") {
  1136.                 suite = 1;
  1137.                 i = fin;
  1138.                 deb = -1;
  1139.                 fin = -1;
  1140.                 sep1 = -1;
  1141.                 sep2 = -1;
  1142.                 state = 0;
  1143.             } else {
  1144.                 suite = -1;
  1145.                 i = str.length - 1;
  1146.                 str2 = str2 + str.substring(fin+1, str.length);
  1147.             }
  1148.             break;      
  1149.         }
  1150.     }
  1151.     return str2;
  1152. }
  1153.  
  1154. function IsNumeric(str) {
  1155.     var ValidChars = "0123456789.";
  1156.     for (i = 0; i < str.length; i++) {
  1157.         if (ValidChars.indexOf(str.charAt(i)) == -1) {
  1158.             return false;
  1159.         }
  1160.     }
  1161.     return true;
  1162. }
  1163.  
  1164. function IsTimestamped(str) {
  1165.     var ValidChars = "[0123456789:.]";
  1166.     var count = 0;
  1167.     for (i = 0; i < (str.length>10?10:str.length); i++) {
  1168.         if (ValidChars.indexOf(str.charAt(i)) >=0) {
  1169.             count++;
  1170.         }
  1171.     }
  1172.     if(count>=6 && count <=11) {
  1173.         return true;
  1174.     } else {
  1175.         return false;
  1176.     }
  1177. }
  1178.  
  1179. function check_file(path, filename) {
  1180.     if(file_exists(path+filename+".lrc")) {
  1181.         g_lyrics_filename  = filename+".lrc";
  1182.         g_lyrics_path = path;
  1183.         return true;
  1184.     } else {
  1185.         if(file_exists(path+filename+".txt")) {
  1186.             g_lyrics_filename  = filename+".txt";
  1187.             g_lyrics_path = path;
  1188.             return true;
  1189.         }
  1190.     }
  1191.     return false;
  1192. }
  1193.  
  1194. function get_lyrics() {
  1195.     var i, count, delta, tag;
  1196.     var tpath = Array(g_metadb?lyrics_dir1.EvalWithMetadb(g_metadb):lyrics_dir2, lyrics_dir2);
  1197.     var tfilename = Array(artist2.Eval() + " -" + title2.Eval(), artist2.Eval() + " - " + title2.Eval());
  1198.     var bool_tag = false;
  1199.     var bool_file = false;
  1200.  
  1201.     g_codepage=0;
  1202.  
  1203.     // reset lyrics tab
  1204.     g_lyrics_status = 0;
  1205.     if(g_tab.length>0) g_tab.splice(0, g_tab.length);
  1206.     pos = midpoint;
  1207.     focus = 0;
  1208.     window.Repaint();
  1209.  
  1210.     // check TAGs
  1211.     tag = lyrics.Eval();
  1212.     if(tag.length>0) {
  1213.         bool_tag = true;
  1214.         if(tag.substring(0,1)=="[") g_lyrics_status = 1; else g_lyrics_status = 2;
  1215.     } else {
  1216.         // check files
  1217.         i = 0;
  1218.         while(!bool_file && i<2) {
  1219.             j = 0;
  1220.             while(!bool_file && j<2) {
  1221.                 bool_file = check_file(tpath[i], tfilename[j]);
  1222.                 j++;
  1223.             }
  1224.             i++;
  1225.         }
  1226.     }
  1227.  
  1228.     // if lyrics found
  1229.     if(bool_tag || bool_file) {
  1230.         if(bool_tag) {
  1231.             g_tab = parse_tag(tag, "[");
  1232.         } else {
  1233.                 g_codepage = utils.FileTest(g_lyrics_path+g_lyrics_filename, "chardet");
  1234.                 if(g_codepage==0) g_codepage = get_encoding(g_lyrics_path, g_lyrics_filename);
  1235.                 g_tab = parse_tag(load_txt_file(g_lyrics_path, g_lyrics_filename, g_codepage), "[");
  1236.         }
  1237.     }  else {
  1238.         g_tab = load_track_info();
  1239.         delta = (g_tab[g_tab.length-1].ante_lines + g_tab[g_tab.length-1].total_lines);
  1240.         pos = Math.round(((wh-REFLECT_HEIGHT) / 2) - (delta * LINE_HEIGHT / 2));
  1241.     }
  1242.  
  1243.     if(g_lyrics_status==2) {
  1244.         for(i=0;i<g_tab.length-1;i++) {
  1245.             g_tab[i].timer = i * Math.floor(len_seconds.Eval() * 100 / g_tab.length);
  1246.         }
  1247.     }
  1248.    
  1249.     // dump
  1250.     for(i=0;i<g_tab.length;i++) {
  1251.         //fb.trace("i="+i+" // timer="+g_tab[i].timer+" // txt="+g_tab[i].text+" // ante="+g_tab[i].ante_lines+" // nbl="+g_tab[i].total_lines);
  1252.     }
  1253. }
  1254.  
  1255.  
  1256. function refresh_images() {
  1257.     var i, j;
  1258.     var iw, ir;
  1259.    
  1260.     // Icons colours
  1261.     var cc01 = RGB(10,10,10);
  1262.     var cc02 = RGB(150,150,150);
  1263.     var cc03 = RGB(250,250,250);
  1264.     var cc04 = RGB(200,200,200);
  1265.    
  1266.     // Artist Icon
  1267.     icon_artist_img = gdi.CreateImage(26, 20);
  1268.     gb = icon_artist_img.GetGraphics();
  1269.     gb.SetSmoothingMode(2);
  1270.     gb.FillEllipse(05, 0, 7, 6, cc03 & 0xa0ffffff);
  1271.     gb.DrawEllipse(05, 0, 7, 6, 1.0, RGBA(0,0,0,080));
  1272.     gb.FillEllipse(01, 6, 15, 8, cc03 & 0xa0ffffff);
  1273.     gb.DrawEllipse(01, 6, 15, 8, 1.0, RGBA(0,0,0,080));
  1274.     gb.DrawLine(04,11,04,13,1.0, RGBA(0,0,0,100));
  1275.     gb.DrawLine(13,11,13,13,1.0, RGBA(0,0,0,100));
  1276.     gb.SetSmoothingMode(0);
  1277.     icon_artist_img.ReleaseGraphics(gb);
  1278.  
  1279.     // Album Icon
  1280.     icon_album_img = gdi.CreateImage(30, 20);
  1281.     gb = icon_album_img.GetGraphics();
  1282.     gb.SetSmoothingMode(2);
  1283.     gb.FillEllipse(11, 0, 15, 15, cc03 & 0x60ffffff);
  1284.     gb.DrawEllipse(11, 0, 15, 15, 1.0, RGBA(0,0,0,080));
  1285.     gb.DrawEllipse(12, 1, 13, 13, 1.0, cc03 & 0x70ffffff);
  1286.     gb.FillEllipse(15, 4, 7, 7, cc03 & 0xbbffffff);
  1287.     gb.FillEllipse(17, 6, 3, 3, cc01 & 0x80ffffff);
  1288.     gb.SetSmoothingMode(0);
  1289.     icon_album_img.ReleaseGraphics(gb);
  1290.  
  1291.     // crop Icon
  1292.     icon_crop_img = gdi.CreateImage(20, 20);
  1293.     gb = icon_crop_img.GetGraphics();
  1294.     gb.SetSmoothingMode(0);
  1295.     gb.DrawRect(2,0,12,12,1.0,cc02);
  1296.     gb.DrawRect(0,2,16,8,1.0,cc04);
  1297.     icon_crop_img.ReleaseGraphics(gb);
  1298.  
  1299.     // center Icon
  1300.     icon_center_img = gdi.CreateImage(20, 20);
  1301.     gb = icon_center_img.GetGraphics();
  1302.     gb.SetSmoothingMode(0);
  1303.     gb.DrawRect(2,0,12,12,1.0,cc02);
  1304.     gb.DrawRect(2,2,12,8,1.0,cc04);
  1305.     icon_center_img.ReleaseGraphics(gb);
  1306.  
  1307.     // fill Icon
  1308.     icon_fill_img = gdi.CreateImage(20, 20);
  1309.     gb = icon_fill_img.GetGraphics();
  1310.     gb.SetSmoothingMode(0);
  1311.     gb.DrawRect(2,0,12,12,1.0,cc02);
  1312.     gb.FillSolidRect(8,1,1,4,cc04);
  1313.     gb.FillSolidRect(7,2,3,1,cc04);
  1314.     gb.FillSolidRect(8,8,1,4,cc04);
  1315.     gb.FillSolidRect(7,10,3,1,cc04);
  1316.     gb.FillSolidRect(3,6,4,1,cc04);
  1317.     gb.FillSolidRect(4,5,1,3,cc04);
  1318.     gb.FillSolidRect(10,6,4,1,cc04);
  1319.     gb.FillSolidRect(12,5,1,3,cc04);
  1320.     icon_fill_img.ReleaseGraphics(gb);
  1321.  
  1322.     // initialize icon buttons
  1323.     for (i = 0; i < mybutton.length; i++) {
  1324.         switch (i) {
  1325.             case 0: // album icon
  1326.                 mybutton[i].create(icon_album_img, icon_album_img, icon_album_img, "", -01);
  1327.                 break;
  1328.             case 1: // artist icon
  1329.                 mybutton[i].create(icon_artist_img, icon_artist_img, icon_artist_img, "", -02);
  1330.                 break;
  1331.             case 2: // crop icon
  1332.                 mybutton[i].create(icon_crop_img, icon_crop_img, icon_crop_img, "", -03);
  1333.                 break;
  1334.             case 3: // center icon
  1335.                 mybutton[i].create(icon_center_img, icon_center_img, icon_center_img, "", -04);
  1336.                 break;
  1337.             case 4: // fill icon
  1338.                 mybutton[i].create(icon_fill_img, icon_fill_img, icon_fill_img, "", -05);
  1339.                 break;
  1340.         }
  1341.     }
  1342.    
  1343.     CollectGarbage();
  1344. }
  1345.  
  1346. function settings_menu(x, y) {
  1347.     var MF_SEPARATOR = 0x00000800;
  1348.     var MF_STRING = 0x00000000;
  1349.     var MF_GRAYED = 0x00000001;
  1350.     var MF_DISABLED = 0x00000002;
  1351.     var _menu = window.CreatePopupMenu();
  1352.     var idx;
  1353.  
  1354.     //_menu.AppendMenuItem(MF_STRING, 1, "Enable Lyrics Display");
  1355.     _menu.AppendMenuItem(opt_show_lyrics ? (fb.IsPlaying ? MF_STRING : MF_GRAYED) : MF_GRAYED, 2, "Refresh Lyrics");
  1356.     _menu.AppendMenuItem(MF_SEPARATOR, 0, "");
  1357.     _menu.AppendMenuItem(MF_STRING, 3, "Panel Properties...");
  1358.     //_menu.AppendMenuItem(MF_STRING, 4, "Configure...");
  1359.     _menu.CheckMenuItem(1, opt_show_lyrics?1:0);
  1360.     idx = _menu.TrackPopupMenu(x, y);
  1361.     switch (idx) {
  1362.     case 1:
  1363.         if(opt_show_lyrics) {
  1364.             opt_show_lyrics = update_option("show_lyrics",0)==1?true:false;
  1365.         } else {
  1366.             opt_show_lyrics = update_option("show_lyrics",1)==1?true:false;
  1367.         }
  1368.         window.Repaint();
  1369.         break;
  1370.     case 2:
  1371.         reset_lyrics();
  1372.         window.Repaint();
  1373.         break;
  1374.     case 3:
  1375.         window.ShowProperties();
  1376.         break;
  1377.     case 4:
  1378.         window.ShowConfigure();
  1379.         break;
  1380.     }
  1381.     _menu.Dispose();
  1382.     return true;
  1383. }
  1384.  
  1385. //=================================================// Playlist Callbacks
  1386. function on_playlists_changed() {
  1387.     on_item_focus_change();
  1388. }
  1389.  
  1390. function on_playlist_switch() {
  1391.     on_item_focus_change();
  1392. }
  1393.  
  1394. //=================================================// MetaDB Callbacks
  1395. function on_item_focus_change() {
  1396.     if(g_metadb) {
  1397.         window.UnwatchMetadb();
  1398.     }
  1399.  
  1400.     g_metadb = (fb.IsPlaying||fb.IsPaused)?fb.GetNowPlaying():fb.PlaylistItemCount(fb.ActivePlaylist)>0?fb.GetFocusItem():false;
  1401.  
  1402.     if(g_metadb) {
  1403.         on_metadb_changed();
  1404.         window.WatchMetadb(g_metadb);
  1405.     }
  1406. }
  1407.  
  1408. function on_metadb_changed() {
  1409.     g_path = tf_path.EvalWithMetadb(g_metadb);
  1410.     g_track_type = TrackType(g_path);
  1411.     reset_lyrics();
  1412. }
  1413.  
  1414. function on_notify_data(name, info) {
  1415.     switch(name) {
  1416.         case "colour":
  1417.             break;
  1418.     }
  1419. }
  1420.  
  1421. function on_drag_enter(action) {
  1422.     action.Parsable = false;
  1423. }
  1424.  
  1425. function on_mouse_rbtn_up(x, y) {
  1426.    settings_menu(x, y);
  1427.    return true;
  1428. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement