Advertisement
Guest User

WSH Simple Playlist Viewer

a guest
Oct 8th, 2011
313
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==PREPROCESSOR==
  2. // @name "WSH Simple Playlist Viewer"
  3. // @version "0.6.1"
  4. // @author "Br3tt"
  5. // @feature "dragdrop"
  6. // ==/PREPROCESSOR==
  7.  
  8. //=================================================// Constants
  9. var DT_LEFT = 0x00000000;
  10. var DT_RIGHT = 0x00000002;
  11. var DT_TOP = 0x00000000;
  12. var DT_CENTER = 0x00000001;
  13. var DT_VCENTER = 0x00000004;
  14. var DT_WORDBREAK = 0x00000010;
  15. var DT_SINGLELINE = 0x00000020;
  16. var DT_CALCRECT = 0x00000400;
  17. var DT_NOPREFIX = 0x00000800;
  18. var DT_EDITCONTROL = 0x00002000;
  19. var DT_END_ELLIPSIS = 0x00008000;
  20.  
  21. var VK_BACK = 0x08;
  22. var VK_RETURN = 0x0D;
  23. var VK_SHIFT = 0x10;
  24. var VK_CONTROL = 0x11;
  25. var VK_ALT = 0x12;
  26. var VK_ESCAPE = 0x1B;
  27. var VK_PGUP = 0x21;
  28. var VK_PGDN = 0x22;
  29. var VK_END = 0x23;
  30. var VK_HOME = 0x24;
  31. var VK_LEFT = 0x25;
  32. var VK_UP = 0x26;
  33. var VK_RIGHT = 0x27;
  34. var VK_DOWN = 0x28;
  35. var VK_INSERT = 0x2D;
  36. var VK_DELETE = 0x2E;
  37. var KMask = {
  38.     none: 0,
  39.     ctrl: 1,
  40.     shift: 2,
  41.     ctrlshift: 3,
  42.     ctrlalt: 4,
  43.     ctrlaltshift: 5
  44. }
  45.  
  46. //=================================================// Globals
  47. var myitem = Array();
  48. var myscreen = Array();
  49. var myscrollbarbt = Array();
  50. var mytoolbarbt = Array();
  51. var ttt;
  52. var g_metadb;
  53. var g_metadb_playlist;
  54. var g_is_focused;
  55. var g_start_new_track = false;
  56. var ww, wh;
  57. var mouse_x;
  58. var mouse_y;
  59. var refresh_timer;
  60. var scroller_drag_timer;
  61. var draw_cover_timer;
  62. var init_mouse_down_timer;
  63. var mouse_down_timer;
  64. var wheel_up_timer;
  65. var wheel_dn_timer;
  66. var wheel_up_timer;
  67. var wheel_dn_timer;
  68. var cover_w = 45;
  69. var cover_h = 45;
  70. var cover_margin = 5;
  71. var g_playtime_parity = 0;
  72. var foo_playcount = utils.CheckComponent("foo_playcount", true);
  73.  
  74. // rating globals
  75. var rating_x = 0;
  76. var rating_y = 0;
  77. var rating_w, rating_h;
  78. var hand;
  79.  
  80. //=================================================// Image declarations
  81. var playicon_off;
  82. var scroller;
  83. var scroller_popup;
  84. var nocover;
  85. var streamcover;
  86. var star_img_off;
  87. var star_img_on;
  88. var star_img_hov;
  89. var star_img_kill;
  90. var scrollbarbt_menu;
  91. var scrollbarbt_up;
  92. var scrollbarbt_down;
  93. var mytoolbarbt_shownowplaying;
  94. var mytoolbarbt_scrollbar;
  95.  
  96. //=================================================// Tools
  97. function RGB(r, g, b) {
  98.     return (0xff000000 | (r << 16) | (g << 8) | (b))
  99. }
  100.  
  101. function RGBA(r, g, b, a) {
  102.     return ((a << 24) | (r << 16) | (g << 8) | (b))
  103. }
  104.  
  105. function GetKeyboardMask() {
  106.     var c = utils.IsKeyPressed(VK_CONTROL) ? true : false;
  107.     var a = utils.IsKeyPressed(VK_ALT) ? true : false;
  108.     var s = utils.IsKeyPressed(VK_SHIFT) ? true : false;
  109.     var ret = KMask.none;
  110.     if (c && !a && !s) ret = KMask.ctrl;
  111.     if (!c && !a && s) ret = KMask.shift;
  112.     if (c && !a && s) ret = KMask.ctrlshift;
  113.     if (c && a && !s) ret = KMask.ctrlalt;
  114.     if (c && a && s) ret = KMask.ctrlaltshift;
  115.     return ret;
  116. }
  117.  
  118. function num(strg, nb) {
  119.     var i;
  120.     var str = strg.toString();
  121.     var k = nb - str.length;
  122.     if (k > 0) {
  123.         for (i=0;i<k;i++) {
  124.             str = "0" + str;
  125.         }
  126.     }
  127.     return str.toString();
  128. }
  129.  
  130. function StringFormat() {
  131.     var h_align = 0,
  132.     v_align = 0,
  133.     trimming = 0,
  134.     flags = 0;
  135.     switch (arguments.length) {
  136.         case 3:
  137.         trimming = arguments[2];
  138.         case 2:
  139.         v_align = arguments[1];
  140.         case 1:
  141.         h_align = arguments[0];
  142.         break;
  143.         default:
  144.         return 0;
  145.     }
  146.     return ((h_align << 28) | (v_align << 24) | (trimming << 20) | flags);
  147. }
  148. var StringAlignment = {
  149.     Near: 0,
  150.     Centre: 1,
  151.     Far: 2
  152. };
  153. var lt_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Near);
  154. var ct_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Near);
  155. var rt_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Near);
  156. var lc_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Centre);
  157. var cc_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Centre);
  158. var rc_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Centre);
  159. var lb_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Far);
  160. var cb_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Far);
  161. var rb_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Far);
  162.  
  163. //=================================================// Title Format
  164. var tf_path = fb.TitleFormat("$left(%_path_raw%,4)");
  165. var tf_cover_path = fb.TitleFormat("$replace(%path%,%filename_ext%,)");
  166. var tf_tracknumber = fb.TitleFormat("%tracknumber%");
  167. var tf_artist = fb.TitleFormat("$if(%length%,%artist%,'Stream')");
  168. var tf_title = fb.TitleFormat("%title%");
  169. var tf_albumartist = fb.TitleFormat("$if(%length%,%album artist%,'Stream')");
  170. var tf_album = fb.TitleFormat("$if2(%album%,$if(%length%,'Single','web radios'))");
  171. var tf_disc = fb.TitleFormat("$if2(%discnumber%,0)");
  172. var tf_rating = fb.TitleFormat("$if2(%rating%,0)");
  173. var tf_length = fb.TitleFormat("$if2(%length%,' 0:00')");
  174. var tf_date = fb.TitleFormat("$if2($year(%date%),)");
  175. var tf_playback_time = fb.TitleFormat("%playback_time%");
  176. var tf_playback_time_remaining = fb.TitleFormat("$if(%length%,-%playback_time_remaining%,'0:00')");
  177.  
  178. //=================================================// Objects
  179. button = function () {
  180.     this.font = gdi.Font("segoe ui", 12, 0);
  181.     this.ButtonStates = {
  182.         normal: 0,
  183.         hover: 1,
  184.         down: 2
  185.     };
  186.     var tmp;
  187.     this.create = function (normal, hover, down, id) {
  188.         if (normal.Width) {
  189.             this.normal = normal.Width?normal:gdi.Image(normal);
  190.             this.hover = hover.Width?hover:gdi.Image(hover);
  191.             this.down = down.Width?down:gdi.Image(down);
  192.             this.zorder = id;
  193.             this.x = 0;
  194.             this.y = 0;
  195.             this.w = this.normal.Width;
  196.             this.h = this.normal.Height;
  197.             this.state = this.ButtonStates.normal;
  198.             this.g_timer_counter = 0;
  199.         }
  200.     }
  201.  
  202.      this.resize = function (w, h) {
  203.          if (typeof this.normal != "undefined") {
  204.              this.normal.Resize(w, h);
  205.              this.hover.Resize(w, h);
  206.              this.down.Resize(w, h);
  207.              this.w = w;
  208.              this.h = h;
  209.          }
  210.      }
  211.  
  212.      this.ontimer = function (id) {
  213.          if (this.g_timer) {
  214.              switch (id) {
  215.              case this.g_timer.ID:
  216.                  if (this.g_timer_sens == 1) {
  217.                      this.g_timer_counter = (this.g_timer_counter < 10) ? this.g_timer_counter + 2 : this.g_timer_counter;
  218.                      if (this.g_timer_counter == 10) this.g_timer && window.KillTimer(this.g_timer);
  219.                  } else {
  220.                      this.g_timer_counter = (this.g_timer_counter > 0) ? this.g_timer_counter - 2 : 0;
  221.                      if (this.g_timer_counter == 0) this.g_timer && window.KillTimer(this.g_timer);
  222.                  }
  223.  
  224.                  if (this.y >= 0) {
  225.                      window.RepaintRect(this.x, this.y, this.w + 1, this.h + 1)
  226.                  }
  227.  
  228.                  break;
  229.              }
  230.  
  231.          }
  232.      }
  233.  
  234.      this.draw = function (gr, bx, by, alpha, label) {
  235.          this.x = bx;
  236.          this.y = by;
  237.          switch (this.state) {
  238.              case this.ButtonStates.normal:
  239.                  this.img_displayed = this.normal;
  240.                  break;
  241.              case this.ButtonStates.hover:
  242.                  this.img_displayed = this.hover;
  243.                  break;
  244.              case this.ButtonStates.down:
  245.                  this.img_displayed = this.down;
  246.                  break;
  247.          }
  248.          switch (alpha) {
  249.              case 000:
  250.                  gr.DrawImage(this.img_displayed, this.x, this.y, this.w, this.h, 0, 0, this.w, this.h, 0, 255);
  251.                  break;
  252.              case 100:
  253.                  gr.DrawImage(this.img_displayed, this.x, this.y, this.w, this.h, 0, 0, this.w, this.h, 0, 060);
  254.                  break;
  255.              case 888:
  256.                  gr.DrawImage(this.img_displayed, this.x, this.y, this.w, this.h, 0, 0, this.w, this.h, 0, 215 + this.g_timer_counter * 04);
  257.                  break;
  258.              case 999:
  259.                  gr.DrawImage(this.img_displayed, this.x, this.y, this.w, this.h, 0, 0, this.w, this.h, 0, 175 + this.g_timer_counter * 08);
  260.                  break;
  261.              default:
  262.                  gr.DrawImage(this.img_displayed, this.x, this.y, this.w, this.h, 0, 0, this.w, this.h, 0, 115 + this.g_timer_counter * 14);
  263.                  break;
  264.          }
  265.      }
  266.  
  267.      this.checkstate = function (event, x, y, id) {
  268.          if (x > this.x && x < this.x + this.w - 1 && y > this.y && y < this.y + this.h - 1) {
  269.              this.is_hover = true;
  270.              this.mousecursor = 32649;
  271.          } else {
  272.              this.is_hover = false;
  273.              this.mousecursor = 32512;
  274.          }
  275.          switch (event) {
  276.          case "down":
  277.              if (this.is_hover) {
  278.                  this.state = this.ButtonStates.down;
  279.              } else if (this.state == this.ButtonStates.down) {
  280.                  this.state = this.ButtonStates.normal;
  281.                  this.g_timer && window.KillTimer(this.g_timer);
  282.                  this.g_timer_sens = 0;
  283.                  this.g_timer = window.CreateTimerInterval(40);
  284.              }
  285.              break;
  286.          case "right":
  287.              if (this.is_hover) {
  288.                  display_context_menu(x, y, id);
  289.              }
  290.              break;
  291.          case "move":
  292.              if (this.is_hover) {
  293.                  if (this.state != this.ButtonStates.down) {
  294.                      if (this.state != this.ButtonStates.hover) {
  295.                          this.g_timer_sens = 1;
  296.                          this.g_timer && window.KillTimer(this.g_timer);
  297.                          this.g_timer = window.CreateTimerInterval(40);
  298.                          this.state = this.ButtonStates.hover;
  299.                      }
  300.  
  301.                  }
  302.              } else if (this.state == this.ButtonStates.hover) {
  303.                  this.state = this.ButtonStates.normal;
  304.                  this.g_timer && window.KillTimer(this.g_timer);
  305.                  this.g_timer_sens = 0;
  306.                  this.g_timer = window.CreateTimerInterval(40)
  307.              }
  308.              break;
  309.          case "up":
  310.              if (this.is_hover) {
  311.                  if (this.state == this.ButtonStates.down) {
  312.                      this.state = this.ButtonStates.hover;
  313.                  } else {
  314.                      this.state = this.ButtonStates.normal;
  315.                      this.g_timer && window.KillTimer(this.g_timer);
  316.                      this.g_timer_sens = 0;
  317.                      this.g_timer = window.CreateTimerInterval(40);
  318.                  }
  319.              } else {
  320.                  this.state = this.ButtonStates.normal;
  321.                  this.g_timer && window.KillTimer(this.g_timer);
  322.                  this.g_timer_sens = 0;
  323.                  this.g_timer = window.CreateTimerInterval(40);
  324.              }
  325.              break;
  326.          case "leave":
  327.              this.state = this.ButtonStates.normal;
  328.              this.g_timer && window.KillTimer(this.g_timer);
  329.              this.g_timer_sens = 0;
  330.              this.g_timer = window.CreateTimerInterval(40);
  331.              break;
  332.          }
  333.          if (this.y >= 0) {
  334.              this.is_hover && window.RepaintRect(this.x, this.y, this.w + 1, this.h + 1);
  335.          }
  336.          return this.state;
  337.      }
  338. }
  339.  
  340. IC = {
  341.     list_total: 0,
  342.     height: window.GetProperty("Row Height", 28),
  343.     show_coverart: window.GetProperty("Show Cover Art", true),
  344.     draw_cover: false,
  345.     pad_top: 0,
  346.     pad_bot: 0,
  347.     pad_left: 0,
  348.     pad_right: 0,
  349.     toolbar: window.GetProperty("Show Toolbar", false),
  350.     default_toolbar_height: window.GetProperty("Default Toolbar Height", 20),
  351.     toolbar_height: this.default_toolbar_height,
  352.     scrollbar: window.GetProperty("Show Scrollbar", true),
  353.     scrollbar_y : 0,
  354.     scrollbar_h : 0,
  355.     scrollbar_bt_h : 20,
  356.     scrollbar_width: window.GetProperty("Scrollbar Width", 17),
  357.     scroller_y: 0,
  358.     scroller_drag: false,
  359.     font: gdi.Font("segoe ui", 12, 0),
  360.     scroll: window.GetProperty("Scrolling", false),
  361.     scrollstep: window.GetProperty("Scroll Step", 3),
  362.     pos: window.GetProperty("Item Offset", 0),
  363.     ghnbrows: window.GetProperty("Group Header rows number", 2),
  364.     artist_group_font: gdi.Font("segoe ui", 17, 0),
  365.     album_group_font: gdi.Font("segoe ui", 12, 0),
  366.     rating_font: gdi.Font("guifx v2 transports", 17, 0),
  367.     grp_total_items_font: gdi.Font("segoe ui", 12, 1),
  368.     nbvis: 0,
  369.     topcut: window.GetProperty("Group Offset", 0),
  370.     scrollstep_min: 0,
  371.     total_items_visible: 0,
  372.     paint_count: 0,
  373.     metadblist_selection: plman.GetPlaylistSelectedItems(fb.ActivePlaylist),
  374.     context_menu_called: false,
  375.     nb_hidden_lines: 0,
  376.     nowplaying: plman.GetPlayingItemLocation(),
  377.     singleton_select_id: 0,
  378.     bot_reached: false,
  379.     scroll_down: false
  380. };
  381. item = function () {
  382.     var i;
  383.     this.ItemStates = {
  384.         normal: 0,
  385.         hover: 1,
  386.         selected: 2
  387.     };
  388.     this.create = function(id, metadb, idx) {
  389.         if (typeof this.id == "undefined") {
  390.             this.idx = idx;
  391.             this.id = id;
  392.             this.state = this.ItemStates.normal;
  393.             this.metadb = metadb;
  394.             if(metadb) {
  395.                 this.track_type = TrackType(this.metadb.rawpath.substring(0,4));
  396.                 this.tracknumber = tf_tracknumber.EvalWithMetadb(this.metadb);
  397.                 if(this.tracknumber=="?") this.tracknumber = num(this.id+1,2);
  398.                 this.artist = tf_artist.EvalWithMetadb(this.metadb);
  399.                 this.title = tf_title.EvalWithMetadb(this.metadb);
  400.                 this.albumartist = tf_albumartist.EvalWithMetadb(this.metadb);
  401.                 this.album = tf_album.EvalWithMetadb(this.metadb);
  402.                 this.disc = tf_disc.EvalWithMetadb(this.metadb);
  403.                 this.rating = tf_rating.EvalWithMetadb(this.metadb);
  404.                 this.length = tf_length.EvalWithMetadb(this.metadb);
  405.                 this.date = tf_date.EvalWithMetadb(this.metadb);
  406.                 this.group_key = this.albumartist+this.album+this.disc;
  407.             }
  408.             this.x = 0;
  409.             this.y = 0;
  410.             this.w = ww - IC.pad_left - IC.pad_right - (IC.scrollbar?IC.scrollbar_width:0);
  411.             this.h = IC.height - IC.pad_top - IC.pad_bot;
  412.         }
  413.     }
  414.     this.template_it = function(id, metadb) {
  415.         if (typeof this.id == "undefined") {
  416.             this.id = id;
  417.             this.metadb = metadb;
  418.             if(metadb) {
  419.                 this.albumartist = tf_albumartist.EvalWithMetadb(this.metadb);
  420.                 this.album = tf_album.EvalWithMetadb(this.metadb);
  421.                 this.disc = tf_disc.EvalWithMetadb(this.metadb);
  422.                 this.group_key = this.albumartist+this.album+this.disc;
  423.             }
  424.         }
  425.     }
  426.     this.draw = function (gr, id) {
  427.  
  428.         this.w = ww - IC.pad_left - IC.pad_right - (IC.scrollbar?IC.scrollbar_width:0);
  429.  
  430.         // Draw group header
  431.         if(IC.ghnbrows>0 && this.gridx!=0) {
  432.             var artist_group_text_colour = RGB(220, 220, 220);
  433.             var album_group_text_colour = RGB(160, 160, 160);
  434.             var group_y = this.y - (this.gridx-1)*IC.height;
  435.             // get cover art (from cache or disk)
  436.             if(IC.show_coverart && this.metadb) {
  437.                 this.cover_path = this.metadb.path;
  438.                 this.cover_img = g_image_cache.hit(this);
  439.             }
  440.             gr.FillGradRect(this.x, group_y, this.w, IC.ghnbrows*IC.height, 90, RGB(245,245,245), RGB(230,230,230), 1.0);
  441.             gr.FillSolidRect(this.x, group_y, this.w, 1, RGB(210,210,210));
  442.             gr.FillSolidRect(this.x, group_y+1, this.w, 1, RGB(255,255,255));
  443.             gr.FillSolidRect(this.x, group_y+IC.ghnbrows*IC.height-1, this.w, 1, RGB(200,200,200));
  444.             gr.GdiDrawText(this.albumartist, IC.artist_group_font, RGB(160,160,160), this.x + 10 + cover_w, group_y+2, this.w-20-cover_w, Math.ceil(IC.ghnbrows*IC.height/2), DT_LEFT | DT_NOPREFIX | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS);
  445.             gr.GdiDrawText(this.albumartist, IC.artist_group_font, RGB(255,255,255), this.x + 10 + cover_w, group_y+4, this.w-20-cover_w, Math.ceil(IC.ghnbrows*IC.height/2), DT_LEFT | DT_NOPREFIX | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS);
  446.             gr.GdiDrawText(this.albumartist, IC.artist_group_font, artist_group_text_colour, this.x + 10 + cover_w, group_y+3, this.w-20-cover_w, Math.ceil(IC.ghnbrows*IC.height/2), DT_LEFT | DT_NOPREFIX | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS);
  447.             gr.GdiDrawText(this.album, IC.album_group_font, RGB(255,255,255), this.x + 10 + cover_w, group_y+Math.ceil(IC.ghnbrows*IC.height/2)-0, this.w-20-cover_w, Math.ceil(IC.ghnbrows*IC.height/2), DT_LEFT | DT_NOPREFIX | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS);
  448.             gr.GdiDrawText(this.album, IC.album_group_font, album_group_text_colour, this.x + 10 + cover_w, group_y+Math.ceil(IC.ghnbrows*IC.height/2)-1, this.w-20-cover_w, Math.ceil(IC.ghnbrows*IC.height/2), DT_LEFT | DT_NOPREFIX | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS);
  449.             if(IC.show_coverart && this.cover_img) {
  450.                 gr.DrawRect(this.x+cover_margin-1+5, group_y+cover_margin-1, cover_w-cover_margin*2+1, cover_h-cover_margin*2+1, 1.0, RGBA(0,0,0,15));
  451.                 gr.DrawRect(this.x+cover_margin+1+5, group_y+cover_margin+1, cover_w-cover_margin*2-1, cover_h-cover_margin*2-1, 1.0, RGBA(0,0,0,120));
  452.                 gr.DrawRect(this.x+cover_margin+2+5, group_y+cover_margin+2, cover_w-cover_margin*2-1, cover_h-cover_margin*2-1, 1.0, RGBA(0,0,0,40));
  453.                 gr.DrawImage(this.cover_img, this.x+cover_margin+5, group_y+cover_margin, cover_w-cover_margin*2, cover_h-cover_margin*2, 0, 0, cover_w, cover_h, 0, 255);
  454.             }
  455.             if(this.date.length>0 && this.gridx==IC.ghnbrows) {
  456.                 gr.SetSmoothingMode(2);
  457.                 gr.FillRoundRect(this.x+this.w-50, this.y-9, 40, 18, 3, 3, RGBA(0,0,0,050));
  458.                 gr.GdiDrawText(this.date, IC.grp_total_items_font, RGB(255,255,255), this.x+this.w-50, this.y-9+1, 40, 18, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS);
  459.                 gr.SetSmoothingMode(0);
  460.             }
  461.         }
  462.        
  463.         // Draw item
  464.         if(this.gridx==0) {
  465.             var parity = (this.id/2-Math.floor(this.id/2)==0)?0:1;
  466.  
  467.             if(this.metadb.Compare(fb.GetFocusItem())) {
  468.                 if(this.state!=this.ItemStates.selected) {
  469.                     this.state = this.ItemStates.selected;
  470.                     if(IC.metadblist_selection.Count==0) {
  471.                         IC.metadblist_selection.RemoveAll();
  472.                         plman.ClearPlaylistSelection(fb.ActivePlaylist);
  473.                         plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, g_metadb_playlist.Find(this.metadb), true);
  474.                         IC.metadblist_selection.Add(this.metadb);
  475.                     }
  476.                     IC.singleton_select_id = this.id;
  477.                 }
  478.             }
  479.            
  480.             switch(this.state) {
  481.             case this.ItemStates.normal:
  482.                 var text_colour = RGB(120, 120, 120);
  483.                 var artist_text_colour = RGB(180, 180, 180);
  484.                 var title_text_colour = RGB(120, 120, 120);
  485.                 break;
  486.             case this.ItemStates.hover:
  487.                 var text_colour = RGB(120, 120, 120);
  488.                 var artist_text_colour = RGB(180, 180, 180);
  489.                 var title_text_colour = RGB(120, 120, 120);
  490.                 break;
  491.             case this.ItemStates.selected:
  492.                 var text_colour = RGB(60, 80, 220);
  493.                 var artist_text_colour = RGB(140, 160, 250);
  494.                 var title_text_colour = RGB(60, 80, 220);
  495.                 break;
  496.             }
  497.             // Item background
  498.             var bg_colour = (parity==0)?RGB(247, 247, 247):RGB(250,250,250);
  499.             gr.FillSolidRect(this.x, this.y, this.w, this.h, bg_colour);
  500.             gr.FillGradRect(this.x, this.y, this.w, 1, 0, 0, RGB(220,220,220), 0.5);
  501.             gr.FillGradRect(this.x, this.y+1, this.w, 1, 0, 0, RGB(255,255,255), 0.5);
  502.             if(this.state==this.ItemStates.selected) {
  503.                 gr.FillSolidRect(this.x, this.y, this.w, 1, RGB(225,225,225));
  504.                 gr.FillGradRect(this.x, this.y+1, this.w, this.h/2+1, 90, RGB(235,245,255), 0, 1.0);
  505.             }
  506.             // if last item, draw bottom shadow!
  507.             if(this.id==IC.list_total-1) {
  508.                 gr.FillGradRect(this.x, this.y+this.h, this.w, 4, 90, RGB(90,90,90), 0, 1.0);
  509.             }
  510.             // tag fields display
  511.             gr.GdiDrawText(this.tracknumber+".", IC.font, text_colour, this.x + 10, this.y, 50, this.h, DT_RIGHT | DT_NOPREFIX | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS);
  512.             if(this.artist!=this.albumartist) {
  513.                 gr.GdiDrawText(this.title+" "+this.artist, IC.font, artist_text_colour, this.x + 70, this.y, this.w-70-65-60, this.h, DT_NOPREFIX | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS);
  514.                 gr.GdiDrawText(this.title+" ", IC.font, title_text_colour, this.x + 70, this.y, this.w-70-65-60, this.h, DT_NOPREFIX | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS);
  515.             } else {
  516.                 gr.GdiDrawText(this.title, IC.font, title_text_colour, this.x + 70, this.y, this.w-70-65-60, this.h, DT_NOPREFIX | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS);
  517.             }
  518.            
  519.             // draw play icon + time
  520.             if(fb.PlayingPlaylist==fb.ActivePlaylist) {
  521.                 if(fb.IsPlaying && this.metadb.Compare(fb.GetNowPlaying())) {
  522.                     gr.DrawImage(playicon_off, this.x + 5, this.y+this.h/2-playicon_off.Height/2-1, playicon_off.Width, playicon_off.Height, 0, 0, playicon_off.Width, playicon_off.Height, 0, (g_playtime_parity==1)?255:127);
  523.                     if(this.length==" 0:00") {
  524.                         this.playback_time_remaining = tf_playback_time.Eval(true);
  525.                     } else {
  526.                         this.playback_time_remaining = tf_playback_time_remaining.Eval(true);
  527.                     }
  528.                     gr.GdiDrawText(this.playback_time_remaining, IC.font, text_colour, this.w - 60, this.y, 50, this.h, DT_RIGHT | DT_NOPREFIX | DT_CALCRECT | DT_VCENTER);
  529.                 } else {
  530.                     gr.GdiDrawText(this.length, IC.font, text_colour, this.w - 60, this.y, 50, this.h, DT_RIGHT | DT_NOPREFIX | DT_CALCRECT | DT_VCENTER);
  531.                 }
  532.             } else {
  533.                 gr.GdiDrawText(this.length, IC.font, text_colour, this.w - 60, this.y, 50, this.h, DT_RIGHT | DT_NOPREFIX | DT_CALCRECT | DT_VCENTER);
  534.             }
  535.            
  536.             // Rating engine
  537.             this.rating_x = this.x+this.w-120;
  538.             this.rating_y = this.y + Math.round(IC.height/2 - star_img_off.Height/2)+1;
  539.             if(this.rating_hov) {
  540.                 for (i = 1; i < 6; i++){
  541.                     if(this.track_type<2){
  542.                         var img = (i > (this.rating_hov ? this.l_rating : this.rating)) ? star_img_off : (this.rating_hov ? (i==this.rating ? (i==this.l_rating ? star_img_kill : star_img_hov) : star_img_hov) : star_img_on);
  543.                         if(this.rating_hov && this.l_rating==this.rating) {
  544.                             img = i<=this.l_rating ? star_img_kill : star_img_off;
  545.                         }
  546.                     } else {
  547.                         var img = star_img_off;
  548.                     }
  549.                     gr.DrawImage(img, this.rating_x+img.Width*(i-1), this.rating_y, img.Width, img.Height, 0, 0, img.Width, img.Height, 0, 255);
  550.                 }
  551.             } else {
  552.                 gr.SetTextRenderingHint(4);
  553.                 for(i=0;i<5;i++) {
  554.                     gr.DrawString("b", IC.rating_font, (i+1<=this.rating)?title_text_colour:RGB(230,230,230), this.rating_x+i*13, this.rating_y, 13, 18, lt_stringformat);
  555.                 }
  556.                
  557.             }
  558.         }      
  559.     }
  560.  
  561.     this.checkstate = function (event, x, y, id) {
  562.         this.ishover = (this.gridx==0 && x > this.x && x < this.x + this.w && y >= this.y && y < this.y + this.h)?true:false;
  563.         this.isgrphover = (this.gridx>0 && x > this.x && x < this.x + this.w && y >= this.y && y < this.y + this.h)?true:false;
  564.         var tmp = this.rating_hov;
  565.         var tmp_l_rating = this.l_rating;
  566.         this.rating_hov = (this.gridx==0 && x > this.x+this.w-120 && x < this.x+this.w-55 && y > this.rating_y+4 && y < this.rating_y + 18)?true:false;
  567.         switch (event) {
  568.         case "down":
  569.             switch(this.state) {
  570.             case this.ItemStates.normal:
  571.             case this.ItemStates.hover:
  572.                 if(this.ishover && !this.rating_hov) {
  573.                     if(utils.IsKeyPressed(VK_CONTROL)) { // if Ctrl key pressed, add item to selection
  574.                         plman.SetPlaylistFocusItem(fb.ActivePlaylist, this.id);
  575.                         plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, this.id, true);
  576.                         this.state = this.ItemStates.selected;
  577.                         IC.singleton_select_id = this.id;
  578.                         on_item_focus_change();
  579.                     } else if(utils.IsKeyPressed(VK_SHIFT)) {
  580.                         if(IC.singleton_select_id != this.id) {
  581.                             SelectAtoB(IC.singleton_select_id, this.id);
  582.                         }
  583.                     } else {
  584.                         plman.SetPlaylistFocusItem(fb.ActivePlaylist, this.id);
  585.                         plman.ClearPlaylistSelection(fb.ActivePlaylist);
  586.                         plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, this.id, true);
  587.                         this.state = this.ItemStates.selected;
  588.                         IC.singleton_select_id = this.id;
  589.                         on_item_focus_change();
  590.                     }
  591.                 } else if(this.isgrphover) {
  592.                     SelectGroupItems(this.id, this.group_key);
  593.                 }
  594.                 break;
  595.             case this.ItemStates.selected:
  596.                 if(this.ishover && !this.rating_hov && IC.metadblist_selection.Count>1) {
  597.                     if(utils.IsKeyPressed(VK_CONTROL)) { // if Ctrl key pressed, remove item from selection
  598.                         plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, this.id, false);
  599.                         this.state = this.ItemStates.hover;
  600.                         on_item_focus_change();
  601.                     } else {
  602.                         plman.SetPlaylistFocusItem(fb.ActivePlaylist, this.id);
  603.                         plman.ClearPlaylistSelection(fb.ActivePlaylist);
  604.                         plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, this.id, true);
  605.                         this.state = this.ItemStates.selected;
  606.                         IC.singleton_select_id = this.id;
  607.                         on_item_focus_change();
  608.                     }
  609.                 }
  610.                 break;
  611.             }
  612.             break;
  613.            
  614.         case "dblclk":
  615.             switch(this.state) {
  616.             case this.ItemStates.selected:
  617.                 if(this.ishover && !this.rating_hov) {
  618.                     fb.RunContextCommandWithMetadb("Play", this.metadb);
  619.                 }
  620.                 break;
  621.             }
  622.             break;
  623.            
  624.         case "right":
  625.             if(this.ishover && !this.rating_hov) {
  626.                 switch(this.state) {
  627.                     case this.ItemStates.normal:
  628.                     case this.ItemStates.hover:
  629.                         plman.SetPlaylistFocusItem(fb.ActivePlaylist, this.id);
  630.                         plman.ClearPlaylistSelection(fb.ActivePlaylist);
  631.                         plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, this.id, true);
  632.                         this.state = this.ItemStates.selected;
  633.                         on_item_focus_change();
  634.                         break;
  635.                 }
  636.                 new_context_menu(x, y, this.id, this.idx);
  637.             } else if(this.isgrphover) {
  638.                 SelectGroupItems(this.id, this.group_key);
  639.                 new_context_menu(x, y, this.id, this.idx);
  640.             }
  641.             break;
  642.         case "up":
  643.             // Rating
  644.             if(this.track_type<2 && this.rating_hov) {
  645.                 if(foo_playcount) {
  646.                     // Rate to database statistics brought by foo_playcount.dll
  647.                     if (this.l_rating != this.rating) {
  648.                         if(this.metadb) {
  649.                             var bool = fb.RunContextCommandWithMetadb("Rating/"+((this.l_rating==0) ? "<not set>" : this.l_rating), this.metadb);
  650.                             this.rating = this.l_rating;
  651.                         }
  652.                     } else {
  653.                         var bool = fb.RunContextCommandWithMetadb("Rating/<not set>", this.metadb);
  654.                         this.rating = 0;
  655.                     }
  656.                 } else {
  657.                     // Rate to file
  658.                     if (this.l_rating != this.rating) {
  659.                         if(this.metadb) {
  660.                             var bool = this.metadb.UpdateFileInfoSimple("RATING", this.l_rating);
  661.                             this.rating = this.l_rating;
  662.                         }
  663.                     } else {
  664.                         var bool = this.metadb.UpdateFileInfoSimple("RATING","");
  665.                         this.rating = 0;
  666.                     }
  667.                 }
  668.             }
  669.             break;
  670.            
  671.         case "move":
  672.             // Rating
  673.             if(this.rating_hov) {
  674.                 this.l_rating = Math.floor((x - this.rating_x) / star_img_off.Width) + 1;
  675.             } else {
  676.                 this.l_rating = 0;
  677.             }
  678.  
  679.             switch(this.state) {
  680.             case this.ItemStates.normal:
  681.                 if(this.ishover) {
  682.                     this.state = this.ItemStates.hover;
  683.                 }
  684.                 break;
  685.             case this.ItemStates.selected:
  686.                 if(this.rating_hov!=tmp || (this.rating_hov && this.l_rating!=tmp_l_rating) || (this.rating_hov && this.l_rating==0)) {
  687.                     window.RepaintRect(this.rating_x, this.rating_y, rating_w, rating_h);
  688.                 }
  689.                 break;
  690.             case this.ItemStates.hover:
  691.                 if(!this.ishover) {
  692.                     this.state = this.ItemStates.normal;
  693.                     if(this.rating_hov!=tmp) {
  694.                         window.RepaintRect(this.rating_x, this.rating_y, rating_w, rating_h);
  695.                     }  
  696.                 } else {
  697.                     if(this.rating_hov!=tmp || (this.rating_hov && this.l_rating!=tmp_l_rating) || (this.rating_hov && this.l_rating==0)) {
  698.                         window.RepaintRect(this.rating_x, this.rating_y, rating_w, rating_h);
  699.                     }
  700.                 }
  701.                 break;
  702.             }
  703.             break;
  704.            
  705.         case "leave":
  706.             break;
  707.         }
  708.         return this.state;
  709.     }
  710. }
  711.  
  712. //=================================================// Main Callbacks
  713. function on_init() {
  714.     var i;
  715.    
  716.     if(IC.show_coverart) {
  717.         cover_w = IC.ghnbrows*IC.height - 1;
  718.         cover_h = cover_w;
  719.     } else {
  720.         cover_w = 0;
  721.         cover_h = 0;
  722.     }
  723.    
  724.     if(IC.toolbar) {
  725.         IC.toolbar_height = IC.default_toolbar_height;
  726.     } else {
  727.         IC.toolbar_height = 0;
  728.     }
  729.  
  730.     IC.pos = 0;
  731.     IC.topcut = 0;
  732.     g_metadb_playlist = plman.GetPlaylistItems(fb.ActivePlaylist);
  733.     IC.list_total = fb.PlaylistItemCount(fb.ActivePlaylist);
  734.    
  735.     refresh_timer && window.KillTimer(refresh_timer);
  736.  
  737.     on_focus(false);
  738.    
  739.     on_item_focus_change();
  740.    
  741.     draw_icons();
  742.     refresh_buttons();
  743.    
  744.     if(IC.list_total>0) {
  745.         IC.singleton_select_id = g_metadb_playlist.Find(fb.GetFocusItem());
  746.         ShowSelectedItem(IC.singleton_select_id);
  747.     }
  748. }
  749. on_init();
  750.  
  751. function on_size() {
  752.     ww = window.Width;
  753.     wh = window.Height - IC.toolbar_height;
  754.     IC.scrollbar_y = IC.scrollbar_bt_h*2;
  755.     IC.scrollbar_h = window.Height - IC.scrollbar_bt_h*3;
  756.     on_item_focus_change();
  757.     ShowSelectedItem(-1);
  758. }
  759.  
  760. function on_paint(gr) {
  761.     var i, k;
  762.    
  763.     if(myscreen.length>0) {
  764.         if(myscreen[0].id == 0 && myscreen[myscreen.length-1].id == IC.list_total-1 && myscreen.length<IC.nbvis) {
  765.             IC.scroller_y = IC.scrollbar_y;
  766.             IC.pos = 0;
  767.             IC.topcut = 0;
  768.         } else {
  769.             if(!IC.scroller_drag) {
  770.                 IC.scroller_y = IC.scrollbar_y + Math.round((IC.pos/(IC.list_total-IC.total_items_visible)*-1)*(IC.scrollbar_h-scroller.Height));
  771.             }
  772.         }
  773.     } else {
  774.         IC.scroller_y = IC.scrollbar_y;
  775.         IC.pos = 0;
  776.         IC.topcut = 0;
  777.     }
  778.    
  779.     // draw main bg
  780.     gr.FillSolidRect(0,0,ww,wh+IC.toolbar_height,RGB(225,225,225));
  781.    
  782.     // draw playlist
  783.     for(k=0;k<myscreen.length;k++) {
  784.         if(myscreen[k].y<wh+IC.toolbar_height+IC.height) myscreen[k].draw(gr, k);
  785.     }
  786.    
  787.     // draw scrollbar
  788.     if(IC.scrollbar) {
  789.         gr.FillSolidRect(ww-IC.scrollbar_width, 0, 1, wh+IC.toolbar_height, RGB(100,100,100));
  790.         gr.FillGradRect(ww-IC.scrollbar_width, IC.scrollbar_y, 4, IC.scrollbar_h, 0, RGB(130,130,130), 0, 1.0);
  791.         gr.FillGradRect(ww-2, IC.scrollbar_y, 0, IC.scrollbar_h, 0, 0, RGB(150,150,150), 1.0);
  792.         gr.DrawImage(scroller, ww-IC.scrollbar_width+1, IC.scroller_y, scroller.Width, scroller.Height, 0, 0, scroller.Width, scroller.Height, 0, 255);
  793.         for(i=0;i<myscrollbarbt.length;i++) {
  794.             switch (i) {
  795.             case 0:
  796.                 myscrollbarbt[i].draw(gr, ww-IC.scrollbar_width, 0, 255, "");
  797.                 break;
  798.             case 1:
  799.                 myscrollbarbt[i].draw(gr, ww-IC.scrollbar_width, IC.scrollbar_bt_h, 255, "");
  800.                 break;
  801.             case 2:
  802.                 myscrollbarbt[i].draw(gr, ww-IC.scrollbar_width, IC.scrollbar_y+IC.scrollbar_h, 255, "");
  803.                 break;
  804.             }
  805.         }
  806.         if(IC.scroller_drag && myscreen.length>0) {
  807.             refresh_scroller_popup(myscreen[0].albumartist.substring(0,1));
  808.             gr.DrawImage(scroller_popup, ww-IC.scrollbar_width+1-scroller_popup.Width-5, IC.scroller_y-1, scroller_popup.Width, scroller_popup.Height, 0, 0, scroller_popup.Width, scroller_popup.Height, 0, 255);
  809.         }
  810.     }
  811.     // draw toolbar
  812.     if(IC.toolbar) {
  813.         var tw = (IC.scrollbar?IC.scrollbar_width:0);
  814.         gr.FillGradRect(0, 0, ww-tw, IC.toolbar_height, 90, RGB(245,245,245), RGB(230,230,230), 1.0);
  815.         gr.FillSolidRect(0, 0, ww-tw, 1, RGB(210,210,210));
  816.         gr.FillSolidRect(0, 1, ww-tw, 1, RGB(255,255,255));
  817.         gr.FillSolidRect(0, IC.toolbar_height-1, ww-tw, 1, RGB(150,150,150));
  818.         gr.FillGradRect(1, 2, ww-tw-2, IC.toolbar_height-4, 90, RGB(245,245,245), RGB(230,230,230), 0.5);
  819.         for(i=0;i<mytoolbarbt.length;i++) {
  820.             switch (i) {
  821.             case 0:
  822.                 mytoolbarbt[i].draw(gr, 0, 0, 255, "");
  823.                 break;
  824.             case 1:
  825.                 mytoolbarbt[i].draw(gr, ww-tw-mytoolbarbt_scrollbar.Width, 0, 255, "");
  826.                 break;
  827.             case 2:
  828.                 mytoolbarbt[i].draw(gr, mytoolbarbt_shownowplaying.Width, 0, 255, "");
  829.                 break;
  830.             case 3:
  831.                 mytoolbarbt[i].draw(gr, mytoolbarbt_shownowplaying.Width+mytoolbarbt_search.Width, 0, 255, "");
  832.                 break;
  833.             }
  834.         }
  835.     }
  836. }
  837.  
  838. //=================================================// Mouse Callbacks
  839. function on_mouse_lbtn_down(x, y) {
  840.     var k;
  841.  
  842.     if(IC.scrollbar) {
  843.         for(k=0;k<myscrollbarbt.length;k++) {
  844.             switch(k) {
  845.                 case 0:
  846.                     myscrollbarbt[k].checkstate("down", x, y, k);
  847.                     break;
  848.                 case 1:
  849.                     if(myscrollbarbt[k].checkstate("down", x, y, k)==myscrollbarbt[k].ButtonStates.down) {
  850.                         mouse_down_timer && window.KillTimer(mouse_down_timer);
  851.                         mouse_down_timer = false;
  852.                         init_mouse_down_timer && window.KillTimer(init_mouse_down_timer);
  853.                         init_mouse_down_timer = window.CreateTimerInterval(500);
  854.                         IC.scrollstep = 1;
  855.                         if(IC.scrollstep_min>0) IC.scrollstep_min = 1;
  856.                         on_mouse_wheel(1);
  857.                     }
  858.                     break;
  859.                 case 2:
  860.                     if(myscrollbarbt[k].checkstate("down", x, y, k)==myscrollbarbt[k].ButtonStates.down) {
  861.                         mouse_down_timer && window.KillTimer(mouse_down_timer);
  862.                         mouse_down_timer = false;
  863.                         init_mouse_down_timer && window.KillTimer(init_mouse_down_timer);
  864.                         init_mouse_down_timer = window.CreateTimerInterval(500);
  865.                         IC.scrollstep = 1;
  866.                         if(IC.scrollstep_min>0) IC.scrollstep_min = 1;
  867.                         on_mouse_wheel(-1);
  868.                     }
  869.                     break;
  870.                 }
  871.         }
  872.     }
  873.  
  874.     if(IC.toolbar) {
  875.         for(k=0;k<mytoolbarbt.length;k++) {
  876.             switch(k) {
  877.                 case 0:
  878.                     mytoolbarbt[k].checkstate("down", x, y, k);
  879.                     break;
  880.                 case 1:
  881.                     mytoolbarbt[k].checkstate("down", x, y, k);
  882.                     break;
  883.                 case 2:
  884.                     mytoolbarbt[k].checkstate("down", x, y, k);
  885.                     break;
  886.                 case 3:
  887.                     mytoolbarbt[k].checkstate("down", x, y, k);
  888.                     break;
  889.                 }
  890.         }
  891.     }
  892.    
  893.     for(k=0;k<myscreen.length;k++) {
  894.         myscreen[k].checkstate("down", x, y, k);
  895.     }
  896.    
  897.     IC.scroller_drag = (x>ww-IC.scrollbar_width && y>=IC.scroller_y && y<=IC.scroller_y+scroller.Height)?true:false;
  898.    
  899.     if(!IC.scroller_drag && x>ww-IC.scrollbar_width && y>=IC.scrollbar_y && y<=IC.scrollbar_y+IC.scrollbar_h) {
  900.         IC.scroller_drag = true;
  901.         IC.scroll_down = false;
  902.         IC.draw_cover = false;
  903.         IC.scroller_y = y-Math.floor(scroller.Height/2);
  904.         if(IC.scroller_y<=IC.scrollbar_y) {
  905.             IC.scroller_y = IC.scrollbar_y;
  906.             IC.pos = 0;
  907.             IC.topcut = 0;
  908.         } else if(IC.scroller_y>IC.scrollbar_y+IC.scrollbar_h-scroller.Height) {
  909.             IC.scroller_y = (IC.scrollbar_y+IC.scrollbar_h-scroller.Height);
  910.             IC.pos = scroller2pos(IC.scroller_y);
  911.             if(y>=mouse_y) {
  912.                 IC.scroll_down = true;
  913.             }
  914.         } else {
  915.             if(myscreen.length>0) {
  916.                 IC.pos = scroller2pos(IC.scroller_y);
  917.             }
  918.         }
  919.         scroller_drag_timer = window.CreateTimerInterval(50);
  920.         mouse_y = y;
  921.     }
  922. }
  923.  
  924. function on_mouse_lbtn_up(x, y) {
  925.     var k;
  926.    
  927.     IC.scrollstep = window.GetProperty("Scroll Step", 3);
  928.  
  929.     init_mouse_down_timer && window.KillTimer(init_mouse_down_timer);
  930.     init_mouse_down_timer = false;
  931.     mouse_down_timer && window.KillTimer(mouse_down_timer);
  932.     mouse_down_timer = false;
  933.    
  934.     if(IC.scrollbar) {
  935.         for (k=0;k<myscrollbarbt.length;k++) {
  936.             switch (k) {
  937.             case 0:
  938.                 if(myscrollbarbt[k].checkstate("up", x, y, k) == myscrollbarbt[k].ButtonStates.hover) {
  939.                     IC.toolbar = !IC.toolbar;
  940.                     window.SetProperty("Show Toolbar", IC.toolbar);
  941.                     if(IC.toolbar) {
  942.                         IC.toolbar_height = IC.default_toolbar_height;
  943.                     } else {
  944.                         IC.toolbar_height = 0;
  945.                     }
  946.                     wh = window.Height - IC.toolbar_height;
  947.                     refresh_buttons();
  948.                     on_item_focus_change();              
  949.                 }
  950.                 break;
  951.             case 1:
  952.                 if(myscrollbarbt[k].checkstate("up", x, y, k) == myscrollbarbt[k].ButtonStates.hover) {
  953.  
  954.                 }
  955.                 break;
  956.             case 2:
  957.                 if(myscrollbarbt[k].checkstate("up", x, y, k) == myscrollbarbt[k].ButtonStates.hover) {
  958.  
  959.                 }
  960.                 break;
  961.             }
  962.         }
  963.     }
  964.  
  965.     if(IC.toolbar) {
  966.         for (k=0;k<mytoolbarbt.length;k++) {
  967.             switch (k) {
  968.             case 0:
  969.                 if(mytoolbarbt[k].checkstate("up", x, y, k) == mytoolbarbt[k].ButtonStates.hover) {
  970.                     ShowNowPlaying();
  971.                     on_item_focus_change();            
  972.                 }
  973.                 break;
  974.             case 1:
  975.                 if(mytoolbarbt[k].checkstate("up", x, y, k) == mytoolbarbt[k].ButtonStates.hover) {
  976.                     IC.scrollbar = !IC.scrollbar;
  977.                     window.SetProperty("Show Scrollbar", IC.scrollbar);
  978.                     refresh_buttons();
  979.                     on_item_focus_change();              
  980.                 }
  981.                 break;
  982.             case 2:
  983.                 if(mytoolbarbt[k].checkstate("up", x, y, k) == mytoolbarbt[k].ButtonStates.hover) {
  984.                     fb.RunMainMenuCommand("Edit/Search");
  985.                 }
  986.                 break;
  987.             case 3:
  988.                 if(mytoolbarbt[k].checkstate("up", x, y, k) == mytoolbarbt[k].ButtonStates.hover) {
  989.                     fb.RunMainMenuCommand("Edit/Sort/Sort by...");
  990.                 }
  991.                 break;
  992.             }
  993.         }
  994.     }
  995.  
  996.     for(k=0;k<myscreen.length;k++) {
  997.         myscreen[k].checkstate("up", x, y, k);
  998.     }
  999.    
  1000.     IC.scroller_drag = false;
  1001.     window.Repaint();
  1002.    
  1003. }
  1004.  
  1005. function on_mouse_lbtn_dblclk(x, y, mask) {
  1006.     var k;
  1007.    
  1008.     if(x>ww-IC.scrollbar_width) on_mouse_lbtn_down(x, y);
  1009.    
  1010.     for(k=0;k<myscreen.length;k++) {
  1011.         myscreen[k].checkstate("dblclk", x, y, k);
  1012.     }
  1013. }
  1014.  
  1015. function on_mouse_rbtn_down(x, y) {
  1016.     var k;
  1017.     for(k=0;k<myscreen.length;k++) {
  1018.         myscreen[k].checkstate("right", x, y, k);
  1019.     }
  1020. }
  1021.  
  1022. function on_mouse_move(x, y) {
  1023.     var k;    
  1024.    
  1025.     refresh_timer && window.KillTimer(refresh_timer);
  1026.     refresh_timer = false;
  1027.  
  1028.     if(IC.scrollbar && x>=ww-IC.scrollbar_width) {
  1029.         for(k=0;k<myscrollbarbt.length;k++) {
  1030.             myscrollbarbt[k].checkstate("move", x, y, k);
  1031.         }
  1032.     }
  1033.  
  1034.     if(IC.toolbar && y<IC.toolbar_height) {
  1035.         for(k=0;k<mytoolbarbt.length;k++) {
  1036.             mytoolbarbt[k].checkstate("move", x, y, k);
  1037.         }
  1038.     }
  1039.  
  1040.     for(k=0;k<myscreen.length;k++) {
  1041.         if(myscreen[k].checkstate("move", x, y, k)==myscreen[k].ItemStates.hover) {
  1042.            
  1043.         }
  1044.     }
  1045.    
  1046.     if(IC.scroller_drag) {
  1047.         IC.scroll_down = false;
  1048.         IC.draw_cover = false;
  1049.         IC.scroller_y = y-Math.floor(scroller.Height/2);
  1050.         if(IC.scroller_y<=IC.scrollbar_y) {
  1051.             IC.scroller_y = IC.scrollbar_y;
  1052.             IC.pos = 0;
  1053.             IC.topcut = 0;
  1054.         } else if(IC.scroller_y>IC.scrollbar_y+IC.scrollbar_h-scroller.Height) {
  1055.             IC.scroller_y = (IC.scrollbar_y+IC.scrollbar_h-scroller.Height);
  1056.             if(!IC.bot_reached) {
  1057.                 IC.pos = scroller2pos(IC.scroller_y);
  1058.             }
  1059.             if(y>=mouse_y) {
  1060.                 IC.scroll_down = true;
  1061.             }
  1062.         } else {
  1063.             if(myscreen.length>0) {
  1064.                 if(myscreen[myscreen.length-1].id == IC.list_total-1 && myscreen[myscreen.length-1].visible) {
  1065.                     if(y<mouse_y) {
  1066.                         IC.pos = scroller2pos(IC.scroller_y);
  1067.                     }
  1068.                 } else {
  1069.                     IC.pos = scroller2pos(IC.scroller_y);
  1070.                 }
  1071.             }
  1072.         }
  1073.         if(y!=mouse_y && !scroller_drag_timer) {
  1074.             scroller_drag_timer = window.CreateTimerInterval(60);
  1075.         }
  1076.     }
  1077.     mouse_x = x;
  1078.     mouse_y = y;
  1079. }
  1080.  
  1081. function on_mouse_wheel(delta) {
  1082.     var i;
  1083.     var scrollstep, scrollstep_min;
  1084.    
  1085.     IC.scroll_down = false;
  1086.    
  1087.     if(delta>0) {
  1088.         delta = 1;
  1089.         scrollstep = IC.scrollstep;
  1090.         scrollstep_min = IC.scrollstep_min;
  1091.     } else {
  1092.         delta = -1;
  1093.         scrollstep = IC.scrollstep;
  1094.         scrollstep_min = IC.scrollstep_min;
  1095.     }
  1096.    
  1097.     if(IC.scroll) {  
  1098.         IC.draw_cover = false;
  1099.         refresh_timer && window.KillTimer(refresh_timer);
  1100.         refresh_timer = false;
  1101.         if(delta>0) {
  1102.             for(i=0;i<scrollstep;i++) {
  1103.                 if(IC.topcut>0) {
  1104.                     IC.topcut--;
  1105.                 } else {
  1106.                     IC.pos += delta;
  1107.                 }
  1108.             }
  1109.             if(IC.pos>0) {
  1110.                 IC.pos = 0;
  1111.                 IC.topcut = 0;
  1112.             }
  1113.         } else {
  1114.             for(i=0;i<scrollstep_min;i++) {
  1115.                 switch(myscreen[i].gridx){
  1116.                     case 0:
  1117.                         IC.pos += delta;
  1118.                         IC.topcut = 0;
  1119.                         break;
  1120.                     default:
  1121.                         IC.topcut++;
  1122.                 }
  1123.             }
  1124.         }
  1125.         window.SetProperty("Item Offset", IC.pos);
  1126.         window.SetProperty("Group Offset", IC.topcut);
  1127.         on_item_focus_change();
  1128.     }
  1129. }
  1130.  
  1131. function on_mouse_leave() {
  1132.     var k;
  1133.     for(k=0;k<myscrollbarbt.length;k++) {
  1134.         myscrollbarbt[k].checkstate("leave", 0, 0, k);
  1135.     }
  1136.     for(k=0;k<mytoolbarbt.length;k++) {
  1137.         mytoolbarbt[k].checkstate("leave", 0, 0, k);
  1138.     }
  1139.  
  1140.     g_is_focused = false;
  1141.     on_item_focus_change();
  1142.     refresh_timer && window.KillTimer(refresh_timer);
  1143.     refresh_timer = false;
  1144.     refresh_timer = window.CreateTimerInterval(1000);
  1145. }
  1146.  
  1147. //=================================================// Event Callbacks
  1148. function on_timer(id) {
  1149.     var i;
  1150.    
  1151.     if(IC.scrollbar) {
  1152.         for (i=0;i<myscrollbarbt.length;i++) {
  1153.             myscrollbarbt[i].ontimer(id);
  1154.         }
  1155.     }
  1156.     if(IC.toolbar) {
  1157.         for (i=0;i<mytoolbarbt.length;i++) {
  1158.             mytoolbarbt[i].ontimer(id);
  1159.         }
  1160.     }
  1161.     if(scroller_drag_timer) {
  1162.         if(scroller_drag_timer.ID == id) {
  1163.             on_item_focus_change();
  1164.             scroller_drag_timer && window.KillTimer(scroller_drag_timer);
  1165.             scroller_drag_timer = false;
  1166.             if(IC.scroll_down) {
  1167.                 while(!IC.bot_reached) {
  1168.                     IC.scrollstep = IC.nbvis-1;
  1169.                     on_mouse_wheel(-1);
  1170.                 }
  1171.                 IC.scroll_down = false;
  1172.             }
  1173.         }
  1174.     }
  1175.     if(draw_cover_timer) {
  1176.         if(draw_cover_timer.ID == id) {
  1177.             IC.draw_cover = true;
  1178.             window.Repaint();
  1179.             draw_cover_timer && window.KillTimer(draw_cover_timer);
  1180.             draw_cover_timer = false;
  1181.         }
  1182.     }
  1183.     if(init_mouse_down_timer) {
  1184.         if(init_mouse_down_timer.ID == id) {
  1185.             mouse_down_timer && window.KillTimer(mouse_down_timer);
  1186.             mouse_down_timer = window.CreateTimerInterval(75);
  1187.             init_mouse_down_timer && window.KillTimer(init_mouse_down_timer);
  1188.             init_mouse_down_timer = false;
  1189.         }
  1190.     }
  1191.     if(mouse_down_timer) {
  1192.         if(mouse_down_timer.ID == id) {
  1193.             if(myscrollbarbt[1].state == myscrollbarbt[1].ButtonStates.down) {
  1194.                 on_mouse_wheel(1);
  1195.             } else {
  1196.                 on_mouse_wheel(-1);
  1197.             }
  1198.         }
  1199.     }
  1200.     if(wheel_up_timer) {
  1201.         if(wheel_up_timer.ID == id) {
  1202.             on_mouse_wheel(1);
  1203.         }
  1204.     }
  1205.     if(wheel_dn_timer) {
  1206.         if(wheel_dn_timer.ID == id) {
  1207.             on_mouse_wheel(-1);
  1208.         }
  1209.     }
  1210. }
  1211.  
  1212. function on_notify_data(name, info) {
  1213. }
  1214.  
  1215. function on_playlists_changed() {
  1216. }
  1217.  
  1218. function on_playlist_switch() {
  1219.     g_metadb_playlist = plman.GetPlaylistItems(fb.ActivePlaylist);
  1220.     IC.list_total = fb.PlaylistItemCount(fb.ActivePlaylist);
  1221.     ShowSelectedItem(-1);
  1222.     refresh_spv();
  1223.     if(IC.list_total>0) {
  1224.         IC.singleton_select_id = g_metadb_playlist.Find(fb.GetFocusItem());
  1225.         ShowSelectedItem(IC.singleton_select_id);
  1226.     }
  1227.     window.Repaint();
  1228. }
  1229.  
  1230. function on_playlist_items_added(playlist_idx) {
  1231.     if(playlist_idx==fb.ActivePlaylist) {
  1232.         g_metadb_playlist = plman.GetPlaylistItems(fb.ActivePlaylist);
  1233.         IC.list_total = fb.PlaylistItemCount(fb.ActivePlaylist);
  1234.         refresh_spv();
  1235.         ShowSelectedItem(-1);
  1236.         window.Repaint();
  1237.     }
  1238. }
  1239.  
  1240. function on_playlist_items_reordered(playlist_idx) {
  1241.     if(playlist_idx==fb.ActivePlaylist) {
  1242.         g_metadb_playlist = plman.GetPlaylistItems(fb.ActivePlaylist);
  1243.         IC.list_total = fb.PlaylistItemCount(fb.ActivePlaylist);
  1244.         refresh_spv();
  1245.         ShowSelectedItem(-1);
  1246.         window.Repaint();
  1247.     }
  1248. }
  1249.  
  1250. function on_selection_changed(metadb) {
  1251.     g_start_new_track = false;
  1252.     if(!IC.context_menu_called) {
  1253.         ShowSelectedItem(-1);
  1254.         on_item_focus_change();
  1255.     } else {
  1256.         IC.context_menu_called = false;
  1257.         ShowSelectedItem(-1);
  1258.         window.Repaint();
  1259.     }
  1260. }
  1261.  
  1262. function on_playlist_items_selection_change() {
  1263.     on_item_focus_change();
  1264. }
  1265.  
  1266. function on_item_focus_change() {  
  1267.     if(g_metadb) {
  1268.         window.UnwatchMetadb();
  1269.     }
  1270.     g_metadb = fb.GetFocusItem();
  1271.     IC.list_total = fb.PlaylistItemCount(fb.ActivePlaylist);
  1272.     IC.metadblist_selection = plman.GetPlaylistSelectedItems(fb.ActivePlaylist);
  1273.    
  1274.     if(IC.metadblist_selection) {
  1275.         on_metadb_changed();
  1276.         g_metadb && window.WatchMetadb(g_metadb);
  1277.     }
  1278. }
  1279.  
  1280. function on_metadb_changed() {
  1281.     if(g_metadb) {}
  1282.     refresh_spv();
  1283.     window.Repaint();
  1284. }
  1285.  
  1286. function on_focus(is_focused) {
  1287.     g_is_focused = is_focused;
  1288. }
  1289.  
  1290. function on_key_up(vkey) {
  1291.     wheel_up_timer && window.KillTimer(wheel_up_timer);
  1292.     wheel_up_timer = false;
  1293.     wheel_dn_timer && window.KillTimer(wheel_dn_timer);
  1294.     wheel_dn_timer = false;
  1295. }
  1296.  
  1297. function on_key_down(vkey) {
  1298.     var mask = GetKeyboardMask();
  1299.     var focus_id;
  1300.  
  1301.     if (mask == KMask.none) {
  1302.         switch (vkey) {
  1303.         case VK_UP:
  1304.             IC.scrollstep = 1;
  1305.             if(!wheel_up_timer) {
  1306.                 wheel_up_timer = window.CreateTimerInterval(75);
  1307.             }
  1308.             break;
  1309.         case VK_DOWN:
  1310.             IC.scrollstep = 1;
  1311.             if(!wheel_dn_timer) {
  1312.                 wheel_dn_timer = window.CreateTimerInterval(75);
  1313.             }
  1314.             break;
  1315.         case VK_PGUP:
  1316.             IC.scrollstep = IC.nbvis-1;
  1317.             if(!wheel_up_timer) {
  1318.                 wheel_up_timer = window.CreateTimerInterval(75);
  1319.             }
  1320.             break;
  1321.         case VK_PGDN:
  1322.             IC.scrollstep = IC.nbvis-1;
  1323.             if(!wheel_dn_timer) {
  1324.                 wheel_dn_timer = window.CreateTimerInterval(75);
  1325.             }
  1326.             break;
  1327.         case VK_RETURN:
  1328.             // play focus item
  1329.             fb.RunContextCommandWithMetadb("Play", fb.GetFocusItem());
  1330.             break;
  1331.         case VK_ESCAPE:
  1332.             // clear selection (select only the focused item)
  1333.             plman.ClearPlaylistSelection(fb.ActivePlaylist);
  1334.             on_item_focus_change();
  1335.             break;
  1336.         case VK_END:
  1337.             IC.pos = 0 - (IC.list_total-(IC.nbvis-1));
  1338.             IC.topcut = 0;
  1339.             IC.scroll_down = true;
  1340.             // check if bot reached, if not, reaching it
  1341.             scroller_drag_timer = window.CreateTimerInterval(60);
  1342.             break;
  1343.         case VK_HOME:
  1344.             IC.pos = 0;
  1345.             IC.topcut = 0;
  1346.             on_item_focus_change();
  1347.             break;
  1348.         case VK_DELETE:
  1349.             IC.metadblist_selection.Sort();
  1350.             var id_to_remove;
  1351.             var new_focus_id;
  1352.             for(i=0;i<IC.metadblist_selection.Count;i++) {
  1353.                 id_to_remove = Math.round(g_metadb_playlist.Find(IC.metadblist_selection.Item(i)));
  1354.                 if(id_to_remove==IC.list_total-1) {
  1355.                     new_focus_id = Math.round(IC.list_total-1);
  1356.                 } else {
  1357.                     new_focus_id = Math.round(id_to_remove);
  1358.                 }
  1359.                 plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, id_to_remove, true);
  1360.                 plman.SetPlaylistFocusItem(fb.ActivePlaylist, id_to_remove);
  1361.                 fb.RunMainMenuCommand("Edit/Selection/Remove");
  1362.                 g_metadb_playlist = plman.GetPlaylistItems(fb.ActivePlaylist);
  1363.                 IC.list_total = fb.PlaylistItemCount(fb.ActivePlaylist);
  1364.             }
  1365.             if(IC.list_total>0) {
  1366.                 plman.SetPlaylistFocusItem(fb.ActivePlaylist, new_focus_id);
  1367.             }
  1368.             break;
  1369.         }
  1370.     }
  1371. }
  1372.  
  1373. //=================================================// Playback Callbacks
  1374. function on_playback_new_track(info) {
  1375.     g_start_new_track = true;
  1376.     CursorFollowsPlayback();
  1377.     on_item_focus_change();
  1378. }  
  1379.  
  1380. function on_playback_stop(reason) {
  1381.     if(reason==0) { // on user Stop
  1382.         on_item_focus_change();
  1383.     }
  1384. }
  1385.  
  1386. function on_playback_pause(state){
  1387. }
  1388.  
  1389. function on_playback_time(time) {
  1390.     g_playtime_parity = (time/2-Math.floor(time/2)==0)?0:1;
  1391.     window.Repaint();
  1392. }
  1393.  
  1394. //=================================================// Populate playlist
  1395. function refresh_spv() {
  1396.     var i, m;
  1397.     var j=0; // idx of bounded items
  1398.     var k=0; // idx of screen lines
  1399.     var gstart = null;
  1400.  
  1401.     IC.nb_hidden_lines = 0;
  1402.     IC.total_items_visible = 0;
  1403.     IC.nbvis = Math.ceil(wh/IC.height);  
  1404.     IC.list_total = fb.PlaylistItemCount(fb.ActivePlaylist);
  1405.    
  1406.     var deb = IC.pos>0?0:IC.pos*-1;
  1407.     var end = deb + IC.nbvis - 1;
  1408.     if(end>IC.list_total-1) end = IC.list_total-1;
  1409.        
  1410.     myitem.splice(0, myitem.length);
  1411.     myscreen.splice(0, myscreen.length);
  1412.    
  1413.     for(i=deb;i<end+1;i++) {
  1414.         myitem.push(new item);
  1415.         myitem[j].create(i, g_metadb_playlist.Item(i), j);
  1416.  
  1417.         if(myitem[j].id>0) {
  1418.             var previous_item = new item;
  1419.             if(myitem[j].idx>0) {
  1420.                 previous_item = myitem[myitem[j].idx-1];
  1421.             } else {
  1422.                 previous_item.create(myitem[j].id-1, g_metadb_playlist.Item(myitem[j].id-1), -1);
  1423.             }
  1424.             myitem[j].isgroup = (myitem[j].group_key!=previous_item.group_key)?true:false;
  1425.         } else {
  1426.             myitem[j].isgroup = true;
  1427.         }
  1428.                
  1429.         if(myitem[j].isgroup) {
  1430.             gstart = k>0?0:IC.topcut;
  1431.             for(m=gstart;m<IC.ghnbrows;m++) {
  1432.                 myscreen.push(new item);
  1433.                 myscreen[k].create(i, g_metadb_playlist.Item(i), k);
  1434.                 myscreen[k].gridx = m+1;
  1435.                 myscreen[k].y = myscreen[k].idx*IC.height + IC.toolbar_height;
  1436.                 myscreen[k].visible = (k<IC.nbvis-1)?true:false;
  1437.                 if(!myscreen[k].visible) {
  1438.                     IC.nb_hidden_lines++;
  1439.                 }
  1440.                 k++;
  1441.             }
  1442.         }
  1443.        
  1444.         // item
  1445.         myscreen.push(new item);
  1446.         myscreen[k].create(i, g_metadb_playlist.Item(i), k);
  1447.         myscreen[k].gridx = 0;
  1448.         myscreen[k].y = myscreen[k].idx*IC.height + IC.toolbar_height;
  1449.         myscreen[k].visible = (k<IC.nbvis-1)?true:false;
  1450.         if(plman.IsPlaylistItemSelected(fb.ActivePlaylist, i)) {
  1451.             myscreen[k].state = myscreen[k].ItemStates.selected;
  1452.         }
  1453.         if(!myscreen[k].visible) {
  1454.             IC.nb_hidden_lines++;
  1455.         } else {
  1456.             IC.total_items_visible++;
  1457.         }
  1458.         myitem[j].visible = myscreen[k].visible;
  1459.         k++;
  1460.                
  1461.         // test if scrolling required
  1462.         if(IC.pos<0) {
  1463.             IC.scroll = true;
  1464.         } else {
  1465.             if(myitem[j].id==IC.list_total-1 && myitem[j].visible) {
  1466.                 IC.scroll = false;
  1467.             } else {
  1468.                 IC.scroll = true;
  1469.             }
  1470.         }
  1471.         j++;
  1472.     }
  1473.    
  1474.     // test if last item of the playlist is visible (bottom of the list reached, no more scrolling down!)
  1475.     if(myscreen.length>0) {
  1476.         if(myscreen[myscreen.length-1].id==IC.list_total-1) {
  1477.             var hh = Math.round(IC.toolbar_height) + (IC.nbvis-2)*IC.height;
  1478.             if(myscreen[myscreen.length-1].y <= hh) {
  1479.                 IC.bot_reached = true;
  1480.             } else {
  1481.                 IC.bot_reached = false;
  1482.             }
  1483.         }
  1484.     }
  1485.    
  1486.     // if last item of myscreen not the last playlist item => scrollstep is default
  1487.     if(myscreen.length>0) {
  1488.         if(myscreen[myscreen.length-1].id==IC.list_total-1) {
  1489.             if(IC.nb_hidden_lines<IC.scrollstep) {
  1490.                 IC.scrollstep_min = IC.nb_hidden_lines;
  1491.             } else {
  1492.                 IC.scrollstep_min = IC.scrollstep;
  1493.             }
  1494.         } else {
  1495.             IC.scrollstep_min = IC.scrollstep;
  1496.         }
  1497.     }
  1498.    
  1499.     // launch a timer to request an asynchronous cover art refresh
  1500.     if(IC.show_coverart && !IC.draw_cover) {
  1501.         draw_cover_timer && window.KillTimer(draw_cover_timer);
  1502.         draw_cover_timer = false;
  1503.         draw_cover_timer = window.CreateTimerInterval(250);
  1504.     }
  1505. }
  1506.  
  1507. //=================================================// Item Context Menu
  1508. function new_context_menu(x, y, id, array_id) {
  1509.     var MF_STRING = 0x00000000;
  1510.     var MF_SEPARATOR = 0x00000800;
  1511.     var MF_GRAYED = 0x00000001;
  1512.     var MF_DISABLED = 0x00000002;
  1513.    
  1514.     IC.context_menu_called = true;
  1515.    
  1516.     var _menu = window.CreatePopupMenu();
  1517.     var Context = fb.CreateContextMenuManager();
  1518.     Context.InitContext(IC.metadblist_selection);
  1519.     Context.BuildMenu(_menu, 1, -1);
  1520.  
  1521.     _menu.AppendMenuItem(MF_SEPARATOR, 0, "");
  1522.     _menu.AppendMenuItem((fb.IsAutoPlaylist(fb.ActivePlaylist))?MF_DISABLED|MF_GRAYED:MF_STRING, 810, "Remove");
  1523.     _menu.AppendMenuItem(MF_SEPARATOR, 0, "");
  1524.     _menu.AppendMenuItem(fb.IsPlaying?MF_STRING:MF_DISABLED|MF_GRAYED, 800, "Show Now Playing");
  1525.    
  1526.     var ret = _menu.TrackPopupMenu(x, y);
  1527.     if(ret<800) {
  1528.         Context.ExecuteByID(ret - 1);
  1529.     } else {
  1530.         switch (ret) {
  1531.         case 800:
  1532.             ShowNowPlaying();
  1533.             on_item_focus_change();
  1534.             break;
  1535.         case 810:
  1536.             IC.metadblist_selection.Sort();
  1537.             var id_to_remove = -1;
  1538.             var new_focus_id = 0;
  1539.             for(i=0;i<IC.metadblist_selection.Count;i++) {
  1540.                 id_to_remove = g_metadb_playlist.Find(IC.metadblist_selection.Item(i));
  1541.                 if(id_to_remove==IC.list_total-1) {
  1542.                     new_focus_id = IC.list_total==1?-1:IC.list_total-1;
  1543.                 } else {
  1544.                     new_focus_id = id_to_remove;
  1545.                 }
  1546.                 plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, id_to_remove, true);
  1547.                 plman.SetPlaylistFocusItem(fb.ActivePlaylist, id_to_remove);
  1548.                 fb.RunMainMenuCommand("Edit/Selection/Remove");
  1549.                 g_metadb_playlist = plman.GetPlaylistItems(fb.ActivePlaylist);
  1550.                 IC.list_total = fb.PlaylistItemCount(fb.ActivePlaylist);
  1551.             }
  1552.             break;
  1553.         }
  1554.     }
  1555. }
  1556.  
  1557. function draw_icons() {
  1558.     var i;
  1559.     var gb;
  1560.     var gui_font = gdi.Font("guifx v2 transports", 15, 0);
  1561.    
  1562.     playicon_off = gdi.CreateImage(16, 16);
  1563.     gb = playicon_off.GetGraphics();
  1564.     gb.SetTextRenderingHint(4);
  1565.     gb.DrawString("1", gui_font, RGB(255,255,255), 0, 0, playicon_off.Width, playicon_off.Height, cc_stringformat);
  1566.     gb.DrawString("1", gui_font, RGB(100,100,100), 0, 2, playicon_off.Width, playicon_off.Height, cc_stringformat);
  1567.     gb.DrawString("1", gui_font, RGB(150,150,150), 0, 1, playicon_off.Width, playicon_off.Height, cc_stringformat);
  1568.     playicon_off.ReleaseGraphics(gb);
  1569.  
  1570.     star_img_off = gdi.CreateImage(13, 18);
  1571.     gb = star_img_off.GetGraphics();
  1572.     gui_font = gdi.Font("guifx v2 transports", 17, 0);
  1573.     gb.SetTextRenderingHint(4);
  1574.     gb.DrawString("b", gui_font, RGB(230,230,230), 0, 0, 13, 18, lt_stringformat);
  1575.     star_img_off.ReleaseGraphics(gb);
  1576.  
  1577.     star_img_on = gdi.CreateImage(13, 18);
  1578.     gb = star_img_on.GetGraphics();
  1579.     gui_font = gdi.Font("guifx v2 transports", 17, 0);
  1580.     gb.SetTextRenderingHint(4);
  1581.     gb.DrawString("b", gui_font, RGB(150,150,150), 0, 0, 13, 18, lt_stringformat);
  1582.     star_img_on.ReleaseGraphics(gb);
  1583.  
  1584.     star_img_hov = gdi.CreateImage(13, 18);
  1585.     gb = star_img_hov.GetGraphics();
  1586.     gui_font = gdi.Font("guifx v2 transports", 17, 0);
  1587.     gb.SetTextRenderingHint(3);
  1588.     gb.DrawString("b", gui_font, RGB(50, 50, 200), 0, 0, 13, 18, lt_stringformat);
  1589.     star_img_hov.ReleaseGraphics(gb);
  1590.  
  1591.     star_img_kill = gdi.CreateImage(13, 18);
  1592.     gb = star_img_kill.GetGraphics();
  1593.     gui_font = gdi.Font("guifx v2 transports", 15, 0);
  1594.     gb.SetTextRenderingHint(3);
  1595.     gui_font = gdi.Font("guifx v2 transports", 17, 0);
  1596.     gb.DrawString("b", gui_font, RGB(200,50,50), 0, 0, 13, 18, lt_stringformat);
  1597.     star_img_kill.ReleaseGraphics(gb);
  1598.    
  1599.     // Set rating area width
  1600.     rating_w = Math.floor(star_img_off.Width*5);
  1601.     rating_h = Math.floor(star_img_off.Height);
  1602.    
  1603.     scroller = gdi.CreateImage(IC.scrollbar_width-2, 18);
  1604.     gb = scroller.GetGraphics();
  1605.     gb.SetSmoothingMode(2);
  1606.     gb.FillRoundRect(2,2,IC.scrollbar_width-5,15,2,2,RGB(120,120,120));
  1607.     gb.FillGradRect(1,1,IC.scrollbar_width-5,15,0,RGB(200,200,200),RGB(240,240,240),0.5);
  1608.     gb.DrawRoundRect(1,1,IC.scrollbar_width-5,15,2,2,1.0,RGB(255,255,255));
  1609.     gb.SetSmoothingMode(0);
  1610.     gb.FillSolidRect(4,6,IC.scrollbar_width-10,1,RGB(175,175,175));
  1611.     gb.FillSolidRect(4,9,IC.scrollbar_width-10,1,RGB(175,175,175));
  1612.     gb.FillSolidRect(4,12,IC.scrollbar_width-10,1,RGB(175,175,175));
  1613.     gb.FillSolidRect(4,5,IC.scrollbar_width-10,1,RGB(255,255,255));
  1614.     gb.FillSolidRect(4,8,IC.scrollbar_width-10,1,RGB(255,255,255));
  1615.     gb.FillSolidRect(4,11,IC.scrollbar_width-10,1,RGB(255,255,255));
  1616.     scroller.ReleaseGraphics(gb);
  1617.  
  1618.     nocover = gdi.CreateImage(200, 200);
  1619.     gb = nocover.GetGraphics();
  1620.     gb.SetSmoothingMode(2);
  1621.     gb.FillGradRect(0,0,200,200,90,RGB(200,200,200),RGB(240,240,240),1.0);
  1622.     gb.SetTextRenderingHint(3);
  1623.     gui_font = gdi.Font("guifx v2 transports", 132, 0);
  1624.     gb.DrawString("x", gui_font, RGB(255,255,255), 1, 3, 200, 200, cc_stringformat);
  1625.     gb.DrawString("x", gui_font, RGB(120,120,120), 1, 0, 200, 200, cc_stringformat);
  1626.     nocover.ReleaseGraphics(gb);
  1627.  
  1628.     streamcover = gdi.CreateImage(200, 200);
  1629.     gb = streamcover.GetGraphics();
  1630.     gb.SetSmoothingMode(2);
  1631.     gb.FillGradRect(0,0,nocover.Width,nocover.Height,90,RGB(200,200,200),RGB(240,240,240),1.0);
  1632.     gb.SetTextRenderingHint(3);
  1633.     gui_font = gdi.Font("guifx v2 transports", 126, 0);
  1634.     gb.DrawString("$", gui_font, RGB(255,255,255), 1, 3, 200, 200, cc_stringformat);
  1635.     gb.DrawString("$", gui_font, RGB(120,120,120), 1, 0, 200, 200, cc_stringformat);
  1636.     streamcover.ReleaseGraphics(gb);
  1637.  
  1638.     CollectGarbage();
  1639. }
  1640.  
  1641. function refresh_scroller_popup(letter) {
  1642.     var gb;
  1643.     var font = gdi.Font("segoe ui", 14, 1);
  1644.    
  1645.     scroller_popup = gdi.CreateImage(22, 22);
  1646.     gb = scroller_popup.GetGraphics();
  1647.     gb.SetSmoothingMode(2);
  1648.     gb.FillRoundRect(0,0,scroller_popup.Width-1,scroller_popup.Height-1,3,3,RGBA(40,40,40,200));
  1649.     gb.DrawRoundRect(0,0,scroller_popup.Width-1,scroller_popup.Height-1,3,3,1.0,RGB(0,0,0));
  1650.     gb.SetTextRenderingHint(3);
  1651.     gb.DrawString(letter.toUpperCase(), font, RGB(0,0,0), 0, 0, scroller_popup.Width, scroller_popup.Height, cc_stringformat);
  1652.     gb.DrawString(letter.toUpperCase(), font, RGB(255,255,255), 0, -1, scroller_popup.Width, scroller_popup.Height, cc_stringformat);
  1653.     scroller_popup.ReleaseGraphics(gb);
  1654.  
  1655.     CollectGarbage();
  1656. }
  1657.  
  1658. function refresh_buttons() {
  1659.     var i;
  1660.     var gb;
  1661.     var gui_font = gdi.Font("guifx v2 transports", 12, 0);
  1662.     var DT_LT = DT_LEFT | DT_TOP | DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOPREFIX;
  1663.        
  1664.     scrollbarbt_menu = gdi.CreateImage(IC.scrollbar_width, IC.scrollbar_bt_h);
  1665.     gb = scrollbarbt_menu.GetGraphics();
  1666.     gb.FillSolidRect(1, 0, scrollbarbt_menu.Width-2, scrollbarbt_menu.Height-1, RGB(250,250,250));
  1667.     gb.FillSolidRect(2, 1, scrollbarbt_menu.Width-2, scrollbarbt_menu.Height-1, RGB(100,100,100));
  1668.     gb.FillSolidRect(2, 1, scrollbarbt_menu.Width-3, scrollbarbt_menu.Height-2, RGB(200,200,200));
  1669.     gb.SetTextRenderingHint(4);
  1670.     gui_font = gdi.Font("guifx v2 transports", 14, 0);
  1671.     gb.DrawString(IC.toolbar?"s":"a", gui_font, RGB(250,250,250), 1, 1, scrollbarbt_menu.Width-1, scrollbarbt_menu.Height, cc_stringformat);
  1672.     gb.DrawString(IC.toolbar?"s":"a", gui_font, RGB(100,100,100), 1, 0, scrollbarbt_menu.Width-1, scrollbarbt_menu.Height, cc_stringformat);
  1673.     scrollbarbt_menu.ReleaseGraphics(gb);
  1674.  
  1675.     scrollbarbt_up = gdi.CreateImage(IC.scrollbar_width, IC.scrollbar_bt_h);
  1676.     gb = scrollbarbt_up.GetGraphics();
  1677.     gb.FillSolidRect(1, 0, scrollbarbt_menu.Width-2, scrollbarbt_menu.Height-1, RGB(250,250,250));
  1678.     gb.FillSolidRect(2, 1, scrollbarbt_menu.Width-2, scrollbarbt_menu.Height-1, RGB(100,100,100));
  1679.     gb.FillSolidRect(2, 1, scrollbarbt_menu.Width-3, scrollbarbt_menu.Height-2, RGB(200,200,200));
  1680.     gb.SetTextRenderingHint(4);
  1681.     gui_font = gdi.Font("guifx v2 transports", 12, 0);
  1682.     gb.DrawString(".", gui_font, RGB(250,250,250), 1, 1, scrollbarbt_menu.Width-1, scrollbarbt_menu.Height, cc_stringformat);
  1683.     gb.DrawString(".", gui_font, RGB(100,100,100), 1, 0, scrollbarbt_menu.Width-1, scrollbarbt_menu.Height, cc_stringformat);
  1684.     scrollbarbt_up.ReleaseGraphics(gb);
  1685.  
  1686.     scrollbarbt_down = gdi.CreateImage(IC.scrollbar_width, IC.scrollbar_bt_h);
  1687.     gb = scrollbarbt_down.GetGraphics();
  1688.     gb.FillSolidRect(1, 0, scrollbarbt_menu.Width-2, scrollbarbt_menu.Height-1, RGB(250,250,250));
  1689.     gb.FillSolidRect(2, 1, scrollbarbt_menu.Width-2, scrollbarbt_menu.Height-1, RGB(100,100,100));
  1690.     gb.FillSolidRect(2, 1, scrollbarbt_menu.Width-3, scrollbarbt_menu.Height-2, RGB(200,200,200));
  1691.     gb.SetTextRenderingHint(4);
  1692.     gui_font = gdi.Font("guifx v2 transports", 12, 0);
  1693.     gb.DrawString(",", gui_font, RGB(250,250,250), 1, 1, scrollbarbt_menu.Width-1, scrollbarbt_menu.Height, cc_stringformat);
  1694.     gb.DrawString(",", gui_font, RGB(100,100,100), 1, 0, scrollbarbt_menu.Width-1, scrollbarbt_menu.Height, cc_stringformat);
  1695.     scrollbarbt_down.ReleaseGraphics(gb);
  1696.  
  1697.     myscrollbarbt.splice(0, myscrollbarbt.length);
  1698.     for(i=0;i<3;i++) {
  1699.         myscrollbarbt.push(new button);
  1700.         switch(i) {
  1701.         case 0:
  1702.             myscrollbarbt[i].create(scrollbarbt_menu, scrollbarbt_menu, scrollbarbt_menu, "", -01);
  1703.             break;
  1704.         case 1:
  1705.             myscrollbarbt[i].create(scrollbarbt_up, scrollbarbt_up, scrollbarbt_up, "", -02);
  1706.             break;            
  1707.         case 2:
  1708.             myscrollbarbt[i].create(scrollbarbt_down, scrollbarbt_down, scrollbarbt_down, "", -03);
  1709.             break;            
  1710.         }
  1711.     }
  1712.  
  1713.     mytoolbarbt_shownowplaying = gdi.CreateImage(20, IC.default_toolbar_height);
  1714.     gb = mytoolbarbt_shownowplaying.GetGraphics();
  1715.     gb.FillSolidRect(mytoolbarbt_shownowplaying.Width-1, 1, 1, mytoolbarbt_shownowplaying.Height-2, RGB(100,100,100));
  1716.     gb.FillSolidRect(mytoolbarbt_shownowplaying.Width-0, 1, 1, mytoolbarbt_shownowplaying.Height-2, RGB(255,255,255));
  1717.     gb.SetTextRenderingHint(4);
  1718.     gui_font = gdi.Font("guifx v2 transports", 16, 0);
  1719.     gb.DrawString("i", gui_font, RGB(255,255,255), 0, 1, mytoolbarbt_shownowplaying.Width-1, mytoolbarbt_shownowplaying.Height, cc_stringformat);
  1720.     gb.DrawString("i", gui_font, RGB(130,130,130), 0, 0, mytoolbarbt_shownowplaying.Width-1, mytoolbarbt_shownowplaying.Height, cc_stringformat);
  1721.     mytoolbarbt_shownowplaying.ReleaseGraphics(gb);
  1722.    
  1723.     mytoolbarbt_scrollbar = gdi.CreateImage(20, IC.default_toolbar_height);
  1724.     gb = mytoolbarbt_scrollbar.GetGraphics();
  1725.     gb.FillSolidRect(0, 1, 1, mytoolbarbt_scrollbar.Height-2, RGB(100,100,100));
  1726.     gb.FillSolidRect(1, 1, 1, mytoolbarbt_scrollbar.Height-2, RGB(255,255,255));
  1727.     gb.SetTextRenderingHint(4);
  1728.     gui_font = gdi.Font("guifx v2 transports", 15, 0);
  1729.     gb.DrawString(IC.scrollbar?"D":"A", gui_font, RGB(255,255,255), 1, 1, mytoolbarbt_scrollbar.Width-1, mytoolbarbt_scrollbar.Height, cc_stringformat);
  1730.     gb.DrawString(IC.scrollbar?"D":"A", gui_font, RGB(130,130,130), 1, 0, mytoolbarbt_scrollbar.Width-1, mytoolbarbt_scrollbar.Height, cc_stringformat);
  1731.     mytoolbarbt_scrollbar.ReleaseGraphics(gb);
  1732.  
  1733.     mytoolbarbt_search = gdi.CreateImage(20, IC.default_toolbar_height);
  1734.     gb = mytoolbarbt_search.GetGraphics();
  1735.     gb.FillSolidRect(mytoolbarbt_search.Width-1, 1, 1, mytoolbarbt_search.Height-2, RGB(100,100,100));
  1736.     gb.FillSolidRect(mytoolbarbt_search.Width-0, 1, 1, mytoolbarbt_search.Height-2, RGB(255,255,255));
  1737.     gb.SetTextRenderingHint(4);
  1738.     gui_font = gdi.Font("guifx v2 transports", 15, 0);
  1739.     gb.DrawString(")", gui_font, RGB(255,255,255), 0, 1, mytoolbarbt_search.Width-1, mytoolbarbt_search.Height, cc_stringformat);
  1740.     gb.DrawString(")", gui_font, RGB(130,130,130), 0, 0, mytoolbarbt_search.Width-1, mytoolbarbt_search.Height, cc_stringformat);
  1741.     mytoolbarbt_search.ReleaseGraphics(gb);
  1742.  
  1743.     mytoolbarbt_sort = gdi.CreateImage(20, IC.default_toolbar_height);
  1744.     gb = mytoolbarbt_sort.GetGraphics();
  1745.     gb.FillSolidRect(mytoolbarbt_sort.Width-1, 1, 1, mytoolbarbt_sort.Height-2, RGB(100,100,100));
  1746.     gb.FillSolidRect(mytoolbarbt_sort.Width-0, 1, 1, mytoolbarbt_sort.Height-2, RGB(255,255,255));
  1747.     gb.SetTextRenderingHint(4);
  1748.     gui_font = gdi.Font("segoe ui", 12, 0);
  1749.     gb.DrawString("Az", gui_font, RGB(255,255,255), 0, 0, mytoolbarbt_sort.Width-1, mytoolbarbt_sort.Height, cc_stringformat);
  1750.     gb.DrawString("Az", gui_font, RGB(130,130,130), 0, -1, mytoolbarbt_sort.Width-1, mytoolbarbt_sort.Height, cc_stringformat);
  1751.     mytoolbarbt_sort.ReleaseGraphics(gb);
  1752.  
  1753.     mytoolbarbt.splice(0, mytoolbarbt.length);
  1754.     for(i=0;i<4;i++) {
  1755.         mytoolbarbt.push(new button);
  1756.         switch(i) {
  1757.         case 0:
  1758.             mytoolbarbt[i].create(mytoolbarbt_shownowplaying, mytoolbarbt_shownowplaying, mytoolbarbt_shownowplaying, "", -01);
  1759.             break;          
  1760.         case 1:
  1761.             mytoolbarbt[i].create(mytoolbarbt_scrollbar, mytoolbarbt_scrollbar, mytoolbarbt_scrollbar, "", -02);
  1762.             break;  
  1763.         case 2:
  1764.             mytoolbarbt[i].create(mytoolbarbt_search, mytoolbarbt_search, mytoolbarbt_search, "", -03);
  1765.             break;  
  1766.         case 3:
  1767.             mytoolbarbt[i].create(mytoolbarbt_sort, mytoolbarbt_sort, mytoolbarbt_sort, "", -04);
  1768.             break;  
  1769.         }
  1770.     }
  1771.    
  1772.     CollectGarbage();
  1773. }
  1774.  
  1775. function CursorFollowsPlayback() {
  1776.     var i;
  1777.     if(fb.ActivePlaylist!=fb.PlayingPlaylist) {
  1778.         fb.ActivePlaylist = fb.PlayingPlaylist;
  1779.         g_metadb_playlist = plman.GetPlaylistItems(fb.ActivePlaylist);
  1780.         IC.list_total = fb.PlaylistItemCount(fb.ActivePlaylist);
  1781.     }
  1782.     IC.nowplaying = plman.GetPlayingItemLocation();
  1783.     var pid = IC.nowplaying.PlaylistItemIndex;
  1784.     var already_shown = false;
  1785.     for(i=0;i<myitem.length;i++) {
  1786.         if(myitem[i].id == pid) {
  1787.             if(myitem[i].visible) {
  1788.                 already_shown = true;
  1789.             }
  1790.             break;
  1791.         }
  1792.     }
  1793.     if(!already_shown) {
  1794.         IC.pos = 0 - pid +1;
  1795.         if(IC.pos>0) {
  1796.             IC.pos = 0;
  1797.             IC.topcut = 0;
  1798.         }
  1799.         if(pid < Math.ceil(IC.viscount/2)) {
  1800.             IC.pos = 0;
  1801.         }
  1802.     }
  1803.     plman.ClearPlaylistSelection(fb.ActivePlaylist);
  1804.     plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, pid, true);
  1805.     plman.SetPlaylistFocusItem(fb.ActivePlaylist, pid);
  1806.     IC.metadblist_selection = plman.GetPlaylistSelectedItems(fb.ActivePlaylist);
  1807.     IC.singleton_select_id = pid;
  1808. }
  1809.  
  1810. function ShowNowPlaying() {
  1811.    
  1812.     if(!fb.IsPlaying) return true;
  1813.    
  1814.     if(fb.ActivePlaylist!=fb.PlayingPlaylist) {
  1815.         fb.ActivePlaylist = fb.PlayingPlaylist;
  1816.         g_metadb_playlist = plman.GetPlaylistItems(fb.ActivePlaylist);
  1817.         IC.list_total = fb.PlaylistItemCount(fb.ActivePlaylist);
  1818.     }
  1819.     IC.nowplaying = plman.GetPlayingItemLocation();
  1820.     var pid = IC.nowplaying.PlaylistItemIndex;
  1821.     IC.pos = 0 - pid +1;
  1822.     if(IC.pos>0) {
  1823.         IC.pos = 0;
  1824.         IC.topcut = 0;
  1825.     }
  1826.     if(pid < Math.ceil(IC.viscount/2)) {
  1827.         IC.pos = 0;
  1828.     }
  1829.     refresh_spv();
  1830. }
  1831.  
  1832. function ShowSelectedItem(pid) {
  1833.     var i;
  1834.     if(IC.list_total==0) return true;
  1835.     if(pid<0) {
  1836.         var focus_item = fb.GetFocusItem();
  1837.         pid = g_metadb_playlist.Find(focus_item);
  1838.     }
  1839.     var already_shown = false;
  1840.     for(i=0;i<myitem.length;i++) {
  1841.         if(myitem[i].id == pid) {
  1842.             if(myitem[i].visible) {
  1843.                 already_shown = true;
  1844.             }
  1845.             break;
  1846.         }
  1847.     }
  1848.     if(!already_shown) {
  1849.         IC.pos = 0 - pid +1;
  1850.         if(IC.pos>0) {
  1851.             IC.pos = 0;
  1852.             IC.topcut = 0;
  1853.         }
  1854.         if(pid < Math.ceil(IC.viscount/2)) {
  1855.             IC.pos = 0;
  1856.         }
  1857.         refresh_spv();
  1858.     }
  1859.     plman.SetPlaylistFocusItem(fb.ActivePlaylist, pid);
  1860.     plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, pid, true);
  1861. }
  1862.  
  1863. function SelectGroupItems(start_id, group_key) {
  1864.     var i;
  1865.     var count=0;
  1866.     var gitem;
  1867.     var gitem_prev;
  1868.     if(!utils.IsKeyPressed(VK_CONTROL)) {
  1869.         plman.ClearPlaylistSelection(fb.ActivePlaylist);
  1870.     }
  1871.     for(i=start_id;i<IC.list_total;i++) {
  1872.         gitem_prev = gitem;
  1873.         gitem = new item;
  1874.         gitem.template_it(i, g_metadb_playlist.Item(i));
  1875.         if(gitem.group_key==group_key) {
  1876.             plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, gitem.id, true);
  1877.         } else {
  1878.             break;
  1879.         }
  1880.         count++;
  1881.         if(count>999) break;
  1882.     }
  1883.     plman.SetPlaylistFocusItem(fb.ActivePlaylist, gitem_prev.id);
  1884.     IC.singleton_select_id = gitem_prev.id;
  1885.     CollectGarbage();
  1886.     on_item_focus_change();
  1887. }
  1888.  
  1889. function SelectAtoB(start_id, end_id) {
  1890.     var i;
  1891.     var affectedItems = Array();
  1892.    
  1893.     if(start_id<end_id) {
  1894.         var deb = start_id;
  1895.         var fin = end_id;
  1896.     } else {
  1897.         var deb = end_id;
  1898.         var fin = start_id;        
  1899.     }
  1900.  
  1901.     for(i=deb;i<=fin;i++) {
  1902.         affectedItems.push(i);
  1903.     }
  1904.     plman.SetPlaylistSelection(fb.ActivePlaylist, affectedItems, true);
  1905.     on_item_focus_change();
  1906. }
  1907.  
  1908. //=================================================// Cover Art Tools
  1909. image_cache = function () {
  1910.     this._cachelist = {};
  1911.     this.hit = function (item) {
  1912.         var img = this._cachelist[item.cover_path];
  1913.         if (typeof img == "undefined") {
  1914.             if(IC.draw_cover) {
  1915.                 img = refresh_cover(item);
  1916.                 this._cachelist[item.cover_path] = img;
  1917.             }
  1918.         }
  1919.         return img;
  1920.     }
  1921. }
  1922. var g_image_cache = new image_cache;
  1923.  
  1924. function TrackType(trkpath) {
  1925.     var taggable;
  1926.     var type;
  1927.     switch (trkpath) {
  1928.         case "file":
  1929.         taggable = 1;
  1930.         type = 0;
  1931.         break;
  1932.         case "cdda":
  1933.         taggable = 1;
  1934.         type = 1;
  1935.         break;
  1936.         case "FOO_":
  1937.         taggable = 0;
  1938.         type = 2;
  1939.         break;
  1940.         case "http":
  1941.         taggable = 0;
  1942.         type = 3;
  1943.         break;
  1944.         case "mms:":
  1945.         taggable = 0;
  1946.         type = 3;
  1947.         break;
  1948.         case "unpa":
  1949.         taggable = 0;
  1950.         type = 4;
  1951.         break;
  1952.         default:
  1953.         taggable = 0;
  1954.         type = 5;
  1955.     }
  1956.     return type;
  1957. }
  1958.  
  1959. function FormatCover(image) {
  1960.     if(!image) return image;
  1961.     if(cover_w<=0 || cover_h<=0) return image;
  1962.     var tmp_img = gdi.CreateImage(cover_w, cover_h);
  1963.     var gp = tmp_img.GetGraphics();
  1964.     gp.SetInterpolationMode(7);
  1965.     gp.DrawImage(image, -1, -1, cover_w+2, cover_h+2, 0, 0, image.width, image.height, 0, 255);
  1966.     gp.SetSmoothingMode(2);
  1967.     // frame
  1968.     gp.DrawRect(0, 0, cover_w-1, cover_h-1, 1.0, RGBA(250,250,250,255));
  1969.     gp.DrawRect(1, 1, cover_w-3, cover_h-3, 1.0, RGBA(0,0,0,055));
  1970.     tmp_img.ReleaseGraphics(gp);
  1971.     CollectGarbage();
  1972.     return tmp_img;
  1973. }
  1974.  
  1975. function refresh_cover(item) {
  1976.     var type = 0;
  1977.     var cover_img;
  1978.     if(item.track_type!=3) {
  1979.         if(item.metadb) {
  1980.             cover_img = FormatCover(utils.GetAlbumArtEmbedded(item.metadb.rawpath, type));
  1981.             if(!cover_img) {
  1982.                 cover_img = FormatCover(utils.GetAlbumArtV2(item.metadb, type));
  1983.                 if(!cover_img) cover_img = FormatCover(nocover);
  1984.             }
  1985.         }
  1986.     } else if (fb.IsPlaying && fb.PlaybackLength) {
  1987.         cover_img = FormatCover(streamcover);
  1988.     } else {
  1989.         cover_img = FormatCover(nocover);
  1990.     }
  1991.     return cover_img;
  1992. }
  1993.  
  1994. function scroller2pos(scroller_y) {
  1995.     var r = (scroller_y-IC.scrollbar_y) / (IC.scrollbar_h-scroller.Height);
  1996.     var pos = 0 - Math.round(r*(IC.list_total-(IC.nbvis-1)));
  1997.     return pos;
  1998. }
  1999.  
  2000.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement