Advertisement
soKindly

lastfm panel hotfix2

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