Advertisement
soKindly

Lastfm panel 1.2

Feb 11th, 2014
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==PREPROCESSOR==
  2. // @name "WSH Last.fm panel"
  3. // @version "1.2"
  4. // @author "so_kindly"
  5. // ==/PREPROCESSOR==
  6. //== changelog ======================================
  7. // 1.1: "Microsoft.XMLHTTP" activex object replaced on "Msxml2.XMLHTTP.6.0"
  8. // 1.2: Added stream support, minor fixes
  9. //===================================================
  10.  
  11. // Variables {{
  12. // Text flags
  13. var DT_TOP = 0x00000000;
  14. var DT_LEFT = 0x00000000;
  15. var DT_CENTER = 0x00000001;
  16. var DT_RIGHT = 0x00000002;
  17. var DT_VCENTER = 0x00000004;
  18. var DT_BOTTOM = 0x00000008;
  19. var DT_WORDBREAK = 0x00000010;
  20. var DT_CALCRECT = 0x00000400;
  21. var DT_NOPREFIX = 0x00000800;
  22. var DT_END_ELLIPSIS = 0x00008000;
  23. var DT_NOCLIP = 0x00000100;
  24.  
  25. var IDC_HAND = 32649;
  26. var IDC_ARROW = 32512;
  27.  
  28. var FontStyle = {
  29.     Regular: 0,
  30.     Bold: 1,
  31.     Italic: 2,
  32.     BoldItalic: 3,
  33.     Underline: 4,
  34.     Strikeout: 8
  35. };
  36.  
  37. var StringAlignment = {
  38.     Near: 0,
  39.     Center: 1,
  40.     Far: 2
  41. };
  42.  
  43. var StringTrimming = {
  44.     None: 0,
  45.     Character: 1,
  46.     Word: 2,
  47.     EllipsisCharacter: 3,
  48.     EllipsisWord: 4,
  49.     EllipsisPath: 5
  50. };
  51.  
  52. var StringFormatFlags = {
  53.     DirectionRightToLeft: 0x00000001,
  54.     DirectionVertical: 0x00000002,
  55.     NoFitBlackBox: 0x00000004,
  56.     DisplayFormatControl: 0x00000020,
  57.     NoFontFallback: 0x00000400,
  58.     MeasureTrailingSpaces: 0x00000800,
  59.     NoWrap: 0x00001000,
  60.     LineLimit: 0x00002000,
  61.     NoClip: 0x00004000,
  62.     BypassGDI: 0x80000000
  63. }
  64.  
  65. // Flags of Menu
  66. var MF_SEPARATOR = 0x00000800;
  67. var MF_ENABLED = 0x00000000;
  68. var MF_GRAYED = 0x00000001;
  69. var MF_DISABLED = 0x00000002;
  70. var MF_UNCHECKED = 0x00000000;
  71. var MF_CHECKED = 0x00000008;
  72. var MF_STRING = 0x00000000;
  73. var MF_POPUP = 0x00000010;
  74.  
  75. var MK_SHIFT = 0x0004;
  76. var FOCUSFLAG;
  77.  
  78. var CursorFollowMode = {
  79.     OnlyStopped: 2,
  80.     Always: 3
  81. }
  82.  
  83. // globals
  84. var ww = 0;
  85. var wh = 0;
  86. var Properties = new GetProperties();
  87. var MetaDB;
  88.  
  89. //margins
  90. var lm = 5;
  91. var rm = 5;
  92. var tm = 5;
  93. var bm = 0;
  94.  
  95. // text vars
  96. FontStyles = {
  97.     Regular: 0,
  98.     Bold: 1,
  99.     Italic: 2,
  100.     BoldItalic: 3,
  101.     Underline: 4,
  102.     Strikeout: 8
  103. }
  104.  
  105. var font_label = gdi.Font("Segoe UI", 12, FontStyles.Bold);
  106. var font_num = gdi.Font("Segoe UI", 11, FontStyles.Bold);
  107. var font_normal = gdi.Font("Segoe UI", 13, FontStyles.Regular);
  108. var font_header = gdi.Font("Segoe UI", 15, FontStyles.Bold);
  109. var font_gui = gdi.Font("Web Symbols", 13, FontStyles.Regular);
  110.  
  111. var normal_color = RGB(180, 180, 180);
  112. var hover_color = RGB(200, 200, 200);
  113. var LineStrFmt = StringFormat(StringAlignment.Near, StringAlignment.Near, StringTrimming.None, StringFormatFlags.LineLimit);
  114.  
  115. var settings_dir = fb.ProfilePath + "Damask\\settings\\";
  116.  
  117. //img vars
  118. var images_path = fb.FoobarPath + "skins\\Damask\\images\\lastfm\\";
  119. var img_lastfm_logo_red = gdi.Image(images_path + "lastfm_logo_red.jpg");
  120. var img_lastfm_flip = gdi.Image(images_path + "scrobbleflip.png");
  121. var img_avatar = gdi.Image(settings_dir + "avatar.jpg");
  122.  
  123. var img_asterisk = gdi.Image(images_path + "asterisk_small.png");
  124. var img_heart = gdi.Image(images_path + "t2.png");
  125. var max_avatar_height = Properties.Avatar.MaxHeight;
  126.  
  127. var ava_height = img_avatar.height > max_avatar_height ? max_avatar_height : img_avatar.height;
  128. var ava_width = img_avatar.height > max_avatar_height ? max_avatar_height * img_avatar.width / img_avatar.height : img_avatar.width;
  129. var avatar_need_refresh = true;
  130.  
  131. var imgPath = fb.FoobarPath + "skins\\Damask\\images\\";
  132. var img_main_wallpaper = gdi.Image(imgPath + "DamaskBG.png").CreateRawBitmap();
  133.  
  134. var opt_username = read_option("lastfm_username", "");
  135. var username = "";
  136. var opt_api_key = read_option("lastfm_api_key", "");
  137. var WshShell = new ActiveXObject("WScript.Shell");
  138.  
  139. var lastfm_data = new Array();
  140. var lastfm_xmlhttp = new Array();
  141. var lastfm_xmlDoc = new Array();
  142.  
  143. var wait = 1;
  144. var lastfm_status = 0;
  145. var error_count = 0;
  146. var loved_track = false;
  147.  
  148. var Y_OFFSET = 0;
  149. var sum_height = 0;
  150. var text_H = 0;
  151. var text_W = 0;
  152.  
  153. var mouse_x = 0;
  154. var mouse_y = 0;
  155.  
  156. var regdate_error = false;
  157.  
  158. // scrollbar colors
  159. var vs_normal_color = RGB(50, 50, 50);
  160. var vs_hover_color = RGB(70, 70, 70);
  161. var vs_down_color = RGB(60, 60, 60);
  162. var vs_bg_color = RGB(33, 33, 33);
  163. var vs_bg_color_hover = RGB(35, 35, 35);
  164.  
  165. var text_Hs = new Array();
  166. var text_Ws = new Array();
  167. var TL_ys = new Array();
  168. var TL_xs = new Array();
  169.  
  170. var np = [fb.TitleFormat("%artist%").Eval(true), fb.TitleFormat("%album%").Eval(true), fb.TitleFormat("%title%").Eval(true)];
  171.  
  172. var spcounter = 0;
  173. var charcounter = 0;
  174. var longeststr = "";
  175. var linecounter = 1;
  176.  
  177. var WaitTimerID;
  178. var StopTimerID;
  179.  
  180. var CorrectedData = []; //artist - album - track
  181.  
  182. // text buttons array [artist, album, track, tag1, tag2, tag3, tag4, tag5, similar1, similar2, similar3, similar4, similar5]
  183. var TLs = new Array(
  184.     TL1 = new TextLink(0, 0, 0, 0, function () {}, "", ""),
  185.     TL2 = new TextLink(0, 0, 0, 0, function () {}, "", ""),
  186.     TL3 = new TextLink(0, 0, 0, 0, function () {}, "", ""),
  187.     TLtag1 = new TextLink(0, 0, 0, 0, function () {}, "", ""),
  188.     TLtag2 = new TextLink(0, 0, 0, 0, function () {}, "", ""),
  189.     TLtag3 = new TextLink(0, 0, 0, 0, function () {}, "", ""),
  190.     TLtag4 = new TextLink(0, 0, 0, 0, function () {}, "", ""),
  191.     TLtag5 = new TextLink(0, 0, 0, 0, function () {}, "", ""),
  192.     TLsimilar1 = new TextLink(0, 0, 0, 0, function () {}, "", ""),
  193.     TLsimilar2 = new TextLink(0, 0, 0, 0, function () {}, "", ""),
  194.     TLsimilar3 = new TextLink(0, 0, 0, 0, function () {}, "", ""),
  195.     TLsimilar4 = new TextLink(0, 0, 0, 0, function () {}, "", ""),
  196.     TLsimilar5 = new TextLink(0, 0, 0, 0, function () {}, "", ""),
  197.     TLheart = new TextLink(0, 0, 25, 25, function () {}, "N", "Loved Track"));
  198.  
  199. var Tooltip = window.CreateTooltip();
  200. var TLAnimationTimerID;
  201. var TLAnimationTimer;
  202. var EnableTooltip = true;
  203. var MaxRange;
  204. var h_link, d_link;
  205. var StreamFlag = false;
  206.  
  207. // Variables}}
  208.  
  209.  
  210. //===========================================================================================================
  211. //===========================================================================================================
  212. // foo_silk-lastfm engine
  213. // http://code.google.com/p/foobar-silk/
  214. // (C) 2010 by Matthijs Brobbel
  215. /*
  216. /////////////////////////////////////////////////////////////////////////
  217. //###   | lastfm_data arrays    #########################################
  218. /////////////////////////////////////////////////////////////////////////
  219. //      | 0             | 1             | 2             | 3             |
  220. //      -----------------------------------------------------------------
  221. //  id: | userinfo      | artistinfo    | albuminfo     | trackinfo     |
  222. //      -----------------------------------------------------------------
  223. //  0:  | playcount     | playcount     | playcount     | playcount     |
  224. //  1:  | avg_day       | userplaycount | userplaycount | userplaycount |
  225. //  2:  | avg_week      | listeners     | listeners     | listeners     |
  226. //  3:  | avg_month     | tags          | 0             | userloved     |
  227. //  4:  | joindate      | similar       | 0             | 0             |
  228. //  5:  | avatar        | 0             | 0             | 0             |
  229. //      -----------------------------------------------------------------
  230. /////////////////////////////////////////////////////////////////////////
  231. */
  232.  
  233. function reset_lastfm_data() {
  234.     for (id = 0; id <= 4; id++) {
  235.         lastfm_data[id] = new Array(4);
  236.     }
  237.  
  238.     for (id = 0; id <= 3; id++) {
  239.         for (n = 0; n <= 5; n++) {
  240.             lastfm_data[id][n] = 0;
  241.         }
  242.     }
  243.  
  244.     lastfm_data[1][3] = new Array();
  245.     lastfm_data[1][4] = new Array();
  246.  
  247.     for (i = 0; i < 5; i++) {
  248.         lastfm_data[1][3][i] = "0";
  249.         lastfm_data[1][4][i] = "0";
  250.     }
  251. }
  252.  
  253. function get_lastfm_data() {
  254.     if (opt_username.length == 0 || opt_api_key.length != 32) {
  255.         window.Repaint();
  256.     } else { //lastfm_status counts here
  257.         contact_lastfm("user.getinfo", 0);
  258.         contact_lastfm("artist.getinfo&artist=" + encodeURIComponent(np[0]) + "&autocorrect=1", 1);
  259.         contact_lastfm("album.getinfo&artist=" + encodeURIComponent(np[0]) + "&album=" + encodeURIComponent(np[1]), 2);
  260.         contact_lastfm("track.getinfo&artist=" + encodeURIComponent(np[0]) + "&track=" + encodeURIComponent(np[2]) + "&autocorrect=1", 3);
  261.  
  262.     }
  263. }
  264.  
  265. function contact_lastfm(method, id) {
  266.     lastfm_xmlhttp[id] = new ActiveXObject("Msxml2.XMLHTTP.6.0"); //Microsoft.XMLHTTP
  267.     lastfm_xmlhttp[id].open("GET", "http://ws.audioscrobbler.com/2.0?api_key=" + opt_api_key + "&username=" + opt_username + "&user=" + opt_username + "&method=" + method + "&s=" + Math.random(), true);
  268.     lastfm_xmlhttp[id].setRequestHeader('User-Agent', "foo_silk_mod");
  269.     lastfm_xmlhttp[id].send();
  270.     lastfm_xmlhttp[id].onreadystatechange = function () {
  271.         if (lastfm_xmlhttp[id].readyState == 4) { // 'DONE' state
  272.             if (lastfm_xmlhttp[id].status == 200) { //success
  273.                 lastfm_status++;
  274.                 wait_lastfm_data();
  275.             }
  276.             if (lastfm_xmlhttp[id].status >= 400) { //error statuses
  277.  
  278.                 error_count++;
  279.                 lastfm_status++;
  280.                 wait_lastfm_data();
  281.             }
  282.         }
  283.     }
  284. }
  285.  
  286. function wait_lastfm_data() {
  287.     if (lastfm_status == 4 && error_count < 4) {
  288.         process_lastfm_data();
  289.         lastfm_status = wait = 0;
  290.         Y_OFFSET = 0;
  291.         error_count = 0;
  292.         return;
  293.     } else if (lastfm_status < 4) {
  294.         wait = 1;
  295.     } else if (error_count == 4) {
  296.         wait = -1;
  297.         error_count = 0;
  298.         window.Repaint();
  299.  
  300.     }
  301. }
  302.  
  303. function process_lastfm_data() {
  304.     for (id = 0; id < 4; id++) {
  305.         lastfm_xmlDoc[id] = lastfm_xmlhttp[id].responseXML;
  306.         try {
  307.             error = "last.fm API error: " + lastfm_xmlDoc[id].getElementsByTagName("error")[0].childNodes[0].nodeValue;
  308.         } catch (e) {
  309.             error = null;
  310.         }
  311.     }
  312.  
  313.     // Userinfo
  314.     try {
  315.         lastfm_data[0][0] = lastfm_xmlDoc[0].getElementsByTagName("playcount")[0].childNodes[0].nodeValue;
  316.         username = lastfm_xmlDoc[0].getElementsByTagName("name")[0].childNodes[0].nodeValue;
  317.     } catch (e) {
  318.         lastfm_data[0][0] = "0";
  319.     }
  320.     try {
  321.         lastfm_data[0][4] = lastfm_xmlDoc[0].getElementsByTagName("registered")[0].childNodes[0].nodeValue;
  322.         regdate_error = false;
  323.     } catch (e) {
  324.         regdate_error = true;
  325.         lastfm_data[0][4] = "";
  326.  
  327.     }
  328.     try {
  329.         lastfm_data[0][5] = lastfm_xmlDoc[0].getElementsByTagName("image")[2].childNodes[0].nodeValue;
  330.         if (avatar_need_refresh) {
  331.             fso = new ActiveXObject("Scripting.FileSystemObject");
  332.             img_avatar.Dispose();
  333.             img_avatar = gdi.Image(images_path + "default_avatar.png");
  334.             WshShell.Run("\"" + fb.FoobarPath + "skins\\Damask\\scripts\\" + "url2disk.exe\"" + " -i " + lastfm_data[0][5] + " -o " + "\"" + settings_dir + "\avatar.jpg\"", 0, true);
  335.             img_avatar = gdi.Image(settings_dir + "avatar.jpg");
  336.             ava_height = img_avatar.height > max_avatar_height ? max_avatar_height : img_avatar.height;
  337.             ava_width = img_avatar.height > max_avatar_height ? max_avatar_height * img_avatar.width / img_avatar.height : img_avatar.width;
  338.             avatar_need_refresh = false;
  339.         }
  340.     } catch (e) {
  341.         lastfm_data[0][5] = "";
  342.         if (avatar_need_refresh) {
  343.             img_avatar.Dispose();
  344.             img_avatar = gdi.Image(images_path + "default_avatar.png");
  345.             ava_height = img_avatar.height > max_avatar_height ? max_avatar_height : img_avatar.height;
  346.             ava_width = img_avatar.height > max_avatar_height ? max_avatar_height * img_avatar.width / img_avatar.height : img_avatar.width;
  347.             avatar_need_refresh = false;
  348.         }
  349.     }
  350.  
  351.     date = new Date().getTime() / 1;
  352.  
  353.     if (!regdate_error) {
  354.         try {
  355.             utc = Date.UTC(lastfm_data[0][4].substring(0, 4), (lastfm_data[0][4].substring(5, 7) - 1), lastfm_data[0][4].substring(8, 10), 0, 0, 0);
  356.         } catch (e) {
  357.             utc = 0;
  358.         }
  359.         try {
  360.             lastfm_data[0][1] = "" + Math.round((lastfm_data[0][0] / ((date - utc) / 86400000)) * 100) / 100;
  361.             lastfm_data[0][1] = lastfm_data[0][1].replace(/(\d)(?=(\d\d\d)+([^\d]|$))/g, '$1 ');
  362.         } catch (e) {
  363.             lastfm_data[0][1] = "0";
  364.         };
  365.  
  366.         try {
  367.             lastfm_data[0][2] = "" + Math.round((lastfm_data[0][0] / ((date - utc) / 604800000)) * 10) / 10;
  368.             lastfm_data[0][2] = lastfm_data[0][2].replace(/(\d)(?=(\d\d\d)+([^\d]|$))/g, '$1 ');
  369.         } catch (e) {
  370.             lastfm_data[0][2] = "0";
  371.         };
  372.  
  373.         try {
  374.             lastfm_data[0][3] = "" + Math.round((lastfm_data[0][0] / ((date - utc) / 2629743000)) * 1) / 1;
  375.             lastfm_data[0][3] = lastfm_data[0][3].replace(/(\d)(?=(\d\d\d)+([^\d]|$))/g, '$1 ');
  376.         } catch (e) {
  377.             lastfm_data[0][3] = "0";
  378.         };
  379.  
  380.  
  381.     } else {
  382.         lastfm_data[0][1] = "0";
  383.         lastfm_data[0][2] = "0";
  384.         lastfm_data[0][3] = "0";
  385.     }
  386.  
  387.  
  388.     try {
  389.         lastfm_data[0][0] = lastfm_data[0][0].replace(/(\d)(?=(\d\d\d)+([^\d]|$))/g, '$1 ');
  390.     } catch (e) {
  391.         lastfm_data[0][0] = "0";
  392.     }
  393.  
  394.  
  395.     // Artistinfo - Albuminfo - Trackinfo
  396.     for (id = 1; id <= 3; id++) {
  397.         try {
  398.             lastfm_data[id][0] = lastfm_xmlDoc[id].getElementsByTagName("playcount")[0].childNodes[0].nodeValue;
  399.             lastfm_data[id][0] = lastfm_data[id][0].replace(/(\d)(?=(\d\d\d)+([^\d]|$))/g, '$1 ');
  400.         } catch (e) {
  401.             lastfm_data[id][0] = "0";
  402.         }
  403.  
  404.         try {
  405.             lastfm_data[id][1] = lastfm_xmlDoc[id].getElementsByTagName("userplaycount")[0].childNodes[0].nodeValue;
  406.             lastfm_data[id][1] = lastfm_data[id][1].replace(/(\d)(?=(\d\d\d)+([^\d]|$))/g, '$1 ');
  407.         } catch (e) {
  408.             lastfm_data[id][1] = "0";
  409.         }
  410.  
  411.         try {
  412.             lastfm_data[id][2] = lastfm_xmlDoc[id].getElementsByTagName("listeners")[0].childNodes[0].nodeValue;
  413.             lastfm_data[id][2] = lastfm_data[id][2].replace(/(\d)(?=(\d\d\d)+([^\d]|$))/g, '$1 ');
  414.         } catch (e) {
  415.             lastfm_data[id][2] = "0";
  416.         }
  417.  
  418.  
  419.         switch (id) {
  420.         case 1:
  421.             try {
  422.                 CorrectedData[id] = lastfm_xmlDoc[id].getElementsByTagName("name")[0].childNodes[0].nodeValue;
  423.                 for (i = 0; i < 5; i++) {
  424.                     try {
  425.                         lastfm_data[id][3][i] = lastfm_xmlDoc[id].getElementsByTagName("tag")[i].childNodes[0].childNodes[0].nodeValue; //artist tags
  426.                     } catch (e) {
  427.                         lastfm_data[id][3][i] = "";
  428.                     }
  429.  
  430.                     try {
  431.                         lastfm_data[id][4][i] = lastfm_xmlDoc[id].getElementsByTagName("artist")[i + 1].childNodes[0].childNodes[0].nodeValue; //similar artists
  432.                     } catch (e) {
  433.                         lastfm_data[id][4][i] = "no data";
  434.                     }
  435.                 }
  436.             } catch (e) {
  437.                 CorrectedData[id] = "~no data";
  438.             }
  439.             break;
  440.         case 2:
  441.             try {
  442.                 CorrectedData[id] = lastfm_xmlDoc[id].getElementsByTagName("name")[0].childNodes[0].nodeValue;
  443.             } catch (e) {
  444.                 CorrectedData[id] = "~no data";
  445.             }
  446.             break;
  447.         case 3:
  448.             try {
  449.                 CorrectedData[id] = lastfm_xmlDoc[id].getElementsByTagName("name")[0].childNodes[0].nodeValue;
  450.             } catch (e) {
  451.                 CorrectedData[id] = "~no data";
  452.             }
  453.  
  454.             try {
  455.                 lastfm_data[id][3] = lastfm_xmlDoc[id].getElementsByTagName("userloved")[0].childNodes[0].nodeValue;
  456.             } catch (e) {
  457.                 lastfm_data[id][3] = "0";
  458.             }
  459.             break;
  460.         }
  461.  
  462.     }
  463.  
  464.     for (i = 0; i < TLs.length; i++) {
  465.         TLs[i].NeedReset = true;
  466.     }
  467.  
  468.     window.Repaint();
  469. }
  470.  
  471. //lfm end
  472. //===========================================================================================================
  473. //===========================================================================================================
  474.  
  475. // Tools {{
  476.  
  477. function StringFormat(h_align, v_align, trim, flag) {
  478.     return ((h_align << 28) | (v_align << 24) | (trim << 20) | flag);
  479. }
  480.  
  481. function RGB(r, g, b) {
  482.     return (0xff000000 | (r << 16) | (g << 8) | (b));
  483. }
  484.  
  485. function RGBA(r, g, b, a) {
  486.     return ((a << 24) | (r << 16) | (g << 8) | (b));
  487. }
  488.  
  489. //Properties
  490. function GetProperties() {
  491.     this.Avatar = {
  492.         MaxHeight: window.GetProperty("A01.Avatar.MaxHeight", 100)
  493.     }
  494.  
  495.     this.Avatar.MaxHeight = Math.min(Math.max(this.Avatar.MaxHeight, 30), 252);
  496.  
  497.     this.Panel = {
  498.         CursorFollowMode: window.GetProperty("B01.Panel.CursorFollowMode", CursorFollowMode.OnlyStopped),
  499.     }
  500.  
  501.     this.Panel.CursorFollowMode = Math.max(this.Panel.CursorFollowMode, CursorFollowMode.OnlyStopped);
  502.     this.Panel.CursorFollowMode = Math.min(this.Panel.CursorFollowMode, CursorFollowMode.Always);
  503.     window.SetProperty("B01.Panel.CursorFollowMode", this.Panel.CursorFollowMode);
  504. }
  505.  
  506. // Generate background image.
  507. function GenerateBG() {
  508.     var img_bg = gdi.CreateImage(ww, wh);
  509.     var g = img_bg.GetGraphics();
  510.     // wallpaper
  511.     g.GdiDrawBitmap(img_main_wallpaper, 0, 0, img_bg.width, img_bg.height, 0, 0, img_bg.width, img_bg.height);
  512.  
  513.     img_bg_bmp = img_bg.CreateRawBitmap();
  514.     img_bg.ReleaseGraphics(g);
  515. }
  516.  
  517. // Tools }}
  518. //===================================================================================================================================================
  519.  
  520. //timers
  521. function c_WaitTimer() {
  522.     this.Stop = function () {
  523.         if (WaitTimerID) {
  524.             window.ClearTimeout(WaitTimerID);
  525.             WaitTimerID = null;
  526.             //window.Repaint();
  527.         }
  528.     }
  529.  
  530.     this.Start = function () {
  531.         WaitTimerID = window.SetTimeout(function () {
  532.             WaitTimerID = null;
  533.             lastfm_status = 0;
  534.             wait = 1;
  535.  
  536.             MetaDB = fb.GetFocusItem();
  537.             FOCUSFLAG = true;
  538.             if (fb.IsPlaying && fb.PlaybackLength == -1 && fb.GetFocusItem().Path == fb.GetNowPlaying().Path) {
  539.                 FOCUSFLAG = false;
  540.                 np = [fb.TitleFormat("%artist%").Eval(), fb.TitleFormat("%album%").Eval(), fb.TitleFormat("%title%").Eval()]
  541.                 if (np[0] == "?" && np[1] == "?") {
  542.                     wait = -2;
  543.                     window.Repaint();
  544.                     return;
  545.                 }
  546.                 lastfm_status = 0;
  547.                 wait = 1;
  548.                 window.Repaint();
  549.                 get_lastfm_data();
  550.             } else if (MetaDB) {
  551.                 np = [fb.TitleFormat("%artist%").EvalWithMetadb(MetaDB), fb.TitleFormat("%album%").EvalWithMetadb(MetaDB), fb.TitleFormat("%title%").EvalWithMetadb(MetaDB)]
  552.                 if (np[0] == "?" && np[1] == "?") {
  553.                     wait = -2;
  554.                     window.Repaint();
  555.                     return;
  556.                 }
  557.                 lastfm_status = 0;
  558.                 wait = 1;
  559.                 window.Repaint();
  560.                 get_lastfm_data();
  561.             } else {
  562.                 wait = -2;
  563.                 window.Repaint();
  564.             }
  565.  
  566.         }, 250);
  567.     }
  568. }
  569.  
  570.  
  571. function c_ButtonAnimationTimer() {
  572.     this.Stop = function () {
  573.         if (TLAnimationTimerID) {
  574.             window.ClearInterval(TLAnimationTimerID);
  575.             TLAnimationTimerID = null;
  576.         }
  577.     }
  578.  
  579.     this.Start = function () {
  580.         TLAnimationTimerID = window.SetInterval(function () {
  581.             var NeedRepaint = 0;
  582.             for (var i = 0; i < TLs.length; i++) {
  583.                 if (TLs[i].NeedRefresh) {
  584.                     TLs[i].RefreshOpacity();
  585.                     NeedRepaint += 1;
  586.                     Onlybtn = TLs[i]; // If only one button need to be repainted.
  587.                 }
  588.             }
  589.  
  590.             if (NeedRepaint) {
  591.                 if (NeedRepaint == 1) window.RepaintRect(Onlybtn.x, Onlybtn.y + Y_OFFSET, Onlybtn.width, Onlybtn.height);
  592.                 else window.RepaintRect(MaxRange.x, MaxRange.y, MaxRange.width, MaxRange.height); // This is range of buttons.
  593.             } else {
  594.                 TLAnimationTimer.Stop();
  595.             }
  596.         }, 50)
  597.     }
  598. }
  599.  
  600. // VB wrapper {{
  601. var vb = {};
  602. vb.Function = function (func) {
  603.     return function () {
  604.         return vb.Function.eval.call(this, func, arguments);
  605.     }
  606. };
  607. vb.Function.eval = function (func) {
  608.     var args = Array.prototype.slice.call(arguments[1]);
  609.     for (var i = 0; i < args.length; i++) {
  610.         if (typeof args[i] != 'string') continue;
  611.         args[i] = '"' + args[i].replace(/"/g, '" + Chr(34) + "') + '"';
  612.     }
  613.     var vbe;
  614.     vbe = new ActiveXObject('ScriptControl');
  615.     vbe.Language = 'VBScript';
  616.     return vbe.eval(func + '(' + args.join(', ') + ')');
  617. };
  618. var InputBox = vb.Function('InputBox');
  619. var MsgBox = vb.Function('MsgBox');
  620. // VB wrapper}}
  621.  
  622. //===================================================================================================================================================
  623. // Options engine {{
  624.  
  625. function update_option(optname, optvalue) {
  626.     var fso, f1, ts, s;
  627.     var ForReading = 1;
  628.     var ForWriting = 2;
  629.     fso = new ActiveXObject("Scripting.FileSystemObject");
  630.  
  631.     // Read the contents of the txt file
  632.     ts = fso.OpenTextFile(settings_dir + optname + ".txt", ForReading);
  633.     s = ts.ReadLine();
  634.     ts.Close();
  635.     // renaming the empty file used after in the PSS with the new value
  636.     f1 = fso.MoveFile(settings_dir + optname + "_" + s, settings_dir + optname + "_" + optvalue);
  637.  
  638.     // updating the txt file with the new value
  639.     ts = fso.OpenTextFile(settings_dir + optname + ".txt", ForWriting);
  640.     ts.WriteLine(optvalue);
  641.     ts.Close();
  642.     return optvalue;
  643. }
  644.  
  645. function read_option(optname, initvalue) {
  646.     var fso, ts, ts2, s;
  647.     var ForReading = 1;
  648.     var ForWriting = 2;
  649.     fso = new ActiveXObject("Scripting.FileSystemObject");
  650.  
  651.     if (file_exists(settings_dir + optname + ".txt")) {
  652.         ts = fso.OpenTextFile(settings_dir + optname + ".txt", ForReading);
  653.         s = ts.ReadLine();
  654.         ts.Close();
  655.         return s;
  656.     } else {
  657.         ts = fso.CreateTextFile(settings_dir + optname + ".txt", ForWriting);
  658.         ts.WriteLine(initvalue);
  659.         ts.Close();
  660.         ts2 = fso.CreateTextFile(settings_dir + optname + "_" + initvalue, ForWriting);
  661.         ts2.Close();
  662.         return initvalue;
  663.     }
  664. }
  665.  
  666. function folder_exists(chemin) {
  667.     var fso, bool;
  668.     fso = new ActiveXObject("Scripting.FileSystemObject");
  669.     bool = fso.FolderExists(chemin);
  670.     return bool;
  671. }
  672.  
  673. function file_exists(chemin) {
  674.     var fso, bool;
  675.     fso = new ActiveXObject("Scripting.FileSystemObject");
  676.     bool = fso.Fileexists(chemin);
  677.     return bool;
  678. }
  679.  
  680. // Options engine }}
  681.  
  682. // Cursor follow tools {{
  683. function SetCursorFollowMode(FollowMode) {
  684.     if (FollowMode != Properties.Panel.CursorFollowMode) {
  685.         Properties.Panel.CursorFollowMode = FollowMode;
  686.         window.SetProperty("B01.Panel.CursorFollowMode", FollowMode);
  687.         CursorFollow(FollowMode);
  688.     }
  689. }
  690.  
  691. function CursorFollow(FollowMode) {
  692.     switch (FollowMode) {
  693.     case CursorFollowMode.OnlyStopped:
  694.         if (fb.IsPlaying) on_playback_new_track();
  695.         else on_item_focus_change();
  696.         break;
  697.     case CursorFollowMode.Always:
  698.         on_item_focus_change();
  699.         break;
  700.     }
  701. }
  702.  
  703. // Cursor follow tools }}
  704.  
  705.  
  706. //context menu
  707. function show_context_menu(x, y) {
  708.     var _menu = window.CreatePopupMenu();
  709.     var _avatar = window.CreatePopupMenu();
  710.     var _followMode = window.CreatePopupMenu();
  711.     var ret;
  712.  
  713.     if (opt_username.length == 0 || opt_api_key.length != 32) {
  714.         _menu.AppendMenuItem(MF_STRING, 10, "Set your Last.fm username...");
  715.         //_menu.AppendMenuItem(MF_STRING, 11, "Set your API KEY...");
  716.     } else {
  717.         _menu.AppendMenuItem(opt_username.length > 0 && opt_api_key.length == 32 ? MF_STRING : MF_GRAYED, 1, "Update Last.fm Data");
  718.         _menu.AppendMenuItem(MF_SEPARATOR, 0, 0);
  719.  
  720.         _followMode.AppendMenuItem(MF_STRING, 2, "Only Stopped");
  721.         _followMode.AppendMenuItem(MF_STRING, 3, "Always");
  722.         _followMode.CheckMenuRadioItem(2, 3, Properties.Panel.CursorFollowMode);
  723.         _followMode.AppendTo(_menu, MF_STRING, "Cursor follow mode");
  724.  
  725.         _avatar.AppendMenuItem(MF_STRING, 4, "Download avatar");
  726.         _avatar.AppendMenuItem(MF_STRING, 5, "Restore default avatar");
  727.         _avatar.AppendTo(_menu, MF_STRING, "Avatar");
  728.  
  729.         _menu.AppendMenuItem(MF_STRING, 6, "Change username");
  730.         //_menu.AppendMenuItem(MF_STRING, 7, "Change API Key");
  731.         _menu.AppendMenuItem(MF_SEPARATOR, 0, 0);
  732.         _menu.AppendMenuItem(MF_STRING, 8, "Properties");
  733.     }
  734.  
  735.     ret = _menu.TrackPopupMenu(x, y);
  736.     switch (ret) {
  737.     case 1:
  738.         lastfm_status = 0;
  739.         wait = 1;
  740.         window.Repaint();
  741.         CursorFollow(Properties.Panel.CursorFollowMode);
  742.         break;
  743.     case 2:
  744.         SetCursorFollowMode(CursorFollowMode.OnlyStopped);
  745.         break;
  746.     case 3:
  747.         SetCursorFollowMode(CursorFollowMode.Always);
  748.         break;
  749.     case 4:
  750.         fso = new ActiveXObject("Scripting.FileSystemObject");
  751.         img_avatar.Dispose();
  752.         img_avatar = gdi.Image(images_path + "default_avatar.png")
  753.         window.Repaint();
  754.  
  755.         WshShell.Run("\"" + fb.FoobarPath + "skins\\Damask\\scripts\\" + "url2disk.exe\"" + " -i " + lastfm_data[0][5] + " -o " + "\"" + settings_dir + "\avatar.jpg\"", 0, true);
  756.         img_avatar = gdi.Image(settings_dir + "avatar.jpg");
  757.         ava_height = img_avatar.height > max_avatar_height ? max_avatar_height : img_avatar.height;
  758.         ava_width = img_avatar.height > max_avatar_height ? max_avatar_height * img_avatar.width / img_avatar.height : img_avatar.width;
  759.         window.Repaint();
  760.         break;
  761.     case 5:
  762.         img_avatar.Dispose();
  763.         img_avatar = gdi.Image(images_path + "default_avatar.png");
  764.         ava_height = img_avatar.height > max_avatar_height ? max_avatar_height : img_avatar.height;
  765.         ava_width = img_avatar.height > max_avatar_height ? max_avatar_height * img_avatar.width / img_avatar.height : img_avatar.width;
  766.         window.Repaint();
  767.         break;
  768.     case 6:
  769.         opt_username = InputBox("Please enter your Last.fm username", "Last.fm panel", opt_username);
  770.         if (!opt_username) opt_username = "";
  771.         update_option("lastfm_username", opt_username);
  772.  
  773.         avatar_need_refresh = true;
  774.  
  775.         CursorFollow(Properties.Panel.CursorFollowMode);
  776.         break;
  777.     case 7:
  778.         opt_api_key = InputBox("Please enter your Last.fm API KEY (http://www.last.fm/api/account)", "Last.fm panel", opt_api_key);
  779.         if (!opt_api_key) opt_api_key = "";
  780.         update_option("lastfm_api_key", opt_api_key);
  781.         CursorFollow(Properties.Panel.CursorFollowMode);
  782.         break;
  783.     case 8:
  784.         window.ShowProperties();
  785.         break;
  786.     case 10:
  787.         opt_username = InputBox("Please enter your Last.fm username", "Last.fm panel", opt_username);
  788.         if (!opt_username) opt_username = "";
  789.         update_option("lastfm_username", opt_username);
  790.  
  791.         avatar_need_refresh = true;
  792.  
  793.         CursorFollow(Properties.Panel.CursorFollowMode);
  794.         break;
  795.     case 11:
  796.         opt_api_key = InputBox("Please enter your Last.fm API KEY (http://www.last.fm/api/account)", "Last.fm panel", opt_api_key);
  797.         if (!opt_api_key) opt_api_key = "";
  798.         update_option("lastfm_api_key", opt_api_key);
  799.         CursorFollow(Properties.Panel.CursorFollowMode);
  800.         break;
  801.     }
  802.     _menu.Dispose();
  803.     _avatar.Dispose();
  804.     _followMode.Dispose();
  805.     return true;
  806. }
  807.  
  808. // button class
  809. function TextLink(x, y, width, height, fn_onclick, label, tiptext) {
  810.     this.x = x;
  811.     this.y = y;
  812.     this.width = width;
  813.     this.height = height;
  814.     this.label = label;
  815.     this.tiptext = tiptext;
  816.     this.TestProp = "";
  817.     this.NeedRefresh = 0;
  818.     this.oldstate = 0; // 0=normal, 1=hover, 2=down.
  819.     this.state = 0;
  820.     this.opacity = 0; // Opacity of new state image.
  821.     this.step = 0;
  822.     this.show = true;
  823.     this.NeedReset = false;
  824.  
  825.     this.OnClick = fn_onclick;
  826.  
  827.     this.ChangeState = function (s) {
  828.         this.oldstate = this.state;
  829.         this.state = s;
  830.         this.opacity = 0;
  831.         this.NeedRefresh = 1;
  832.         switch (s) {
  833.         case 0:
  834.             this.step = 40; // Step of changing to normal state.
  835.             Tooltip.Deactivate();
  836.             Tooltip.Text = "";
  837.             break;
  838.         case 1:
  839.             this.step = 75; // hover state.
  840.             if (EnableTooltip) {
  841.                 Tooltip.Text = this.tiptext;
  842.                 Tooltip.Activate();
  843.             }
  844.             break;
  845.         case 2:
  846.             this.step = 85; // down state.
  847.             Tooltip.Deactivate();
  848.             Tooltip.Text = "";
  849.             break;
  850.         }
  851.  
  852.         if (!TLAnimationTimerID) // start animation
  853.             TLAnimationTimer.Start();
  854.     }
  855.  
  856.     this.isXYok = function (x2, y2) {
  857.         return (x2 >= this.x && y2 >= this.y + Y_OFFSET && x2 <= this.x + this.width && y2 <= this.y + Y_OFFSET + this.height) ? true : false;
  858.     }
  859.  
  860.     this.Draw = function (x2, y2, gr) {
  861.         x2 = this.x; //disabled
  862.         y2 = this.y; //disabled
  863.         if (this.opacity < 255) {
  864.             switch (this.oldstate) {
  865.             case 0:
  866.                 gr.FillSolidRect(this.x, this.y + Y_OFFSET, this.width, this.height, RGBA(20, 20, 20, 255));
  867.                 gr.DrawString(this.label, font_normal, normal_color, this.x + 4, this.y + Y_OFFSET, this.width - 4, this.height, LineStrFmt);
  868.                 break;
  869.             case 1:
  870.                 gr.FillSolidRect(this.x, this.y + Y_OFFSET, this.width, this.height, RGBA(30, 30, 30, 255));
  871.                 gr.DrawString(this.label, font_normal, hover_color, this.x + 4, this.y + Y_OFFSET, this.width - 4, this.height, LineStrFmt);
  872.                 break;
  873.             case 2:
  874.                 gr.FillSolidRect(this.x, this.y + Y_OFFSET, this.width, this.height, RGBA(36, 36, 36, 255));
  875.                 gr.DrawString(this.label, font_normal, hover_color, this.x + 4, this.y + Y_OFFSET, this.width - 4, this.height, LineStrFmt);
  876.                 break;
  877.             default:
  878.                 break;
  879.             }
  880.         }
  881.  
  882.         if (this.opacity) {
  883.             switch (this.state) {
  884.             case 0:
  885.                 gr.FillSolidRect(this.x, this.y + Y_OFFSET, this.width, this.height, RGBA(20, 20, 20, this.opacity));
  886.                 gr.DrawString(this.label, font_normal, normal_color, this.x + 4, this.y + Y_OFFSET, this.width, this.height, LineStrFmt);
  887.                 break;
  888.             case 1:
  889.                 gr.FillSolidRect(this.x, this.y + Y_OFFSET, this.width, this.height, RGBA(30, 30, 30, this.opacity));
  890.                 gr.DrawString(this.label, font_normal, hover_color, this.x + 4, this.y + Y_OFFSET, this.width, this.height, LineStrFmt);
  891.                 break;
  892.             case 2:
  893.                 gr.FillSolidRect(this.x, this.y + Y_OFFSET, this.width, this.height, RGBA(36, 36, 36, this.opacity));
  894.                 gr.DrawString(this.label, font_normal, hover_color, this.x + 4, this.y + Y_OFFSET, this.width, this.height, LineStrFmt);
  895.                 break;
  896.             }
  897.         }
  898.     }
  899.  
  900.     this.RefreshOpacity = function (fn) {
  901.         if (this.opacity < 255) this.opacity = Math.min(this.opacity + this.step, 255);
  902.         else {
  903.             this.oldstate = this.state;
  904.             this.opacity = 0;
  905.             this.NeedRefresh = 0;
  906.         }
  907.     }
  908. }
  909.  
  910. function GetCoordinates() {
  911.  
  912.     // Calculate the max range of buttons, for increasing refresh speed.
  913.     MaxRange = {
  914.         x: TLs[0].x,
  915.         y: TLs[0].y + Y_OFFSET,
  916.         width: TLs[0].width,
  917.         height: TLs[0].height
  918.     }
  919.  
  920.     for (var i = 1; i < TLs.length - 1; i++) {
  921.         if (TLs[i].show) {
  922.             MaxRange.x = Math.min(TLs[i].x, MaxRange.x);
  923.             MaxRange.y = Math.min(TLs[i].y + Y_OFFSET, MaxRange.y);
  924.             MaxRange.width = Math.max(TLs[i].x + TLs[i].width - MaxRange.x, MaxRange.width);
  925.             MaxRange.height = Math.max(TLs[i].y + Y_OFFSET + TLs[i].height - MaxRange.y, MaxRange.height);
  926.         }
  927.     }
  928.  
  929. }
  930.  
  931. // Scrollbar tools {{
  932. var scrollpos;
  933. var scrollmax;
  934. var ratio;
  935. var NeedScrollbar;
  936.  
  937. var slider_hover;
  938. var slider_y_rel;
  939. var slider_drag;
  940.  
  941. function SetSlider() {
  942.     if (sum_height < wh) {
  943.  
  944.         if (Y_OFFSET != 0) {
  945.             Y_OFFSET = 0;
  946.         }
  947.         NeedScrollbar = false;
  948.         return;
  949.     } else {
  950.         NeedScrollbar = true;
  951.         scrollmax = sum_height + tm - wh;
  952.         scrollpos = -1 * Y_OFFSET;
  953.  
  954.         ratio = wh / (sum_height + tm); // какая часть = страница от всего док.
  955.         if (ratio > 1) ratio = 1;
  956.  
  957.         Scrollbar.step = 1 / ratio;
  958.         Scrollbar.slider.height = Math.round(ratio * wh);
  959.         if (Scrollbar.slider.height < Scrollbar.min_height) {
  960.             Scrollbar.slider.height = Scrollbar.min_height;
  961.         }
  962.  
  963.         Scrollbar.slider.y = Math.round((wh - Scrollbar.slider.height) * scrollpos / scrollmax);
  964.         Scrollbar.slider.x = ww - 18;
  965.         Scrollbar.slider.width = 16;
  966.  
  967.         if (Y_OFFSET < -1 * (sum_height - wh + tm)) {
  968.             Y_OFFSET = -1 * (sum_height - wh + tm);
  969.         }
  970.     }
  971. }
  972.  
  973. function V_SCROLLBAR(width, min_h) {
  974.     this.width = width;
  975.     this.step = 0;
  976.     this.state = 0;
  977.     this.slider = {
  978.         x: 0,
  979.         y: 0,
  980.         width: 0,
  981.         height: 0,
  982.         min_height: min_h
  983.     }
  984.  
  985.     this.isXYok = function (x, y) {
  986.         return (x >= ww - 20 && y >= 0 && x <= ww && y <= wh) ? true : false;
  987.     }
  988.  
  989.     this.slider_isXYok = function (x, y) {
  990.         return (x >= this.slider.x && y >= this.slider.y && x <= this.slider.x + this.slider.width && y <= this.slider.y + this.slider.height) ? true : false;
  991.     }
  992.  
  993.     this.Draw = function (gr) {
  994.         if (NeedScrollbar) {
  995.             //bg
  996.             gr.DrawRect(ww - 20, 0, 19, wh - 1, 1, RGB(20, 20, 20));
  997.             gr.FillSolidRect(ww - 19, 1, 18, wh - 2, vs_bg_color);
  998.  
  999.             //slider
  1000.             gr.FillSolidRect(this.slider.x, this.slider.y, this.slider.width, this.slider.height, (slider_drag) ? vs_down_color : (slider_hover ? vs_hover_color : vs_normal_color));
  1001.             gr.DrawRect(this.slider.x, this.slider.y, this.slider.width - 1, this.slider.height - 1, 1, RGB(25, 25, 25));
  1002.  
  1003.         }
  1004.     }
  1005.  
  1006. }
  1007. // Scrollbar tools }}
  1008.  
  1009. //===================================================================================================================================================
  1010. //===================================================================================================================================================
  1011.  
  1012.  
  1013. function on_init() {
  1014.     Scrollbar = new V_SCROLLBAR(20, 45);
  1015.     WaitTimer = new c_WaitTimer();
  1016.     TLAnimationTimer = new c_ButtonAnimationTimer();
  1017.     update_option("lastfm_api_key", "179b25d95e633097ec682c58b4a993ec");
  1018.     reset_lastfm_data();
  1019.     //WaitTimer.Start();
  1020. }
  1021. on_init();
  1022.  
  1023.  
  1024. function on_size() {
  1025.     if (!window.Width || !window.Height) return;
  1026.     ww = window.Width;
  1027.     wh = window.Height;
  1028.  
  1029.     SetSlider();
  1030.     GetCoordinates();
  1031.     CursorFollow(Properties.Panel.CursorFollowMode);
  1032.     GenerateBG();
  1033. }
  1034.  
  1035. function on_paint(gr) {
  1036.     //don't draw if panel sizes are less than min values
  1037.     if (window.Width < 185 || window.Height < 100) {
  1038.         if (img_bg_bmp) gr.GdiDrawBitmap(img_bg_bmp, 0, 0, ww, wh, 0, 0, img_bg_bmp.width, img_bg_bmp.height);
  1039.         return;
  1040.     }
  1041.  
  1042.     sum_height = 0;
  1043.     gr.SetTextRenderingHint(5);
  1044.     // Draw background image.
  1045.     if (img_bg_bmp) gr.GdiDrawBitmap(img_bg_bmp, 0, 0, ww, wh, 0, 0, img_bg_bmp.width, img_bg_bmp.height);
  1046.  
  1047.  
  1048.     if (opt_username.length == 0 || opt_api_key.length != 32) {
  1049.         gr.GdiDrawText("Last.fm panel \n Please enter your username with context menu", font_normal, normal_color, 0, 0, ww, wh, DT_CENTER | DT_VCENTER | DT_CALCRECT | DT_NOPREFIX);
  1050.         return;
  1051.     }
  1052.     if (wait == 0) {
  1053.         //draw last.fm logo
  1054.         gr.FillSolidRect(0, tm + Y_OFFSET, ww, 30, RGBA(210, 19, 9, 255));
  1055.         gr.DrawImage(img_lastfm_logo_red, (ww - 100) / 2, tm + Y_OFFSET, 100, 30, 0, 0, 900, 269);
  1056.         //draw user avatar
  1057.         gr.DrawImage(img_avatar, lm, tm + 30 + tm + Y_OFFSET, ava_width, ava_height, 0, 0, img_avatar.width, img_avatar.height);
  1058.         sum_height += ava_height < 100 ? tm + 30 + tm + 100 : tm + 30 + tm + ava_height;
  1059.         gr.DrawRect(lm, tm + 30 + tm + Y_OFFSET, ava_width, ava_height, 2, normal_color);
  1060.         //draw username
  1061.         if (ww >= 175 + ava_width) {
  1062.             gr.GdiDrawText(username != "" ? username : opt_username, font_header, normal_color, lm + ava_width + 15, 45 + Y_OFFSET, ww, wh);
  1063.         } else {
  1064.             gr.GdiDrawText(username != "" ? username : opt_username, font_header, normal_color, lm, sum_height + 5 + Y_OFFSET, ww, wh);
  1065.             sum_height += font_header.height + 9;
  1066.         }
  1067.  
  1068.  
  1069.         // plays ========================================================================================================================================================================================
  1070.  
  1071.         for (i = 0; i <= 3; i++) {
  1072.             charcounter = 0;
  1073.             spcounter = 0;
  1074.  
  1075.             switch (i) {
  1076.             case 0:
  1077.                 txt_plays = " plays";
  1078.                 break;
  1079.             case 1:
  1080.                 txt_plays = " per day";
  1081.                 break;
  1082.             case 2:
  1083.                 txt_plays = " per week";
  1084.                 break;
  1085.             case 3:
  1086.                 txt_plays = " per month";
  1087.                 break;
  1088.             }
  1089.  
  1090.             if (longeststr.length < lastfm_data[0][i].length) longeststr = lastfm_data[0][i];
  1091.  
  1092.             if (ww >= 175 + ava_width) {
  1093.                 for (j = 0; j < lastfm_data[0][i].length; j++) {
  1094.                     if (lastfm_data[0][i].substring((j), j + 1) != " ") {
  1095.                         gr.DrawImage(img_lastfm_flip, lm + ava_width + 15 + charcounter * 11 + spcounter * 5, 70 + (i * 15) + Y_OFFSET, img_lastfm_flip.width, img_lastfm_flip.height, 0, 0, img_lastfm_flip.width, img_lastfm_flip.height);
  1096.                         charcounter++;
  1097.                     } else {
  1098.                         spcounter++;
  1099.                     }
  1100.                     gr.GdiDrawText(lastfm_data[0][i].substring((j), j + 1), font_num, RGB(255, 255, 255), lm + ava_width + 17 + (charcounter - 1) * 11 + spcounter * 5, 69 + (i * 15) + Y_OFFSET, ww, wh, DT_TOP | DT_LEFT);
  1101.                 }
  1102.                 gr.GdiDrawText(txt_plays, font_num, normal_color, lm + ava_width + 15 + charcounter * 11 + spcounter * 5 + 3, 69 + (i * 15) + Y_OFFSET, ww, wh, DT_TOP | DT_LEFT);
  1103.             } else {
  1104.                 for (j = 0; j < lastfm_data[0][i].length; j++) {
  1105.                     if (lastfm_data[0][i].substring((j), j + 1) != " ") {
  1106.                         gr.DrawImage(img_lastfm_flip, lm + charcounter * 11 + spcounter * 5, sum_height + Y_OFFSET, img_lastfm_flip.width, img_lastfm_flip.height, 0, 0, img_lastfm_flip.width, img_lastfm_flip.height);
  1107.                         charcounter++;
  1108.                     } else {
  1109.                         spcounter++;
  1110.                     }
  1111.                     gr.GdiDrawText(lastfm_data[0][i].substring((j), j + 1), font_num, RGB(255, 255, 255), lm + 2 + (charcounter - 1) * 11 + spcounter * 5, sum_height - 1 + Y_OFFSET, ww, wh, DT_TOP | DT_LEFT);
  1112.                 }
  1113.                 gr.GdiDrawText(txt_plays, font_num, normal_color, lm + charcounter * 11 + spcounter * 5 + 3, sum_height - 1 + Y_OFFSET, ww, wh, DT_TOP | DT_LEFT);
  1114.                 sum_height += img_lastfm_flip.height + 3;
  1115.             }
  1116.  
  1117.         }
  1118.  
  1119.  
  1120.         //========================================================================================================================================================================================
  1121.         gr.GdiDrawText("Current track", font_header, normal_color, lm, sum_height + 6 + Y_OFFSET, ww, wh);
  1122.         // artist - album - track ========================================================================================================================================================================================
  1123.  
  1124.         if (lastfm_data[3][3] == "1") { //userloved
  1125.             TLs[13].x = 105;
  1126.             TLs[13].y = sum_height + 6;
  1127.  
  1128.             TLs[13].Draw = function (gr) {
  1129.                 gr.GdiDrawText(TLs[13].label, font_gui, normal_color, TLs[13].x, TLs[13].y + Y_OFFSET, TLs[13].width, TLs[13].height);
  1130.             }
  1131.             TLs[13].Draw(gr);
  1132.         } else {
  1133.             TLs[13].x = ww + 10;
  1134.         }
  1135.  
  1136.         sum_height += font_header.height + 17;
  1137.  
  1138.  
  1139.         for (i = 0; i < 3; i++) {
  1140.             TLs[i].y = sum_height;
  1141.  
  1142.             if (TLs[i].NeedReset) {
  1143.                 if (CorrectedData[i + 1] != "~no data") {
  1144.                     text_Ws[i] = Math.ceil(gr.MeasureString(CorrectedData[i + 1] == np[i] ? np[i] : CorrectedData[i + 1] + " [*]", font_normal, 0, 0, ww - 50 - lm - rm - 20, wh, LineStrFmt).Width);
  1145.                     text_Hs[i] = Math.ceil(gr.MeasureString(CorrectedData[i + 1] == np[i] ? np[i] : CorrectedData[i + 1] + " [*]", font_normal, 0, 0, ww - 50 - lm - rm - 20, wh, LineStrFmt).Height);
  1146.  
  1147.                     switch (i) {
  1148.                     case 0:
  1149.                         TLs[i].OnClick = function () {
  1150.                             WshShell.run("http://www.last.fm/music/" + encodeURIComponent(CorrectedData[1]))
  1151.                         };
  1152.                         break;
  1153.                     case 1:
  1154.                         TLs[i].OnClick = function () {
  1155.                             WshShell.run("http://www.last.fm/music/" + encodeURIComponent(CorrectedData[1]) + "/" + encodeURIComponent(CorrectedData[2]))
  1156.                         };
  1157.                         break;
  1158.                     case 2:
  1159.                         TLs[i].OnClick = function () {
  1160.                             WshShell.run("http://www.last.fm/music/" + encodeURIComponent(CorrectedData[1]) + "/" + encodeURIComponent(CorrectedData[2]) + "/" + encodeURIComponent(CorrectedData[3]))
  1161.                         };
  1162.                         break;
  1163.                     }
  1164.  
  1165.                     TLs[i].x = 50 + lm;
  1166.                     TLs[i].width = text_Ws[i] + 8;
  1167.                     TLs[i].height = text_Hs[i];
  1168.                     TLs[i].label = CorrectedData[i + 1] == np[i] ? np[i] : CorrectedData[i + 1] + " [*]";
  1169.                     TLs[i].tiptext = CorrectedData[i + 1] == np[i] ? "" : "Auto-corrected from: " + "'" + np[i] + "'";
  1170.                     TLs[i].NeedReset = false;
  1171.                 } else {
  1172.                     text_Ws[i] = Math.ceil(gr.MeasureString(np[i], font_normal, 0, 0, ww - 50 - lm - rm - 20, wh, LineStrFmt).Width);
  1173.                     text_Hs[i] = Math.ceil(gr.MeasureString(np[i], font_normal, 0, 0, ww - 50 - lm - rm - 20, wh, LineStrFmt).Height);
  1174.  
  1175.                     switch (i) {
  1176.                     case 0:
  1177.                         TLs[i].OnClick = function () {
  1178.                             WshShell.run("http://www.last.fm/music/" + encodeURIComponent(np[0]))
  1179.                         };
  1180.                         break;
  1181.                     case 1:
  1182.                         TLs[i].OnClick = function () {
  1183.                             WshShell.run("http://www.last.fm/music/" + encodeURIComponent(np[0]) + "/" + encodeURIComponent(np[1]))
  1184.                         };
  1185.                         break;
  1186.                     case 2:
  1187.                         TLs[i].OnClick = function () {
  1188.                             WshShell.run("http://www.last.fm/music/" + encodeURIComponent(np[0]) + "/" + encodeURIComponent(np[1]) + "/" + encodeURIComponent(np[2]))
  1189.                         };
  1190.                         break;
  1191.                     }
  1192.  
  1193.                     TLs[i].x = 50 + lm;
  1194.                     TLs[i].width = text_Ws[i] + 8;
  1195.                     TLs[i].height = text_Hs[i];
  1196.                     TLs[i].label = np[i];
  1197.                     TLs[i].tiptext = "";
  1198.                     TLs[i].NeedReset = false;
  1199.                 }
  1200.  
  1201.  
  1202.             }
  1203.             if (TLs[i].label != "?") TLs[i].Draw(TLs[i].x, TLs[i].y, gr);
  1204.             else {
  1205.                 TLs[i].show = false;
  1206.                 gr.DrawString("No data", font_normal, normal_color, TLs[i].x + 4, TLs[i].y + Y_OFFSET, ww, TLs[i].height, LineStrFmt);
  1207.             }
  1208.  
  1209.             switch (i) {
  1210.             case 0:
  1211.                 txt_t = "Artist:";
  1212.                 break;
  1213.             case 1:
  1214.                 txt_t = "Album:";
  1215.                 break;
  1216.             case 2:
  1217.                 txt_t = "Track:";
  1218.                 break;
  1219.             }
  1220.             gr.GdiDrawText(txt_t, font_label, normal_color, lm, sum_height + 2 + Y_OFFSET, 50, wh);
  1221.             sum_height += text_Hs[i] + 3;
  1222.         }
  1223.  
  1224.         sum_height += 3;
  1225.  
  1226.         // tags ========================================================================================================================================================================================
  1227.  
  1228.         gr.GdiDrawText("Artist", font_label, normal_color, lm, sum_height + 2 + Y_OFFSET, 50, wh);
  1229.         gr.GdiDrawText("tags:", font_label, normal_color, lm, sum_height + 2 + font_label.height + Y_OFFSET, 50, wh);
  1230.         linecounter = 1;
  1231.  
  1232.         if (lastfm_data[1][3][0] != "no data") {
  1233.             for (i = 0; i < 5; i++) {
  1234.                 text_Ws[i + 3] = Math.ceil(gr.MeasureString(lastfm_data[1][3][i], font_normal, 0, 0, ww - 50 - lm - rm - 20, wh, LineStrFmt).Width);
  1235.                 text_Hs[i + 3] = Math.ceil(gr.MeasureString(lastfm_data[1][3][i], font_normal, 0, 0, ww - 50 - lm - rm - 20, wh, LineStrFmt).Height);
  1236.  
  1237.  
  1238.                 TLs[i + 3].x = i == 0 ? 50 + lm : (TLs[i + 2].x + text_Ws[i + 2] + 8 + text_Ws[i + 3] + 8 + 1 < ww - rm - 20 ? TLs[i + 2].x + text_Ws[i + 2] + 11 : 50 + lm);
  1239.                 TLs[i + 3].y = i == 0 ? sum_height : (TLs[i + 2].x + text_Ws[i + 2] + 8 + text_Ws[i + 3] + 8 + 1 < ww - rm - 20 ? TLs[i + 2].y : sum_height + font_normal.height + 3);
  1240.                 linecounter += (TLs[i + 2].x + text_Ws[i + 2] + 8 + text_Ws[i + 3] + 8 + 1 < ww - rm - 20) || i == 0 ? 0 : 1;
  1241.  
  1242.  
  1243.                 if (TLs[i + 3].NeedReset) {
  1244.                     switch (i) {
  1245.                     case 0:
  1246.                         TLs[i + 3].OnClick = function () {
  1247.                             WshShell.run("http://www.last.fm/tag/" + encodeURIComponent(lastfm_data[1][3][0]))
  1248.                         };
  1249.                         break;
  1250.                     case 1:
  1251.                         TLs[i + 3].OnClick = function () {
  1252.                             WshShell.run("http://www.last.fm/tag/" + encodeURIComponent(lastfm_data[1][3][1]))
  1253.                         };
  1254.                         break;
  1255.                     case 2:
  1256.                         TLs[i + 3].OnClick = function () {
  1257.                             WshShell.run("http://www.last.fm/tag/" + encodeURIComponent(lastfm_data[1][3][2]))
  1258.                         };
  1259.                         break;
  1260.                     case 3:
  1261.                         TLs[i + 3].OnClick = function () {
  1262.                             WshShell.run("http://www.last.fm/tag/" + encodeURIComponent(lastfm_data[1][3][3]))
  1263.                         };
  1264.                         break;
  1265.                     case 4:
  1266.                         TLs[i + 3].OnClick = function () {
  1267.                             WshShell.run("http://www.last.fm/tag/" + encodeURIComponent(lastfm_data[1][3][4]))
  1268.                         };
  1269.                         break;
  1270.                     }
  1271.  
  1272.  
  1273.                     TLs[i + 3].width = text_Ws[i + 3] + 8;
  1274.                     TLs[i + 3].height = text_Hs[i + 3];
  1275.                     TLs[i + 3].label = lastfm_data[1][3][i];
  1276.                     TLs[i + 3].tiptext = "";
  1277.                     TLs[i + 3].NeedReset = false;
  1278.  
  1279.                 }
  1280.                 TLs[i + 3].Draw(0, 0, gr);
  1281.  
  1282.                 if (i == 0) sum_height += gr.MeasureString(lastfm_data[1][3][i], font_normal, 0, 0, ww - 50 - lm - rm - 20, wh, LineStrFmt).lines > 1 ? text_Hs[i + 3] - font_normal.height : 0;
  1283.                 else sum_height += (TLs[i + 2].x + text_Ws[i + 2] + 8 + text_Ws[i + 3] + 8 + 1 < ww - rm - 20) ? 0 : text_Hs[i + 3] + 3;
  1284.             }
  1285.         } else {
  1286.             for (i = 0; i < 5; i++) {
  1287.                 TLs[i + 3].show = false;
  1288.             }
  1289.             gr.GdiDrawText("Tags did not recieved", font_normal, normal_color, lm + 50, sum_height + 2 + Y_OFFSET, ww, wh);
  1290.         }
  1291.  
  1292.         sum_height += linecounter == 1 ? font_normal.height * 2 + 6 : font_normal.height + 6;
  1293.         // similar ========================================================================================================================================================================================
  1294.  
  1295.         gr.GdiDrawText("Similar", font_label, normal_color, lm, sum_height + 2 + Y_OFFSET, 50, wh);
  1296.         gr.GdiDrawText("artists:", font_label, normal_color, lm, sum_height + 2 + font_label.height + Y_OFFSET, 50, wh);
  1297.         linecounter = 1;
  1298.  
  1299.         if (lastfm_data[1][4][0] != "no data") {
  1300.             for (i = 0; i < 5; i++) {
  1301.                 text_Ws[i + 8] = Math.ceil(gr.MeasureString(lastfm_data[1][4][i], font_normal, 0, 0, ww - 50 - lm - rm - 20, wh, LineStrFmt).Width);
  1302.                 text_Hs[i + 8] = Math.ceil(gr.MeasureString(lastfm_data[1][4][i], font_normal, 0, 0, ww - 50 - lm - rm - 20, wh, LineStrFmt).Height);
  1303.  
  1304.  
  1305.                 TLs[i + 8].x = i == 0 ? 50 + lm : (TLs[i + 7].x + text_Ws[i + 7] + 8 + text_Ws[i + 8] + 8 + 1 < ww - rm - 20 ? TLs[i + 7].x + text_Ws[i + 7] + 11 : 50 + lm);
  1306.                 TLs[i + 8].y = i == 0 ? sum_height : (TLs[i + 7].x + text_Ws[i + 7] + 8 + text_Ws[i + 8] + 8 + 1 < ww - rm - 20 ? TLs[i + 7].y : sum_height + font_normal.height + 3);
  1307.                 linecounter += (TLs[i + 7].x + text_Ws[i + 7] + 8 + text_Ws[i + 8] + 8 + 1 < ww - rm - 20) || i == 0 ? 0 : 1;
  1308.  
  1309.                 if (TLs[i + 8].NeedReset) {
  1310.                     switch (i) {
  1311.                     case 0:
  1312.                         TLs[i + 8].OnClick = function () {
  1313.                             WshShell.run("http://www.last.fm/music/" + encodeURIComponent(lastfm_data[1][4][0]))
  1314.                         };
  1315.                         break;
  1316.                     case 1:
  1317.                         TLs[i + 8].OnClick = function () {
  1318.                             WshShell.run("http://www.last.fm/music/" + encodeURIComponent(lastfm_data[1][4][1]))
  1319.                         };
  1320.                         break;
  1321.                     case 2:
  1322.                         TLs[i + 8].OnClick = function () {
  1323.                             WshShell.run("http://www.last.fm/music/" + encodeURIComponent(lastfm_data[1][4][2]))
  1324.                         };
  1325.                         break;
  1326.                     case 3:
  1327.                         TLs[i + 8].OnClick = function () {
  1328.                             WshShell.run("http://www.last.fm/music/" + encodeURIComponent(lastfm_data[1][4][3]))
  1329.                         };
  1330.                         break;
  1331.                     case 4:
  1332.                         TLs[i + 8].OnClick = function () {
  1333.                             WshShell.run("http://www.last.fm/music/" + encodeURIComponent(lastfm_data[1][4][4]))
  1334.                         };
  1335.                         break;
  1336.                     }
  1337.  
  1338.  
  1339.                     TLs[i + 8].width = text_Ws[i + 8] + 8;
  1340.                     TLs[i + 8].height = text_Hs[i + 8];
  1341.                     TLs[i + 8].label = lastfm_data[1][4][i];
  1342.                     TLs[i + 8].tiptext = "";
  1343.                     TLs[i + 8].NeedReset = false;
  1344.  
  1345.                 }
  1346.                 TLs[i + 8].Draw(0, 0, gr);
  1347.  
  1348.                 if (i == 0) sum_height += gr.MeasureString(lastfm_data[1][4][i], font_normal, 0, 0, ww - 50 - lm - rm - 20, wh, LineStrFmt).lines > 1 ? text_Hs[i + 8] - font_normal.height : 0;
  1349.                 else sum_height += (TLs[i + 7].x + text_Ws[i + 7] + 8 + text_Ws[i + 8] + 8 + 1 < ww - rm - 20) ? 0 : text_Hs[i + 8] + 3;
  1350.             }
  1351.         } else {
  1352.             for (i = 0; i < 5; i++) {
  1353.                 TLs[i + 8].show = false;
  1354.             }
  1355.             gr.GdiDrawText("Artists did not recieved", font_normal, normal_color, lm + 50, sum_height + 2 + Y_OFFSET, ww, wh);
  1356.         }
  1357.  
  1358.         sum_height += linecounter == 1 ? font_normal.height * 2 + 2 : font_normal.height + 2;
  1359.         GetCoordinates(); //run this when all buttons are resetted
  1360.  
  1361.         // listeners ========================================================================================================================================================================================
  1362.         gr.GdiDrawText("Listeners", font_header, normal_color, lm, sum_height + Y_OFFSET, ww, wh);
  1363.         sum_height += font_header.height + 5;
  1364.  
  1365.         for (id = 1; id <= 3; id++) {
  1366.             charcounter = 0;
  1367.             spcounter = 0;
  1368.  
  1369.             for (j = 0; j < lastfm_data[id][2].length; j++) {
  1370.                 if (lastfm_data[id][2].substring((j), j + 1) != " ") {
  1371.                     gr.DrawImage(img_lastfm_flip, lm + 50 + charcounter * 11 + spcounter * 5, sum_height + Y_OFFSET, img_lastfm_flip.width, img_lastfm_flip.height, 0, 0, img_lastfm_flip.width, img_lastfm_flip.height);
  1372.                     charcounter++;
  1373.                 } else {
  1374.                     spcounter++;
  1375.                 }
  1376.                 gr.GdiDrawText(lastfm_data[id][2].substring((j), j + 1), font_num, RGB(255, 255, 255), lm + (charcounter - 1) * 11 + spcounter * 5 + 2 + 50, sum_height - 1 + Y_OFFSET, ww, wh);
  1377.             }
  1378.  
  1379.             switch (id) {
  1380.             case 1:
  1381.                 txt_t = "Artist:";
  1382.                 break;
  1383.             case 2:
  1384.                 txt_t = "Album:";
  1385.                 break;
  1386.             case 3:
  1387.                 txt_t = "Track:";
  1388.                 break;
  1389.             }
  1390.             gr.GdiDrawText(txt_t, font_label, normal_color, lm, sum_height - 1 + Y_OFFSET, ww, wh);
  1391.             sum_height += 18;
  1392.         }
  1393.  
  1394.  
  1395.         // plays ========================================================================================================================================================================================
  1396.         gr.GdiDrawText("Plays", font_header, normal_color, lm, sum_height + Y_OFFSET, ww, wh);
  1397.         sum_height += font_header.height + 5;
  1398.  
  1399.         for (id = 1; id <= 3; id++) {
  1400.             charcounter = 0;
  1401.             spcounter = 0;
  1402.             for (j = 0; j < lastfm_data[id][0].length; j++) {
  1403.                 if (lastfm_data[id][0].substring((j), j + 1) != " ") {
  1404.                     gr.DrawImage(img_lastfm_flip, lm + 50 + charcounter * 11 + spcounter * 5, sum_height + Y_OFFSET, img_lastfm_flip.width, img_lastfm_flip.height, 0, 0, img_lastfm_flip.width, img_lastfm_flip.height);
  1405.                     charcounter++;
  1406.                 } else {
  1407.                     spcounter++;
  1408.                 }
  1409.                 gr.GdiDrawText(lastfm_data[id][0].substring((j), j + 1), font_num, RGB(255, 255, 255), lm + (charcounter - 1) * 11 + spcounter * 5 + 2 + 50, sum_height - 1 + Y_OFFSET, ww, wh);
  1410.             }
  1411.  
  1412.             switch (id) {
  1413.             case 1:
  1414.                 txt_tt = "Artist:";
  1415.                 break;
  1416.             case 2:
  1417.                 txt_tt = "Album:";
  1418.                 break;
  1419.             case 3:
  1420.                 txt_tt = "Track:";
  1421.                 break;
  1422.             }
  1423.  
  1424.             gr.GdiDrawText(txt_tt, font_label, normal_color, lm, sum_height - 1 + Y_OFFSET, ww, wh);
  1425.             sum_height += 18;
  1426.         }
  1427.  
  1428.         // by user ========================================================================================================================================================================================
  1429.         gr.GdiDrawText(username != "" ? "Plays by " + username : "Plays by " + opt_username, font_header, normal_color, lm, sum_height + Y_OFFSET, ww, wh);
  1430.  
  1431.         sum_height += font_header.height + 5;
  1432.  
  1433.         for (id = 1; id <= 3; id++) {
  1434.             charcounter = 0;
  1435.             spcounter = 0;
  1436.             for (j = 0; j < lastfm_data[id][1].length; j++) {
  1437.                 if (lastfm_data[id][1].substring((j), j + 1) != " ") {
  1438.                     gr.DrawImage(img_lastfm_flip, lm + 50 + charcounter * 11 + spcounter * 5, sum_height + Y_OFFSET, img_lastfm_flip.width, img_lastfm_flip.height, 0, 0, img_lastfm_flip.width, img_lastfm_flip.height);
  1439.                     charcounter++;
  1440.                 } else {
  1441.                     spcounter++;
  1442.                 }
  1443.                 gr.GdiDrawText(lastfm_data[id][1].substring((j), j + 1), font_num, RGB(255, 255, 255), lm + (charcounter - 1) * 11 + spcounter * 5 + 2 + 50, sum_height - 1 + Y_OFFSET, ww, wh);
  1444.             }
  1445.  
  1446.             switch (id) {
  1447.             case 1:
  1448.                 txt_tt = "Artist:";
  1449.                 break;
  1450.             case 2:
  1451.                 txt_tt = "Album:";
  1452.                 break;
  1453.             case 3:
  1454.                 txt_tt = "Track:";
  1455.                 break;
  1456.             }
  1457.  
  1458.             gr.GdiDrawText(txt_tt, font_label, normal_color, lm, sum_height - 1 + Y_OFFSET, ww, wh);
  1459.             sum_height += 18;
  1460.         }
  1461.  
  1462.     } else if (wait == 1) {
  1463.         gr.GdiDrawText("Grabbing last.fm data.\n Hold on!", font_normal, normal_color, 0, 0, ww, wh, DT_CENTER | DT_VCENTER | DT_CALCRECT | DT_NOPREFIX);
  1464.         return;
  1465.     } else if (wait == -1) {
  1466.         gr.GdiDrawText("Artist: " + np[0] + "\n Album: " + np[1] + "\n Track: " + np[2] + "\n \n Something went wrong :( \n Data did not recieved.", font_normal, normal_color, 0, 0, ww, wh, DT_CENTER | DT_VCENTER | DT_CALCRECT | DT_NOPREFIX);
  1467.     } else if (wait == -2) {
  1468.         gr.GdiDrawText("No track specified", font_normal, normal_color, 0, 0, ww, wh, DT_CENTER | DT_VCENTER | DT_CALCRECT | DT_NOPREFIX);
  1469.     }
  1470.  
  1471.     //draw vscrollbar
  1472.     SetSlider();
  1473.     Scrollbar.Draw(gr);
  1474. }
  1475.  
  1476. function on_playback_new_track() {
  1477.     if (Properties.Panel.CursorFollowMode == CursorFollowMode.OnlyStopped) {
  1478.         if (fb.IsPlaying && fb.PlaybackLength == -1) {
  1479.             np = [fb.TitleFormat("%artist%").Eval(), fb.TitleFormat("%album%").Eval(), fb.TitleFormat("%title%").Eval()]
  1480.         } else {
  1481.             MetaDB = fb.GetNowPlaying();
  1482.             FOCUSFLAG = false;
  1483.             np = [fb.TitleFormat("%artist%").EvalWithMetadb(MetaDB), fb.TitleFormat("%album%").EvalWithMetadb(MetaDB), fb.TitleFormat("%title%").EvalWithMetadb(MetaDB)]
  1484.         }
  1485.         WaitTimer.Stop();
  1486.  
  1487.         if (np[0] == "?" && np[1] == "?") {
  1488.             wait = -2;
  1489.             window.Repaint();
  1490.             return;
  1491.         }
  1492.         lastfm_status = 0;
  1493.         wait = 1;
  1494.         window.Repaint();
  1495.         get_lastfm_data();
  1496.     }
  1497. }
  1498.  
  1499. function on_playback_dynamic_info_track() {
  1500.     if (fb.PlaybackLength == -1) {
  1501.         FOCUSFLAG = false;
  1502.         np = [fb.TitleFormat("%artist%").Eval(), fb.TitleFormat("%album%").Eval(), fb.TitleFormat("%title%").Eval()]
  1503.         if (np[0] == "?" && np[1] == "?") {
  1504.             wait = -2;
  1505.             window.Repaint();
  1506.             return;
  1507.         }
  1508.         lastfm_status = 0;
  1509.         wait = 1;
  1510.         window.Repaint();
  1511.         get_lastfm_data();
  1512.     }
  1513. }
  1514.  
  1515.  
  1516. function on_item_focus_change() {
  1517.     if (Properties.Panel.CursorFollowMode == CursorFollowMode.Always || (Properties.Panel.CursorFollowMode == CursorFollowMode.OnlyStopped && !fb.IsPlaying && !fb.IsPaused)) {
  1518.         WaitTimer.Stop();
  1519.         WaitTimer.Start();
  1520.     }
  1521. }
  1522.  
  1523. function on_playback_stop(reason) {
  1524.     if (!reason || reason == 1) {
  1525.         if (Properties.Panel.CursorFollowMode == CursorFollowMode.OnlyStopped && !FOCUSFLAG) {
  1526.             WaitTimer.Stop();
  1527.             WaitTimer.Start();
  1528.         }
  1529.     }
  1530. }
  1531.  
  1532. function on_mouse_move(x, y) {
  1533.     if (window.Width < 185 || window.Height < 100) return;
  1534.     if (wait != 0) return;
  1535.  
  1536.     if (slider_drag) {
  1537.         Scrollbar.slider.y = Math.min(Math.max(y - slider_y_rel, 0), wh - Scrollbar.slider.height);
  1538.         Y_OFFSET = Math.round(Math.min(Math.max(-1 * Scrollbar.step * Scrollbar.slider.y, -1 * scrollmax), 0));
  1539.         window.Repaint();
  1540.     } else {
  1541.         if (Scrollbar.slider_isXYok(x, y)) {
  1542.             if (!slider_hover && !d_link) slider_hover = true;
  1543.             window.RepaintRect(ww - 20, 0, ww, wh);
  1544.         } else if (slider_hover) {
  1545.             slider_hover = false;
  1546.             window.RepaintRect(ww - 20, 0, ww, wh);
  1547.         }
  1548.     }
  1549.  
  1550.     if (d_link) {
  1551.         if (d_link.isXYok(x, y)) {
  1552.             if (d_link.state != 2) d_link.ChangeState(2);
  1553.         } else if (d_link.state != 1) d_link.ChangeState(1);
  1554.     } else {
  1555.         for (var i = 0; i < TLs.length; i++)
  1556.             if (TLs[i].isXYok(x, y) && TLs[i].show) {
  1557.                 if (h_link != TLs[i]) {
  1558.                     if (h_link) h_link.ChangeState(0);
  1559.                     h_link = TLs[i];
  1560.                     if (h_link != TLs[13]) window.SetCursor(IDC_HAND);
  1561.                     h_link.ChangeState(1);
  1562.                 }
  1563.                 break;
  1564.             }
  1565.         if (i == TLs.length) {
  1566.  
  1567.             if (h_link) {
  1568.                 if (h_link) h_link.ChangeState(0);
  1569.                 h_link = undefined;
  1570.                 window.SetCursor(IDC_ARROW);
  1571.             }
  1572.         }
  1573.     }
  1574.  
  1575. }
  1576.  
  1577. function on_mouse_lbtn_down(x, y) {
  1578.     if (window.Width < 185 || window.Height < 100) return;
  1579.     if (h_link && !d_link) {
  1580.         d_link = h_link;
  1581.         d_link.ChangeState(2);
  1582.     }
  1583.  
  1584.     if (NeedScrollbar) {
  1585.         if (slider_hover && !slider_drag && !d_link) {
  1586.             slider_drag = true;
  1587.             slider_y_rel = y - Scrollbar.slider.y;
  1588.         } else if (!slider_hover && !slider_drag && !d_link && Scrollbar.isXYok(x, y)) {
  1589.             slider_drag = true;
  1590.             slider_y_rel = Scrollbar.slider.height / 2;
  1591.             on_mouse_move(x, y);
  1592.         }
  1593.     }
  1594.  
  1595. }
  1596.  
  1597. function on_mouse_lbtn_up(x, y) {
  1598.     if (window.Width < 185 || window.Height < 100) return;
  1599.     if (d_link) {
  1600.         if (d_link.state == 2) {
  1601.             d_link.OnClick();
  1602.         }
  1603.         d_link = undefined;
  1604.         on_mouse_move(x, y);
  1605.     }
  1606.  
  1607.     if (slider_drag) {
  1608.         slider_drag = false;
  1609.     }
  1610. }
  1611.  
  1612. function on_mouse_leave() {
  1613.     if (window.Width < 185 || window.Height < 100) return;
  1614.     if (h_link) {
  1615.         h_link.ChangeState(0);
  1616.         h_link = undefined;
  1617.         window.SetCursor(IDC_ARROW);
  1618.     }
  1619.     Tooltip.Text = "";
  1620.  
  1621.     if (slider_hover) {
  1622.         slider_hover = false;
  1623.         window.RepaintRect(ww - 20, 0, ww, wh);
  1624.     }
  1625. }
  1626.  
  1627. function on_mouse_wheel(delta) {
  1628.     if (window.Width < 185 || window.Height < 100) return;
  1629.     if (NeedScrollbar && !d_link && !slider_drag) {
  1630.         Y_OFFSET = Math.min(Math.max(Y_OFFSET + delta * 35, -1 * scrollmax), 0);
  1631.         on_mouse_move();
  1632.         window.Repaint();
  1633.     }
  1634. }
  1635.  
  1636. function on_mouse_rbtn_down(x, y, vkey) {
  1637.     rbtnDown = true;
  1638. }
  1639.  
  1640. function on_mouse_rbtn_up(x, y, vkey) {
  1641.     if (window.Width < 185 || window.Height < 100) return false;
  1642.     if (rbtnDown) {
  1643.         rbtnDown = false;
  1644.         if (vkey == MK_SHIFT) {
  1645.             return false; // if shift button pressed, show default context menu.
  1646.         } else {
  1647.             show_context_menu(x, y);
  1648.             return true;
  1649.         }
  1650.     }
  1651. }
  1652.  
  1653. function on_playlist_items_removed(playlist, new_count) {
  1654.     on_playlists_changed();
  1655. }
  1656.  
  1657. function on_playlist_switch() {
  1658.     on_playlists_changed();
  1659. }
  1660.  
  1661. function on_playlists_changed() {
  1662.     on_item_focus_change();
  1663. }
  1664.  
  1665. //EOF
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement