Skip to main content

Topic: WSH Panel Mod script discussion/help (Read 843737 times) previous topic - next topic

0 Members and 2 Guests are viewing this topic.
  • marc2003
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #1400
samples updated: http://dl.dropbox.com/u/22801321/samples.zip

-very minor bugfixes/tidy up. existing users should overwrite the marc2003 folder in their profile folder.
-similar artists remove last.fm button from each artist. click the text to open the last.fm website.
-autoplaylists remove lightning button. clicking the text runs the query.
-rating if foo_playcount is not found, your browser will open on the download page automatically

the mouse pointer changes to a hand when hovering and there are tooltips so you can't really miss these changes.

edit: i just a made a boo boo. if anybody downloaded this in the 30 minutes since i posted, please download and extract the marc2003 folder again.
  • Last Edit: 16 March, 2012, 02:49:32 PM by marc2003

  • Falstaff
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #1401
WSH CoverFlow v1 beta1 now available here : [LINK]


WSH Panel Mod script discussion/help
Reply #1402
WSH CoverFlow v1 beta1 now available here : [LINK]


Good Attempt !  I tried it and it works well, just a little slow.

(I want something like the good-old 'Album Art Panel' for scanned artworks.
I use it,this source codes :
$replace(%path%,%filename_ext%,)*.*\*.*\*
$replace(%path%,%filename_ext%,)*.*
$replace(%path%,%filename_ext%,)*.*\*.*  ..........)
  • Last Edit: 17 March, 2012, 03:38:23 PM by BunnyHoover

  • Falstaff
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #1403
thanx for feedback, but what do you mean by "slow" ? maybe if you make the panel too big, but it's a panel, not a screen
  • Last Edit: 17 March, 2012, 05:12:37 PM by Falstaff

  • Falstaff
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #1404
WSH CoverFlow v1 beta2



jscript:

[code]// ==PREPROCESSOR==
// @name "WSH CoverFlow v1"
// @version "0.0.2.20120318.1815"
// @author "Br3tt"
// @feature "v1.4"
// @feature "watch-metadb"
// @feature "dragdrop"
// ==/PREPROCESSOR==
// [Requirements]
// * foobar2000 v1.1 or better  >> http://foobar2000.org
// * WSH panel Mod v1.5.2 or better  >> http://code.google.com/p/foo-wsh-panel-mod/downloads/list
// [/Requirements]
// [Informations]
// * change colors and fonts in foobar2000 Preferences > DefaultUI or ColumsUI
// * Some Settings can be changed in window Properties (right click empty space > Properties)
// * double click on album text infos > Show Now Playing album
// * middle click on centered cover > Send album tracks to specific playlist "WSH CoverFlow"
// * keyboard keys : left/right arrows, Home/End, page up/down, spacebar to set focus on the centered album
// [/Informations]
SM_CXVSCROLL = 2;
SM_CYHSCROLL = 3;
DLGC_WANTARROWS = 0x0001;
DLGC_WANTALLKEYS = 0x0004;
MF_STRING = 0x00000000;
MF_SEPARATOR = 0x00000800;
MF_GRAYED = 0x00000001;
MF_DISABLED = 0x00000002;
MF_POPUP = 0x00000010;
IDC_ARROW = 32512;
IDC_IBEAM = 32513;
IDC_WAIT = 32514;
IDC_CROSS = 32515;
IDC_UPARROW = 32516;
IDC_SIZE = 32640;
IDC_ICON = 32641;
IDC_SIZENWSE = 32642;
IDC_SIZENESW = 32643;
IDC_SIZEWE = 32644;
IDC_SIZENS = 32645;
IDC_SIZEALL = 32646;
IDC_NO = 32648;
IDC_APPSTARTING = 32650;
IDC_HAND = 32649;
IDC_HELP = 32651;
DT_LEFT = 0x00000000;
DT_RIGHT = 0x00000002;
DT_TOP = 0x00000000;
DT_CENTER = 0x00000001;
DT_VCENTER = 0x00000004;
DT_WORDBREAK = 0x00000010;
DT_SINGLELINE = 0x00000020;
DT_CALCRECT = 0x00000400;
DT_NOPREFIX = 0x00000800;
DT_EDITCONTROL = 0x00002000;
DT_END_ELLIPSIS = 0x00008000;
VK_BACK = 0x08;
VK_RETURN = 0x0D;
VK_SHIFT = 0x10;
VK_CONTROL = 0x11;
VK_ALT = 0x12;
VK_ESCAPE = 0x1B;
VK_PGUP = 0x21;
VK_PGDN = 0x22;
VK_END = 0x23;
VK_HOME = 0x24;
VK_LEFT = 0x25;
VK_UP = 0x26;
VK_RIGHT = 0x27;
VK_DOWN = 0x28;
VK_INSERT = 0x2D;
VK_DELETE = 0x2E;
VK_SPACEBAR = 0x20;
KMask = {
  none: 0,
  ctrl: 1,
  shift: 2,
  ctrlshift: 3,
  ctrlalt: 4,
  ctrlaltshift: 5,
  alt: 6
};

function GetKeyboardMask() {
  var c = utils.IsKeyPressed(VK_CONTROL) ? true : false;
  var a = utils.IsKeyPressed(VK_ALT) ? true : false;
  var s = utils.IsKeyPressed(VK_SHIFT) ? true : false;
  var b = KMask.none;
  if (c && !a && !s) b = KMask.ctrl;
  if (!c && !a && s) b = KMask.shift;
  if (c && !a && s) b = KMask.ctrlshift;
  if (c && a && !s) b = KMask.ctrlalt;
  if (c && a && s) b = KMask.ctrlaltshift;
  if (!c && a && !s) b = KMask.alt;
  return b
};
ColorTypeCUI = {
  text: 0,
  selection_text: 1,
  inactive_selection_text: 2,
  background: 3,
  selection_background: 4,
  inactive_selection_background: 5,
  active_item_frame: 6
};
FontTypeCUI = {
  items: 0,
  labels: 1
};
ColorTypeDUI = {
  text: 0,
  background: 1,
  highlight: 2,
  selection: 3
};
FontTypeDUI = {
  defaults: 0,
  tabs: 1,
  lists: 2,
  playlists: 3,
  statusbar: 4,
  console: 5
};

function StringFormat() {
  var a = 0,
   v_align = 0,
   trimming = 0,
   flags = 0;
  switch (arguments.length) {
  case 3:
   trimming = arguments[2];
  case 2:
   v_align = arguments[1];
  case 1:
   a = arguments[0];
   break;
  default:
   return 0
  };
  return ((a << 28) | (v_align << 24) | (trimming << 20) | flags)
};
StringAlignment = {
  Near: 0,
  Centre: 1,
  Far: 2
};
var lt_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Near);
var ct_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Near);
var rt_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Near);
var lc_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Centre);
var cc_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Centre);
var rc_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Centre);
var lb_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Far);
var cb_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Far);
var rb_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Far);

function RGB(r, g, b) {
  return (0xff000000 | (r << 16) | (g << 8) | (b))
};

function RGBA(r, g, b, a) {
  return ((a << 24) | (r << 16) | (g << 8) | (b))
};

function getAlpha(a) {
  return ((a >> 24) & 0xff)
}

function getRed(a) {
  return ((a >> 16) & 0xff)
}

function getGreen(a) {
  return ((a >> 8) & 0xff)
}

function getBlue(a) {
  return (a & 0xff)
}

function num(a, b) {
  var i;
  var c = a.toString();
  var k = b - c.length;
  if (k > 0) {
   for (i = 0; i < k; i++) {
     c = "0" + c
   }
  };
  return c.toString()
};

function TrackType(a) {
  var b;
  var c;
  switch (a) {
  case "file":
   b = 1;
   c = 0;
   break;
  case "cdda":
   b = 1;
   c = 1;
   break;
  case "FOO_":
   b = 0;
   c = 2;
   break;
  case "http":
   b = 0;
   c = 3;
   break;
  case "mms:":
   b = 0;
   c = 3;
   break;
  case "unpa":
   b = 0;
   c = 4;
   break;
  default:
   b = 0;
   c = 5
  };
  return c
};
ButtonStates = {
  normal: 0,
  hover: 1,
  down: 2
};
button = function (d, e, f) {
  this.img = Array(d, e, f);
  this.w = this.img[0].Width;
  this.h = this.img[0].Height;
  this.state = ButtonStates.normal;
  this.update = function (a, b, c) {
   this.img = Array(a, b, c)
  };
  this.draw = function (a, x, y, b) {
   this.x = x;
   this.y = y;
   this.img[this.state] && a.DrawImage(this.img[this.state], this.x, this.y, this.w, this.h, 0, 0, this.w, this.h, 0, b)
  };
  this.display_context_menu = function (x, y, a) {};
  this.repaint = function () {
   window.RepaintRect(this.x, this.y, this.w, this.h)
  };
  this.checkstate = function (a, x, y) {
   this.ishover = (x > this.x && x < this.x + this.w - 1 && y > this.y && y < this.y + this.h - 1);
   this.old = this.state;
   switch (a) {
   case "down":
     switch (this.state) {
     case ButtonStates.normal:
     case ButtonStates.hover:
       this.state = this.ishover ? ButtonStates.down : ButtonStates.normal;
       break
     };
     break;
   case "up":
     this.state = this.ishover ? ButtonStates.hover : ButtonStates.normal;
     break;
   case "right":
     if (this.ishover) this.display_context_menu(x, y, id);
     break;
   case "move":
     switch (this.state) {
     case ButtonStates.normal:
     case ButtonStates.hover:
       this.state = this.ishover ? ButtonStates.hover : ButtonStates.normal;
       break
     };
     break;
   case "leave":
     this.state = this.isdown ? ButtonStates.down : ButtonStates.normal;
     break
   };
   if (this.state != this.old) this.repaint();
   return this.state
  }
};

function get_system_scrollbar_width() {
  var a = utils.GetSystemMetrics(SM_CXVSCROLL);
  return a
};

function get_system_scrollbar_height() {
  var a = utils.GetSystemMetrics(SM_CYHSCROLL);
  return a
};
var nocover;
var nocover_img;
var streamcover;
var star_img_off;
var star_img_on;
var star_img_hov;
var star_img_kill;
var toggle_scrollbar;
var menu_button;
cover2load = function () {
  this.create = function (a, b) {
   this.item = a;
   this.timer = window.SetInterval(function () {
     window.ClearInterval(mycover2load[0].timer);
     mycover2load[0].item.cover_img = g_image_cache.getit(mycover2load[0].item);
     mycover2load.shift();
     if (a.show) {
       window.RepaintRect(0, cover.pad_top_mid, ww, wh - cover.pad_top_mid)
     } else {
       a.show = true
     }
   }, b)
  }
};
var mycover2load = Array();
image_cache = function () {
  this._cachelist = {};
  this.hit = function (a) {
   var b = this._cachelist[a.cover_path + a.album];
   if (typeof b == "undefined") {
     mycover2load.push(new cover2load);
     mycover2load[mycover2load.length - 1].create(a, (75 + mycover2load.length * 1) * mycover2load.length)
   };
   return b
  };
  this.getit = function (a) {
   var b = refresh_cover(a);
   this._cachelist[a.cover_path + a.album] = b;
   return b
  }
};
var g_image_cache = new image_cache;

function FormatCover(a, w, h) {
  if (!a || w <= 0 || h <= 0) return a;
  return a.Resize(w, h, 2)
};

function refresh_cover(a) {
  var b = 0;
  var c;
  var d = (cover.w - cover.margin * 2) * cover.quality / 100;
  var e = (cover.h - cover.margin * 2) * cover.quality / 100;
  if (a.track_type != 3) {
   if (a.metadb) {
     c = FormatCover(utils.GetAlbumArtEmbedded(a.metadb.rawpath, b), d, e);
     if (!c) {
       c = FormatCover(utils.GetAlbumArtV2(a.metadb, b), d, e);
       if (!c) {
         c = FormatCover(nocover, d, e);
         a.cover_type = 0
       } else {
         a.cover_type = 1
       }
     } else {
       a.cover_type = 2
     }
   }
  } else if (fb.IsPlaying && fb.PlaybackLength) {
   c = FormatCover(streamcover, d, e);
   a.cover_type = 3
  } else {
   c = FormatCover(nocover, d, e);
   a.cover_type = 0
  };
  return c
};

function reset_cover_timers() {
  for (var i in mycover2load) {
   mycover2load.timer && window.ClearInterval(mycover2load.timer)
  };
  mycover2load.splice(0, mycover2load.length)
};
ItemStates = {
  normal: 0,
  hover: 1,
  selected: 2
};
item = function (g, h, j) {
  var i;
  if (typeof this.id == "undefined") {
   if (g < 0) {
     this.id = g;
     this.idx = h;
     this.gh_id = j;
     this.metadb = false;
     this.albumartist = "";
     this.album = "";
     this.track_type = null;
     this.cover_path = "";
     this.date = "";
     this.genre = ""
   } else {
     this.id = g;
     this.idx = h;
     this.gh_id = j;
     this.metadb = list.handlelist.Item(this.id);
     if (this.metadb) {
       this.albumartist = tf_albumartist.EvalWithMetadb(this.metadb);
       this.album = tf_album.EvalWithMetadb(this.metadb);
       this.track_type = TrackType(this.metadb.rawpath.substring(0, 4));
       this.cover_path = tf_cover_path.EvalWithMetadb(this.metadb);
       this.date = tf_date.EvalWithMetadb(this.metadb);
       this.genre = tf_genre.EvalWithMetadb(this.metadb)
     }
   }
  };
  this.update_infos = function () {
   if (this.metadb) {
     this.albumartist = tf_albumartist.EvalWithMetadb(this.metadb);
     this.album = tf_album.EvalWithMetadb(this.metadb);
     this.track_type = TrackType(this.metadb.rawpath.substring(0, 4));
     this.cover_path = tf_cover_path.EvalWithMetadb(this.metadb);
     this.date = tf_date.EvalWithMetadb(this.metadb);
     this.genre = tf_genre.EvalWithMetadb(this.metadb)
   } else {
     this.albumartist = "";
     this.album = "";
     this.track_type = null;
     this.cover_path = "";
     this.date = "";
     this.genre = ""
   }
  };
  this.draw = function (a, b, c, d, e) {
   this.show = e;
   if (list.mid == c) {
     this.w = cover.w;
     this.h = this.w;
     this.y = cover.pad_top_mid;
     this.x = Math.floor((ww / 2) - (cover.w / 2));
     this.cut = 1
   } else {
     this.w = Math.abs(d) == 1 ? cover.w - cover.normal_delta * 1 : cover.w - cover.normal_delta * 2;
     this.h = this.w;
     this.x = Math.abs(d) == 1 ? Math.floor((ww / 2) - (this.w / 2)) - (d * (this.w - 5)) : Math.floor((ww / 2) - (this.w / 2)) - (d * this.w);
     this.y = Math.abs(d) == 1 ? cover.pad_top_mid + Math.ceil(cover.normal_delta / 2) : cover.pad_top_mid + cover.normal_delta;
     this.cut = Math.abs(d) == 1 ? 1 : 0
   };
   if (this.id >= 0 && cover.show && cover.visible) {
     this.cover_img = g_image_cache.hit(this);
     if (e && this.cover_img) {
       a.DrawImage(this.cover_img, Math.floor(cover.margin / 2) + this.x, this.y + this.h * 2 - 2, this.w, -1 * this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255);
       a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y + this.h + 1, this.w - cover.margin * 2 + 1, this.h - cover.margin * 2 + 1, 2.0, RGB(0, 0, 0));
       a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y + this.h + 1, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(255, 255, 255));
       a.FillGradRect(Math.floor(cover.margin / 2) + this.x - 1, this.y + this.h - 1, this.w + 0 - this.cut, this.h + 1, 90, g_backcolor & 0xccffffff, g_backcolor, 1.0);
       a.FillGradRect(Math.floor(cover.margin / 2) + this.x - 1, this.y + this.h - 1, this.w + 0 - this.cut, this.h + 1, 90, g_backcolor & 0x66ffffff, g_backcolor, 1.0);
       a.DrawImage(this.cover_img, Math.floor(cover.margin / 2) + this.x, this.y, this.w, this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255);
       a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y, this.w - cover.margin * 2 + 1, this.h - cover.margin * 2 + 1, 2.0, RGB(0, 0, 0));
       a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(255, 255, 255))
     } else {
       a.DrawImage(nocover_img, Math.floor(cover.margin / 2) + this.x, this.y + this.h * 2 - 2, this.w, -1 * this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255);
       a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y + this.h + 1, this.w - cover.margin * 2 + 1, this.h - cover.margin * 2 + 1, 2.0, RGB(0, 0, 0));
       a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y + this.h + 1, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(255, 255, 255));
       a.FillGradRect(Math.floor(cover.margin / 2) + this.x - 1, this.y + this.h - 1, this.w + 0 - this.cut, this.h + 1, 90, g_backcolor & 0xccffffff, g_backcolor, 1.0);
       a.FillGradRect(Math.floor(cover.margin / 2) + this.x - 1, this.y + this.h - 1, this.w + 0 - this.cut, this.h + 1, 90, g_backcolor & 0x66ffffff, g_backcolor, 1.0);
       a.DrawImage(nocover_img, Math.floor(cover.margin / 2) + this.x, this.y, this.w, this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255);
       a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y, this.w - cover.margin * 2 + 1, this.h - cover.margin * 2 + 1, 2.0, RGB(0, 0, 0));
       a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(255, 255, 255))
     };
     if (this.gh_id == list.selected_gh_id) {
       a.SetSmoothingMode(2);
       a.DrawRoundRect(Math.floor(cover.margin / 2) + this.x - 1, this.y - 1, this.w - cover.margin * 2 + 2, this.h - cover.margin * 2 + 2, 2, 2, 3.0, g_backcolor_sel);
       a.DrawRoundRect(Math.floor(cover.margin / 2) + this.x - 2, this.y - 2, this.w - cover.margin * 2 + 4, this.h - cover.margin * 2 + 4, 3, 3, 1.0, RGBA(255, 255, 255, 60));
       a.SetSmoothingMode(0);
       a.DrawRect(Math.floor(cover.margin / 2) + this.x + 1, this.y + 1, this.w - cover.margin * 2 - 2, this.h - cover.margin * 2 - 2, 1.0, g_backcolor_sel);
       a.DrawRect(Math.floor(cover.margin / 2) + this.x + 1, this.y + 1, this.w - cover.margin * 2 - 2, this.h - cover.margin * 2 - 2, 1.0, RGBA(0, 0, 0, 40))
     }
   }
  };
  this.checkstate = function (a, x, y, b) {
   if (this.id >= 0 && y > cover.pad_top_mid) {
     this.ishover = (x > this.x && x < this.x + this.w && y >= this.y && y < this.y + this.h)
   } else {
     this.ishover = false
   };
   switch (a) {
   case "down":
     if (!list.down_timerID && this.id >= 0) {
       if (plman.IsPlaylistItemSelected(fb.ActivePlaylist, this.id)) {
         if (this.ishover) {
           SelectGroupItems(this.id, this.gh_id);
           g_saved = this
         }
       } else {
         if (this.ishover) {
           if (utils.IsKeyPressed(VK_SHIFT)) {
             if (list.focus_id != this.id) {
               if (list.SHIFT_start_id != null) {
                 SelectAtoB(list.SHIFT_start_id, this.id)
               } else {
                 SelectAtoB(list.focus_id, this.id)
               }
             }
           } else if (utils.IsKeyPressed(VK_CONTROL)) {
             plman.SetPlaylistFocusItem(fb.ActivePlaylist, this.id);
             plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, this.id, true)
           } else {
             SelectGroupItems(this.id, this.gh_id);
             g_saved = this
           }
         }
       }
     };
     break;
   case "dblclk":
     if (this.id >= 0 && g_saved != null) {
       if (plman.IsPlaylistItemSelected(fb.ActivePlaylist, this.id)) {
         if (this.id == g_saved.id) {
           plman.ExecutePlaylistDefaultAction(fb.ActivePlaylist, list.hlist[g_saved.gh_id]);
           g_saved = null;
           window.Repaint()
         }
       }
     };
     break;
   case "mid":
     if (this.ishover && this.idx == list.mid) {
       if (plman.GetPlaylistName(plman.ActivePlaylist) != "WSH CoverFlow") {
         SelectGroupItems(this.id, this.gh_id);
         var c = false;
         var d = 0;
         var e = plman.ActivePlaylist;
         for (var i = 0; i < plman.PlaylistCount; i++) {
           if (plman.GetPlaylistName(i) == "WSH CoverFlow") {
             c = true;
             d = i;
             break
           }
         };
         if (!c) {
           d = plman.PlaylistCount;
           plman.CreatePlaylist(plman.PlaylistCount, "WSH CoverFlow")
         };
         plman.ActivePlaylist = d;
         fb.ClearPlaylist();
         var f = fb.PlaylistItemCount(d);
         plman.InsertPlaylistItems(d, f, plman.GetPlaylistSelectedItems(e), false);
         plman.SetPlaylistFocusItem(d, 0)
       }
     };
     break;
   case "right":
     if (this.ishover && this.idx == list.mid) {
       SelectGroupItems(this.id, this.gh_id);
       new_context_menu(x, y, this.id, this.idx)
     };
     break;
   case "up":
     break;
   case "move":
     if (this.ishover) {}
     break;
   case "leave":
     break
   };
   return this.state
  }
};
var tf_path = fb.TitleFormat("$left(%_path_raw%,4)");
var tf_cover_path = fb.TitleFormat("$replace(%path%,%filename_ext%,)");
var tf_tracknumber = fb.TitleFormat("$num($if2(%tracknumber%,1),2)");
var tf_artist = fb.TitleFormat("$if(%length%,%artist%,'Stream')");
var tf_title = fb.TitleFormat("%title%");
var tf_albumartist = fb.TitleFormat("$if(%length%,%album artist%,'Stream')");
var tf_album = fb.TitleFormat("$if2(%album%,$if(%length%,'Single','web radios'))");
var tf_disc = fb.TitleFormat("$if2(%discnumber%,0)");
var tf_disc_info = fb.TitleFormat("$if(%discnumber%,$ifgreater(%totaldiscs%,1,' - [disc '%discnumber%$if(%totaldiscs%,'/'%totaldiscs%']',']'),),)");
var tf_rating = fb.TitleFormat("$if2(%rating%,0)");
var tf_playcount = fb.TitleFormat("$if2(%play_counter%,$if2(%play_count%,0))");
var tf_length = fb.TitleFormat("$if2(%length%,' 0:00')");
var tf_date = fb.TitleFormat("$if2($year(%date%),)");
var tf_genre = fb.TitleFormat("$if2(%genre%,'Other')");
var tf_playback_time = fb.TitleFormat("%playback_time%");
var tf_playback_time_remaining = fb.TitleFormat("$if(%length%,-%playback_time_remaining%,'0:00')");
var tf_group_key = fb.TitleFormat("%album artist%%album%");
var g_instancetype = window.InstanceType;
var g_font = null;
var g_font_headers = null;
var ww = 0,
  wh = 0;
var mouse_x = 0,
  mouse_y = 0;
var g_textcolor = 0,
  g_textcolor_sel = 0,
  g_textcolor_hl = 0,
  g_backcolor = 0,
  g_backcolor_sel = 0;
var g_metadb;
var bool_on_size = false;
var g_search_string = "";
var incsearch_font = gdi.Font("lucida console", 9, 0);
var incsearch_font_big = gdi.Font("lucida console", 20, 1);
var clear_incsearch_timer = false;
var incsearch_timer = false;
var g_saved = null;
panel = {
  max_height: window.GetProperty("panel.maximum.height", 300),
  arr_buttons: Array(),
  button_total: 2,
  show_text: window.GetProperty("panel.album.info.visible", true),
  custom_textcolor: window.GetProperty("panel.custom.text.color.normal", ""),
  custom_textcolor_selection: window.GetProperty("panel.custom.text.color.selection", ""),
  custom_backcolor: window.GetProperty("panel.custom.background.color", ""),
  custom_textcolor_highlight: window.GetProperty("panel.custom.text.color.hightlight", "")
};
list = {
  first_launch: true,
  total: 0,
  total_gh: 0,
  start_id: 0,
  nbvis: 0,
  mid: 0,
  item: Array(),
  hlist: Array(),
  handlelist: null,
  metadblist_selection: plman.GetPlaylistSelectedItems(fb.ActivePlaylist),
  focus_id: 0,
  selected_gh_id: 0,
  gh_id: 0,
  mousewheel_timer_value: 50,
  key_timer_value: 60,
  nowplaying: 0,
  SHIFT_start_id: null,
  SHIFT_count: 0,
  inc_search_noresult: false,
  nb_cover_to_draw: 0,
  buttonclicked: false
};
hscrollbar = {
  theme: false,
  themed: window.GetProperty("list.hscrollbar.themed", true),
  show: window.GetProperty("list.hscrollbar.visible", true),
  visible: true,
  hover: false,
  x: 0,
  y: 0,
  default_h: get_system_scrollbar_height(),
  h: get_system_scrollbar_height(),
  w: 0,
  button_total: 2,
  step: 3,
  arr_buttons: Array(),
  letter: null,
  timerID: false
};
button_up = {
  img_normal: null,
  img_hover: null,
  img_down: null,
  x: 0,
  y: 0,
  w: hscrollbar.default_h,
  h: hscrollbar.default_h,
  timerID: false
};
button_down = {
  img_normal: null,
  img_hover: null,
  img_down: null,
  x: 0,
  y: 0,
  w: hscrollbar.default_h,
  h: hscrollbar.default_h,
  timerID: false
};
cursor = {
  bt: null,
  img_normal: null,
  img_hover: null,
  img_down: null,
  popup: null,
  x: 0,
  y: 0,
  w: hscrollbar.default_h + 3,
  h: hscrollbar.default_h,
  default_w: hscrollbar.default_h + 3,
  hover: false,
  drag: false,
  grap_x: 0,
  timerID: false,
  last_x: 0
};
cover = {
  show: true,
  visible: true,
  margin: 2,
  w: 0,
  h: 0,
  top_offset: 0,
  pad_top_mid: 35,
  pad_bot_mid: 30,
  normal_delta: 20,
  quality: window.GetProperty("list.covers.quality.percent", 100)
};

function refresh_spv_cursor(a) {
  var b = (cursor.x - hscrollbar.x) / (hscrollbar.w - cursor.w);
  if (b > 1) b = 1;
  if (b < 0) b = 0;
  var r = Math.round(b * list.total_gh);
  set_gh_id(a, list.hlist[r - 1]);
  window.Repaint()
}

function set_gh_id(a, b) {
  reset_cover_timers();
  list.item.splice(0, list.item.length);
  if (list.total_gh <= 0) return true;
  list.gh_id = get_gh_id(b);
  if (list.gh_id == null) {
   list.gh_id = 0
  }
  var r = list.gh_id - list.mid;
  if (r < 0) {
   list.start_id = Math.abs®;
   r = 0
  } else {
   list.start_id = 0
  };
  for (var k = 0; k < list.nbvis; k++) {
   if (k >= list.start_id && r < list.total_gh) {
     list.item.push(new item(list.hlist[r], k, r));
     r++
   } else {
     list.item.push(new item(-1, k, -1))
   }
  }
};

function scrollup_spv(a) {
  var r = list.item[list.mid].gh_id;
  if (r > 0) {
   var s = list.item[0].gh_id;
   if (s > 0) {
     list.item.unshift(new item(list.hlist[s - 1], 0, s - 1))
   } else {
     list.item.unshift(new item(-1, 0, -1))
   };
   list.item.pop()
  };
  for (var i = 0; i < list.item.length; i++) {
   list.item.idx = i
  };
  setcursorx()
};

function scrolldown_spv(a) {
  var r = list.item[list.mid].gh_id;
  if (r < list.total_gh - 1) {
   var s = list.item[list.item.length - 1].gh_id;
   if (s > 0 && s < list.total_gh - 1) {
     list.item.push(new item(list.hlist[s + 1], 0, s + 1))
   } else {
     list.item.push(new item(-1, 0, -1))
   };
   list.item.shift()
  };
  for (var i = 0; i < list.item.length; i++) {
   list.item.idx = i
  };
  setcursorx()
};

function refresh_spv(a, b) {
  reset_cover_timers();
  list.item.splice(0, list.item.length);
  if (list.total_gh <= 0) return true;
  list.gh_id = get_gh_id(list.focus_id);
  if (list.gh_id == null) {
   init_active_pls();
   return true
  }
  list.selected_gh_id = list.gh_id;
  var r = list.gh_id - list.mid;
  if (r < 0) {
   list.start_id = Math.abs®;
   r = 0
  } else {
   list.start_id = 0
  };
  for (var k = 0; k < list.nbvis; k++) {
   if (k >= list.start_id && r < list.total_gh) {
     list.item.push(new item(list.hlist[r], k, r));
     r++
   } else {
     list.item.push(new item(-1, k, -1))
   }
  };
  if (hscrollbar.show) {
   if (list.total_gh < 2) hscrollbar.visible = false;
   else hscrollbar.visible = true
  } else {
   hscrollbar.visible = false
  };
  cursor.w = Math.round(hscrollbar.w / list.total_gh);
  if (cursor.w > hscrollbar.w) cursor.w = hscrollbar.w;
  if (cursor.w < cursor.default_w) cursor.w = cursor.default_w;
  set_scroller();
  setcursorx()
};

function get_gh_id(a) {
  var b = Math.floor(list.total_gh / 2);
  if (a < list.hlist) {
   var c = 0
  } else {
   var c = b
  };
  for (var i = c; i < list.total_gh; i++) {
   if (i < list.total_gh - 1) {
     if (a >= list.hlist && a < list.hlist[i + 1]) {
       return i
     }
   } else {
     if (a >= list.hlist) {
       return i
     } else {
       fb.trace("error: gh_id not found");
       return null
     }
   }
  }
};

function setcursorx() {
  var a = Math.floor(list.item.length / 2);
  var b = list.item[a].gh_id;
  var c = b / (list.total_gh - 1);
  cursor.x = hscrollbar.x + Math.round(c * (hscrollbar.w - cursor.w))
};

function init_active_pls() {
  var a;
  var b;
  list.hlist.splice(0, list.hlist.length);
  list.handlelist = plman.GetPlaylistItems(fb.ActivePlaylist);
  list.total = list.handlelist.Count;
  for (var i = 0; i < list.total; i++) {
   b = tf_group_key.EvalWithMetadb(list.handlelist.Item(i));
   if (a != b) {
     list.hlist.push(i);
     a = b
   }
  };
  list.total_gh = list.hlist.length
};

function on_font_changed() {
  get_font();
  window.Repaint()
};

function on_colors_changed() {
  get_colors();
  init_icons();
  nocover_img = FormatCover(nocover, (cover.w - cover.margin * 2) * cover.quality / 100, (cover.h - cover.margin * 2) * cover.quality / 100);
  init_hscrollbar_buttons();
  set_scroller();
  g_image_cache = new image_cache;
  CollectGarbage();
  window.Repaint()
};

function on_init() {};

function on_size() {
  if (!window.Width || !window.Height) return;
  window.DlgCode = DLGC_WANTALLKEYS;
  bool_on_size = true;
  if (g_instancetype == 0) {
   window.MinWidth = 200;
   window.MinHeight = 170;
   window.MaxHeight = panel.max_height
  } else if (g_instancetype == 1) {
   window.MinWidth = 200;
   window.MinHeight = 170;
   window.MaxHeight = panel.max_height
  };
  ww = window.Width;
  wh = window.Height;
  if (wh < 170) wh = 170;
  get_font();
  get_colors();
  init_icons();
  cover.w = wh - cover.pad_top_mid - cover.pad_bot_mid;
  cover.h = cover.w;
  list.nbvis = Math.floor(ww / (cover.w - cover.normal_delta * 2)) + 2;
  if (list.nbvis / 2 == Math.floor(list.nbvis / 2)) {
   list.nbvis--
  }
  if (list.nbvis > 13) list.nbvis = 13;
  list.mid = Math.floor(list.nbvis / 2);
  list.nb_cover_to_draw = list.nbvis;
  if (hscrollbar.themed) {
   hscrollbar.theme = window.CreateThemeManager("scrollbar")
  } else {
   hscrollbar.theme = false
  };
  init_hscrollbar_buttons();
  button_up.x = 0;
  button_up.y = wh - hscrollbar.h;
  button_down.x = ww - button_down.w;
  button_down.y = wh - hscrollbar.h;
  hscrollbar.x = button_up.w;
  hscrollbar.w = ww - button_up.w - button_down.w;
  cursor.y = wh - hscrollbar.h;
  cursor.x = hscrollbar.x;
  nocover_img = FormatCover(nocover, (cover.w - cover.margin * 2) * cover.quality / 100, (cover.h - cover.margin * 2) * cover.quality / 100);
  if (list.first_launch) {
   list.first_launch = false;
   on_playlist_switch()
  } else {
   g_image_cache = new image_cache;
   CollectGarbage();
   refresh_spv(fb.ActivePlaylist, true);
   window.Repaint()
  }
};

function on_paint(a) {
  a.FillGradRect(0, 0, ww, wh, 90, g_backcolor, g_backcolor & 0xd0ffffff, 0.3);
  if (list.item.length > 0) {
   var b;
   var c = (list.nb_cover_to_draw - 1) / 2;
   list.item[list.mid].draw(a, list.item[list.mid].id, list.mid, 0, true);
   for (var d = 1; d < list.mid + 1; d++) {
     if (d > 1 && d <= c) {
       b = true
     } else {
       b = false
     };
     mid2 = list.mid - d;
     if (mid2 >= 0 && mid2 <= list.item.length - 1) {
       list.item[mid2].draw(a, list.item[mid2].id, mid2, d, b)
     }
     mid2 = list.mid + d;
     if (mid2 >= 0 && mid2 <= list.item.length - 1) {
       list.item[mid2].draw(a, list.item[mid2].id, mid2, d * -1, b)
     }
   };
   mid2 = list.mid - 1;
   if (mid2 >= 0 && mid2 <= list.item.length - 1) {
     list.item[mid2].draw(a, list.item[mid2].id, mid2, 1, true)
   }
   mid2 = list.mid + 1;
   if (mid2 >= 0 && mid2 <= list.item.length - 1) {
     list.item[mid2].draw(a, list.item[mid2].id, mid2, -1, true)
   }
   list.item[list.mid].draw(a, list.item[list.mid].id, list.mid, 0, true);
   if (panel.show_text) {
     var f = 30;
     var g = ww - 60;
     if (list.item[list.mid].id >= 0) {
       if (list.item[list.mid].date.length > 0) {
         a.GdiDrawText(list.item[list.mid].albumartist + " | " + list.item[list.mid].album + " (" + list.item[list.mid].date + ")", g_font, g_textcolor, f, 0, g, cover.pad_top_mid - 4, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX)
       } else {
         a.GdiDrawText(list.item[list.mid].albumartist + " | " + list.item[list.mid].album, g_font, g_textcolor, f, 0, g, cover.pad_top_mid - 4, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX)
       }
     }
   }
  };
  if (list.total_gh > 0 && hscrollbar.visible && hscrollbar.show) {
   try {
     hscrollbar.theme.SetPartAndStateId(4, 1);
     hscrollbar.theme.DrawThemeBackground(a, 0, wh - hscrollbar.h, ww, hscrollbar.h);
     a.FillSolidRect(0, wh - hscrollbar.h - 1, ww, 1, RGBA(0, 0, 0, 10))
   } catch (e) {
     a.FillSolidRect(0, wh - hscrollbar.h, ww, hscrollbar.h, g_backcolor);
     a.FillGradRect(0, wh - hscrollbar.h, ww, hscrollbar.h, 0, RGBA(0, 0, 0, 100), g_backcolor, 0.5);
     a.FillGradRect(0, wh - hscrollbar.h, ww, hscrollbar.h, 0, 0, RGBA(255, 255, 255, 25), 0.5);
     a.FillSolidRect(0, wh - hscrollbar.h - 1, ww, 1, RGBA(0, 0, 0, 10))
   };
   try {
     cursor.bt.draw(a, cursor.x, cursor.y, 255)
   } catch (e) {};
   try {
     hscrollbar.theme.SetPartAndStateId(8, 1);
     hscrollbar.theme.DrawThemeBackground(a, cursor.x, wh - hscrollbar.h + 0, cursor.w, cursor.h)
   } catch (e) {};
   for (i = 0; i < hscrollbar.arr_buttons.length; i++) {
     switch (i) {
     case 0:
       hscrollbar.arr_buttons.draw(a, button_up.x, button_up.y, 255);
       break;
     case 1:
       hscrollbar.arr_buttons.draw(a, button_down.x, button_down.y, 255);
       break
     }
   };
   if (cursor.drag) {
     hscrollbar.letter = list.item[Math.floor(list.nb_cover_to_draw / 2)].albumartist.substring(0, 1).toUpperCase();
     cursor.popup && a.DrawImage(cursor.popup, cursor.x + Math.floor(cursor.w / 2) - Math.floor(cursor.popup.Width / 2), wh - hscrollbar.h - cursor.popup.Height, cursor.popup.Width, cursor.popup.Height, 0, 0, cursor.popup.Width, cursor.popup.Height, 0, 155);
     cursor.popup && a.GdiDrawText(hscrollbar.letter, gdi.Font("segoe ui", 14, 0), g_backcolor, cursor.x + Math.floor(cursor.w / 2) - Math.floor(cursor.popup.Width / 2), wh - hscrollbar.h - cursor.popup.Height, cursor.popup.Width, cursor.popup.Height - 5, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX)
   }
  };
  for (i = 0; i < panel.arr_buttons.length; i++) {
   switch (i) {
   case 0:
     panel.arr_buttons.draw(a, 5, 5, 255);
     break;
   case 1:
     panel.arr_buttons.draw(a, ww - 22 - 5, 5, 255);
     break
   }
  };
  a.FillGradRect(0, 0, ww, 1, 0, 0, g_textcolor & 0x25ffffff, 0.5)
};

function on_mouse_lbtn_down(x, y) {
  bool_on_size = false;
  for (var i = 0; i < list.item.length; i++) {
   list.item.checkstate("down", x, y, i)
  };
  if (list.total_gh > 0 && hscrollbar.visible && hscrollbar.show) {
   if (cursor.bt.checkstate("down", x, y) == ButtonStates.down) {
     cursor.drag = true;
     cursor.grap_x = x - cursor.x;
     cursor.last_x = cursor.x
   };
   if (hscrollbar.hover && !cursor.drag) {
     hscrollbar.step = Math.floor(list.nb_cover_to_draw / 2);
     if (hscrollbar.step < 1) hscrollbar.step = 1;
     if (x < cursor.x) {
       if (!list.buttonclicked) {
         list.buttonclicked = true;
         on_mouse_wheel(hscrollbar.step);
         button_up.first_timerID = window.SetTimeout(function () {
           on_mouse_wheel(hscrollbar.step);
           button_up.timerID = window.SetInterval(function () {
             if (hscrollbar.hover) {
               if (mouse_y > wh - hscrollbar.h && cursor.x > mouse_x) {
                 on_mouse_wheel(hscrollbar.step)
               }
             }
           }, list.key_timer_value)
         }, 400)
       }
     } else {
       if (!list.buttonclicked) {
         list.buttonclicked = true;
         on_mouse_wheel(-1 * hscrollbar.step);
         button_down.first_timerID = window.SetTimeout(function () {
           on_mouse_wheel(-1 * hscrollbar.step);
           button_down.timerID = window.SetInterval(function () {
             if (hscrollbar.hover) {
               if (mouse_y > wh - hscrollbar.h && cursor.x + cursor.w < mouse_x) {
                 on_mouse_wheel(-1 * hscrollbar.step)
               }
             }
           }, list.key_timer_value)
         }, 400)
       }
     }
   };
   for (i = 0; i < hscrollbar.arr_buttons.length; i++) {
     switch (i) {
     case 0:
       if (hscrollbar.arr_buttons.checkstate("down", x, y) == ButtonStates.down) {
         if (!list.buttonclicked) {
           list.buttonclicked = true;
           on_mouse_wheel(1);
           window.Repaint();
           button_up.first_timerID = window.SetTimeout(function () {
             reset_cover_timers();
             button_up.timerID = window.SetInterval(function () {
               on_mouse_wheel(1);
               window.Repaint()
             }, list.key_timer_value)
           }, 400)
         }
       };
       break;
     case 1:
       if (hscrollbar.arr_buttons.checkstate("down", x, y) == ButtonStates.down) {
         if (!list.buttonclicked) {
           list.buttonclicked = true;
           on_mouse_wheel(-1);
           window.Repaint();
           button_down.first_timerID = window.SetTimeout(function () {
             reset_cover_timers();
             button_down.timerID = window.SetInterval(function () {
               on_mouse_wheel(-1);
               window.Repaint()
             }, list.key_timer_value)
           }, 400)
         }
       };
       break
     }
   }
  };
  for (i = 0; i < panel.arr_buttons.length; i++) {
   switch (i) {
   case 0:
     if (panel.arr_buttons.checkstate("down", x, y) == ButtonStates.down) {
       ShowNowPlaying()
     };
     break;
   case 1:
     if (panel.arr_buttons.checkstate("down", x, y) == ButtonStates.down) {
       if (list.total_gh >= 2) {
         hscrollbar.show = !hscrollbar.show;
         if (hscrollbar.show) {
           hscrollbar.visible = true
         } else {
           hscrollbar.visible = false
         }
       } else {
         hscrollbar.visible = false
       };
       window.SetProperty("list.hscrollbar.visible", hscrollbar.show);
       window.Repaint()
     };
     break
   }
  }
};

function on_mouse_lbtn_dblclk(x, y, a) {
  if (y < cover.pad_top_mid) {} else if (y < wh - cover.pad_bot_mid) {
   for (var i = 0; i < list.item.length; i++) {
     list.item.checkstate("dblclk", x, y, i)
   }
  } else {
   on_mouse_lbtn_down(x, y)
  }
};

function on_mouse_lbtn_up(x, y) {
  list.buttonclicked = false;
  hscrollbar.timerID && window.ClearTimeout(hscrollbar.timerID);
  hscrollbar.timerID = false;
  button_up.first_timerID && window.ClearTimeout(button_up.first_timerID);
  button_up.first_timerID = false;
  button_down.first_timerID && window.ClearTimeout(button_down.first_timerID);
  button_down.first_timerID = false;
  button_up.timerID && window.ClearInterval(button_up.timerID);
  button_up.timerID = false;
  button_down.timerID && window.ClearInterval(button_down.timerID);
  button_down.timerID = false;
  if (list.total_gh > 0) {
   cursor.bt.checkstate("up", x, y);
   for (var i = 0; i < hscrollbar.arr_buttons.length; i++) {
     hscrollbar.arr_buttons.checkstate("up", x, y)
   };
   for (var i = 0; i < panel.arr_buttons.length; i++) {
     panel.arr_buttons.checkstate("up", x, y)
   };
   if (cursor.drag) {
     window.RepaintRect(0, wh - hscrollbar.h, ww, hscrollbar.h);
     cursor.drag = false
   } else {
     for (i = 0; i < list.item.length; i++) {
       list.item.checkstate("up", x, y, i)
     }
   };
   setcursorx();
   window.Repaint()
  }
};

function on_mouse_mbtn_down(x, y, a) {
  bool_on_size = false;
  for (var i = 0; i < list.item.length; i++) {
   list.item.checkstate("mid", x, y, i)
  }
};

function on_mouse_rbtn_down(x, y) {
  bool_on_size = false;
  for (var i = 0; i < list.item.length; i++) {
   list.item.checkstate("right", x, y, i)
  }
};

function on_mouse_move(x, y) {
  if (x == mouse_x && y == mouse_y) return true;
  if (list.total_gh > 0 && hscrollbar.visible && hscrollbar.show) {
   hscrollbar.hover = (y >= wh - hscrollbar.h && y <= wh && x >= hscrollbar.x && x <= hscrollbar.x + hscrollbar.w);
   cursor.hover = (x >= cursor.x && x <= cursor.x + cursor.w && y >= cursor.y && y <= cursor.y + cursor.h);
   cursor.bt.checkstate("move", x, y);
   for (var i = 0; i < hscrollbar.arr_buttons.length; i++) {
     hscrollbar.arr_buttons.checkstate("move", x, y)
   };
   if (cursor.drag && mouse_x != x) {
     reset_cover_timers();
     cursor.x = x - cursor.grap_x;
     if (cursor.x < hscrollbar.x) cursor.x = hscrollbar.x;
     if (cursor.x > hscrollbar.x + hscrollbar.w - cursor.w) cursor.x = hscrollbar.x + hscrollbar.w - cursor.w;
     if (!cursor.timerID) {
       cursor.timerID = window.SetTimeout(function () {
         refresh_spv_cursor(fb.ActivePlaylist);
         window.Repaint();
         cursor.timerID && window.ClearTimeout(cursor.timerID);
         cursor.timerID = false
       }, 30)
     }
   }
  };
  for (var j = 0; j < panel.arr_buttons.length; j++) {
   panel.arr_buttons[j].checkstate("move", x, y)
  };
  mouse_x = x;
  mouse_y = y
};

function on_mouse_wheel(a) {
  reset_cover_timers();
  if (!hscrollbar.timerID) {
   if (Math.abs(a) >= 1) {
     if (a > 0) {
       for (var i = 0; i < Math.abs(a); i++) {
         scrollup_spv(fb.ActivePlaylist)
       };
       hscrollbar.timerID = window.SetTimeout(function () {
         window.Repaint();
         hscrollbar.timerID && window.ClearTimeout(hscrollbar.timerID);
         hscrollbar.timerID = false
       }, list.mousewheel_timer_value)
     } else {
       for (var i = 0; i < Math.abs(a); i++) {
         scrolldown_spv(fb.ActivePlaylist)
       }
       hscrollbar.timerID = window.SetTimeout(function () {
         window.Repaint();
         hscrollbar.timerID && window.ClearTimeout(hscrollbar.timerID);
         hscrollbar.timerID = false
       }, list.mousewheel_timer_value)
     }
   }
  }
};

function on_mouse_leave() {
  for (i = 0; i < list.item.length; i++) {
   list.item.checkstate("leave", 0, 0, i)
  };
  window.Repaint()
};

function on_playlist_switch() {
  if (fb.ActivePlaylist < 0 || fb.ActivePlaylist > fb.PlaylistCount) {
   if (fb.PlaylistCount > 0) {
     fb.ActivePlaylist = 0
   }
  };
  init_active_pls();
  list.focus_id = plman.GetPlaylistFocusItemIndex(fb.ActivePlaylist);
  if (list.focus_id < 0) {
   list.focus_id = 0
  }
  refresh_spv(fb.ActivePlaylist, true);
  window.Repaint()
};

function on_playlist_items_added(a) {
  if (a == fb.ActivePlaylist) {
   on_playlist_switch()
  };
  plman.SetActivePlaylistContext()
};

function on_playlist_items_reordered(a) {
  if (a == fb.ActivePlaylist) {
   on_playlist_switch()
  }
};

function on_selection_changed(a) {};

function on_playlist_items_selection_change() {};

function on_playlists_changed() {};

function on_item_focus_change(a, b, c) {
  list.focus_id = c;
  plman.SetActivePlaylistContext();
  refresh_spv(fb.ActivePlaylist, bool_on_size);
  bool_on_size = false;
  window.Repaint()
};

function on_metadb_changed(a, b) {
  for (var i = 0; i < list.item.length; i++) {
   list.item.update_infos()
  };
  window.Repaint()
};

function on_focus(a) {};

function on_key_up(a) {};

function on_key_down(a) {
  var b = GetKeyboardMask();
  if (b == KMask.none) {
   switch (a) {
   case VK_SHIFT:
     list.SHIFT_count = 0;
     break;
   case VK_BACK:
     break;
   case VK_ESCAPE:
   case 222:
     break;
   case VK_SPACEBAR:
     var c = list.item[Math.floor(list.nb_cover_to_draw / 2)].id;
     plman.SetPlaylistFocusItem(fb.ActivePlaylist, c);
     plman.ClearPlaylistSelection(fb.ActivePlaylist);
     plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, c, true);
     break;
   case VK_LEFT:
     on_mouse_wheel(1);
     break;
   case VK_RIGHT:
     on_mouse_wheel(-1);
     break;
   case VK_PGUP:
     hscrollbar.step = Math.floor(list.nb_cover_to_draw / 2);
     if (hscrollbar.step < 1) hscrollbar.step = 1;
     on_mouse_wheel(hscrollbar.step);
     break;
   case VK_PGDN:
     hscrollbar.step = Math.floor(list.nb_cover_to_draw / 2);
     if (hscrollbar.step < 1) hscrollbar.step = 1;
     on_mouse_wheel(hscrollbar.step * -1);
     break;
   case VK_RETURN:
     plman.ExecutePlaylistDefaultAction(fb.ActivePlaylist, list.focus_id);
     break;
   case VK_END:
     plman.SetPlaylistFocusItem(fb.ActivePlaylist, list.total - 1);
     plman.ClearPlaylistSelection(fb.ActivePlaylist);
     plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, list.total - 1, true);
     break;
   case VK_HOME:
     plman.SetPlaylistFocusItem(fb.ActivePlaylist, 0);
     plman.ClearPlaylistSelection(fb.ActivePlaylist);
     plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, 0, true);
     break;
   case VK_DELETE:
     if (!fb.IsAutoPlaylist(fb.ActivePlaylist)) {
       plman.RemovePlaylistSelection(fb.ActivePlaylist, false);
       plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, plman.GetPlaylistFocusItemIndex(fb.ActivePlaylist), true)
     }
     break;
   default:
     break
   }
  } else {
   switch (b) {
   case KMask.shift:
     break;
   case KMask.ctrl:
     if (a == 65) {
       fb.RunMainMenuCommand("Edit/Select all");
       window.Repaint()
     };
     if (a == 70) {
       fb.RunMainMenuCommand("Edit/Search")
     };
     if (a == 78) {
       fb.RunMainMenuCommand("File/New playlist")
     };
     if (a == 79) {
       fb.RunMainMenuCommand("File/Open...")
     };
     if (a == 80) {
       fb.RunMainMenuCommand("File/Preferences")
     };
     if (a == 83) {
       fb.RunMainMenuCommand("File/Save playlist...")
     };
     break;
   case KMask.alt:
     if (a == 65) {
       fb.RunMainMenuCommand("View/Always on Top")
     };
     break
   }
  }
};

function on_playback_new_track(a) {
  g_metadb = fb.GetNowPlaying();
  window.Repaint()
};

function on_playback_stop(a) {
  if (a == 0) {
   g_metadb = fb.GetFocusItem();
   on_metadb_changed()
  }
};

function on_playback_pause(a) {};

function on_playback_time(a) {};

function get_font() {
  if (g_instancetype == 0) {
   g_font = window.GetFontCUI(FontTypeCUI.items);
   g_font_headers = window.GetFontCUI(FontTypeCUI.labels)
  } else if (g_instancetype == 1) {
   g_font = window.GetFontDUI(FontTypeDUI.playlists);
   g_font_headers = window.GetFontDUI(FontTypeDUI.tabs)
  }
};

function get_colors() {
  if (g_instancetype == 0) {
   g_textcolor = window.GetColorCUI(ColorTypeCUI.text);
   g_textcolor_sel = window.GetColorCUI(ColorTypeCUI.selection_text);
   g_textcolor_hl = window.GetColorCUI(ColorTypeCUI.active_item_frame);
   g_backcolor = window.GetColorCUI(ColorTypeCUI.background);
   g_backcolor_sel = window.GetColorCUI(ColorTypeCUI.selection_background)
  } else if (g_instancetype == 1) {
   g_textcolor = window.GetColorDUI(ColorTypeDUI.text);
   g_textcolor_sel = window.GetColorDUI(ColorTypeDUI.selection);
   g_textcolor_hl = window.GetColorDUI(ColorTypeDUI.highlight);
   g_backcolor = window.GetColorDUI(ColorTypeDUI.background);
   g_backcolor_sel = g_textcolor_sel
  };
  try {
   if (panel.custom_textcolor.length > 0) g_textcolor = eval(panel.custom_textcolor);
   if (panel.custom_textcolor_selection.length > 0) g_textcolor_sel = eval(panel.custom_textcolor_selection);
   if (panel.custom_backcolor.length > 0) g_backcolor = eval(panel.custom_backcolor);
   if (panel.custom_textcolor_highlight.length > 0) g_textcolor_hl = eval(panel.custom_textcolor_highlight)
  } catch (e) {};
  g_backcolor_R = getRed(g_backcolor);
  g_backcolor_G = getGreen(g_backcolor);
  g_backcolor_B = getBlue(g_backcolor)
};

function set_scroller() {
  var a;
  try {
   cursor.img_normal = gdi.CreateImage(cursor.w, cursor.h)
  } catch (e) {
   cursor.h = cursor.default_h;
   cursor.img_normal = gdi.CreateImage(cursor.w, cursor.h)
  };
  a = cursor.img_normal.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(2, 1);
   hscrollbar.theme.DrawThemeBackground(a, 0, 0, cursor.w, cursor.h)
  } catch (e) {
   a.FillSolidRect(0, 1, cursor.w - 0, cursor.h - 2, g_backcolor);
   a.FillSolidRect(0, 1, cursor.w - 0, cursor.h - 2, RGBA(0, 0, 0, 100));
   a.FillSolidRect(0, 1, cursor.w - 1, cursor.h - 3, g_textcolor & 0x77ffffff);
   a.FillSolidRect(1, 2, cursor.w - 2, cursor.h - 4, g_backcolor);
   a.FillSolidRect(1, 2, cursor.w - 2, cursor.h - 4, RGBA(255, 255, 255, 25))
  };
  cursor.img_normal.ReleaseGraphics(a);
  cursor.img_hover = gdi.CreateImage(cursor.w, cursor.h);
  a = cursor.img_hover.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(2, 2);
   hscrollbar.theme.DrawThemeBackground(a, 0, 0, cursor.w, cursor.h)
  } catch (e) {
   a.FillSolidRect(0, 1, cursor.w - 0, cursor.h - 2, g_backcolor);
   a.FillSolidRect(0, 1, cursor.w - 0, cursor.h - 2, RGBA(0, 0, 0, 70));
   a.FillSolidRect(0, 1, cursor.w - 1, cursor.h - 3, g_textcolor & 0x99ffffff);
   a.FillSolidRect(1, 2, cursor.w - 2, cursor.h - 4, g_backcolor);
   a.FillSolidRect(1, 2, cursor.w - 2, cursor.h - 4, RGBA(255, 255, 255, 50))
  };
  cursor.img_hover.ReleaseGraphics(a);
  cursor.bt = new button(cursor.img_normal, cursor.img_hover, cursor.img_hover)
};

function init_hscrollbar_buttons() {
  var i, gb;
  cursor.popup = gdi.CreateImage(22, 27);
  gb = cursor.popup.GetGraphics();
  gb.SetSmoothingMode(2);
  gb.FillRoundRect(0, 0, 22 - 1, 22 - 1, 3, 3, g_textcolor);
  gb.DrawRoundRect(0, 0, 22 - 1, 22 - 1, 3, 3, 1.0, RGBA(0, 0, 0, 150));
  var a = Array(7, 22 - 2, 11, 22 - 2 + 6, 22 - 7, 22 - 2);
  gb.FillPolygon(g_textcolor, 0, a);
  gb.DrawPolygon(RGBA(0, 0, 0, 150), 1.0, a);
  gb.SetSmoothingMode(0);
  gb.FillSolidRect(6, 22 - 4, 22 - 10, 3, g_textcolor);
  cursor.popup.ReleaseGraphics(gb);
  button_up.img_normal = gdi.CreateImage(button_up.w, button_up.h);
  gb = button_up.img_normal.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(1, 9);
   hscrollbar.theme.DrawThemeBackground(gb, 0, 0, button_up.w, button_up.h)
  } catch (e) {
   gb.FillSolidRect(0, 0, button_up.w - 0, button_up.h - 0, g_backcolor);
   gb.FillSolidRect(0, 0, button_up.w - 0, button_up.h - 0, RGBA(0, 0, 0, 100));
   gb.FillSolidRect(0, 0, button_up.w - 1, button_up.h - 1, g_textcolor & 0x77ffffff);
   gb.FillSolidRect(1, 1, button_up.w - 2, button_up.h - 2, g_backcolor);
   gb.FillSolidRect(1, 1, button_up.w - 2, button_up.h - 2, RGBA(255, 255, 255, 25));
   gb.SetTextRenderingHint(4);
   gui_font = gdi.Font("guifx v2 transports", 12, 0);
   gb.DrawString(".", gui_font, RGBA(255, 255, 255, 25), 0, 1, button_up.w - 0, button_up.h, cc_stringformat);
   gb.DrawString(".", gui_font, g_textcolor, 0, 0, button_up.w - 0, button_up.h, cc_stringformat)
  };
  button_up.img_normal.ReleaseGraphics(gb);
  button_up.img_hover = gdi.CreateImage(button_up.w, button_up.h);
  gb = button_up.img_hover.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(1, 10);
   hscrollbar.theme.DrawThemeBackground(gb, 0, 0, button_up.w, button_up.h)
  } catch (e) {
   gb.FillSolidRect(0, 0, button_up.w - 0, button_up.h - 0, g_backcolor);
   gb.FillSolidRect(0, 0, button_up.w - 0, button_up.h - 0, RGBA(0, 0, 0, 70));
   gb.FillSolidRect(0, 0, button_up.w - 1, button_up.h - 1, g_textcolor & 0x99ffffff);
   gb.FillSolidRect(1, 1, button_up.w - 2, button_up.h - 2, g_backcolor);
   gb.FillSolidRect(1, 1, button_up.w - 2, button_up.h - 2, RGBA(255, 255, 255, 50));
   gb.SetTextRenderingHint(4);
   gui_font = gdi.Font("guifx v2 transports", 12, 0);
   gb.DrawString(".", gui_font, RGBA(255, 255, 255, 50), 0, 1, button_up.w - 0, button_up.h, cc_stringformat);
   gb.DrawString(".", gui_font, g_textcolor, 0, 0, button_up.w - 0, button_up.h, cc_stringformat)
  };
  button_up.img_hover.ReleaseGraphics(gb);
  button_up.img_down = gdi.CreateImage(button_up.w, button_up.h);
  gb = button_up.img_down.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(1, 11);
   hscrollbar.theme.DrawThemeBackground(gb, 0, 0, button_up.w, button_up.h)
  } catch (e) {
   gb.FillSolidRect(0, 0, button_up.w - 0, button_up.h - 0, g_textcolor & 0x77ffffff);
   gb.FillSolidRect(0, 0, button_up.w - 0, button_up.h - 0, g_backcolor);
   gb.FillSolidRect(0, 0, button_up.w - 1, button_up.h - 1, RGBA(0, 0, 0, 100));
   gb.FillSolidRect(1, 1, button_up.w - 2, button_up.h - 2, g_backcolor);
   gb.FillSolidRect(1, 1, button_up.w - 2, button_up.h - 2, RGBA(255, 255, 255, 25));
   gb.SetTextRenderingHint(4);
   gui_font = gdi.Font("guifx v2 transports", 12, 0);
   gb.DrawString(".", gui_font, RGBA(255, 255, 255, 25), 0, 1, button_up.w - 0, button_up.h, cc_stringformat);
   gb.DrawString(".", gui_font, g_textcolor, 0, 0, button_up.w - 0, button_up.h, cc_stringformat)
  };
  button_up.img_down.ReleaseGraphics(gb);
  button_down.img_normal = gdi.CreateImage(button_down.w, button_down.h);
  gb = button_down.img_normal.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(1, 13);
   hscrollbar.theme.DrawThemeBackground(gb, 0, 0, button_down.w, button_down.h)
  } catch (e) {
   gb.FillSolidRect(0, 0, button_down.w - 0, button_down.h - 0, g_backcolor);
   gb.FillSolidRect(0, 0, button_down.w - 0, button_down.h - 0, RGBA(0, 0, 0, 100));
   gb.FillSolidRect(0, 0, button_down.w - 1, button_down.h - 1, g_textcolor & 0x77ffffff);
   gb.FillSolidRect(1, 1, button_down.w - 2, button_down.h - 2, g_backcolor);
   gb.FillSolidRect(1, 1, button_down.w - 2, button_down.h - 2, RGBA(255, 255, 255, 25));
   gb.SetTextRenderingHint(4);
   gui_font = gdi.Font("guifx v2 transports", 12, 0);
   gb.DrawString(",", gui_font, RGBA(255, 255, 255, 25), 0, 1, button_down.w - 0, button_down.h, cc_stringformat);
   gb.DrawString(",", gui_font, g_textcolor, 0, 0, button_down.w - 0, button_down.h, cc_stringformat)
  };
  button_down.img_normal.ReleaseGraphics(gb);
  button_down.img_hover = gdi.CreateImage(button_down.w, button_down.h);
  gb = button_down.img_hover.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(1, 14);
   hscrollbar.theme.DrawThemeBackground(gb, 0, 0, button_down.w, button_down.h)
  } catch (e) {
   gb.FillSolidRect(0, 0, button_down.w - 0, button_down.h - 0, g_backcolor);
   gb.FillSolidRect(0, 0, button_down.w - 0, button_down.h - 0, RGBA(0, 0, 0, 70));
   gb.FillSolidRect(0, 0, button_down.w - 1, button_down.h - 1, g_textcolor & 0x99ffffff);
   gb.FillSolidRect(1, 1, button_down.w - 2, button_down.h - 2, g_backcolor);
   gb.FillSolidRect(1, 1, button_down.w - 2, button_down.h - 2, RGBA(255, 255, 255, 50));
   gb.SetTextRenderingHint(4);
   gui_font = gdi.Font("guifx v2 transports", 12, 0);
   gb.DrawString(",", gui_font, RGBA(255, 255, 255, 50), 0, 1, button_down.w - 0, button_down.h, cc_stringformat);
   gb.DrawString(",", gui_font, g_textcolor, 0, 0, button_down.w - 0, button_down.h, cc_stringformat)
  };
  button_down.img_hover.ReleaseGraphics(gb);
  button_down.img_down = gdi.CreateImage(button_down.w, button_down.h);
  gb = button_down.img_down.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(1, 15);
   hscrollbar.theme.DrawThemeBackground(gb, 0, 0, button_down.w, button_down.h)
  } catch (e) {
   gb.FillSolidRect(0, 0, button_down.w - 0, button_down.h - 0, g_textcolor & 0x77ffffff);
   gb.FillSolidRect(0, 0, button_down.w - 0, button_down.h - 0, g_backcolor);
   gb.FillSolidRect(0, 0, button_down.w - 1, button_down.h - 1, RGBA(0, 0, 0, 100));
   gb.FillSolidRect(1, 1, button_down.w - 2, button_down.h - 1, g_backcolor);
   gb.FillSolidRect(1, 1, button_down.w - 2, button_down.h - 1, RGBA(255, 255, 255, 25));
   gb.SetTextRenderingHint(4);
   gui_font = gdi.Font("guifx v2 transports", 12, 0);
   gb.DrawString(",", gui_font, RGBA(255, 255, 255, 25), 0, 1, button_down.w - 0, button_down.h, cc_stringformat);
   gb.DrawString(",", gui_font, g_textcolor, 0, 0, button_down.w - 0, button_down.h, cc_stringformat)
  };
  button_down.img_down.ReleaseGraphics(gb);
  hscrollbar.arr_buttons.splice(0, hscrollbar.arr_buttons.length);
  for (i = 0; i < hscrollbar.button_total; i++) {
   switch (i) {
   case 0:
     hscrollbar.arr_buttons.push(new button(button_up.img_normal, button_up.img_hover, button_up.img_down));
     break;
   case 1:
     hscrollbar.arr_buttons.push(new button(button_down.img_normal, button_down.img_hover, button_down.img_down));
     break
   }
  }
};

function init_icons() {
  var a;
  var b = gdi.Font("guifx v2 transports", 15, 0);
  nocover = gdi.CreateImage(200, 200);
  a = nocover.GetGraphics();
  a.SetSmoothingMode(2);
  a.FillSolidRect(0, 0, 200, 200, g_textcolor);
  a.FillGradRect(0, 0, 200, 200, 90, g_backcolor & 0xbbffffff, g_backcolor, 1.0);
  a.SetTextRenderingHint(3);
  b = gdi.Font("guifx v2 transports", 132, 0);
  a.DrawString("x", b, RGB(0, 0, 0), 1, -2, 200, 200, cc_stringformat);
  a.DrawString("x", b, RGB(255, 255, 255), 1, 2, 200, 200, cc_stringformat);
  a.DrawString("x", b, g_backcolor, 1, 0, 200, 200, cc_stringformat);
  a.DrawString("x", b, g_textcolor & 0x88ffffff, 1, 0, 200, 200, cc_stringformat);
  nocover.ReleaseGraphics(a);
  streamcover = gdi.CreateImage(200, 200);
  a = streamcover.GetGraphics();
  a.SetSmoothingMode(2);
  a.FillSolidRect(0, 0, 200, 200, g_textcolor);
  a.FillGradRect(0, 0, 200, 200, 90, g_backcolor & 0xbbffffff, g_backcolor, 1.0);
  a.SetTextRenderingHint(3);
  b = gdi.F
  • Last Edit: 18 March, 2012, 01:45:02 PM by Falstaff

  • marc2003
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #1405
samples updated: http://dl.dropbox.com/u/22801321/samples.zip

thumbs: the thumbnails in grid mode are now horizontally centred. also added new thumbnail size: 250px.
  • Last Edit: 20 March, 2012, 01:14:02 PM by marc2003

  • Falstaff
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #1406
WSH CoverFlow v1 beta3 (optimized and new settings in properties!)

[code]// ==PREPROCESSOR==
// @name "WSH CoverFlow v1"
// @version "0.0.3.20120320.2015"
// @author "Br3tt"
// @feature "v1.4"
// @feature "watch-metadb"
// @feature "dragdrop"
// ==/PREPROCESSOR==

// [Requirements]
// * foobar2000 v1.1 or better  >> http://foobar2000.org
// * WSH panel Mod v1.5.2 or better  >> http://code.google.com/p/foo-wsh-panel-mod/downloads/list
// [/Requirements]

// [Informations]
// * change colors and fonts in foobar2000 Preferences > DefaultUI or ColumsUI
// * Some Settings can be changed in window Properties (right click empty space > Properties)
// * for custom colors in Properties, use e.g. RGB(255,255,255) for white color, RGB(0,0,0) for black color, ...
// * double click on album text infos > Show Now Playing album
// * middle click on centered cover > Send album tracks to specific playlist "WSH CoverFlow"
// * keyboard keys : left/right arrows, Home/End, page up/down, spacebar to set focus on the centered album
// [/Informations]

SM_CXVSCROLL = 2;
SM_CYHSCROLL = 3;
DLGC_WANTARROWS = 0x0001;
DLGC_WANTALLKEYS = 0x0004;
MF_STRING = 0x00000000;
MF_SEPARATOR = 0x00000800;
MF_GRAYED = 0x00000001;
MF_DISABLED = 0x00000002;
MF_POPUP = 0x00000010;
IDC_ARROW = 32512;
IDC_IBEAM = 32513;
IDC_WAIT = 32514;
IDC_CROSS = 32515;
IDC_UPARROW = 32516;
IDC_SIZE = 32640;
IDC_ICON = 32641;
IDC_SIZENWSE = 32642;
IDC_SIZENESW = 32643;
IDC_SIZEWE = 32644;
IDC_SIZENS = 32645;
IDC_SIZEALL = 32646;
IDC_NO = 32648;
IDC_APPSTARTING = 32650;
IDC_HAND = 32649;
IDC_HELP = 32651;
var DT_LEFT = 0x00000000;
var DT_RIGHT = 0x00000002;
var DT_TOP = 0x00000000;
var DT_CENTER = 0x00000001;
var DT_VCENTER = 0x00000004;
var DT_WORDBREAK = 0x00000010;
var DT_SINGLELINE = 0x00000020;
var DT_CALCRECT = 0x00000400;
var DT_NOPREFIX = 0x00000800;
var DT_EDITCONTROL = 0x00002000;
var DT_END_ELLIPSIS = 0x00008000;
var VK_BACK = 0x08;
var VK_RETURN = 0x0D;
var VK_SHIFT = 0x10;
var VK_CONTROL = 0x11;
var VK_ALT = 0x12;
var VK_ESCAPE = 0x1B;
var VK_PGUP = 0x21;
var VK_PGDN = 0x22;
var VK_END = 0x23;
var VK_HOME = 0x24;
var VK_LEFT = 0x25;
var VK_UP = 0x26;
var VK_RIGHT = 0x27;
var VK_DOWN = 0x28;
var VK_INSERT = 0x2D;
var VK_DELETE = 0x2E;
var VK_SPACEBAR = 0x20;
var KMask = {
  none: 0,
  ctrl: 1,
  shift: 2,
  ctrlshift: 3,
  ctrlalt: 4,
  ctrlaltshift: 5,
  alt: 6
};

function GetKeyboardMask() {
  var c = utils.IsKeyPressed(VK_CONTROL) ? true : false;
  var a = utils.IsKeyPressed(VK_ALT) ? true : false;
  var s = utils.IsKeyPressed(VK_SHIFT) ? true : false;
  var b = KMask.none;
  if (c && !a && !s) b = KMask.ctrl;
  if (!c && !a && s) b = KMask.shift;
  if (c && !a && s) b = KMask.ctrlshift;
  if (c && a && !s) b = KMask.ctrlalt;
  if (c && a && s) b = KMask.ctrlaltshift;
  if (!c && a && !s) b = KMask.alt;
  return b
};
ColorTypeCUI = {
  text: 0,
  selection_text: 1,
  inactive_selection_text: 2,
  background: 3,
  selection_background: 4,
  inactive_selection_background: 5,
  active_item_frame: 6
};
FontTypeCUI = {
  items: 0,
  labels: 1
};
ColorTypeDUI = {
  text: 0,
  background: 1,
  highlight: 2,
  selection: 3
};
FontTypeDUI = {
  defaults: 0,
  tabs: 1,
  lists: 2,
  playlists: 3,
  statusbar: 4,
  console: 5
};

function StringFormat() {
  var a = 0,
   v_align = 0,
   trimming = 0,
   flags = 0;
  switch (arguments.length) {
  case 3:
   trimming = arguments[2];
  case 2:
   v_align = arguments[1];
  case 1:
   a = arguments[0];
   break;
  default:
   return 0
  };
  return ((a << 28) | (v_align << 24) | (trimming << 20) | flags)
};
StringAlignment = {
  Near: 0,
  Centre: 1,
  Far: 2
};
var lt_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Near);
var ct_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Near);
var rt_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Near);
var lc_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Centre);
var cc_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Centre);
var rc_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Centre);
var lb_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Far);
var cb_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Far);
var rb_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Far);

function RGB(r, g, b) {
  return (0xff000000 | (r << 16) | (g << 8) | (b))
};

function RGBA(r, g, b, a) {
  return ((a << 24) | (r << 16) | (g << 8) | (b))
};

function getAlpha(a) {
  return ((a >> 24) & 0xff)
}
function getRed(a) {
  return ((a >> 16) & 0xff)
}
function getGreen(a) {
  return ((a >> 8) & 0xff)
}
function getBlue(a) {
  return (a & 0xff)
}
function num(a, b) {
  var i;
  var c = a.toString();
  var k = b - c.length;
  if (k > 0) {
   for (i = 0; i < k; i++) {
     c = "0" + c
   }
  };
  return c.toString()
};

function TrackType(a) {
  var b;
  var c;
  switch (a) {
  case "file":
   b = 1;
   c = 0;
   break;
  case "cdda":
   b = 1;
   c = 1;
   break;
  case "FOO_":
   b = 0;
   c = 2;
   break;
  case "http":
   b = 0;
   c = 3;
   break;
  case "mms:":
   b = 0;
   c = 3;
   break;
  case "unpa":
   b = 0;
   c = 4;
   break;
  default:
   b = 0;
   c = 5
  };
  return c
};
ButtonStates = {
  normal: 0,
  hover: 1,
  down: 2
};
button = function (d, e, f) {
  this.img = Array(d, e, f);
  this.w = this.img[0].Width;
  this.h = this.img[0].Height;
  this.state = ButtonStates.normal;
  this.update = function (a, b, c) {
   this.img = Array(a, b, c)
  };
  this.draw = function (a, x, y, b) {
   this.x = x;
   this.y = y;
   this.img[this.state] && a.DrawImage(this.img[this.state], this.x, this.y, this.w, this.h, 0, 0, this.w, this.h, 0, b)
  };
  this.display_context_menu = function (x, y, a) {};
  this.repaint = function () {
   window.RepaintRect(this.x, this.y, this.w, this.h)
  };
  this.checkstate = function (a, x, y) {
   this.ishover = (x > this.x && x < this.x + this.w - 1 && y > this.y && y < this.y + this.h - 1);
   this.old = this.state;
   switch (a) {
   case "down":
     switch (this.state) {
     case ButtonStates.normal:
     case ButtonStates.hover:
       this.state = this.ishover ? ButtonStates.down : ButtonStates.normal;
       break
     };
     break;
   case "up":
     this.state = this.ishover ? ButtonStates.hover : ButtonStates.normal;
     break;
   case "right":
     if (this.ishover) this.display_context_menu(x, y, id);
     break;
   case "move":
     switch (this.state) {
     case ButtonStates.normal:
     case ButtonStates.hover:
       this.state = this.ishover ? ButtonStates.hover : ButtonStates.normal;
       break
     };
     break;
   case "leave":
     this.state = this.isdown ? ButtonStates.down : ButtonStates.normal;
     break
   };
   if (this.state != this.old) this.repaint();
   return this.state
  }
};

function get_system_scrollbar_width() {
  var a = utils.GetSystemMetrics(SM_CXVSCROLL);
  return a
};

function get_system_scrollbar_height() {
  var a = utils.GetSystemMetrics(SM_CYHSCROLL);
  return a
};
var nocover;
var nocover_img;
var streamcover;
var star_img_off;
var star_img_on;
var star_img_hov;
var star_img_kill;
var toggle_scrollbar;
var menu_button;
cover2load = function (a, b) {
  this.item = a;
  this.timer = window.SetTimeout(function () {
   if (mycover2load.length > 0) {
     mycover2load[0].timer && window.ClearTimeout(mycover2load[0].timer);
     utils.GetAlbumArtAsync(window.ID, mycover2load[0].item.metadb, 0, true, false, false)
   }
  }, b)
};
var mycover2load = Array();
image_cache = function () {
  this._cachelist = {};
  this.hit = function (a) {
   var b = this._cachelist[a.cover_path + a.album];
   if (typeof b == "undefined") {
     mycover2load.push(new cover2load(a, (80 * (mycover2load.length > 0 ? 1 : 0)) + (10 * mycover2load.length)))
   };
   return b
  };
  this.getit = function (a) {
   var b = refresh_cover(a);
   this._cachelist[a.cover_path + a.album] = b;
   return b
  }
};
var g_image_cache = new image_cache;

function FormatCover(a, w, h) {
  if (!a || w <= 0 || h <= 0) return a;
  return a.Resize(w, h, 2)
};

function refresh_cover(a) {
  var b = 0;
  var c;
  var d = (cover.w - cover.margin * 2) * cover.quality / 100;
  var e = (cover.h - cover.margin * 2) * cover.quality / 100;
  if (a.track_type != 3) {
   if (a.metadb) {
     c = FormatCover(utils.GetAlbumArtEmbedded(a.metadb.rawpath, b), d, e);
     if (!c) {
       c = FormatCover(utils.GetAlbumArtV2(a.metadb, b), d, e);
       if (!c) {
         c = FormatCover(nocover, d, e);
         a.cover_type = 0
       } else {
         a.cover_type = 1
       }
     } else {
       a.cover_type = 2
     }
   }
  } else if (fb.IsPlaying && fb.PlaybackLength) {
   c = FormatCover(streamcover, d, e);
   a.cover_type = 3
  } else {
   c = FormatCover(nocover, d, e);
   a.cover_type = 0
  };
  return c
};

function reset_cover_timers() {
  for (var i in mycover2load) {
   mycover2load.timer && window.ClearInterval(mycover2load.timer)
  };
  mycover2load.splice(0, mycover2load.length)
};

function on_get_album_art_done(a, b, c, d) {
  for (var i = 0; i < mycover2load.length; i++) {
   if (mycover2load[0].item.metadb.Compare(a)) {
     mycover2load.item.cover_img = g_image_cache.getit(mycover2load.item, c, d);
     if (mycover2load.item.show) {
       window.RepaintRect(mycover2load.item.x - 15, cover.pad_top_mid, mycover2load.item.w + 30, wh - cover.pad_top_mid)
     } else {
       mycover2load.item.show = true
     };
     mycover2load.splice(i, 1);
     break
   }
  }
};
ItemStates = {
  normal: 0,
  hover: 1,
  selected: 2
};
item = function (g, h, k) {
  var i;
  if (typeof this.id == "undefined") {
   if (g < 0) {
     this.id = g;
     this.idx = h;
     this.gh_id = k;
     this.metadb = false;
     this.albumartist = "";
     this.album = "";
     this.track_type = null;
     this.cover_path = "";
     this.group_info = ""
   } else {
     this.id = g;
     this.idx = h;
     this.gh_id = k;
     this.metadb = list.handlelist.Item(this.id);
     if (this.metadb) {
       this.albumartist = tf_albumartist.EvalWithMetadb(this.metadb);
       this.album = tf_album.EvalWithMetadb(this.metadb);
       this.track_type = TrackType(this.metadb.rawpath.substring(0, 4));
       this.cover_path = tf_cover_path.EvalWithMetadb(this.metadb);
       this.group_info = tf_group_info.EvalWithMetadb(this.metadb)
     }
   }
  };
  this.update_infos = function () {
   if (this.metadb) {
     this.albumartist = tf_albumartist.EvalWithMetadb(this.metadb);
     this.album = tf_album.EvalWithMetadb(this.metadb);
     this.track_type = TrackType(this.metadb.rawpath.substring(0, 4));
     this.cover_path = tf_cover_path.EvalWithMetadb(this.metadb);
     this.group_info = tf_group_info.EvalWithMetadb(this.metadb)
   } else {
     this.albumartist = "";
     this.album = "";
     this.track_type = null;
     this.cover_path = "";
     this.group_info = ""
   }
  };
  this.draw = function (a, b, c, d, e) {
   this.show = e;
   if (list.mid == c) {
     this.w = cover.w;
     this.h = this.w;
     this.y = cover.pad_top_mid;
     this.x = Math.floor((ww / 2) - (cover.w / 2));
     this.cut = 1
   } else {
     this.w = Math.abs(d) == 1 ? cover.w - cover.normal_delta * 1 : cover.w - cover.normal_delta * 2;
     this.h = this.w;
     this.x = Math.abs(d) == 1 ? Math.floor((ww / 2) - (this.w / 2)) - (d * (this.w - 5)) : Math.floor((ww / 2) - (this.w / 2)) - (d * this.w);
     this.y = Math.abs(d) == 1 ? cover.pad_top_mid + Math.ceil(cover.normal_delta / 2) : cover.pad_top_mid + cover.normal_delta;
     this.cut = Math.abs(d) == 1 ? 1 : 0
   };
   if (this.id >= 0) {
     this.cover_img = g_image_cache.hit(this);
     if (this.show && typeof (this.cover_img) != "undefined") {
       var f = 255 - Math.floor(cover.reflect_strength_percent * 2.55);
       if (cover.draw_reflection && f > 0 && cover.reflect_strength_percent > 0) {
         a.DrawImage(this.cover_img, Math.floor(cover.margin / 2) + this.x, this.y + this.h * 2 - cover.margin - 1, this.w, -1 * this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255);
         if (cover.draw_border) {
           a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y + this.h + 1, this.w - cover.margin * 2 + 1, this.h - cover.margin * 2 + 1, 2.0, RGB(0, 0, 0));
           a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y + this.h + 1, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(255, 255, 255))
         } else {
           a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y + this.h + 1, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(127, 127, 127))
         };
         a.FillGradRect(Math.floor(cover.margin / 2) + this.x - 1, this.y + this.h - 1, this.w - this.cut, this.h + 1, 90, RGBA(g_backcolor_R, g_backcolor_G, g_backcolor_B, f), g_backcolor, 1.0)
       };
       a.DrawImage(this.cover_img, Math.floor(cover.margin / 2) + this.x, this.y, this.w, this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255);
       if (cover.draw_border) {
         a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y, this.w - cover.margin * 2 + 1, this.h - cover.margin * 2 + 1, 2.0, RGB(0, 0, 0));
         a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(255, 255, 255))
       } else {
         a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(127, 127, 127))
       };
       if (cover.draw_shadows) {
         if (d == 0 || d == 1 || d == -1) {
           for (var j = 0; j < 7; j++) {
             if (this.gh_id > 0) {
               a.FillSolidRect(Math.floor(cover.margin / 2) + this.x - j - cover.margin + 1, this.y + cover.normal_delta / 2, 1, this.h - cover.normal_delta - cover.margin - 1, RGBA(0, 0, 0, 150 - j * 25))
             };
             if (this.gh_id < list.total_gh - 1) {
               a.FillSolidRect(Math.floor(cover.margin / 2) + this.x + this.w - cover.margin + j - 1, this.y + cover.normal_delta / 2, 1, this.h - cover.normal_delta - cover.margin - 1, RGBA(0, 0, 0, 150 - j * 25))
             }
           }
         }
       }
     } else {
       var f = 255 - Math.floor(cover.reflect_strength_percent * 2.55);
       if (cover.draw_reflection && f > 0 && cover.reflect_strength_percent > 0) {
         a.DrawImage(nocover_img, Math.floor(cover.margin / 2) + this.x, this.y + this.h * 2 - cover.margin - 1, this.w, -1 * this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255);
         if (cover.draw_border) {
           a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y + this.h + 1, this.w - cover.margin * 2 + 1, this.h - cover.margin * 2 + 1, 2.0, RGB(0, 0, 0));
           a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y + this.h + 1, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(255, 255, 255))
         } else {
           a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y + this.h + 1, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(127, 127, 127))
         };
         a.FillGradRect(Math.floor(cover.margin / 2) + this.x - 1, this.y + this.h - 1, this.w - this.cut, this.h + 1, 90, RGBA(g_backcolor_R, g_backcolor_G, g_backcolor_B, f), g_backcolor, 1.0)
       };
       a.DrawImage(nocover_img, Math.floor(cover.margin / 2) + this.x, this.y, this.w, this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255);
       if (cover.draw_border) {
         a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y, this.w - cover.margin * 2 + 1, this.h - cover.margin * 2 + 1, 2.0, RGB(0, 0, 0));
         a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(255, 255, 255))
       } else {
         a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(127, 127, 127))
       };
       if (cover.draw_shadows) {
         if (d == 0 || d == 1 || d == -1) {
           for (var j = 0; j < 7; j++) {
             if (this.gh_id > 0) {
               a.FillSolidRect(Math.floor(cover.margin / 2) + this.x - j - cover.margin + 1, this.y + cover.normal_delta / 2, 1, this.h - cover.normal_delta - cover.margin - 1, RGBA(0, 0, 0, 150 - j * 25))
             };
             if (this.gh_id < list.total_gh - 1) {
               a.FillSolidRect(Math.floor(cover.margin / 2) + this.x + this.w - cover.margin + j - 1, this.y + cover.normal_delta / 2, 1, this.h - cover.normal_delta - cover.margin - 1, RGBA(0, 0, 0, 150 - j * 25))
             }
           }
         }
       }
     };
     if (cover.draw_focus_border && this.gh_id == list.selected_gh_id) {
       a.SetSmoothingMode(2);
       a.DrawRoundRect(Math.floor(cover.margin / 2) + this.x - 1, this.y - 1, this.w - cover.margin * 2 + 2, this.h - cover.margin * 2 + 2, 2, 2, 3.0, g_backcolor_sel);
       a.DrawRoundRect(Math.floor(cover.margin / 2) + this.x - 2, this.y - 2, this.w - cover.margin * 2 + 4, this.h - cover.margin * 2 + 4, 3, 3, 1.0, RGBA(255, 255, 255, 60));
       a.SetSmoothingMode(0);
       a.DrawRect(Math.floor(cover.margin / 2) + this.x + 1, this.y + 1, this.w - cover.margin * 2 - 2, this.h - cover.margin * 2 - 2, 1.0, g_backcolor_sel);
       a.DrawRect(Math.floor(cover.margin / 2) + this.x + 1, this.y + 1, this.w - cover.margin * 2 - 2, this.h - cover.margin * 2 - 2, 1.0, RGBA(0, 0, 0, 40))
     }
   }
  };
  this.checkstate = function (a, x, y, b) {
   if (this.id >= 0 && y > cover.pad_top_mid) {
     this.ishover = (x > this.x && x < this.x + this.w && y >= this.y && y < this.y + this.h)
   } else {
     this.ishover = false
   };
   switch (a) {
   case "down":
     if (!list.down_timerID && this.id >= 0) {
       if (plman.IsPlaylistItemSelected(fb.ActivePlaylist, this.id)) {
         if (this.ishover) {
           SelectGroupItems(this.id, this.gh_id);
           g_saved = this
         }
       } else {
         if (this.ishover) {
           if (utils.IsKeyPressed(VK_SHIFT)) {
             if (list.focus_id != this.id) {
               if (list.SHIFT_start_id != null) {} else {}
             }
           } else if (utils.IsKeyPressed(VK_CONTROL)) {
             plman.SetPlaylistFocusItem(fb.ActivePlaylist, this.id);
             plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, this.id, true)
           } else {
             SelectGroupItems(this.id, this.gh_id);
             g_saved = this
           }
         }
       }
     };
     break;
   case "dblclk":
     if (this.id >= 0 && g_saved != null) {
       if (plman.IsPlaylistItemSelected(fb.ActivePlaylist, this.id)) {
         if (this.id == g_saved.id) {
           plman.ExecutePlaylistDefaultAction(fb.ActivePlaylist, list.hlist[g_saved.gh_id]);
           g_saved = null;
           window.Repaint()
         }
       }
     };
     break;
   case "mid":
     if (this.ishover && this.idx == list.mid) {
       if (plman.GetPlaylistName(plman.ActivePlaylist) != "WSH CoverFlow") {
         SelectGroupItems(this.id, this.gh_id);
         var c = false;
         var d = 0;
         var e = plman.ActivePlaylist;
         for (var i = 0; i < plman.PlaylistCount; i++) {
           if (plman.GetPlaylistName(i) == "WSH CoverFlow") {
             c = true;
             d = i;
             break
           }
         };
         if (!c) {
           d = plman.PlaylistCount;
           plman.CreatePlaylist(plman.PlaylistCount, "WSH CoverFlow")
         };
         plman.ActivePlaylist = d;
         fb.ClearPlaylist();
         var f = fb.PlaylistItemCount(d);
         plman.InsertPlaylistItems(d, f, plman.GetPlaylistSelectedItems(e), false);
         plman.SetPlaylistFocusItem(d, 0)
       }
     };
     break;
   case "right":
     if (this.ishover && this.idx == list.mid) {
       SelectGroupItems(this.id, this.gh_id);
       new_context_menu(x, y, this.id, this.idx)
     };
     break;
   case "up":
     break;
   case "move":
     if (this.ishover) {}
     break;
   case "leave":
     break
   };
   return this.state
  }
};
var tf_path = fb.TitleFormat("$left(%_path_raw%,4)");
var tf_cover_path = fb.TitleFormat("$replace(%path%,%filename_ext%,)");
var tf_albumartist = fb.TitleFormat("$if(%length%,%album artist%,'Stream')");
var tf_album = fb.TitleFormat("$if2(%album%,$if(%length%,'Single','web radios'))");
var tf_group_key = fb.TitleFormat(window.GetProperty("_group Key", "%album artist%%album%"));
var tf_group_info = fb.TitleFormat(window.GetProperty("_group TF text info", "%album artist%[ | %album%][ | %date%]"));
var g_instancetype = window.InstanceType;
var g_font = null;
var g_font_headers = null;
var ww = 0,
  wh = 0;
var mouse_x = 0,
  mouse_y = 0;
var g_textcolor = 0,
  g_textcolor_sel = 0,
  g_textcolor_hl = 0,
  g_backcolor = 0,
  g_backcolor_sel = 0;
var g_metadb;
var bool_on_size = false;
var g_search_string = "";
var incsearch_font = gdi.Font("lucida console", 9, 0);
var incsearch_font_big = gdi.Font("lucida console", 20, 1);
var clear_incsearch_timer = false;
var incsearch_timer = false;
var g_saved = null;
panel = {
  max_height: window.GetProperty("panel.maximum.height", 300),
  arr_buttons: Array(),
  button_total: 2,
  show_text: window.GetProperty("panel.album.info.visible", true),
  custom_textcolor: window.GetProperty("panel.custom.text.color.normal", ""),
  custom_textcolor_selection: window.GetProperty("panel.custom.text.color.selection", ""),
  custom_backcolor: window.GetProperty("panel.custom.background.color", ""),
  custom_textcolor_highlight: window.GetProperty("panel.custom.text.color.hightlight", "")
};
list = {
  first_launch: true,
  total: 0,
  total_gh: 0,
  start_id: 0,
  nbvis: 0,
  mid: 0,
  item: Array(),
  hlist: Array(),
  handlelist: null,
  metadblist_selection: plman.GetPlaylistSelectedItems(fb.ActivePlaylist),
  focus_id: 0,
  selected_gh_id: 0,
  gh_id: 0,
  mousewheel_timer_value: 20,
  key_timer_value: 60,
  nowplaying: 0,
  SHIFT_start_id: null,
  SHIFT_count: 0,
  inc_search_noresult: false,
  nb_cover_to_draw: 0,
  buttonclicked: false
};
hscrollbar = {
  theme: false,
  themed: window.GetProperty("list.hscrollbar.themed", true),
  show: window.GetProperty("list.hscrollbar.visible", true),
  visible: true,
  hover: false,
  x: 0,
  y: 0,
  default_h: get_system_scrollbar_height(),
  h: get_system_scrollbar_height(),
  w: 0,
  button_total: 2,
  step: 3,
  arr_buttons: Array(),
  letter: null,
  timerID: false
};
button_up = {
  img_normal: null,
  img_hover: null,
  img_down: null,
  x: 0,
  y: 0,
  w: hscrollbar.default_h,
  h: hscrollbar.default_h,
  timerID: false
};
button_down = {
  img_normal: null,
  img_hover: null,
  img_down: null,
  x: 0,
  y: 0,
  w: hscrollbar.default_h,
  h: hscrollbar.default_h,
  timerID: false
};
cursor = {
  bt: null,
  img_normal: null,
  img_hover: null,
  img_down: null,
  popup: null,
  x: 0,
  y: 0,
  w: hscrollbar.default_h + 3,
  h: hscrollbar.default_h,
  default_w: hscrollbar.default_h + 3,
  hover: false,
  drag: false,
  grap_x: 0,
  timerID: false,
  last_x: 0
};
cover = {
  margin: 2,
  w: 0,
  h: 0,
  top_offset: 0,
  pad_top_mid: 35,
  pad_bot_mid: 30,
  normal_delta: 20,
  quality: window.GetProperty("list.covers.quality.percent", 100),
  draw_border: window.GetProperty("cover.draw.border", true),
  draw_reflection: window.GetProperty("cover.draw.reflection", true),
  reflect_strength_percent: window.GetProperty("cover.reflection.percent", 25),
  draw_shadows: window.GetProperty("cover.draw.shadows", true),
  draw_focus_border: window.GetProperty("cover.draw.focus.border", true)
};

function refresh_spv_cursor(a) {
  var b = (cursor.x - hscrollbar.x) / (hscrollbar.w - cursor.w);
  if (b > 1) b = 1;
  if (b < 0) b = 0;
  var r = Math.round(b * list.total_gh);
  set_gh_id(a, list.hlist[r - 1]);
  window.Repaint()
}
function set_gh_id(a, b) {
  reset_cover_timers();
  list.item.splice(0, list.item.length);
  if (list.total_gh <= 0) return true;
  list.gh_id = get_gh_id(b);
  if (list.gh_id == null) {
   list.gh_id = 0
  }
  var r = list.gh_id - list.mid;
  if (r < 0) {
   list.start_id = Math.abs®;
   r = 0
  } else {
   list.start_id = 0
  };
  for (var k = 0; k < list.nbvis; k++) {
   if (k >= list.start_id && r < list.total_gh) {
     list.item.push(new item(list.hlist[r], k, r));
     r++
   } else {
     list.item.push(new item(-1, k, -1))
   }
  }
};

function scrollup_spv(a) {
  var r = list.item[list.mid].gh_id;
  if (r > 0) {
   var s = list.item[0].gh_id;
   if (s > 0) {
     list.item.unshift(new item(list.hlist[s - 1], 0, s - 1))
   } else {
     list.item.unshift(new item(-1, 0, -1))
   };
   list.item.pop()
  };
  for (var i = 0; i < list.item.length; i++) {
   list.item.idx = i
  };
  setcursorx()
};

function scrolldown_spv(a) {
  var r = list.item[list.mid].gh_id;
  if (r < list.total_gh - 1) {
   var s = list.item[list.item.length - 1].gh_id;
   if (s > 0 && s < list.total_gh - 1) {
     list.item.push(new item(list.hlist[s + 1], 0, s + 1))
   } else {
     list.item.push(new item(-1, 0, -1))
   };
   list.item.shift()
  };
  for (var i = 0; i < list.item.length; i++) {
   list.item.idx = i
  };
  setcursorx()
};

function refresh_spv(a, b) {
  reset_cover_timers();
  list.item.splice(0, list.item.length);
  if (list.total_gh <= 0) return true;
  list.gh_id = get_gh_id(list.focus_id);
  if (list.gh_id == null) {
   init_active_pls();
   return true
  }
  list.selected_gh_id = list.gh_id;
  var r = list.gh_id - list.mid;
  if (r < 0) {
   list.start_id = Math.abs®;
   r = 0
  } else {
   list.start_id = 0
  };
  for (var k = 0; k < list.nbvis; k++) {
   if (k >= list.start_id && r < list.total_gh) {
     list.item.push(new item(list.hlist[r], k, r));
     r++
   } else {
     list.item.push(new item(-1, k, -1))
   }
  };
  if (hscrollbar.show) {
   if (list.total_gh < 2) hscrollbar.visible = false;
   else hscrollbar.visible = true
  } else {
   hscrollbar.visible = false
  };
  cursor.w = Math.round(hscrollbar.w / list.total_gh);
  if (cursor.w > hscrollbar.w) cursor.w = hscrollbar.w;
  if (cursor.w < cursor.default_w) cursor.w = cursor.default_w;
  set_scroller();
  setcursorx()
};

function get_gh_id(a) {
  var b = Math.floor(list.total_gh / 2);
  if (a < list.hlist) {
   var c = 0
  } else {
   var c = b
  };
  for (var i = c; i < list.total_gh; i++) {
   if (i < list.total_gh - 1) {
     if (a >= list.hlist && a < list.hlist[i + 1]) {
       return i
     }
   } else {
     if (a >= list.hlist) {
       return i
     } else {
       fb.trace("error: gh_id not found");
       return null
     }
   }
  }
};

function setcursorx() {
  var a = Math.floor(list.item.length / 2);
  var b = list.item[a].gh_id;
  var c = b / (list.total_gh - 1);
  cursor.x = hscrollbar.x + Math.round(c * (hscrollbar.w - cursor.w))
};

function init_active_pls() {
  var a;
  var b;
  list.hlist.splice(0, list.hlist.length);
  list.handlelist = plman.GetPlaylistItems(fb.ActivePlaylist);
  list.total = list.handlelist.Count;
  for (var i = 0; i < list.total; i++) {
   b = tf_group_key.EvalWithMetadb(list.handlelist.Item(i));
   if (a != b) {
     list.hlist.push(i);
     a = b
   }
  };
  list.total_gh = list.hlist.length
};

function on_font_changed() {
  get_font();
  window.Repaint()
};

function on_colors_changed() {
  get_colors();
  init_icons();
  nocover_img = FormatCover(nocover, (cover.w - cover.margin * 2) * cover.quality / 100, (cover.h - cover.margin * 2) * cover.quality / 100);
  init_hscrollbar_buttons();
  set_scroller();
  g_image_cache = new image_cache;
  CollectGarbage();
  window.Repaint()
};

function on_init() {};

function on_size() {
  if (!window.Width || !window.Height) return;
  window.DlgCode = DLGC_WANTALLKEYS;
  bool_on_size = true;
  if (g_instancetype == 0) {
   window.MinWidth = 200;
   window.MinHeight = 170;
   window.MaxHeight = panel.max_height
  } else if (g_instancetype == 1) {
   window.MinWidth = 200;
   window.MinHeight = 170;
   window.MaxHeight = panel.max_height
  };
  ww = window.Width;
  wh = window.Height;
  if (wh < 170) wh = 170;
  var a = window.GetProperty("_group TF text info", "%album artist%[ | %album%][ | %date%]");
  if (a == "") window.SetProperty("_group TF text info", "%album artist%[ | %album%][ | %date%]");
  tf_group_info = fb.TitleFormat(window.GetProperty("_group TF text info", "%album artist%[ | %album%][ | %date%]"));
  get_font();
  get_colors();
  init_icons();
  cover.w = wh - cover.pad_top_mid - cover.pad_bot_mid;
  cover.h = cover.w;
  list.nbvis = Math.floor(ww / (cover.w - cover.normal_delta * 2)) + 2;
  if (list.nbvis / 2 == Math.floor(list.nbvis / 2)) {
   list.nbvis--
  }
  if (list.nbvis > 23) list.nbvis = 23;
  list.mid = Math.floor(list.nbvis / 2);
  list.nb_cover_to_draw = list.nbvis;
  if (hscrollbar.themed) {
   hscrollbar.theme = window.CreateThemeManager("scrollbar")
  } else {
   hscrollbar.theme = false
  };
  init_hscrollbar_buttons();
  button_up.x = 0;
  button_up.y = wh - hscrollbar.h;
  button_down.x = ww - button_down.w;
  button_down.y = wh - hscrollbar.h;
  hscrollbar.x = button_up.w;
  hscrollbar.w = ww - button_up.w - button_down.w;
  cursor.y = wh - hscrollbar.h;
  cursor.x = hscrollbar.x;
  nocover_img = FormatCover(nocover, (cover.w - cover.margin * 2) * cover.quality / 100, (cover.h - cover.margin * 2) * cover.quality / 100);
  if (list.first_launch) {
   list.first_launch = false;
   on_playlist_switch()
  } else {
   g_image_cache = new image_cache;
   CollectGarbage();
   refresh_spv(fb.ActivePlaylist, true);
   window.Repaint()
  }
};

function on_paint(a) {
  a.FillGradRect(0, 0, ww, wh, 90, g_backcolor, g_backcolor & 0xd0ffffff, 0.3);
  if (list.item.length > 0) {
   var b, mid2;
   list.item[list.mid].draw(a, list.item[list.mid].id, list.mid, 0, true);
   for (var c = 1; c < list.mid + 1; c++) {
     if (c > 1 && c <= list.mid) {
       b = true
     } else {
       b = false
     };
     mid2 = list.mid - c;
     if (mid2 >= 0 && mid2 <= list.item.length - 1) {
       list.item[mid2].draw(a, list.item[mid2].id, mid2, c, b)
     }
     mid2 = list.mid + c;
     if (mid2 >= 0 && mid2 <= list.item.length - 1) {
       list.item[mid2].draw(a, list.item[mid2].id, mid2, c * -1, b)
     }
   };
   mid2 = list.mid - 1;
   if (mid2 >= 0 && mid2 <= list.item.length - 1) {
     list.item[mid2].draw(a, list.item[mid2].id, mid2, 1, true)
   }
   mid2 = list.mid + 1;
   if (mid2 >= 0 && mid2 <= list.item.length - 1) {
     list.item[mid2].draw(a, list.item[mid2].id, mid2, -1, true)
   }
   list.item[list.mid].draw(a, list.item[list.mid].id, list.mid, 0, true);
   if (panel.show_text) {
     var d = 30;
     var f = ww - 60;
     if (list.item[list.mid].id >= 0) {
       a.GdiDrawText(list.item[list.mid].group_info, g_font, g_textcolor, d, 0, f, cover.pad_top_mid - 4, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX)
     }
   }
  };
  if (list.total_gh > 0 && hscrollbar.visible && hscrollbar.show) {
   try {
     hscrollbar.theme.SetPartAndStateId(4, 1);
     hscrollbar.theme.DrawThemeBackground(a, 0, wh - hscrollbar.h, ww, hscrollbar.h);
     a.FillSolidRect(0, wh - hscrollbar.h - 1, ww, 1, RGBA(0, 0, 0, 10))
   } catch (e) {
     a.FillSolidRect(0, wh - hscrollbar.h, ww, hscrollbar.h, g_backcolor);
     a.FillGradRect(0, wh - hscrollbar.h, ww, hscrollbar.h, 0, RGBA(0, 0, 0, 100), g_backcolor, 0.5);
     a.FillGradRect(0, wh - hscrollbar.h, ww, hscrollbar.h, 0, 0, RGBA(255, 255, 255, 25), 0.5);
     a.FillSolidRect(0, wh - hscrollbar.h - 1, ww, 1, RGBA(0, 0, 0, 10))
   };
   try {
     cursor.bt.draw(a, cursor.x, cursor.y, 255)
   } catch (e) {};
   try {
     hscrollbar.theme.SetPartAndStateId(8, 1);
     hscrollbar.theme.DrawThemeBackground(a, cursor.x, wh - hscrollbar.h + 0, cursor.w, cursor.h)
   } catch (e) {};
   for (i = 0; i < hscrollbar.arr_buttons.length; i++) {
     switch (i) {
     case 0:
       hscrollbar.arr_buttons.draw(a, button_up.x, button_up.y, 255);
       break;
     case 1:
       hscrollbar.arr_buttons.draw(a, button_down.x, button_down.y, 255);
       break
     }
   };
   if (cursor.drag) {
     hscrollbar.letter = list.item[Math.floor(list.nb_cover_to_draw / 2)].albumartist.substring(0, 1).toUpperCase();
     cursor.popup && a.DrawImage(cursor.popup, cursor.x + Math.floor(cursor.w / 2) - Math.floor(cursor.popup.Width / 2), wh - hscrollbar.h - cursor.popup.Height, cursor.popup.Width, cursor.popup.Height, 0, 0, cursor.popup.Width, cursor.popup.Height, 0, 155);
     cursor.popup && a.GdiDrawText(hscrollbar.letter, gdi.Font("segoe ui", 14, 0), g_backcolor, cursor.x + Math.floor(cursor.w / 2) - Math.floor(cursor.popup.Width / 2), wh - hscrollbar.h - cursor.popup.Height, cursor.popup.Width, cursor.popup.Height - 5, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX)
   }
  };
  for (i = 0; i < panel.arr_buttons.length; i++) {
   switch (i) {
   case 0:
     panel.arr_buttons.draw(a, 5, 5, 255);
     break;
   case 1:
     panel.arr_buttons.draw(a, ww - 22 - 5, 5, 255);
     break
   }
  };
  a.FillGradRect(0, 0, ww, 1, 0, 0, g_textcolor & 0x25ffffff, 0.5)
};

function on_mouse_lbtn_down(x, y) {
  bool_on_size = false;
  for (var i = 0; i < list.item.length; i++) {
   list.item.checkstate("down", x, y, i)
  };
  if (list.total_gh > 0 && hscrollbar.visible && hscrollbar.show) {
   if (cursor.bt.checkstate("down", x, y) == ButtonStates.down) {
     cursor.drag = true;
     cursor.grap_x = x - cursor.x;
     cursor.last_x = cursor.x
   };
   if (hscrollbar.hover && !cursor.drag) {
     hscrollbar.step = Math.floor(list.nb_cover_to_draw / 2);
     if (hscrollbar.step < 1) hscrollbar.step = 1;
     if (x < cursor.x) {
       if (!list.buttonclicked) {
         list.buttonclicked = true;
         on_mouse_wheel(hscrollbar.step);
         button_up.first_timerID = window.SetTimeout(function () {
           on_mouse_wheel(hscrollbar.step);
           button_up.timerID = window.SetInterval(function () {
             if (hscrollbar.hover) {
               if (mouse_y > wh - hscrollbar.h && cursor.x > mouse_x) {
                 on_mouse_wheel(hscrollbar.step)
               }
             }
           }, list.key_timer_value)
         }, 400)
       }
     } else {
       if (!list.buttonclicked) {
         list.buttonclicked = true;
         on_mouse_wheel(-1 * hscrollbar.step);
         button_down.first_timerID = window.SetTimeout(function () {
           on_mouse_wheel(-1 * hscrollbar.step);
           button_down.timerID = window.SetInterval(function () {
             if (hscrollbar.hover) {
               if (mouse_y > wh - hscrollbar.h && cursor.x + cursor.w < mouse_x) {
                 on_mouse_wheel(-1 * hscrollbar.step)
               }
             }
           }, list.key_timer_value)
         }, 400)
       }
     }
   };
   for (i = 0; i < hscrollbar.arr_buttons.length; i++) {
     switch (i) {
     case 0:
       if (hscrollbar.arr_buttons.checkstate("down", x, y) == ButtonStates.down) {
         if (!list.buttonclicked) {
           list.buttonclicked = true;
           on_mouse_wheel(1);
           button_up.first_timerID = window.SetTimeout(function () {
             reset_cover_timers();
             button_up.timerID = window.SetInterval(function () {
               on_mouse_wheel(1)
             }, list.key_timer_value)
           }, 400)
         }
       };
       break;
     case 1:
       if (hscrollbar.arr_buttons.checkstate("down", x, y) == ButtonStates.down) {
         if (!list.buttonclicked) {
           list.buttonclicked = true;
           on_mouse_wheel(-1);
           button_down.first_timerID = window.SetTimeout(function () {
             reset_cover_timers();
             button_down.timerID = window.SetInterval(function () {
               on_mouse_wheel(-1)
             }, list.key_timer_value)
           }, 400)
         }
       };
       break
     }
   }
  };
  for (i = 0; i < panel.arr_buttons.length; i++) {
   switch (i) {
   case 0:
     if (panel.arr_buttons.checkstate("down", x, y) == ButtonStates.down) {
       ShowNowPlaying()
     };
     break;
   case 1:
     if (panel.arr_buttons.checkstate("down", x, y) == ButtonStates.down) {
       if (list.total_gh >= 2) {
         hscrollbar.show = !hscrollbar.show;
         if (hscrollbar.show) {
           hscrollbar.visible = true
         } else {
           hscrollbar.visible = false
         }
       } else {
         hscrollbar.visible = false
       };
       window.SetProperty("list.hscrollbar.visible", hscrollbar.show);
       window.Repaint()
     };
     break
   }
  }
};

function on_mouse_lbtn_dblclk(x, y, a) {
  if (y < cover.pad_top_mid) {} else if (y < wh - cover.pad_bot_mid) {
   for (var i = 0; i < list.item.length; i++) {
     list.item.checkstate("dblclk", x, y, i)
   }
  } else {
   on_mouse_lbtn_down(x, y)
  }
};

function on_mouse_lbtn_up(x, y) {
  list.buttonclicked = false;
  hscrollbar.timerID && window.ClearTimeout(hscrollbar.timerID);
  hscrollbar.timerID = false;
  button_up.first_timerID && window.ClearTimeout(button_up.first_timerID);
  button_up.first_timerID = false;
  button_down.first_timerID && window.ClearTimeout(button_down.first_timerID);
  button_down.first_timerID = false;
  button_up.timerID && window.ClearInterval(button_up.timerID);
  button_up.timerID = false;
  button_down.timerID && window.ClearInterval(button_down.timerID);
  button_down.timerID = false;
  if (list.total_gh > 0) {
   cursor.bt.checkstate("up", x, y);
   for (var i = 0; i < hscrollbar.arr_buttons.length; i++) {
     hscrollbar.arr_buttons.checkstate("up", x, y)
   };
   for (var i = 0; i < panel.arr_buttons.length; i++) {
     panel.arr_buttons.checkstate("up", x, y)
   };
   if (cursor.drag) {
     window.RepaintRect(0, wh - hscrollbar.h, ww, hscrollbar.h);
     cursor.drag = false
   } else {
     for (i = 0; i < list.item.length; i++) {
       list.item.checkstate("up", x, y, i)
     }
   };
   setcursorx();
   window.Repaint()
  }
};

function on_mouse_mbtn_down(x, y, a) {
  bool_on_size = false;
  for (var i = 0; i < list.item.length; i++) {
   list.item.checkstate("mid", x, y, i)
  }
};

function on_mouse_rbtn_down(x, y) {
  bool_on_size = false;
  for (var i = 0; i < list.item.length; i++) {
   list.item.checkstate("right", x, y, i)
  }
};

function on_mouse_move(x, y) {
  if (x == mouse_x && y == mouse_y) return true;
  if (list.total_gh > 0 && hscrollbar.visible && hscrollbar.show) {
   hscrollbar.hover = (y >= wh - hscrollbar.h && y <= wh && x >= hscrollbar.x && x <= hscrollbar.x + hscrollbar.w);
   cursor.hover = (x >= cursor.x && x <= cursor.x + cursor.w && y >= cursor.y && y <= cursor.y + cursor.h);
   cursor.bt.checkstate("move", x, y);
   for (var i = 0; i < hscrollbar.arr_buttons.length; i++) {
     hscrollbar.arr_buttons.checkstate("move", x, y)
   };
   if (cursor.drag && mouse_x != x) {
     reset_cover_timers();
     cursor.x = x - cursor.grap_x;
     if (cursor.x < hscrollbar.x) cursor.x = hscrollbar.x;
     if (cursor.x > hscrollbar.x + hscrollbar.w - cursor.w) cursor.x = hscrollbar.x + hscrollbar.w - cursor.w;
     if (!cursor.timerID) {
       cursor.timerID = window.SetTimeout(function () {
         refresh_spv_cursor(fb.ActivePlaylist);
         window.Repaint();
         cursor.timerID && window.ClearTimeout(cursor.timerID);
         cursor.timerID = false
       }, 30)
     }
   }
  };
  for (var j = 0; j < panel.arr_buttons.length; j++) {
   panel.arr_buttons[j].checkstate("move", x, y)
  };
  mouse_x = x;
  mouse_y = y
};

function on_mouse_wheel(a) {
  reset_cover_timers();
  if (!hscrollbar.timerID) {
   if (Math.abs(a) >= 1) {
     if (a > 0) {
       for (var i = 0; i < Math.abs(a); i++) {
         scrollup_spv(fb.ActivePlaylist)
       };
       hscrollbar.timerID = window.SetTimeout(function () {
         window.Repaint();
         hscrollbar.timerID && window.ClearTimeout(hscrollbar.timerID);
         hscrollbar.timerID = false
       }, list.mousewheel_timer_value)
     } else {
       for (var i = 0; i < Math.abs(a); i++) {
         scrolldown_spv(fb.ActivePlaylist)
       }
       hscrollbar.timerID = window.SetTimeout(function () {
         window.Repaint();
         hscrollbar.timerID && window.ClearTimeout(hscrollbar.timerID);
         hscrollbar.timerID = false
       }, list.mousewheel_timer_value)
     }
   }
  }
};

function on_mouse_leave() {
  for (i = 0; i < list.item.length; i++) {
   list.item.checkstate("leave", 0, 0, i)
  };
  window.Repaint()
};

function on_playlist_switch() {
  if (fb.ActivePlaylist < 0 || fb.ActivePlaylist > fb.PlaylistCount) {
   if (fb.PlaylistCount > 0) {
     fb.ActivePlaylist = 0
   }
  };
  init_active_pls();
  list.focus_id = plman.GetPlaylistFocusItemIndex(fb.ActivePlaylist);
  if (list.focus_id < 0) {
   list.focus_id = 0
  }
  refresh_spv(fb.ActivePlaylist, true);
  window.Repaint()
};

function on_playlist_items_added(a) {
  if (a == fb.ActivePlaylist) {
   on_playlist_switch()
  };
  plman.SetActivePlaylistContext()
};

function on_playlist_items_reordered(a) {
  if (a == fb.ActivePlaylist) {
   on_playlist_switch()
  }
};

function on_selection_changed(a) {};

function on_playlist_items_selection_change() {};

function on_playlists_changed() {};

function on_item_focus_change(a, b, c) {
  list.focus_id = c;
  plman.SetActivePlaylistContext();
  refresh_spv(fb.ActivePlaylist, bool_on_size);
  bool_on_size = false;
  window.Repaint()
};

function on_metadb_changed(a, b) {
  for (var i = 0; i < list.item.length; i++) {
   list.item.update_infos()
  };
  window.Repaint()
};

function on_focus(a) {};

function on_key_up(a) {};

function on_key_down(a) {
  var b = GetKeyboardMask();
  if (b == KMask.none) {
   switch (a) {
   case VK_SHIFT:
     list.SHIFT_count = 0;
     break;
   case VK_BACK:
     break;
   case VK_ESCAPE:
   case 222:
     break;
   case VK_SPACEBAR:
     var c = list.item[Math.floor(list.nb_cover_to_draw / 2)].id;
     plman.SetPlaylistFocusItem(fb.ActivePlaylist, c);
     plman.ClearPlaylistSelection(fb.ActivePlaylist);
     plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, c, true);
     break;
   case VK_LEFT:
     on_mouse_wheel(1);
     break;
   case VK_RIGHT:
     on_mouse_wheel(-1);
     break;
   case VK_PGUP:
     hscrollbar.step = Math.floor(list.nb_cover_to_draw / 2);
     if (hscrollbar.step < 1) hscrollbar.step = 1;
     on_mouse_wheel(hscrollbar.step);
     break;
   case VK_PGDN:
     hscrollbar.step = Math.floor(list.nb_cover_to_draw / 2);
     if (hscrollbar.step < 1) hscrollbar.step = 1;
     on_mouse_wheel(hscrollbar.step * -1);
     break;
   case VK_RETURN:
     plman.ExecutePlaylistDefaultAction(fb.ActivePlaylist, list.focus_id);
     break;
   case VK_END:
     plman.SetPlaylistFocusItem(fb.ActivePlaylist, list.total - 1);
     plman.ClearPlaylistSelection(fb.ActivePlaylist);
     plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, list.total - 1, true);
     break;
   case VK_HOME:
     plman.SetPlaylistFocusItem(fb.ActivePlaylist, 0);
     plman.ClearPlaylistSelection(fb.ActivePlaylist);
     plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, 0, true);
     break;
   case VK_DELETE:
     if (!fb.IsAutoPlaylist(fb.ActivePlaylist)) {
       plman.RemovePlaylistSelection(fb.ActivePlaylist, false);
       plman.SetPlaylistSelectionSingle(fb.ActivePlaylist, plman.GetPlaylistFocusItemIndex(fb.ActivePlaylist), true)
     }
     break;
   default:
     break
   }
  } else {
   switch (b) {
   case KMask.shift:
     break;
   case KMask.ctrl:
     if (a == 65) {
       fb.RunMainMenuCommand("Edit/Select all");
       window.Repaint()
     };
     if (a == 70) {
       fb.RunMainMenuCommand("Edit/Search")
     };
     if (a == 78) {
       fb.RunMainMenuCommand("File/New playlist")
     };
     if (a == 79) {
       fb.RunMainMenuCommand("File/Open...")
     };
     if (a == 80) {
       fb.RunMainMenuCommand("File/Preferences")
     };
     if (a == 83) {
       fb.RunMainMenuCommand("File/Save playlist...")
     };
     break;
   case KMask.alt:
     if (a == 65) {
       fb.RunMainMenuCommand("View/Always on Top")
     };
     break
   }
  }
};

function on_playback_new_track(a) {
  g_metadb = fb.GetNowPlaying();
  window.Repaint()
};

function on_playback_stop(a) {
  if (a == 0) {
   g_metadb = fb.GetFocusItem();
   on_metadb_changed()
  }
};

function on_playback_pause(a) {};

function on_playback_time(a) {};

function get_font() {
  if (g_instancetype == 0) {
   g_font = window.GetFontCUI(FontTypeCUI.items);
   g_font_headers = window.GetFontCUI(FontTypeCUI.labels)
  } else if (g_instancetype == 1) {
   g_font = window.GetFontDUI(FontTypeDUI.playlists);
   g_font_headers = window.GetFontDUI(FontTypeDUI.tabs)
  }
};

function get_colors() {
  if (g_instancetype == 0) {
   g_textcolor = window.GetColorCUI(ColorTypeCUI.text);
   g_textcolor_sel = window.GetColorCUI(ColorTypeCUI.selection_text);
   g_textcolor_hl = window.GetColorCUI(ColorTypeCUI.active_item_frame);
   g_backcolor = window.GetColorCUI(ColorTypeCUI.background);
   g_backcolor_sel = window.GetColorCUI(ColorTypeCUI.selection_background)
  } else if (g_instancetype == 1) {
   g_textcolor = window.GetColorDUI(ColorTypeDUI.text);
   g_textcolor_sel = window.GetColorDUI(ColorTypeDUI.selection);
   g_textcolor_hl = window.GetColorDUI(ColorTypeDUI.highlight);
   g_backcolor = window.GetColorDUI(ColorTypeDUI.background);
   g_backcolor_sel = g_textcolor_sel
  };
  try {
   if (panel.custom_textcolor.length > 0) g_textcolor = eval(panel.custom_textcolor);
   if (panel.custom_textcolor_selection.length > 0) g_textcolor_sel = eval(panel.custom_textcolor_selection);
   if (panel.custom_backcolor.length > 0) g_backcolor = eval(panel.custom_backcolor);
   if (panel.custom_textcolor_highlight.length > 0) g_textcolor_hl = eval(panel.custom_textcolor_highlight)
  } catch (e) {};
  g_backcolor_R = getRed(g_backcolor);
  g_backcolor_G = getGreen(g_backcolor);
  g_backcolor_B = getBlue(g_backcolor)
};

function set_scroller() {
  var a;
  try {
   cursor.img_normal = gdi.CreateImage(cursor.w, cursor.h)
  } catch (e) {
   cursor.h = cursor.default_h;
   cursor.img_normal = gdi.CreateImage(cursor.w, cursor.h)
  };
  a = cursor.img_normal.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(2, 1);
   hscrollbar.theme.DrawThemeBackground(a, 0, 0, cursor.w, cursor.h)
  } catch (e) {
   a.FillSolidRect(0, 1, cursor.w - 0, cursor.h - 2, g_backcolor);
   a.FillSolidRect(0, 1, cursor.w - 0, cursor.h - 2, RGBA(0, 0, 0, 100));
   a.FillSolidRect(0, 1, cursor.w - 1, cursor.h - 3, g_textcolor & 0x77ffffff);
   a.FillSolidRect(1, 2, cursor.w - 2, cursor.h - 4, g_backcolor);
   a.FillSolidRect(1, 2, cursor.w - 2, cursor.h - 4, RGBA(255, 255, 255, 25))
  };
  cursor.img_normal.ReleaseGraphics(a);
  cursor.img_hover = gdi.CreateImage(cursor.w, cursor.h);
  a = cursor.img_hover.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(2, 2);
   hscrollbar.theme.DrawThemeBackground(a, 0, 0, cursor.w, cursor.h)
  } catch (e) {
   a.FillSolidRect(0, 1, cursor.w - 0, cursor.h - 2, g_backcolor);
   a.FillSolidRect(0, 1, cursor.w - 0, cursor.h - 2, RGBA(0, 0, 0, 70));
   a.FillSolidRect(0, 1, cursor.w - 1, cursor.h - 3, g_textcolor & 0x99ffffff);
   a.FillSolidRect(1, 2, cursor.w - 2, cursor.h - 4, g_backcolor);
   a.FillSolidRect(1, 2, cursor.w - 2, cursor.h - 4, RGBA(255, 255, 255, 50))
  };
  cursor.img_hover.ReleaseGraphics(a);
  cursor.bt = new button(cursor.img_normal, cursor.img_hover, cursor.img_hover)
};

function init_hscrollbar_buttons() {
  var i, gb;
  cursor.popup = gdi.CreateImage(22, 27);
  gb = cursor.popup.GetGraphics();
  gb.SetSmoothingMode(2);
  gb.FillRoundRect(0, 0, 22 - 1, 22 - 1, 3, 3, g_textcolor);
  gb.DrawRoundRect(0, 0, 22 - 1, 22 - 1, 3, 3, 1.0, RGBA(0, 0, 0, 150));
  var a = Array(7, 22 - 2, 11, 22 - 2 + 6, 22 - 7, 22 - 2);
  gb.FillPolygon(g_textcolor, 0, a);
  gb.DrawPolygon(RGBA(0, 0, 0, 150), 1.0, a);
  gb.SetSmoothingMode(0);
  gb.FillSolidRect(6, 22 - 4, 22 - 10, 3, g_textcolor);
  cursor.popup.ReleaseGraphics(gb);
  button_up.img_normal = gdi.CreateImage(button_up.w, button_up.h);
  gb = button_up.img_normal.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(1, 9);
   hscrollbar.theme.DrawThemeBackground(gb, 0, 0, button_up.w, button_up.h)
  } catch (e) {
   gb.FillSolidRect(0, 0, button_up.w - 0, button_up.h - 0, g_backcolor);
   gb.FillSolidRect(0, 0, button_up.w - 0, button_up.h - 0, RGBA(0, 0, 0, 100));
   gb.FillSolidRect(0, 0, button_up.w - 1, button_up.h - 1, g_textcolor & 0x77ffffff);
   gb.FillSolidRect(1, 1, button_up.w - 2, button_up.h - 2, g_backcolor);
   gb.FillSolidRect(1, 1, button_up.w - 2, button_up.h - 2, RGBA(255, 255, 255, 25));
   gb.SetTextRenderingHint(4);
   gui_font = gdi.Font("guifx v2 transports", 12, 0);
   gb.DrawString(".", gui_font, RGBA(255, 255, 255, 25), 0, 1, button_up.w - 0, button_up.h, cc_stringformat);
   gb.DrawString(".", gui_font, g_textcolor, 0, 0, button_up.w - 0, button_up.h, cc_stringformat)
  };
  button_up.img_normal.ReleaseGraphics(gb);
  button_up.img_hover = gdi.CreateImage(button_up.w, button_up.h);
  gb = button_up.img_hover.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(1, 10);
   hscrollbar.theme.DrawThemeBackground(gb, 0, 0, button_up.w, button_up.h)
  } catch (e) {
   gb.FillSolidRect(0, 0, button_up.w - 0, button_up.h - 0, g_backcolor);
   gb.FillSolidRect(0, 0, button_up.w - 0, button_up.h - 0, RGBA(0, 0, 0, 70));
   gb.FillSolidRect(0, 0, button_up.w - 1, button_up.h - 1, g_textcolor & 0x99ffffff);
   gb.FillSolidRect(1, 1, button_up.w - 2, button_up.h - 2, g_backcolor);
   gb.FillSolidRect(1, 1, button_up.w - 2, button_up.h - 2, RGBA(255, 255, 255, 50));
   gb.SetTextRenderingHint(4);
   gui_font = gdi.Font("guifx v2 transports", 12, 0);
   gb.DrawString(".", gui_font, RGBA(255, 255, 255, 50), 0, 1, button_up.w - 0, button_up.h, cc_stringformat);
   gb.DrawString(".", gui_font, g_textcolor, 0, 0, button_up.w - 0, button_up.h, cc_stringformat)
  };
  button_up.img_hover.ReleaseGraphics(gb);
  button_up.img_down = gdi.CreateImage(button_up.w, button_up.h);
  gb = button_up.img_down.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(1, 11);
   hscrollbar.theme.DrawThemeBackground(gb, 0, 0, button_up.w, button_up.h)
  } catch (e) {
   gb.FillSolidRect(0, 0, button_up.w - 0, button_up.h - 0, g_textcolor & 0x77ffffff);
   gb.FillSolidRect(0, 0, button_up.w - 0, button_up.h - 0, g_backcolor);
   gb.FillSolidRect(0, 0, button_up.w - 1, button_up.h - 1, RGBA(0, 0, 0, 100));
   gb.FillSolidRect(1, 1, button_up.w - 2, button_up.h - 2, g_backcolor);
   gb.FillSolidRect(1, 1, button_up.w - 2, button_up.h - 2, RGBA(255, 255, 255, 25));
   gb.SetTextRenderingHint(4);
   gui_font = gdi.Font("guifx v2 transports", 12, 0);
   gb.DrawString(".", gui_font, RGBA(255, 255, 255, 25), 0, 1, button_up.w - 0, button_up.h, cc_stringformat);
   gb.DrawString(".", gui_font, g_textcolor, 0, 0, button_up.w - 0, button_up.h, cc_stringformat)
  };
  button_up.img_down.ReleaseGraphics(gb);
  button_down.img_normal = gdi.CreateImage(button_down.w, button_down.h);
  gb = button_down.img_normal.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(1, 13);
   hscrollbar.theme.DrawThemeBackground(gb, 0, 0, button_down.w, button_down.h)
  } catch (e) {
   gb.FillSolidRect(0, 0, button_down.w - 0, button_down.h - 0, g_backcolor);
   gb.FillSolidRect(0, 0, button_down.w - 0, button_down.h - 0, RGBA(0, 0, 0, 100));
   gb.FillSolidRect(0, 0, button_down.w - 1, button_down.h - 1, g_textcolor & 0x77ffffff);
   gb.FillSolidRect(1, 1, button_down.w - 2, button_down.h - 2, g_backcolor);
   gb.FillSolidRect(1, 1, button_down.w - 2, button_down.h - 2, RGBA(255, 255, 255, 25));
   gb.SetTextRenderingHint(4);
   gui_font = gdi.Font("guifx v2 transports", 12, 0);
   gb.DrawString(",", gui_font, RGBA(255, 255, 255, 25), 0, 1, button_down.w - 0, button_down.h, cc_stringformat);
   gb.DrawString(",", gui_font, g_textcolor, 0, 0, button_down.w - 0, button_down.h, cc_stringformat)
  };
  button_down.img_normal.ReleaseGraphics(gb);
  button_down.img_hover = gdi.CreateImage(button_down.w, button_down.h);
  gb = button_down.img_hover.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(1, 14);
   hscrollbar.theme.DrawThemeBackground(gb, 0, 0, button_down.w, button_down.h)
  } catch (e) {
   gb.FillSolidRect(0, 0, button_down.w - 0, button_down.h - 0, g_backcolor);
   gb.FillSolidRect(0, 0, button_down.w - 0, button_down.h - 0, RGBA(0, 0, 0, 70));
   gb.FillSolidRect(0, 0, button_down.w - 1, button_down.h - 1, g_textcolor & 0x99ffffff);
   gb.FillSolidRect(1, 1, button_down.w - 2, button_down.h - 2, g_backcolor);
   gb.FillSolidRect(1, 1, button_down.w - 2, button_down.h - 2, RGBA(255, 255, 255, 50));
   gb.SetTextRenderingHint(4);
   gui_font = gdi.Font("guifx v2 transports", 12, 0);
   gb.DrawString(",", gui_font, RGBA(255, 255, 255, 50), 0, 1, button_down.w - 0, button_down.h, cc_stringformat);
   gb.DrawString(",", gui_font, g_textcolor, 0, 0, button_down.w - 0, button_down.h, cc_stringformat)
  };
  button_down.img_hover.ReleaseGraphics(gb);
  button_down.img_down = gdi.CreateImage(button_down.w, button_down.h);
  gb = button_down.img_down.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(1, 15);
   hscrollbar.theme.DrawThemeBackground(gb, 0, 0, button_down.w, button_down.h)
  } catch (e) {
   gb.FillSolidRect(0, 0, button_down.w - 0, button_down.h - 0, g_textcolor & 0x77ffffff);
   gb.FillSolidRect(0, 0, button_down.w - 0, button_down.h - 0, g_backcolor);
   gb.FillSolidRect(0, 0, button_down.w - 1, button_down.h - 1, RGBA(0, 0, 0, 100));
   gb.FillSolidRect(1, 1, button_down.w - 2, button_down.h - 1, g_backcolor);
   gb.FillSolidRect(1, 1, button_down.w - 2, button_down.h - 1, RGBA(255, 255, 255, 25));
   gb.SetTextRenderingHint(4);

WSH Panel Mod script discussion/help
Reply #1407
Falstaff, is your coverflow script horizontal scrolling only?  If so, any chance for a vertical scrolling one?

  • Falstaff
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #1408
only horizontal for now. maybe a vertical one later, i can't say when.

  • Falstaff
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #1409
WSH CoverFlow v1 beta4

What's New in beta4:
- lock current playlist button: allow you to use the coverflow as an album browser, in your playlist, when lock is on, you only have the tracks of the selected cover album!
- scrollbar button replaced by a menu button
- cover loading engine modded to get better perfs.
- new scrollbar style (not themed one)
- many tweaks ... i can't remember all the changes since beta3



[code]// ==PREPROCESSOR==
// @name "CoverFlow View v1"
// @version "0.0.4.20120324.1412"
// @author "Br3tt"
// @feature "v1.4"
// @feature "watch-metadb"
// @feature "dragdrop"
// ==/PREPROCESSOR==

// [Requirements]
// * foobar2000 v1.1 or better  >> http://foobar2000.org
// * WSH panel Mod v1.5.2 or better  >> http://code.google.com/p/foo-wsh-panel-mod/downloads/list
// [/Requirements]

// * !!! Keep a reasonable size for the panel to avoid bad perf! Loading and Displaying too big or too much covers can be a nightmare for your CPU!

// [Informations]
// * change colors and fonts in foobar2000 Preferences > DefaultUI or ColumsUI
// * Some Settings can be changed in window Properties (right click empty space > Properties)
// * for custom colors in Properties, use e.g. RGB(255,255,255) for white color, RGB(0,0,0) for black color, ...
// * double click on album text infos > Show Now Playing album
// * middle click on centered cover > Send album tracks to specific playlist "CoverFlow View"
// * keyboard keys : left/right arrows, Home/End, page up/down, spacebar to set focus on the centered album
// [/Informations]

SM_CXVSCROLL = 2;
SM_CYHSCROLL = 3;
DLGC_WANTARROWS = 0x0001;
DLGC_WANTALLKEYS = 0x0004;
MF_STRING = 0x00000000;
MF_SEPARATOR = 0x00000800;
MF_GRAYED = 0x00000001;
MF_DISABLED = 0x00000002;
MF_POPUP = 0x00000010;
IDC_ARROW = 32512;
IDC_IBEAM = 32513;
IDC_WAIT = 32514;
IDC_CROSS = 32515;
IDC_UPARROW = 32516;
IDC_SIZE = 32640;
IDC_ICON = 32641;
IDC_SIZENWSE = 32642;
IDC_SIZENESW = 32643;
IDC_SIZEWE = 32644;
IDC_SIZENS = 32645;
IDC_SIZEALL = 32646;
IDC_NO = 32648;
IDC_APPSTARTING = 32650;
IDC_HAND = 32649;
IDC_HELP = 32651;
var DT_LEFT = 0x00000000;
var DT_RIGHT = 0x00000002;
var DT_TOP = 0x00000000;
var DT_CENTER = 0x00000001;
var DT_VCENTER = 0x00000004;
var DT_WORDBREAK = 0x00000010;
var DT_SINGLELINE = 0x00000020;
var DT_CALCRECT = 0x00000400;
var DT_NOPREFIX = 0x00000800;
var DT_EDITCONTROL = 0x00002000;
var DT_END_ELLIPSIS = 0x00008000;
var VK_BACK = 0x08;
var VK_RETURN = 0x0D;
var VK_SHIFT = 0x10;
var VK_CONTROL = 0x11;
var VK_ALT = 0x12;
var VK_ESCAPE = 0x1B;
var VK_PGUP = 0x21;
var VK_PGDN = 0x22;
var VK_END = 0x23;
var VK_HOME = 0x24;
var VK_LEFT = 0x25;
var VK_UP = 0x26;
var VK_RIGHT = 0x27;
var VK_DOWN = 0x28;
var VK_INSERT = 0x2D;
var VK_DELETE = 0x2E;
var VK_SPACEBAR = 0x20;
var KMask = {
  none: 0,
  ctrl: 1,
  shift: 2,
  ctrlshift: 3,
  ctrlalt: 4,
  ctrlaltshift: 5,
  alt: 6
};

function GetKeyboardMask() {
  var c = utils.IsKeyPressed(VK_CONTROL) ? true : false;
  var a = utils.IsKeyPressed(VK_ALT) ? true : false;
  var s = utils.IsKeyPressed(VK_SHIFT) ? true : false;
  var b = KMask.none;
  if (c && !a && !s) b = KMask.ctrl;
  if (!c && !a && s) b = KMask.shift;
  if (c && !a && s) b = KMask.ctrlshift;
  if (c && a && !s) b = KMask.ctrlalt;
  if (c && a && s) b = KMask.ctrlaltshift;
  if (!c && a && !s) b = KMask.alt;
  return b
};
ColorTypeCUI = {
  text: 0,
  selection_text: 1,
  inactive_selection_text: 2,
  background: 3,
  selection_background: 4,
  inactive_selection_background: 5,
  active_item_frame: 6
};
FontTypeCUI = {
  items: 0,
  labels: 1
};
ColorTypeDUI = {
  text: 0,
  background: 1,
  highlight: 2,
  selection: 3
};
FontTypeDUI = {
  defaults: 0,
  tabs: 1,
  lists: 2,
  playlists: 3,
  statusbar: 4,
  console: 5
};

function StringFormat() {
  var a = 0,
   v_align = 0,
   trimming = 0,
   flags = 0;
  switch (arguments.length) {
  case 3:
   trimming = arguments[2];
  case 2:
   v_align = arguments[1];
  case 1:
   a = arguments[0];
   break;
  default:
   return 0
  };
  return ((a << 28) | (v_align << 24) | (trimming << 20) | flags)
};
StringAlignment = {
  Near: 0,
  Centre: 1,
  Far: 2
};
var lt_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Near);
var ct_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Near);
var rt_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Near);
var lc_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Centre);
var cc_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Centre);
var rc_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Centre);
var lb_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Far);
var cb_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Far);
var rb_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Far);

function RGB(r, g, b) {
  return (0xff000000 | (r << 16) | (g << 8) | (b))
};

function RGBA(r, g, b, a) {
  return ((a << 24) | (r << 16) | (g << 8) | (b))
};

function getAlpha(a) {
  return ((a >> 24) & 0xff)
}
function getRed(a) {
  return ((a >> 16) & 0xff)
}
function getGreen(a) {
  return ((a >> 8) & 0xff)
}
function getBlue(a) {
  return (a & 0xff)
}
function num(a, b) {
  var i;
  var c = a.toString();
  var k = b - c.length;
  if (k > 0) {
   for (i = 0; i < k; i++) {
     c = "0" + c
   }
  };
  return c.toString()
};

function TrackType(a) {
  var b;
  var c;
  switch (a) {
  case "file":
   b = 1;
   c = 0;
   break;
  case "cdda":
   b = 1;
   c = 1;
   break;
  case "FOO_":
   b = 0;
   c = 2;
   break;
  case "http":
   b = 0;
   c = 3;
   break;
  case "mms:":
   b = 0;
   c = 3;
   break;
  case "unpa":
   b = 0;
   c = 4;
   break;
  default:
   b = 0;
   c = 5
  };
  return c
};
ButtonStates = {
  normal: 0,
  hover: 1,
  down: 2
};
button = function (d, e, f) {
  this.img = Array(d, e, f);
  this.w = this.img[0].Width;
  this.h = this.img[0].Height;
  this.state = ButtonStates.normal;
  this.update = function (a, b, c) {
   this.img = Array(a, b, c)
  };
  this.draw = function (a, x, y, b) {
   this.x = x;
   this.y = y;
   this.img[this.state] && a.DrawImage(this.img[this.state], this.x, this.y, this.w, this.h, 0, 0, this.w, this.h, 0, b)
  };
  this.display_context_menu = function (x, y, a) {};
  this.repaint = function () {
   window.RepaintRect(this.x, this.y, this.w, this.h)
  };
  this.checkstate = function (a, x, y) {
   this.ishover = (x > this.x && x < this.x + this.w - 1 && y > this.y && y < this.y + this.h - 1);
   this.old = this.state;
   switch (a) {
   case "down":
     switch (this.state) {
     case ButtonStates.normal:
     case ButtonStates.hover:
       this.state = this.ishover ? ButtonStates.down : ButtonStates.normal;
       break
     };
     break;
   case "up":
     this.state = this.ishover ? ButtonStates.hover : ButtonStates.normal;
     break;
   case "right":
     if (this.ishover) this.display_context_menu(x, y, id);
     break;
   case "move":
     switch (this.state) {
     case ButtonStates.normal:
     case ButtonStates.hover:
       this.state = this.ishover ? ButtonStates.hover : ButtonStates.normal;
       break
     };
     break;
   case "leave":
     this.state = this.isdown ? ButtonStates.down : ButtonStates.normal;
     break
   };
   if (this.state != this.old) this.repaint();
   return this.state
  }
};

function get_system_scrollbar_width() {
  var a = utils.GetSystemMetrics(SM_CXVSCROLL);
  return a
};

function get_system_scrollbar_height() {
  var a = utils.GetSystemMetrics(SM_CYHSCROLL);
  return a
};
var nocover;
var nocover_img;
var streamcover;
var star_img_off;
var star_img_on;
var star_img_hov;
var star_img_kill;
var toggle_scrollbar;
var menu_button;
cover2load = function (a, b) {
  this.item = a;
  this.timer = window.SetTimeout(function () {
   if (mycover2load.length > 0) {
     mycover2load[0].timer && window.ClearTimeout(mycover2load[0].timer);
     utils.GetAlbumArtAsync(window.ID, mycover2load[0].item.metadb, 0, true, false, false)
   }
  }, b)
};
var mycover2load = Array();
image_cache = function () {
  this._cachelist = {};
  this.hit = function (a) {
   var b = this._cachelist[a.cover_path + a.album];
   if (list.drag_stop && typeof b == "undefined") {
     mycover2load.push(new cover2load(a, (80*(mycover2load.length>0?1:0))+(9*mycover2load.length)));
   };
   return b
  };
  this.getit = function (a, b) {
   var c;
   var d = (cover.w - cover.margin * 2) * cover.quality / 100;
   var e = (cover.h - cover.margin * 2) * cover.quality / 100;
   if (a.track_type != 3) {
     if (a.metadb) {
       c = FormatCover(b, d, e);
       if (!c) {
         c = FormatCover(nocover, d, e);
         a.cover_type = 0
       } else {
         a.cover_type = 1
       }
     }
   } else if (fb.IsPlaying && fb.PlaybackLength) {
     c = FormatCover(streamcover, d, e);
     a.cover_type = 3
   } else {
     c = FormatCover(nocover, d, e);
     a.cover_type = 0
   };
   this._cachelist[a.cover_path + a.album] = c;
   return c
  }
};
var g_image_cache = new image_cache;

function FormatCover(a, w, h) {
  if (!a || w <= 0 || h <= 0) return a;
  if (cover.draw_glass_effect) {
   var b = a.Resize(w, h, 2);
   var c = b.GetGraphics();
   c.FillGradRect(0, 0, w, h, 90, RGBA(255, 255, 255, 60), RGBA(255, 255, 255, 10), 1.0);
   c.SetSmoothingMode(2);
   c.FillEllipse(-20, 25, w * 2 + 40, h * 2, RGBA(0, 0, 0, 30));
   b.ReleaseGraphics©;
   return b
  } else {
   return a.Resize(w, h, 2)
  }
};

function refresh_cover(a, b) {
  var c = 0;
  var d;
  var e = (cover.w - cover.margin * 2) * cover.quality / 100;
  var f = (cover.h - cover.margin * 2) * cover.quality / 100;
  if (a.track_type != 3) {
   if (a.metadb) {
     d = FormatCover(b, e, f);
     if (!d) {
       d = FormatCover(nocover, e, f);
       a.cover_type = 0
     } else {
       a.cover_type = 1
     }
   }
  } else if (fb.IsPlaying && fb.PlaybackLength) {
   d = FormatCover(streamcover, e, f);
   a.cover_type = 3
  } else {
   d = FormatCover(nocover, e, f);
   a.cover_type = 0
  };
  return d
};

function reset_cover_timers() {
  for (var i in mycover2load) {
   mycover2load.timer && window.ClearTimeout(mycover2load.timer)
  };
  mycover2load.splice(0, mycover2load.length)
};

function on_get_album_art_done(a, b, c, d) {
  for (var i = 0; i < mycover2load.length; i++) {
   if (mycover2load.item.metadb.Compare(a)) {
     mycover2load.item.cover_img = g_image_cache.getit(mycover2load.item, c);
     if (mycover2load.item.show) {
       window.RepaintRect(mycover2load.item.x - 2, cover.pad_top_mid, mycover2load.item.w + 4, wh - cover.pad_top_mid)
     } else {
       mycover2load.item.show = true
     };
     mycover2load.splice(i, 1);
     break
   }
  }
};
ItemStates = {
  normal: 0,
  hover: 1,
  selected: 2
};
item = function (g, h, k) {
  var i;
  if (typeof this.id == "undefined") {
   if (g < 0) {
     this.id = g;
     this.idx = h;
     this.gh_id = k;
     this.metadb = false;
     this.albumartist = "";
     this.album = "";
     this.track_type = null;
     this.cover_path = "";
     this.group_info = ""
   } else {
     this.id = g;
     this.idx = h;
     this.gh_id = k;
     this.metadb = list.handlelist.Item(this.id);
     if (this.metadb) {
       this.albumartist = tf_albumartist.EvalWithMetadb(this.metadb);
       this.album = tf_album.EvalWithMetadb(this.metadb);
       this.track_type = TrackType(this.metadb.rawpath.substring(0, 4));
       this.cover_path = tf_cover_path.EvalWithMetadb(this.metadb);
       this.group_info = tf_group_info.EvalWithMetadb(this.metadb)
     }
   }
  };
  this.update_infos = function () {
   if (this.metadb) {
     this.albumartist = tf_albumartist.EvalWithMetadb(this.metadb);
     this.album = tf_album.EvalWithMetadb(this.metadb);
     this.track_type = TrackType(this.metadb.rawpath.substring(0, 4));
     this.cover_path = tf_cover_path.EvalWithMetadb(this.metadb);
     this.group_info = tf_group_info.EvalWithMetadb(this.metadb)
   } else {
     this.albumartist = "";
     this.album = "";
     this.track_type = null;
     this.cover_path = "";
     this.group_info = ""
   }
  };
  this.draw = function (a, b, c, d, e) {
   this.show = e;
   if (list.mid == c) {
     this.w = cover.w;
     this.h = this.w;
     this.y = cover.pad_top_mid;
     this.x = Math.floor((ww / 2) - (cover.w / 2));
     this.cut = 1
   } else {
     this.w = Math.abs(d) == 1 ? cover.w - cover.normal_delta * 1 : cover.w - cover.normal_delta * 2;
     this.h = this.w;
     this.x = Math.abs(d) == 1 ? Math.floor((ww / 2) - (this.w / 2)) - (d * (this.w - 5)) : Math.floor((ww / 2) - (this.w / 2)) - (d * this.w);
     this.y = Math.abs(d) == 1 ? cover.pad_top_mid + Math.ceil(cover.normal_delta / 2) : cover.pad_top_mid + cover.normal_delta;
     this.cut = Math.abs(d) == 1 ? 1 : 0
   };
   if (this.id >= 0) {
     this.cover_img = g_image_cache.hit(this);
     if (this.show && typeof (this.cover_img) != "undefined") {
       var f = 255 - Math.floor(cover.reflect_strength_percent * 2.55);
       if (cover.draw_reflection && f > 0 && cover.reflect_strength_percent > 0) {
         a.DrawImage(this.cover_img, Math.floor(cover.margin / 2) + this.x, this.y + this.h * 2 - cover.margin - 1, this.w, -1 * this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255);
         if (cover.draw_border) {
           a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y + this.h + 1, this.w - cover.margin * 2 + 1, this.h - cover.margin * 2 + 1, 2.0, RGB(0, 0, 0));
           a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y + this.h + 1, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(255, 255, 255))
         } else {
           a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y + this.h + 1, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(127, 127, 127))
         };
         a.FillGradRect(Math.floor(cover.margin / 2) + this.x - 1, this.y + this.h - 1, this.w - this.cut, this.h + 1, 90, RGBA(g_backcolor_R, g_backcolor_G, g_backcolor_B, f), g_backcolor, 1.0)
       };
       a.DrawImage(this.cover_img, Math.floor(cover.margin / 2) + this.x, this.y, this.w, this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255);
       if (cover.draw_border) {
         a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y, this.w - cover.margin * 2 + 1, this.h - cover.margin * 2 + 1, 2.0, RGB(0, 0, 0));
         a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(255, 255, 255))
       } else {
         a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(127, 127, 127))
       };
       if (cover.draw_shadows) {
         if (d == 0 || d == 1 || d == -1) {
           for (var j = 0; j < 7; j++) {
             if (this.gh_id > 0) {
               a.FillSolidRect(Math.floor(cover.margin / 2) + this.x - j - cover.margin + 1, this.y + cover.normal_delta / 2, 1, this.h - cover.normal_delta - cover.margin - 1, RGBA(0, 0, 0, 150 - j * 25))
             };
             if (this.gh_id < list.total_gh - 1) {
               a.FillSolidRect(Math.floor(cover.margin / 2) + this.x + this.w - cover.margin + j - 1, this.y + cover.normal_delta / 2, 1, this.h - cover.normal_delta - cover.margin - 1, RGBA(0, 0, 0, 150 - j * 25))
             }
           }
         }
       }
     } else {
       var f = 255 - Math.floor(cover.reflect_strength_percent * 2.55);
       if (cover.draw_reflection && f > 0 && cover.reflect_strength_percent > 0) {
         a.DrawImage(nocover_img, Math.floor(cover.margin / 2) + this.x, this.y + this.h * 2 - cover.margin - 1, this.w, -1 * this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255);
         if (cover.draw_border) {
           a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y + this.h + 1, this.w - cover.margin * 2 + 1, this.h - cover.margin * 2 + 1, 2.0, RGB(0, 0, 0));
           a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y + this.h + 1, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(255, 255, 255))
         } else {
           a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y + this.h + 1, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(127, 127, 127))
         };
         a.FillGradRect(Math.floor(cover.margin / 2) + this.x - 1, this.y + this.h - 1, this.w - this.cut, this.h + 1, 90, RGBA(g_backcolor_R, g_backcolor_G, g_backcolor_B, f), g_backcolor, 1.0)
       };
       a.DrawImage(nocover_img, Math.floor(cover.margin / 2) + this.x, this.y, this.w, this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255);
       if (cover.draw_border) {
         a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y, this.w - cover.margin * 2 + 1, this.h - cover.margin * 2 + 1, 2.0, RGB(0, 0, 0));
         a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(255, 255, 255))
       } else {
         a.DrawRect(Math.floor(cover.margin / 2) + this.x, this.y, this.w - cover.margin * 2, this.h - cover.margin * 2, 1.0, RGB(127, 127, 127))
       };
       if (cover.draw_shadows) {
         if (d == 0 || d == 1 || d == -1) {
           for (var j = 0; j < 7; j++) {
             if (this.gh_id > 0) {
               a.FillSolidRect(Math.floor(cover.margin / 2) + this.x - j - cover.margin + 1, this.y + cover.normal_delta / 2, 1, this.h - cover.normal_delta - cover.margin - 1, RGBA(0, 0, 0, 150 - j * 25))
             };
             if (this.gh_id < list.total_gh - 1) {
               a.FillSolidRect(Math.floor(cover.margin / 2) + this.x + this.w - cover.margin + j - 1, this.y + cover.normal_delta / 2, 1, this.h - cover.normal_delta - cover.margin - 1, RGBA(0, 0, 0, 150 - j * 25))
             }
           }
         }
       }
     };
     if (cover.draw_focus_border && this.gh_id == list.selected_gh_id) {
       list.focus_id_item_idx = this.idx;
       a.SetSmoothingMode(2);
       a.DrawRoundRect(Math.floor(cover.margin / 2) + this.x - 1, this.y - 1, this.w - cover.margin * 2 + 2, this.h - cover.margin * 2 + 2, 2, 2, 3.0, g_backcolor_sel);
       a.DrawRoundRect(Math.floor(cover.margin / 2) + this.x - 2, this.y - 2, this.w - cover.margin * 2 + 4, this.h - cover.margin * 2 + 4, 3, 3, 1.0, RGBA(255, 255, 255, 60));
       a.SetSmoothingMode(0);
       a.DrawRect(Math.floor(cover.margin / 2) + this.x + 1, this.y + 1, this.w - cover.margin * 2 - 2, this.h - cover.margin * 2 - 2, 1.0, g_backcolor_sel);
       a.DrawRect(Math.floor(cover.margin / 2) + this.x + 1, this.y + 1, this.w - cover.margin * 2 - 2, this.h - cover.margin * 2 - 2, 1.0, RGBA(0, 0, 0, 40))
     }
   }
  };
  this.checkstate = function (a, x, y, b) {
   if (this.id >= 0 && y > cover.pad_top_mid) {
     this.ishover = (x > this.x && x < this.x + this.w && y >= this.y && y < this.y + this.h)
   } else {
     this.ishover = false
   };
   switch (a) {
   case "down":
     if (!list.down_timerID && this.id >= 0) {
       if (plman.IsPlaylistItemSelected(panel.active_playlist, this.id)) {
         if (this.ishover) {
           if (panel.lock_playlist) {
             this.checkstate("mid", x, y, b)
           };
           SelectGroupItems(this.id, this.gh_id, true);
           g_saved = this;
           refresh_spv(panel.active_playlist, bool_on_size)
         }
       } else {
         if (this.ishover) {
           if (utils.IsKeyPressed(VK_SHIFT)) {
             if (list.focus_id != this.id) {
               if (list.SHIFT_start_id != null) {} else {}
             }
           } else if (utils.IsKeyPressed(VK_CONTROL)) {
             if (panel.lock_playlist) {
               this.checkstate("mid", x, y, b)
             } else {
               SelectGroupItems(this.id, this.gh_id, true)
             }
           } else {
             SelectGroupItems(this.id, this.gh_id, true);
             g_saved = this;
             if (panel.lock_playlist) {
               g_saved.checkstate("mid", x, y, b)
             }
           }
         }
       }
     };
     break;
   case "dblclk":
     if (this.id >= 0 && g_saved != null) {
       if (plman.IsPlaylistItemSelected(panel.active_playlist, this.id)) {
         if (panel.lock_playlist) {
           if (this.id == g_saved.id) {
             plman.ExecutePlaylistDefaultAction(panel.active_playlist, list.hlist[g_saved.gh_id]);
             g_saved = null
           }
         } else {
           if (this.id == g_saved.id) {
             plman.ExecutePlaylistDefaultAction(panel.active_playlist, list.hlist[g_saved.gh_id]);
             g_saved = null;
             window.Repaint()
           }
         }
       }
     };
     break;
   case "mid":
     if (this.ishover) {
       if (plman.GetPlaylistName(panel.active_playlist) != "CoverFlow View") {
         SelectGroupItems(this.id, this.gh_id, true);
         var c = false;
         var d = 0;
         var e = panel.active_playlist;
         for (var i = 0; i < plman.PlaylistCount; i++) {
           if (plman.GetPlaylistName(i) == "CoverFlow View") {
             c = true;
             d = i;
             break
           }
         };
         if (!c) {
           d = plman.PlaylistCount;
           plman.CreatePlaylist(plman.PlaylistCount, "CoverFlow View")
         };
         plman.ActivePlaylist = d;
         fb.ClearPlaylist();
         var f = fb.PlaylistItemCount(d);
         plman.InsertPlaylistItems(d, f, plman.GetPlaylistSelectedItems(e), false);
         plman.SetPlaylistFocusItem(d, 0)
       }
     };
     break;
   case "right":
     if (this.ishover) {
       SelectGroupItems(this.id, this.gh_id, false);
       new_context_menu(x, y, this.id, this.idx)
     };
     break;
   case "up":
     break;
   case "move":
     if (this.ishover) {}
     break;
   case "leave":
     break
   };
   return this.state
  }
};
var tf_path = fb.TitleFormat("$left(%_path_raw%,4)");
var tf_cover_path = fb.TitleFormat("$replace(%path%,%filename_ext%,)");
var tf_albumartist = fb.TitleFormat("$if(%length%,%album artist%,'Stream')");
var tf_album = fb.TitleFormat("$if2(%album%,$if(%length%,'Single','web radios'))");
var tf_group_key = fb.TitleFormat(window.GetProperty("_group Key", "%album artist%%album%"));
var tf_group_info = fb.TitleFormat(window.GetProperty("_group TF text info", "%album artist%[ | %album%][ | %date%]"));
var g_instancetype = window.InstanceType;
var g_font = null;
var g_font_headers = null;
var ww = 0,
  wh = 0;
var mouse_x = 0,
  mouse_y = 0;
var g_textcolor = 0,
  g_textcolor_sel = 0,
  g_textcolor_hl = 0,
  g_backcolor = 0,
  g_backcolor_sel = 0;
var g_metadb;
var bool_on_size = false;
var g_search_string = "";
var incsearch_font = gdi.Font("lucida console", 9, 0);
var incsearch_font_big = gdi.Font("lucida console", 20, 1);
var clear_incsearch_timer = false;
var incsearch_timer = false;
var g_saved = null;
panel = {
  max_height: window.GetProperty("panel.maximum.height", 300),
  arr_buttons: Array(),
  button_total: 3,
  show_text: window.GetProperty("panel.album.info.visible", true),
  custom_textcolor: window.GetProperty("panel.custom.text.color.normal", ""),
  custom_textcolor_selection: window.GetProperty("panel.custom.text.color.selection", ""),
  custom_backcolor: window.GetProperty("panel.custom.background.color", ""),
  custom_textcolor_highlight: window.GetProperty("panel.custom.text.color.hightlight", ""),
  lock_playlist: window.GetProperty("panel.lock.playlist.enabled", false),
  active_playlist: window.GetProperty("panel.active.playlist", 0)
};
list = {
  first_launch: true,
  total: 0,
  total_gh: 0,
  start_id: 0,
  nbvis: 0,
  mid: 0,
  item: Array(),
  hlist: Array(),
  handlelist: null,
  metadblist_selection: plman.GetPlaylistSelectedItems(panel.active_playlist),
  focus_id: 0,
  focus_id_item_idx: 0,
  selected_gh_id: 0,
  gh_id: 0,
  mousewheel_timer_value: 20,
  key_timer_value: 60,
  nowplaying: 0,
  SHIFT_start_id: null,
  SHIFT_count: 0,
  inc_search_noresult: false,
  nb_cover_to_draw: 0,
  buttonclicked: false,
  drag_stop: true,
  drag_timer: false
};
hscrollbar = {
  theme: false,
  themed: window.GetProperty("list.hscrollbar.themed", true),
  show: window.GetProperty("list.hscrollbar.visible", true),
  visible: true,
  hover: false,
  x: 0,
  y: 0,
  default_h: get_system_scrollbar_height(),
  h: get_system_scrollbar_height(),
  w: 0,
  button_total: 2,
  step: 3,
  arr_buttons: Array(),
  letter: null,
  timerID: false
};
button_up = {
  img_normal: null,
  img_hover: null,
  img_down: null,
  x: 0,
  y: 0,
  w: hscrollbar.default_h,
  h: hscrollbar.default_h,
  timerID: false
};
button_down = {
  img_normal: null,
  img_hover: null,
  img_down: null,
  x: 0,
  y: 0,
  w: hscrollbar.default_h,
  h: hscrollbar.default_h,
  timerID: false
};
cursor = {
  bt: null,
  img_normal: null,
  img_hover: null,
  img_down: null,
  popup: null,
  x: 0,
  y: 0,
  w: hscrollbar.default_h + 3,
  h: hscrollbar.default_h,
  default_w: hscrollbar.default_h + 3,
  hover: false,
  drag: false,
  grap_x: 0,
  timerID: false,
  last_x: 0
};
cover = {
  margin: 2,
  w: 0,
  h: 0,
  top_offset: 0,
  default_pad_top_mid: 35,
  default_pad_bot_mid: 30,
  pad_top_mid: 35,
  pad_bot_mid: 30,
  normal_delta: 20,
  quality: window.GetProperty("list.covers.quality.percent", 100),
  draw_border: window.GetProperty("cover.draw.contrasted.border", false),
  draw_reflection: window.GetProperty("cover.draw.ground.reflection", true),
  reflect_strength_percent: window.GetProperty("cover.ground.reflection.percent", 20),
  draw_shadows: window.GetProperty("cover.draw.shadows", true),
  draw_focus_border: window.GetProperty("cover.draw.focus.border", true),
  draw_glass_effect: window.GetProperty("cover.draw.glass.effect", false)
};

function refresh_spv_cursor(a) {
  var b = (cursor.x - hscrollbar.x) / (hscrollbar.w - cursor.w);
  if (b > 1) b = 1;
  if (b < 0) b = 0;
  var r = Math.round(b * list.total_gh);
  set_gh_id(a, list.hlist[r - 1]);
  window.Repaint()
}
function set_gh_id(a, b) {
  reset_cover_timers();
  list.item.splice(0, list.item.length);
  if (list.total_gh <= 0) return true;
  list.gh_id = get_gh_id(b);
  if (list.gh_id == null) {
   list.gh_id = 0
  }
  var r = list.gh_id - list.mid;
  if (r < 0) {
   list.start_id = Math.abs®;
   r = 0
  } else {
   list.start_id = 0
  };
  for (var k = 0; k < list.nbvis; k++) {
   if (k >= list.start_id && r < list.total_gh) {
     list.item.push(new item(list.hlist[r], k, r));
     r++
   } else {
     list.item.push(new item(-1, k, -1))
   }
  }
};

function scrollup_spv(a) {
  var r = list.item[list.mid].gh_id;
  if (r > 0) {
   var s = list.item[0].gh_id;
   if (s > 0) {
     list.item.unshift(new item(list.hlist[s - 1], 0, s - 1))
   } else {
     list.item.unshift(new item(-1, 0, -1))
   };
   list.item.pop()
  };
  for (var i = 0; i < list.item.length; i++) {
   list.item.idx = i
  };
  setcursorx()
};

function scrolldown_spv(a) {
  var r = list.item[list.mid].gh_id;
  if (r < list.total_gh - 1) {
   var s = list.item[list.item.length - 1].gh_id;
   if (s > 0 && s < list.total_gh - 1) {
     list.item.push(new item(list.hlist[s + 1], 0, s + 1))
   } else {
     list.item.push(new item(-1, 0, -1))
   };
   list.item.shift()
  };
  for (var i = 0; i < list.item.length; i++) {
   list.item.idx = i
  };
  setcursorx()
};

function refresh_spv(a, b) {
  reset_cover_timers();
  list.item.splice(0, list.item.length);
  if (list.total_gh <= 0) return true;
  list.gh_id = get_gh_id(list.focus_id);
  if (list.gh_id == null) {
   init_active_pls();
   return true
  }
  list.selected_gh_id = list.gh_id;
  var r = list.gh_id - list.mid;
  if (r < 0) {
   list.start_id = Math.abs®;
   r = 0
  } else {
   list.start_id = 0
  };
  for (var k = 0; k < list.nbvis; k++) {
   if (k >= list.start_id && r < list.total_gh) {
     list.item.push(new item(list.hlist[r], k, r));
     r++
   } else {
     list.item.push(new item(-1, k, -1))
   }
  };
  if (hscrollbar.show) {
   if (list.total_gh < 2) hscrollbar.visible = false;
   else hscrollbar.visible = true
  } else {
   hscrollbar.visible = false
  };
  cursor.w = Math.round(hscrollbar.w / list.total_gh);
  if (cursor.w > hscrollbar.w) cursor.w = hscrollbar.w;
  if (cursor.w < cursor.default_w) cursor.w = cursor.default_w;
  set_scroller();
  setcursorx()
};

function get_gh_id(a) {
  var b = Math.floor(list.total_gh / 2);
  if (a < list.hlist) {
   var c = 0
  } else {
   var c = b
  };
  for (var i = c; i < list.total_gh; i++) {
   if (i < list.total_gh - 1) {
     if (a >= list.hlist && a < list.hlist[i + 1]) {
       return i
     }
   } else {
     if (a >= list.hlist) {
       return i
     } else {
       return null
     }
   }
  }
};

function setcursorx() {
  if (list.item.length > 0) {
   var a = Math.floor(list.item.length / 2);
   var b = list.item[a].gh_id;
   var c = b / (list.total_gh - 1);
   cursor.x = hscrollbar.x + Math.round(c * (hscrollbar.w - cursor.w))
  } else {
   cursor.x = hscrollbar.x
  }
};

function init_active_pls() {
  var a;
  var b;
  var c;
  list.hlist.splice(0, list.hlist.length);
  list.handlelist = plman.GetPlaylistItems(panel.active_playlist);
  list.total = list.handlelist.Count;
  for (var i = 0; i < list.total; i++) {
   if (i > 0 && i < list.total - 1) {
     i++;
     b = tf_group_key.EvalWithMetadb(list.handlelist.Item(i));
     if (a != b) {
       if (i > 0) {
         c = tf_group_key.EvalWithMetadb(list.handlelist.Item(i - 1));
         if (a != c) {
           list.hlist.push(i - 1)
         };
         if (c != b) {
           list.hlist.push(i)
         }
       } else {
         list.hlist.push(i)
       };
       a = b
     }
   } else {
     b = tf_group_key.EvalWithMetadb(list.handlelist.Item(i));
     if (a != b) {
       list.hlist.push(i);
       a = b
     }
   }
  };
  list.total_gh = list.hlist.length
};

function old_init_active_pls() {
  var a;
  var b;
  list.hlist.splice(0, list.hlist.length);
  list.handlelist = plman.GetPlaylistItems(panel.active_playlist);
  list.total = list.handlelist.Count;
  for (var i = 0; i < list.total; i++) {
   b = tf_group_key.EvalWithMetadb(list.handlelist.Item(i));
   if (a != b) {
     list.hlist.push(i);
     a = b
   }
  };
  list.total_gh = list.hlist.length
};

function on_font_changed() {
  get_font();
  on_playlist_switch()
};

function on_colors_changed() {
  get_colors();
  init_icons();
  nocover_img = FormatCover(nocover, (cover.w - cover.margin * 2) * cover.quality / 100, (cover.h - cover.margin * 2) * cover.quality / 100);
  init_hscrollbar_buttons();
  set_scroller();
  g_image_cache = new image_cache;
  CollectGarbage();
  on_playlist_switch()
};

function on_init() {};

function on_size() {
  if (!window.Width || !window.Height) return;
  window.DlgCode = DLGC_WANTALLKEYS;
  bool_on_size = true;
  if (g_instancetype == 0) {
   window.MinWidth = 200;
   window.MinHeight = 170;
   window.MaxHeight = panel.max_height
  } else if (g_instancetype == 1) {
   window.MinWidth = 200;
   window.MinHeight = 170;
   window.MaxHeight = panel.max_height
  };
  ww = window.Width;
  wh = window.Height;
  if (wh < 170) wh = 170;
  var a = window.GetProperty("_group TF text info", "%album artist%[ | %album%][ | %date%]");
  if (a == "") window.SetProperty("_group TF text info", "%album artist%[ | %album%][ | %date%]");
  tf_group_info = fb.TitleFormat(window.GetProperty("_group TF text info", "%album artist%[ | %album%][ | %date%]"));
  get_font();
  get_colors();
  init_icons();
  if (hscrollbar.show) {
   cover.pad_bot_mid = cover.default_pad_bot_mid
  } else {
   cover.pad_bot_mid = cover.default_pad_bot_mid - hscrollbar.default_h
  }
  if (panel.show_text) {
   cover.pad_top_mid = cover.default_pad_top_mid
  } else {
   cover.pad_top_mid = cover.default_pad_top_mid - 16
  };
  cover.w = wh - cover.pad_top_mid - cover.pad_bot_mid;
  cover.h = cover.w;
  list.nbvis = Math.floor(ww / (cover.w - cover.normal_delta * 2)) + 2;
  if (list.nbvis / 2 == Math.floor(list.nbvis / 2)) {
   list.nbvis--
  }
  list.mid = Math.floor(list.nbvis / 2);
  list.nb_cover_to_draw = Math.floor(ww / (cover.w - cover.normal_delta * 2)) + 2;
  if (hscrollbar.themed) {
   hscrollbar.theme = window.CreateThemeManager("scrollbar")
  } else {
   hscrollbar.theme = false
  };
  init_hscrollbar_buttons();
  button_up.x = 0;
  button_up.y = wh - hscrollbar.h;
  button_down.x = ww - button_down.w;
  button_down.y = wh - hscrollbar.h;
  hscrollbar.x = button_up.w;
  hscrollbar.w = ww - button_up.w - button_down.w;
  cursor.y = wh - hscrollbar.h;
  cursor.x = hscrollbar.x;
  nocover_img = FormatCover(nocover, (cover.w - cover.margin * 2) * cover.quality / 100, (cover.h - cover.margin * 2) * cover.quality / 100);
  if (list.first_launch) {
   list.first_launch = false;
   on_playlist_switch()
  } else {
   g_image_cache = new image_cache;
   CollectGarbage();
   refresh_spv(panel.active_playlist, true)
  }
};

function on_paint(a) {
  a.FillGradRect(0, 0, ww, wh, 90, g_backcolor, g_backcolor & 0xd0ffffff, 0.3);
  if (list.item.length > 0) {
   var b, mid2;
   list.item[list.mid].draw(a, list.item[list.mid].id, list.mid, 0, true);
   for (var c = 1; c < list.mid + 1; c++) {
     if (c > 1 && c <= list.mid) {
       b = true
     } else {
       b = false
     };
     mid2 = list.mid - c;
     if (mid2 >= 0 && mid2 <= list.item.length - 1) {
       list.item[mid2].draw(a, list.item[mid2].id, mid2, c, b)
     }
     mid2 = list.mid + c;
     if (mid2 >= 0 && mid2 <= list.item.length - 1) {
       list.item[mid2].draw(a, list.item[mid2].id, mid2, c * -1, b)
     }
   };
   mid2 = list.mid - 1;
   if (mid2 >= 0 && mid2 <= list.item.length - 1) {
     list.item[mid2].draw(a, list.item[mid2].id, mid2, 1, true)
   }
   mid2 = list.mid + 1;
   if (mid2 >= 0 && mid2 <= list.item.length - 1) {
     list.item[mid2].draw(a, list.item[mid2].id, mid2, -1, true)
   }
   list.item[list.mid].draw(a, list.item[list.mid].id, list.mid, 0, true);
   if (panel.show_text) {
     var d = panel.lock_playlist ? 32 : 60;
     var f = panel.lock_playlist ? ww - 64 : ww - 120;
     if (list.item[list.mid].id >= 0) {
       a.GdiDrawText(list.item[list.mid].group_info, g_font, g_textcolor, d, 0, f, cover.pad_top_mid - 4, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX)
     }
   }
  };
  if (list.total_gh > 0 && hscrollbar.visible && hscrollbar.show) {
   try {
     hscrollbar.theme.SetPartAndStateId(4, 1);
     hscrollbar.theme.DrawThemeBackground(a, 0, wh - hscrollbar.h, ww, hscrollbar.h);
     a.FillSolidRect(0, wh - hscrollbar.h - 1, ww, 1, RGBA(0, 0, 0, 10))
   } catch (e) {
     a.FillSolidRect(0, wh - hscrollbar.h, ww, hscrollbar.h, g_backcolor & 0x77ffffff);
     a.FillSolidRect(0, wh - hscrollbar.h, ww, 1, RGBA(0, 0, 0, 20))
   };
   try {
     cursor.bt.draw(a, cursor.x, cursor.y, 255)
   } catch (e) {};
   try {
     hscrollbar.theme.SetPartAndStateId(8, 1);
     hscrollbar.theme.DrawThemeBackground(a, cursor.x, wh - hscrollbar.h + 0, cursor.w, cursor.h)
   } catch (e) {};
   for (i = 0; i < hscrollbar.arr_buttons.length; i++) {
     switch (i) {
     case 0:
       hscrollbar.arr_buttons.draw(a, button_up.x, button_up.y, 255);
       break;
     case 1:
       hscrollbar.arr_buttons.draw(a, button_down.x, button_down.y, 255);
       break
     }
   };
   if (cursor.drag) {
     hscrollbar.letter = list.item[Math.floor(list.nbvis / 2)].albumartist.substring(0, 1).toUpperCase();
     cursor.popup && a.DrawImage(cursor.popup, cursor.x + Math.floor(cursor.w / 2) - Math.floor(cursor.popup.Width / 2), wh - hscrollbar.h - cursor.popup.Height, cursor.popup.Width, cursor.popup.Height, 0, 0, cursor.popup.Width, cursor.popup.Height, 0, 155);
     cursor.popup && a.GdiDrawText(hscrollbar.letter, gdi.Font("segoe ui", 14, 0), g_backcolor, cursor.x + Math.floor(cursor.w / 2) - Math.floor(cursor.popup.Width / 2), wh - hscrollbar.h - cursor.popup.Height, cursor.popup.Width, cursor.popup.Height - 5, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX)
   }
  };
  for (i = 0; i < panel.arr_buttons.length; i++) {
   switch (i) {
   case 0:
     if (!panel.lock_playlist) {
       panel.arr_buttons.draw(a, 30, 5, 255)
     }
     break;
   case 1:
     panel.arr_buttons.draw(a, ww - 22 - 5, 5, 255);
     break;
   case 2:
     panel.arr_buttons.draw(a, 5, 5, 255);
     break
   }
  };
  a.FillGradRect(0, 0, ww, 1, 0, 0, g_textcolor & 0x15ffffff, 0.5)
};

function on_mouse_lbtn_down(x, y) {
  bool_on_size = false;
  for (var i = 0; i < list.item.length; i++) {
   list.item.checkstate("down", x, y, i)
  };
  if (list.total_gh > 0 && hscrollbar.visible && hscrollbar.show) {
   if (cursor.bt.checkstate("down", x, y) == ButtonStates.down) {
     cursor.drag = true;
     cursor.grap_x = x - cursor.x;
     cursor.last_x = cursor.x
   };
   if (hscrollbar.hover && !cursor.drag) {
     hscrollbar.step = Math.floor(list.nb_cover_to_draw / 2);
     if (hscrollbar.step < 1) hscrollbar.step = 1;
     if (x < cursor.x) {
       if (!list.buttonclicked) {
         list.buttonclicked = true;
         on_mouse_wheel(hscrollbar.step);
         button_up.first_timerID = window.SetTimeout(function () {
           on_mouse_wheel(hscrollbar.step);
           button_up.timerID = window.SetInterval(function () {
             if (hscrollbar.hover) {
               if (mouse_y > wh - hscrollbar.h && cursor.x > mouse_x) {
                 on_mouse_wheel(hscrollbar.step)
               }
             }
           }, list.key_timer_value)
         }, 400)
       }
     } else {
       if (!list.buttonclicked) {
         list.buttonclicked = true;
         on_mouse_wheel(-1 * hscrollbar.step);
         button_down.first_timerID = window.SetTimeout(function () {
           on_mouse_wheel(-1 * hscrollbar.step);
           button_down.timerID = window.SetInterval(function () {
             if (hscrollbar.hover) {
               if (mouse_y > wh - hscrollbar.h && cursor.x + cursor.w < mouse_x) {
                 on_mouse_wheel(-1 * hscrollbar.step)
               }
             }
           }, list.key_timer_value)
         }, 400)
       }
     }
   };
   for (i = 0; i < hscrollbar.arr_buttons.length; i++) {
     switch (i) {
     case 0:
       if (hscrollbar.arr_buttons.checkstate("down", x, y) == ButtonStates.down) {
         if (!list.buttonclicked) {
           list.buttonclicked = true;
           on_mouse_wheel(1);
           button_up.first_timerID = window.SetTimeout(function () {
             reset_cover_timers();
             button_up.timerID = window.SetInterval(function () {
               on_mouse_wheel(1)
             }, list.key_timer_value)
           }, 400)
         }
       };
       break;
     case 1:
       if (hscrollbar.arr_buttons.checkstate("down", x, y) == ButtonStates.down) {
         if (!list.buttonclicked) {
           list.buttonclicked = true;
           on_mouse_wheel(-1);
           button_down.first_timerID = window.SetTimeout(function () {
             reset_cover_timers();
             button_down.timerID = window.SetInterval(function () {
               on_mouse_wheel(-1)
             }, list.key_timer_value)
           }, 400)
         }
       };
       break
     }
   }
  };
  for (var i = 0; i < panel.arr_buttons.length; i++) {
   panel.arr_buttons.checkstate("down", x, y)
  }
};

function on_mouse_lbtn_dblclk(x, y, a) {
  if (y < cover.pad_top_mid) {} else if (y < wh - cover.pad_bot_mid) {
   for (var i = 0; i < list.item.length; i++) {
     list.item.checkstate("dblclk", x, y, i)
   }
  } else {
   on_mouse_lbtn_down(x, y)
  }
};

function on_mouse_lbtn_up(x, y) {
  list.buttonclicked = false;
  hscrollbar.timerID && window.ClearTimeout(hscrollbar.timerID);
  hscrollbar.timerID = false;
  button_up.first_timerID && window.ClearTimeout(button_up.first_timerID);
  button_up.first_timerID = false;
  button_down.first_timerID && window.ClearTimeout(button_down.first_timerID);
  button_down.first_timerID = false;
  button_up.timerID && window.ClearInterval(button_up.timerID);
  button_up.timerID = false;
  button_down.timerID && window.ClearInterval(button_down.timerID);
  button_down.timerID = false;
  if (list.drag_timer) {
   window.ClearTimeout(list.drag_timer);
   list.drag_timer = false;
   list.drag_stop = true
  }
  if (list.total_gh > 0) {
   cursor.bt.checkstate("up", x, y);
   for (var i = 0; i < hscrollbar.arr_buttons.length; i++) {
     hscrollbar.arr_buttons.checkstate("up", x, y)
   };
   for (i = 0; i < panel.arr_buttons.length; i++) {
     switch (i) {
     case 0:
       if (panel.arr_buttons.checkstate("up", x, y) == ButtonStates.hover) {
         ShowNowPlaying()
       };
       break;
     case 1:
       if (panel.arr_buttons.checkstate("up", x, y) == ButtonStates.hover) {
         settings_menu(x, y)
       };
       break;
     case 2:
       if (panel.arr_buttons.checkstate("up", x, y) == ButtonStates.hover) {
         if (panel.lock_playlist) {
           panel.lock_playlist = false;
           window.SetProperty("panel.lock.playlist.enabled", panel.lock_playlist);
           plman.ActivePlaylist = panel.active_playlist
         } else {
           panel.lock_playlist = true;
           window.SetProperty("panel.lock.playlist.enabled", panel.lock_playlist);
           panel.active_playlist = plman.ActivePlaylist;
           window.SetProperty("panel.active.playlist", panel.active_playlist);
           var a = Math.floor(list.nbvis / 2);
           a = list.focus_id_item_idx;
           list.item[a].checkstate("mid", list.item[a].x + 5, list.item[a].y + 5, a)
         };
         if (panel.lock_playlist) {
           panel.arr_buttons[2].update(lock_button_normal, lock_button_hover, lock_button_down)
         } else {
           panel.arr_buttons[2].update(unlock_button_normal, unlock_button_hover, unlock_button_down)
         }
       };
       break
     }
   };
   if (cursor.drag) {
     window.RepaintRect(0, wh - hscrollbar.h, ww, hscrollbar.h);
     cursor.drag = false
   } else {
     for (i = 0; i < list.item.length; i++) {
       list.item.checkstate("up", x, y, i)
     }
   };
   setcursorx();
   window.Repaint()
  }
};

function on_mouse_mbtn_down(x, y, a) {
  bool_on_size = false;
  for (var i = 0; i < list.item.length; i++) {
   list.item.checkstate("mid", x, y, i)
  }
};

function on_mouse_rbtn_down(x, y) {
  bool_on_size = false;
  for (var i = 0; i < list.item.length; i++) {
   list.item.checkstate("right", x, y, i)
  }
};

function on_mouse_move(x, y) {
  if (x == mouse_x && y == mouse_y) return true;
  if (cursor.drag) {
   list.drag_stop = false;
   if (list.drag_timer) {
     window.ClearTimeout(list.drag_timer);
     list.drag_timer = false
   }
   list.drag_timer = window.SetTimeout(function () {
     list.drag_stop = true;
     window.ClearTimeout(list.drag_timer);
     list.drag_timer = false;
     window.Repaint()
   }, 260)
  } else {
   list.drag_stop = true
  };
  if (list.total_gh > 0 && hscrollbar.visible && hscrollbar.show) {
   hscrollbar.hover = (y >= wh - hscrollbar.h && y <= wh && x >= hscrollbar.x && x <= hscrollbar.x + hscrollbar.w);
   cursor.hover = (x >= cursor.x && x <= cursor.x + cursor.w && y >= cursor.y && y <= cursor.y + cursor.h);
   cursor.bt.checkstate("move", x, y);
   for (var i = 0; i < hscrollbar.arr_buttons.length; i++) {
     hscrollbar.arr_buttons.checkstate("move", x, y)
   };
   if (cursor.drag && mouse_x != x) {
     reset_cover_timers();
     cursor.x = x - cursor.grap_x;
     if (cursor.x < hscrollbar.x) cursor.x = hscrollbar.x;
     if (cursor.x > hscrollbar.x + hscrollbar.w - cursor.w) cursor.x = hscrollbar.x + hscrollbar.w - cursor.w;
     if (!cursor.timerID) {
       cursor.timerID = window.SetTimeout(function () {
         refresh_spv_cursor(panel.active_playlist);
         cursor.timerID && window.ClearTimeout(cursor.timerID);
         cursor.timerID = false
       }, 30)
     }
   }
  };
  for (var j = 0; j < panel.arr_buttons.length; j++) {
   panel.arr_buttons[j].checkstate("move", x, y)
  };
  mouse_x = x;
  mouse_y = y
};

function on_mouse_wheel(a) {
  reset_cover_timers();
  if (!hscrollbar.timerID) {
   if (Math.abs(a) >= 1) {
     if (a > 0) {
       for (var i = 0; i < Math.abs(a); i++) {
         scrollup_spv(panel.active_playlist)
       };
       hscrollbar.timerID = window.SetTimeout(function () {
         window.Repaint();
         hscrollbar.timerID && window.ClearTimeout(hscrollbar.timerID);
         hscrollbar.timerID = false
       }, list.mousewheel_timer_value)
     } else {
       for (var i = 0; i < Math.abs(a); i++) {
         scrolldown_spv(panel.active_playlist)
       }
       hscrollbar.timerID = window.SetTimeout(function () {
         window.Repaint();
         hscrollbar.timerID && window.ClearTimeout(hscrollbar.timerID);
         hscrollbar.timerID = false
       }, list.mousewheel_timer_value)
     }
   }
  }
};

function on_mouse_leave() {
  for (i = 0; i < list.item.length; i++) {
   list.item.checkstate("leave", 0, 0, i)
  };
  window.Repaint()
};

function on_playlist_switch() {
  if (!panel.lock_playlist) {
   panel.active_playlist = plman.ActivePlaylist
  };
  if (plman.ActivePlaylist < 0 || plman.ActivePlaylist > fb.PlaylistCount) {
   if (fb.PlaylistCount > 0) {
     plman.ActivePlaylist = 0
   }
  };
  init_active_pls();
  list.focus_id = plman.GetPlaylistFocusItemIndex(panel.active_playlist);
  if (list.focus_id < 0) {
   list.focus_id = 0
  }
  refresh_spv(panel.active_playlist, true);
  window.Repaint()
};

function on_playlist_items_added(a) {
  if (a == panel.active_playlist) {
   on_playlist_switch()
  };
  plman.SetActivePlaylistContext()
};

function on_playlist_items_reordered(a) {
  if (a == panel.active_playlist) {
   on_playlist_switch()
  }
};

function on_selection_changed(a) {};

function on_playlist_items_selection_change() {};

function on_playlists_changed() {
  if (panel.lock_playlist) {
   panel.lock_playlist = !panel.lock_playlist;
   window.SetProperty("panel.lock.playlist.enabled", panel.lock_playlist);
   plman.ActivePlaylist = panel.active_playlist
  }
};

function on_item_focus_change(a, b, c) {
  if (a == panel.active_playlist) {
   list.focus_id = c;
   plman.SetActivePlaylistContext();
   refresh_spv(panel.active_playlist, bool_on_size);
   bool_on_size = false;
   window.Repaint()
  }
};

function on_metadb_changed(a, b) {
  for (var i = 0; i < list.item.length; i++) {
   list.item.update_infos()
  };
  window.Repaint()
};

function on_focus(a) {};

function on_key_up(a) {};

function on_key_down(a) {
  var b = GetKeyboardMask();
  if (b == KMask.none) {
   switch (a) {
   case VK_SHIFT:
     list.SHIFT_count = 0;
     break;
   case VK_BACK:
     break;
   case VK_ESCAPE:
   case 222:
     break;
   case VK_SPACEBAR:
     if (panel.lock_playlist) {
       plman.SetPlaylistFocusItem(panel.active_playlist, d);
       plman.ClearPlaylistSelection(panel.active_playlist);
       plman.SetPlaylistSelectionSingle(panel.active_playlist, d, true);
       var c = Math.floor(list.nbvis / 2);
       list.item[c].checkstate("mid", list.item[c].x + 5, list.item[c].y + 5, c)
     } else {
       var d = list.item[Math.floor(list.nbvis / 2)].id;
       SelectGroupItems(d, get_gh_id(d), true)
     };
     break;
   case VK_LEFT:
     on_mouse_wheel(1);
     break;
   case VK_RIGHT:
     on_mouse_wheel(-1);
     break;
   case VK_PGUP:
     hscrollbar.step = Math.floor(list.nb_cover_to_draw / 2);
     if (hscrollbar.step < 1) hscrollbar.step = 1;
     on_mouse_wheel(hscrollbar.step);
     break;
   case VK_PGDN:
     hscrollbar.step = Math.floor(list.nb_cover_to_draw / 2);
     if (hscrollbar.step < 1) hscrollbar.step = 1;
     on_mouse_wheel(hscrollbar.step * -1);
     break;
   case VK_RETURN:
     plman.ExecutePlaylistDefaultAction(panel.active_playlist, list.focus_id);
     break;
   case VK_END:
     plman.SetPlaylistFocusItem(panel.active_playlist, list.total - 1);
     plman.ClearPlaylistSelection(panel.active_playlist);
     plman.SetPlaylistSelectionSingle(panel.active_playlist, list.total - 1, true);
     break;
   case VK_HOME:
     plman.SetPlaylistFocusItem(panel.active_playlist, 0);
     plman.ClearPlaylistSelection(panel.active_playlist);
     plman.SetPlaylistSelectionSingle(panel.active_playlist, 0, true);
     break;
   case VK_DELETE:
     if (!fb.IsAutoPlaylist(panel.active_playlist)) {
       plman.RemovePlaylistSelection(panel.active_playlist, false);
       plman.SetPlaylistSelectionSingle(panel.active_playlist, plman.GetPlaylistFocusItemIndex(panel.active_playlist), true)
     }
     break;
   default:
     break
   }
  } else {
   switch (b) {
   case KMask.shift:
     break;
   case KMask.ctrl:
     if (a == 65) {
       fb.RunMainMenuCommand("Edit/Select all");
       window.Repaint()
     };
     if (a == 70) {
       fb.RunMainMenuCommand("Edit/Search")
     };
     if (a == 78) {
       fb.RunMainMenuCommand("File/New playlist")
     };
     if (a == 79) {
       fb.RunMainMenuCommand("File/Open...")
     };
     if (a == 80) {
       fb.RunMainMenuCommand("File/Preferences")
     };
     if (a == 83) {
       fb.RunMainMenuCommand("File/Save playlist...")
     };
     break;
   case KMask.alt:
     if (a == 65) {
       fb.RunMainMenuCommand("View/Always on Top")
     };
     break
   }
  }
};

function on_playback_new_track(a) {
  g_metadb = fb.GetNowPlaying();
  window.Repaint()
};

function on_playback_stop(a) {
  if (a == 0) {
   g_metadb = fb.GetFocusItem();
   on_metadb_changed()
  }
};

function on_playback_pause(a) {};

function on_playback_time(a) {};

function get_font() {
  if (g_instancetype == 0) {
   g_font = window.GetFontCUI(FontTypeCUI.items);
   g_font_headers = window.GetFontCUI(FontTypeCUI.labels)
  } else if (g_instancetype == 1) {
   g_font = window.GetFontDUI(FontTypeDUI.playlists);
   g_font_headers = window.GetFontDUI(FontTypeDUI.tabs)
  }
};

function get_colors() {
  if (g_instancetype == 0) {
   g_textcolor = window.GetColorCUI(ColorTypeCUI.text);
   g_textcolor_sel = window.GetColorCUI(ColorTypeCUI.selection_text);
   g_textcolor_hl = window.GetColorCUI(ColorTypeCUI.active_item_frame);
   g_backcolor = window.GetColorCUI(ColorTypeCUI.background);
   g_backcolor_sel = window.GetColorCUI(ColorTypeCUI.selection_background)
  } else if (g_instancetype == 1) {
   g_textcolor = window.GetColorDUI(ColorTypeDUI.text);
   g_textcolor_sel = window.GetColorDUI(ColorTypeDUI.selection);
   g_textcolor_hl = window.GetColorDUI(ColorTypeDUI.highlight);
   g_backcolor = window.GetColorDUI(ColorTypeDUI.background);
   g_backcolor_sel = g_textcolor_sel
  };
  try {
   if (panel.custom_textcolor.length > 0) g_textcolor = eval(panel.custom_textcolor);
   if (panel.custom_textcolor_selection.length > 0) g_textcolor_sel = eval(panel.custom_textcolor_selection);
   if (panel.custom_backcolor.length > 0) g_backcolor = eval(panel.custom_backcolor);
   if (panel.custom_textcolor_highlight.length > 0) g_textcolor_hl = eval(panel.custom_textcolor_highlight)
  } catch (e) {};
  g_backcolor_R = getRed(g_backcolor);
  g_backcolor_G = getGreen(g_backcolor);
  g_backcolor_B = getBlue(g_backcolor)
};

function set_scroller() {
  var a;
  try {
   cursor.img_normal = gdi.CreateImage(cursor.w, cursor.h)
  } catch (e) {
   cursor.h = cursor.default_h;
   cursor.img_normal = gdi.CreateImage(cursor.w, cursor.h)
  };
  a = cursor.img_normal.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(2, 1);
   hscrollbar.theme.DrawThemeBackground(a, 0, 0, cursor.w, cursor.h)
  } catch (e) {
   a.FillSolidRect(0, 3, cursor.w, cursor.h - 5, g_textcolor & 0x44ffffff)
  };
  cursor.img_normal.ReleaseGraphics(a);
  cursor.img_hover = gdi.CreateImage(cursor.w, cursor.h);
  a = cursor.img_hover.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(2, 2);
   hscrollbar.theme.DrawThemeBackground(a, 0, 0, cursor.w, cursor.h)
  } catch (e) {
   a.FillSolidRect(0, 3, cursor.w, cursor.h - 5, g_textcolor & 0x88ffffff)
  };
  cursor.img_hover.ReleaseGraphics(a);
  cursor.bt = new button(cursor.img_normal, cursor.img_hover, cursor.img_hover)
};

function init_hscrollbar_buttons() {
  var i, gb;
  cursor.popup = gdi.CreateImage(22, 27);
  gb = cursor.popup.GetGraphics();
  gb.SetSmoothingMode(2);
  gb.FillRoundRect(0, 0, 22 - 1, 22 - 1, 3, 3, g_textcolor);
  gb.DrawRoundRect(0, 0, 22 - 1, 22 - 1, 3, 3, 1.0, RGBA(0, 0, 0, 150));
  var a = Array(7, 22 - 2, 11, 22 - 2 + 6, 22 - 7, 22 - 2);
  gb.FillPolygon(g_textcolor, 0, a);
  gb.DrawPolygon(RGBA(0, 0, 0, 150), 1.0, a);
  gb.SetSmoothingMode(0);
  gb.FillSolidRect(6, 22 - 4, 22 - 10, 3, g_textcolor);
  cursor.popup.ReleaseGraphics(gb);
  button_up.img_normal = gdi.CreateImage(button_up.w, button_up.h);
  gb = button_up.img_normal.GetGraphics();
  try {
   hscrollbar.theme.SetPartAndStateId(1, 9);
   hscrollbar.theme.DrawThemeBackground(gb, 0, 0, button_up.w, button_up.h)
  } catch (e) {
   gb.SetTextRenderingHint(4);
   gui_font = gdi.Font("guifx v2 transports", 12, 0);
   gb.DrawString("<", gui_font, RGBA(255, 255, 255, 25), 1, 0, button_up.w, button_up.h, cc_stringformat);
   gb.DrawString("<", gui_font, g_textcolor & 0x44ffffff, 0, 0, button_up.w, button_up.h, cc_stringformat)
  };
  button_up.img_normal.ReleaseGraphics(gb);
  button_up.img_hover = gdi.CreateImage(button_up.w, button_up.h);
  gb = bu
  • Last Edit: 24 March, 2012, 03:47:46 PM by Falstaff

WSH Panel Mod script discussion/help
Reply #1410
marc2003: Could you please help me to add a little space between the stars in your ratings script?

  • marc2003
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #1411
using paint.net you could make the images with a gap around the edge. you need to edit on.png and off.png in the marc2003\images folder. image menu>canvas size and make sure the anchor is in the middle. then select and delete the border so it's transparent.

then update the bw and bh variables at the top of the script to the size of these new images.
  • Last Edit: 28 March, 2012, 12:11:57 AM by marc2003

WSH Panel Mod script discussion/help
Reply #1412
That was simple. Thanks.

  • Falstaff
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #1413
WSH CoverFlow v1 beta6

[code]// ==PREPROCESSOR==
// @name "CoverFlow View v1 beta6"
// @version "0.0.6.20120330.1917"
// @author "Br3tt"
// @feature "v1.4"
// @feature "watch-metadb"
// @feature "dragdrop"
// ==/PREPROCESSOR==

// [Requirements]
// * foobar2000 v1.1 or better  >> http://foobar2000.org
// * WSH panel Mod v1.5.2 or better  >> http://code.google.com/p/foo-wsh-panel-mod/downloads/list
// [/Requirements]

// * !!! Keep a reasonable size for the panel to avoid bad perf! Loading and Displaying too big or too much covers can be a nightmare for your CPU!

// [Informations]
// * change colors and fonts in foobar2000 Preferences > DefaultUI or ColumsUI
// * Some Settings can be changed in window Properties (right click empty space > Properties)
//  e.g. for custom colors in Properties, use e.g. RGB(255,255,255) for white color, RGB(0,0,0) for black color, ...
// * middle click on cover > Send album tracks to specific playlist "CoverFlow View"
// * keyboard keys : left/right arrows, Home/End, page up/down, spacebar to set focus on the centered album, Return key to play ...
// [/Informations]

SM_CXVSCROLL = 2;
SM_CYHSCROLL = 3;
DLGC_WANTARROWS = 0x0001;
DLGC_WANTALLKEYS = 0x0004;
MF_STRING = 0x00000000;
MF_SEPARATOR = 0x00000800;
MF_GRAYED = 0x00000001;
MF_DISABLED = 0x00000002;
MF_POPUP = 0x00000010;
IDC_ARROW = 32512;
IDC_IBEAM = 32513;
IDC_WAIT = 32514;
IDC_CROSS = 32515;
IDC_UPARROW = 32516;
IDC_SIZE = 32640;
IDC_ICON = 32641;
IDC_SIZENWSE = 32642;
IDC_SIZENESW = 32643;
IDC_SIZEWE = 32644;
IDC_SIZENS = 32645;
IDC_SIZEALL = 32646;
IDC_NO = 32648;
IDC_APPSTARTING = 32650;
IDC_HAND = 32649;
IDC_HELP = 32651;
var DT_LEFT = 0x00000000;
var DT_RIGHT = 0x00000002;
var DT_TOP = 0x00000000;
var DT_CENTER = 0x00000001;
var DT_VCENTER = 0x00000004;
var DT_WORDBREAK = 0x00000010;
var DT_SINGLELINE = 0x00000020;
var DT_CALCRECT = 0x00000400;
var DT_NOPREFIX = 0x00000800;
var DT_EDITCONTROL = 0x00002000;
var DT_END_ELLIPSIS = 0x00008000;
var VK_BACK = 0x08;
var VK_RETURN = 0x0D;
var VK_SHIFT = 0x10;
var VK_CONTROL = 0x11;
var VK_ALT = 0x12;
var VK_ESCAPE = 0x1B;
var VK_PGUP = 0x21;
var VK_PGDN = 0x22;
var VK_END = 0x23;
var VK_HOME = 0x24;
var VK_LEFT = 0x25;
var VK_UP = 0x26;
var VK_RIGHT = 0x27;
var VK_DOWN = 0x28;
var VK_INSERT = 0x2D;
var VK_DELETE = 0x2E;
var VK_SPACEBAR = 0x20;
var KMask = {
  none: 0,
  ctrl: 1,
  shift: 2,
  ctrlshift: 3,
  ctrlalt: 4,
  ctrlaltshift: 5,
  alt: 6
};

function GetKeyboardMask() {
  var c = utils.IsKeyPressed(VK_CONTROL) ? true : false;
  var a = utils.IsKeyPressed(VK_ALT) ? true : false;
  var s = utils.IsKeyPressed(VK_SHIFT) ? true : false;
  var b = KMask.none;
  if (c && !a && !s) b = KMask.ctrl;
  if (!c && !a && s) b = KMask.shift;
  if (c && !a && s) b = KMask.ctrlshift;
  if (c && a && !s) b = KMask.ctrlalt;
  if (c && a && s) b = KMask.ctrlaltshift;
  if (!c && a && !s) b = KMask.alt;
  return b
};
ColorTypeCUI = {
  text: 0,
  selection_text: 1,
  inactive_selection_text: 2,
  background: 3,
  selection_background: 4,
  inactive_selection_background: 5,
  active_item_frame: 6
};
FontTypeCUI = {
  items: 0,
  labels: 1
};
ColorTypeDUI = {
  text: 0,
  background: 1,
  highlight: 2,
  selection: 3
};
FontTypeDUI = {
  defaults: 0,
  tabs: 1,
  lists: 2,
  playlists: 3,
  statusbar: 4,
  console: 5
};

function StringFormat() {
  var a = 0,
   v_align = 0,
   trimming = 0,
   flags = 0;
  switch (arguments.length) {
  case 3:
   trimming = arguments[2];
  case 2:
   v_align = arguments[1];
  case 1:
   a = arguments[0];
   break;
  default:
   return 0
  };
  return ((a << 28) | (v_align << 24) | (trimming << 20) | flags)
};
StringAlignment = {
  Near: 0,
  Centre: 1,
  Far: 2
};
var lt_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Near);
var ct_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Near);
var rt_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Near);
var lc_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Centre);
var cc_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Centre);
var rc_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Centre);
var lb_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Far);
var cb_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Far);
var rb_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Far);

function RGB(r, g, b) {
  return (0xff000000 | (r << 16) | (g << 8) | (b))
};

function RGBA(r, g, b, a) {
  return ((a << 24) | (r << 16) | (g << 8) | (b))
};

function getAlpha(a) {
  return ((a >> 24) & 0xff)
}
function getRed(a) {
  return ((a >> 16) & 0xff)
}
function getGreen(a) {
  return ((a >> 8) & 0xff)
}
function getBlue(a) {
  return (a & 0xff)
}
function num(a, b) {
  var i;
  var c = a.toString();
  var k = b - c.length;
  if (k > 0) {
   for (i = 0; i < k; i++) {
     c = "0" + c
   }
  };
  return c.toString()
};

function TrackType(a) {
  var b;
  var c;
  switch (a) {
  case "file":
   b = 1;
   c = 0;
   break;
  case "cdda":
   b = 1;
   c = 1;
   break;
  case "FOO_":
   b = 0;
   c = 2;
   break;
  case "http":
   b = 0;
   c = 3;
   break;
  case "mms:":
   b = 0;
   c = 3;
   break;
  case "unpa":
   b = 0;
   c = 4;
   break;
  default:
   b = 0;
   c = 5
  };
  return c
};
ButtonStates = {
  normal: 0,
  hover: 1,
  down: 2
};
button = function (d, e, f) {
  this.img = Array(d, e, f);
  this.w = this.img[0].Width;
  this.h = this.img[0].Height;
  this.state = ButtonStates.normal;
  this.update = function (a, b, c) {
   this.img = Array(a, b, c)
  };
  this.draw = function (a, x, y, b) {
   this.x = x;
   this.y = y;
   this.img[this.state] && a.DrawImage(this.img[this.state], this.x, this.y, this.w, this.h, 0, 0, this.w, this.h, 0, b)
  };
  this.display_context_menu = function (x, y, a) {};
  this.repaint = function () {
   window.RepaintRect(this.x, this.y, this.w, this.h)
  };
  this.checkstate = function (a, x, y) {
   this.ishover = (x > this.x && x < this.x + this.w - 1 && y > this.y && y < this.y + this.h - 1);
   this.old = this.state;
   switch (a) {
   case "down":
     switch (this.state) {
     case ButtonStates.normal:
     case ButtonStates.hover:
       this.state = this.ishover ? ButtonStates.down : ButtonStates.normal;
       break
     };
     break;
   case "up":
     this.state = this.ishover ? ButtonStates.hover : ButtonStates.normal;
     break;
   case "right":
     if (this.ishover) this.display_context_menu(x, y, id);
     break;
   case "move":
     switch (this.state) {
     case ButtonStates.normal:
     case ButtonStates.hover:
       this.state = this.ishover ? ButtonStates.hover : ButtonStates.normal;
       break
     };
     break;
   case "leave":
     this.state = this.isdown ? ButtonStates.down : ButtonStates.normal;
     break
   };
   if (this.state != this.old) this.repaint();
   return this.state
  }
};

function get_system_scrollbar_width() {
  var a = utils.GetSystemMetrics(SM_CXVSCROLL);
  return a
};

function get_system_scrollbar_height() {
  var a = utils.GetSystemMetrics(SM_CYHSCROLL);
  return a
};
var nocover;
var nocover_img;
var streamcover;
var streamcover_img;
var loading;
var loading_img;
var star_img_off;
var star_img_on;
var star_img_hov;
var star_img_kill;
var toggle_scrollbar;
var menu_button;
image_cache = function () {
  this._cachelist = {};
  this.hit = function (a) {
   var b = this._cachelist[a.metadb.Path];
   if (list.drag_stop && typeof b == "undefined") {
     if (!cover.load_timer) {
       cover.load_timer = window.SetTimeout(function () {
         utils.GetAlbumArtAsync(window.ID, a.metadb, 0, true, false, false);
         cover.load_timer && window.ClearTimeout(cover.load_timer);
         cover.load_timer = false
       }, 35)
     }
   };
   return b
  };
  this.getit = function (a, b) {
   var c;
   var d = (cover.w - cover.margin * 2) * cover.quality / 100;
   var e = (cover.h - cover.margin * 2) * cover.quality / 100;
   if (a.track_type != 3) {
     if (a.metadb) {
       c = FormatCover(b, d, e);
       if (!c) {
         c = nocover_img;
         a.cover_type = 0
       } else {
         a.cover_type = 1
       }
     }
   } else if (fb.IsPlaying && fb.PlaybackLength) {
     c = streamcover_img;
     a.cover_type = 3
   } else {
     c = nocover_img;
     a.cover_type = 0
   };
   this._cachelist[a.metadb.Path] = c;
   return c
  }
};
var g_image_cache = new image_cache;

function FormatCover(a, w, h) {
  if (!a || w <= 0 || h <= 0) return a;
  if (cover.draw_glass_effect) {
   var b = a.Resize(w, h, 2);
   var c = b.GetGraphics();
   c.FillGradRect(0, 0, w, h, 90, RGBA(255, 255, 255, 60), RGBA(255, 255, 255, 10), 1.0);
   c.SetSmoothingMode(2);
   c.FillEllipse(-20, 25, w * 2 + 40, h * 2, RGBA(0, 0, 0, 30));
   b.ReleaseGraphics©;
   return b
  } else {
   var b = a.Resize(w, h, 2);
   var c = b.GetGraphics();
   c.DrawRect(0, 0, w, h, 2.0, RGB(110, 110, 110));
   b.ReleaseGraphics©;
   return b
  }
};

function reset_cover_timers() {
  cover.load_timer && window.ClearTimeout(cover.load_timer);
  cover.load_timer = false
};

function on_get_album_art_done(a, b, c, d) {
  var e = list.item.length;
  for (var i = 0; i < e; i++) {
   if (list.item.metadb) {
     if (list.item.metadb.Compare(a)) {
       list.item.cover_img = g_image_cache.getit(list.item, c);
       if (list.item.show) {
         if (panel.vertical_mode) {
           window.RepaintRect(cover.pad_left_mid, list.item.y - 2, ww - cover.pad_left_mid, list.item.h + 4)
         } else {
           window.RepaintRect(list.item.x - 2, cover.pad_top_mid, list.item.w + 4, wh - cover.pad_top_mid)
         }
       } else {
         list.item.show = true
       };
       break
     }
   }
  }
};
ItemStates = {
  normal: 0,
  hover: 1,
  selected: 2
};
item = function (h, k, l) {
  var i;
  if (typeof this.id == "undefined") {
   if (h < 0) {
     this.id = h;
     this.idx = k;
     this.gh_id = l;
     this.metadb = false;
     this.albumartist = "";
     this.track_type = null;
     this.group_info = ""
   } else {
     this.id = h;
     this.idx = k;
     this.gh_id = l;
     this.metadb = list.handlelist.Item(this.id);
     if (this.metadb) {
       this.albumartist = tf_albumartist.EvalWithMetadb(this.metadb);
       this.track_type = TrackType(this.metadb.rawpath.substring(0, 4));
       this.group_info = tf_group_info.EvalWithMetadb(this.metadb)
     }
   }
  };
  this.update_infos = function () {
   if (this.metadb) {
     this.albumartist = tf_albumartist.EvalWithMetadb(this.metadb);
     this.track_type = TrackType(this.metadb.rawpath.substring(0, 4));
     this.group_info = tf_group_info.EvalWithMetadb(this.metadb)
   } else {
     this.albumartist = "";
     this.track_type = null;
     this.group_info = ""
   }
  };
  this.draw = function (a, b, c, d, e) {
   if (panel.vertical_mode) {
     this.show = e;
     if (list.mid == c) {
       this.h = cover.h;
       this.w = cover.h;
       this.x = cover.pad_left_mid;
       this.y = Math.floor((wh / 2) - (cover.h / 2));
       this.cut = 1
     } else {
       this.h = Math.abs(d) == 1 ? cover.h - cover.normal_delta * 1 : cover.h - cover.normal_delta * 2;
       this.w = this.h;
       this.y = Math.abs(d) == 1 ? Math.floor((wh / 2) - (this.h / 2)) - (d * (this.h - 5)) : Math.floor((wh / 2) - (this.h / 2)) - (d * this.h);
       this.x = Math.abs(d) == 1 ? cover.pad_left_mid + Math.ceil(cover.normal_delta / 2) : cover.pad_left_mid + cover.normal_delta;
       this.cut = Math.abs(d) == 1 ? 1 : 0
     };
     if (this.id >= 0) {
       this.cover_img = g_image_cache.hit(this);
       if (this.show && typeof (this.cover_img) != "undefined") {
         if (cover.draw_shadows) {
           if (d == 0 || d == 1 || d == -1) {
             for (var j = 0; j < 7; j++) {
               if (d != -1 && this.gh_id > 0) {
                 a.FillSolidRect(this.x + cover.normal_delta / 2, Math.floor(cover.margin / 2) + this.y - j - cover.margin + 1, this.w - cover.normal_delta - cover.margin - 1, 1, RGBA(0, 0, 0, 150 - j * 25))
               };
               if (d != 1 && this.gh_id < list.total_gh - 1) {
                 a.FillSolidRect(this.x + cover.normal_delta / 2, Math.floor(cover.margin / 2) + this.y + this.h - cover.margin + j - 2, this.w - cover.normal_delta - cover.margin - 1, 1, RGBA(0, 0, 0, 150 - j * 25))
               }
             }
           }
         };
         a.DrawImage(this.cover_img, this.x, Math.floor(cover.margin / 2) + this.y, this.w, this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255)
       } else {
         a.DrawImage(loading_img, this.x, Math.floor(cover.margin / 2) + this.y, this.w, this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255);
         if (cover.draw_shadows) {
           if (d == 0 || d == 1 || d == -1) {
             for (var j = 0; j < 7; j++) {
               if (d != -1 && this.gh_id > 0) {
                 a.FillSolidRect(this.x + cover.normal_delta / 2, Math.floor(cover.margin / 2) + this.y - j - cover.margin + 1, this.w - cover.normal_delta - cover.margin - 1, 1, RGBA(0, 0, 0, 150 - j * 25))
               };
               if (d != 1 && this.gh_id < list.total_gh - 1) {
                 a.FillSolidRect(this.x + cover.normal_delta / 2, Math.floor(cover.margin / 2) + this.y + this.h - cover.margin + j - 2, this.w - cover.normal_delta - cover.margin - 1, 1, RGBA(0, 0, 0, 150 - j * 25))
               }
             }
           }
         }
       };
       if (this.gh_id == list.selected_gh_id) {
         list.focus_id_item_idx = this.idx;
         if (cover.draw_focus_border) {
           a.SetSmoothingMode(2);
           a.DrawRoundRect(this.x - 1, Math.floor(cover.margin / 2) + this.y - 1, this.w - cover.margin * 2 + 2, this.h - cover.margin * 2 + 2, 2, 2, 3.0, g_backcolor_sel);
           a.DrawRoundRect(this.x - 2, Math.floor(cover.margin / 2) + this.y - 2, this.w - cover.margin * 2 + 4, this.h - cover.margin * 2 + 4, 3, 3, 1.0, RGBA(255, 255, 255, 60));
           a.SetSmoothingMode(0);
           a.DrawRect(this.x + 1, Math.floor(cover.margin / 2) + this.y + 1, this.w - cover.margin * 2 - 2, this.h - cover.margin * 2 - 2, 1.0, g_backcolor_sel);
           a.DrawRect(this.x + 1, Math.floor(cover.margin / 2) + this.y + 1, this.w - cover.margin * 2 - 2, this.h - cover.margin * 2 - 2, 1.0, RGBA(0, 0, 0, 40))
         }
       }
     }
   } else {
     this.show = e;
     if (list.mid == c) {
       this.w = cover.w;
       this.h = cover.w;
       this.y = cover.pad_top_mid;
       this.x = Math.floor((ww / 2) - (cover.w / 2));
       this.cut = 1
     } else {
       this.w = Math.abs(d) == 1 ? cover.w - cover.normal_delta * 1 : cover.w - cover.normal_delta * 2;
       this.h = this.w;
       this.x = Math.abs(d) == 1 ? Math.floor((ww / 2) - (this.w / 2)) - (d * (this.w - 5)) : Math.floor((ww / 2) - (this.w / 2)) - (d * this.w);
       this.y = Math.abs(d) == 1 ? cover.pad_top_mid + Math.ceil(cover.normal_delta / 2) : cover.pad_top_mid + cover.normal_delta;
       this.cut = Math.abs(d) == 1 ? 1 : 0
     };
     if (this.id >= 0) {
       this.cover_img = g_image_cache.hit(this);
       if (this.show && typeof (this.cover_img) != "undefined") {
         var f = 255 - Math.floor(cover.reflect_strength_percent * 2.55);
         if (cover.draw_reflection && f > 0 && cover.reflect_strength_percent > 0) {
           a.DrawImage(this.cover_img, Math.floor(cover.margin / 2) + this.x + this.w, this.y + this.h - cover.margin - 1, -1 * this.w, this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 180, 255);
           a.FillGradRect(Math.floor(cover.margin / 2) + this.x - 1, this.y + this.h - 1, this.w - this.cut, this.h + 1, 90, RGBA(g_backcolor_R, g_backcolor_G, g_backcolor_B, f), g_backcolor, 1.0)
         };
         if (cover.draw_shadows) {
           if (d == 0 || d == 1 || d == -1) {
             for (var j = 0; j < 7; j++) {
               if (d != -1 && this.gh_id > 0) {
                 a.FillSolidRect(Math.floor(cover.margin / 2) + this.x - j - cover.margin + 1, this.y + cover.normal_delta / 2, 1, this.h - cover.normal_delta - cover.margin - 1, RGBA(0, 0, 0, 150 - j * 25))
               };
               if (d != 1 && this.gh_id < list.total_gh - 1) {
                 a.FillSolidRect(Math.floor(cover.margin / 2) + this.x + this.w - cover.margin + j - 2, this.y + cover.normal_delta / 2, 1, this.h - cover.normal_delta - cover.margin - 1, RGBA(0, 0, 0, 150 - j * 25))
               }
             }
           }
         };
         a.DrawImage(this.cover_img, Math.floor(cover.margin / 2) + this.x, this.y, this.w, this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255)
       } else {
         var f = 255 - Math.floor(cover.reflect_strength_percent * 2.55);
         if (cover.draw_reflection && f > 0 && cover.reflect_strength_percent > 0) {
           a.DrawImage(loading_img, Math.floor(cover.margin / 2) + this.x + this.w, this.y + this.h - cover.margin - 1, -1 * this.w, this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 180, 255);
           a.FillGradRect(Math.floor(cover.margin / 2) + this.x - 1, this.y + this.h - 1, this.w - this.cut, this.h + 1, 90, RGBA(g_backcolor_R, g_backcolor_G, g_backcolor_B, f), g_backcolor, 1.0)
         };
         if (cover.draw_shadows) {
           if (d == 0 || d == 1 || d == -1) {
             for (var j = 0; j < 7; j++) {
               if (d != -1 && this.gh_id > 0) {
                 a.FillSolidRect(Math.floor(cover.margin / 2) + this.x - j - cover.margin + 1, this.y + cover.normal_delta / 2, 1, this.h - cover.normal_delta - cover.margin - 1, RGBA(0, 0, 0, 150 - j * 25))
               };
               if (d != 1 && this.gh_id < list.total_gh - 1) {
                 a.FillSolidRect(Math.floor(cover.margin / 2) + this.x + this.w - cover.margin + j - 2, this.y + cover.normal_delta / 2, 1, this.h - cover.normal_delta - cover.margin - 1, RGBA(0, 0, 0, 150 - j * 25))
               }
             }
           }
         };
         a.DrawImage(loading_img, Math.floor(cover.margin / 2) + this.x, this.y, this.w, this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255)
       };
       if (this.gh_id == list.selected_gh_id) {
         list.focus_id_item_idx = this.idx;
         if (cover.draw_focus_border) {
           a.SetSmoothingMode(2);
           a.DrawRoundRect(Math.floor(cover.margin / 2) + this.x - 1, this.y - 1, this.w - cover.margin * 2 + 2, this.h - cover.margin * 2 + 2, 2, 2, 3.0, g_backcolor_sel);
           a.DrawRoundRect(Math.floor(cover.margin / 2) + this.x - 2, this.y - 2, this.w - cover.margin * 2 + 4, this.h - cover.margin * 2 + 4, 3, 3, 1.0, RGBA(255, 255, 255, 60));
           a.SetSmoothingMode(0);
           a.DrawRect(Math.floor(cover.margin / 2) + this.x + 1, this.y + 1, this.w - cover.margin * 2 - 2, this.h - cover.margin * 2 - 2, 1.0, g_backcolor_sel);
           a.DrawRect(Math.floor(cover.margin / 2) + this.x + 1, this.y + 1, this.w - cover.margin * 2 - 2, this.h - cover.margin * 2 - 2, 1.0, RGBA(0, 0, 0, 40))
         }
       }
     }
   }
  };
  this.checkstate = function (a, x, y, b) {
   if (this.id >= 0) {
     this.ishover = (x > this.x && x < this.x + this.w && y >= this.y && y < this.y + this.h)
   } else {
     this.ishover = false
   };
   switch (a) {
   case "down":
     if (!list.down_timerID && this.id >= 0) {
       if (plman.IsPlaylistItemSelected(panel.active_playlist, this.id)) {
         if (this.ishover) {
           if (panel.lock_playlist) {
             this.checkstate("mid", x, y, b)
           };
           SelectGroupItems(this.id, this.gh_id, true);
           g_saved = this;
           refresh_spv(panel.active_playlist, bool_on_size)
         }
       } else {
         if (this.ishover) {
           if (utils.IsKeyPressed(VK_SHIFT)) {
             if (list.focus_id != this.id) {
               if (list.SHIFT_start_id != null) {} else {}
             }
           } else if (utils.IsKeyPressed(VK_CONTROL)) {
             if (panel.lock_playlist) {
               this.checkstate("mid", x, y, b)
             } else {
               SelectGroupItems(this.id, this.gh_id, true)
             }
           } else {
             SelectGroupItems(this.id, this.gh_id, true);
             g_saved = this;
             if (panel.lock_playlist) {
               g_saved.checkstate("mid", x, y, b)
             }
           }
         }
       }
     };
     break;
   case "dblclk":
     if (this.id >= 0 && g_saved != null) {
       if (plman.IsPlaylistItemSelected(panel.active_playlist, this.id)) {
         if (panel.lock_playlist) {
           if (this.id == g_saved.id) {
             plman.ExecutePlaylistDefaultAction(panel.active_playlist, list.hlist[g_saved.gh_id]);
             g_saved = null
           }
         } else {
           if (this.id == g_saved.id) {
             plman.ExecutePlaylistDefaultAction(panel.active_playlist, list.hlist[g_saved.gh_id]);
             g_saved = null;
             window.Repaint()
           }
         }
       }
     };
     break;
   case "mid":
     if (this.ishover) {
       if (plman.GetPlaylistName(panel.active_playlist) != "CoverFlow View") {
         SelectGroupItems(this.id, this.gh_id, true);
         var c = false;
         var d = 0;
         var e = panel.active_playlist;
         var f = plman.PlaylistCount;
         for (var i = 0; i < f; i++) {
           if (plman.GetPlaylistName(i) == "CoverFlow View") {
             c = true;
             d = i;
             break
           }
         };
         if (!c) {
           panel.adding_coverflow_playlist = true;
           d = plman.PlaylistCount;
           plman.CreatePlaylist(plman.PlaylistCount, "CoverFlow View")
         };
         plman.ActivePlaylist = d;
         fb.ClearPlaylist();
         var g = fb.PlaylistItemCount(d);
         plman.InsertPlaylistItems(d, g, plman.GetPlaylistSelectedItems(e), false);
         plman.SetPlaylistFocusItem(d, 0)
       }
     };
     break;
   case "right":
     if (this.ishover) {
       SelectGroupItems(this.id, this.gh_id, false);
       new_context_menu(x, y, this.id, this.idx)
     };
     break;
   case "up":
     break;
   case "move":
     if (this.ishover) {}
     break;
   case "leave":
     break
   };
   return this.state
  }
};
var tf_path = fb.TitleFormat("$left(%_path_raw%,4)");
var tf_albumartist = fb.TitleFormat("$if(%length%,%album artist%,'Stream')");
var tf_album = fb.TitleFormat("$if2(%album%,$if(%length%,'Single','web radios'))");
var tf_group_key = fb.TitleFormat(window.GetProperty("_group Key", "%album artist%%album%"));
var tf_group_info = fb.TitleFormat(window.GetProperty("_group TF text info", "%album artist%[ | %album%][ | %date%]"));
var g_instancetype = window.InstanceType;
var g_font = null;
var g_font_headers = null;
var ww = 0,
  wh = 0;
var mouse_x = 0,
  mouse_y = 0;
var g_textcolor = 0,
  g_textcolor_sel = 0,
  g_textcolor_hl = 0,
  g_backcolor = 0,
  g_backcolor_sel = 0;
var g_metadb;
var bool_on_size = false;
var g_search_string = "";
var incsearch_font = gdi.Font("lucida console", 9, 0);
var incsearch_font_big = gdi.Font("lucida console", 20, 1);
var clear_incsearch_timer = false;
var incsearch_timer = false;
var g_saved = null;
panel = {
  max_width: 250,
  max_height: 250,
  arr_buttons: Array(),
  button_total: 3,
  show_text: window.GetProperty("panel.album.info.visible", true),
  custom_textcolor: window.GetProperty("panel.custom.text.color.normal", ""),
  custom_textcolor_selection: window.GetProperty("panel.custom.text.color.selection", ""),
  custom_backcolor: window.GetProperty("panel.custom.background.color", ""),
  custom_textcolor_highlight: window.GetProperty("panel.custom.text.color.hightlight", ""),
  lock_playlist: window.GetProperty("panel.lock.playlist.enabled", false),
  active_playlist: window.GetProperty("panel.active.playlist", 0),
  adding_coverflow_playlist: false,
  vertical_mode: true
};
list = {
  first_launch: true,
  total: 0,
  total_gh: 0,
  start_id: 0,
  nbvis: 0,
  mid: 0,
  item: Array(),
  hlist: Array(),
  handlelist: null,
  metadblist_selection: plman.GetPlaylistSelectedItems(panel.active_playlist),
  focus_id: 0,
  focus_id_item_idx: 0,
  selected_gh_id: 0,
  marker_id: 0,
  gh_id: 0,
  mousewheel_timer_value: 20,
  key_timer_value: 60,
  nowplaying: 0,
  SHIFT_start_id: null,
  SHIFT_count: 0,
  inc_search_noresult: false,
  nb_cover_to_draw: 0,
  buttonclicked: false,
  drag_stop: true,
  drag_timer: false
};
scrollbar = {
  theme: false,
  themed: window.GetProperty("list.scrollbar.themed", false),
  show: window.GetProperty("list.scrollbar.visible", true),
  visible: true,
  default_step: window.GetProperty("list.scrollbar.step", 3),
  step: 3,
  letter: null,
  button_total: 2,
  arr_buttons: Array(),
  timerID: false
}
hscrollbar = {
  hover: false,
  x: 0,
  y: 0,
  default_h: get_system_scrollbar_height(),
  h: get_system_scrollbar_height(),
  w: 0
};
vscrollbar = {
  hover: false,
  x: 0,
  y: 0,
  default_w: get_system_scrollbar_width(),
  w: get_system_scrollbar_width(),
  h: 0
};
scrollbarbt = {
  timerID1: false,
  timerID2: false,
  timer1_value: 400,
  timer2_value: 60
};
button_up = {
  img_normal: null,
  img_hover: null,
  img_down: null,
  x: 0,
  y: 0,
  w: hscrollbar.default_h,
  h: hscrollbar.default_h
};
button_down = {
  img_normal: null,
  img_hover: null,
  img_down: null,
  x: 0,
  y: 0,
  w: hscrollbar.default_h,
  h: hscrollbar.default_h
};
cursor = {
  bt: null,
  img_normal: null,
  img_hover: null,
  img_down: null,
  popup: null,
  x: 0,
  y: 0,
  w: hscrollbar.default_h,
  h: hscrollbar.default_h,
  default_w: hscrollbar.default_h + 3,
  hover: false,
  drag: false,
  grap_x: 0,
  timerID: false,
  last_x: 0
};
cover = {
  margin: 2,
  w: 0,
  h: 0,
  top_offset: 0,
  default_pad_top_mid: 35,
  default_pad_bot_mid: 30,
  pad_top_mid: 35,
  pad_bot_mid: 30,
  default_pad_left_mid: 15,
  default_pad_right_mid: 28,
  pad_left_mid: 15,
  pad_right_mid: 28,
  normal_delta: 20,
  quality: window.GetProperty("list.covers.quality.percent", 100),
  draw_reflection: window.GetProperty("cover.draw.ground.reflection", true),
  reflect_strength_percent: window.GetProperty("cover.ground.reflection.percent", 20),
  draw_shadows: window.GetProperty("cover.draw.shadows", true),
  draw_focus_border: window.GetProperty("cover.draw.focus.border", true),
  draw_glass_effect: window.GetProperty("cover.draw.glass.effect", false),
  load_timer: false
};

function refresh_spv_cursor(a) {
  if (panel.vertical_mode) {
   var b = (cursor.y - vscrollbar.y) / (vscrollbar.h - cursor.h)
  } else {
   var b = (cursor.x - hscrollbar.x) / (hscrollbar.w - cursor.w)
  }
  if (b > 1) b = 1;
  if (b < 0) b = 0;
  var r = Math.round(b * list.total_gh);
  set_gh_id(a, list.hlist[r - 1]);
  window.Repaint()
}
function set_gh_id(a, b) {
  reset_cover_timers();
  list.item.splice(0, list.item.length);
  if (list.total_gh <= 0) return true;
  list.gh_id = get_gh_id(b);
  if (list.gh_id == null) {
   list.gh_id = 0
  }
  var r = list.gh_id - list.mid;
  if (r < 0) {
   list.start_id = Math.abs®;
   r = 0
  } else {
   list.start_id = 0
  };
  for (var k = 0; k < list.nbvis; k++) {
   if (k >= list.start_id && r < list.total_gh) {
     list.item.push(new item(list.hlist[r], k, r));
     r++
   } else {
     list.item.push(new item(-1, k, -1))
   }
  }
};

function scrollup_spv(a) {
  var r = list.item[list.mid].gh_id;
  if (r > 0) {
   var s = list.item[0].gh_id;
   if (s > 0) {
     list.item.unshift(new item(list.hlist[s - 1], 0, s - 1))
   } else {
     list.item.unshift(new item(-1, 0, -1))
   };
   list.item.pop()
  };
  var b = list.item.length;
  for (var i = 0; i < b; i++) {
   list.item.idx = i
  };
  setcursorx()
};

function scrolldown_spv(a) {
  var r = list.item[list.mid].gh_id;
  if (r < list.total_gh - 1) {
   var s = list.item[list.item.length - 1].gh_id;
   if (s > 0 && s < list.total_gh - 1) {
     list.item.push(new item(list.hlist[s + 1], 0, s + 1))
   } else {
     list.item.push(new item(-1, 0, -1))
   };
   list.item.shift()
  };
  var b = list.item.length;
  for (var i = 0; i < b; i++) {
   list.item.idx = i
  };
  setcursorx()
};

function refresh_spv(a, b) {
  reset_cover_timers();
  list.item.splice(0, list.item.length);
  if (list.total_gh <= 0) return true;
  list.gh_id = get_gh_id(list.focus_id);
  if (list.gh_id == null) {
   init_active_pls();
   return true
  }
  list.selected_gh_id = list.gh_id;
  var r = list.gh_id - list.mid;
  if (r < 0) {
   list.start_id = Math.abs®;
   r = 0
  } else {
   list.start_id = 0
  };
  for (var k = 0; k < list.nbvis; k++) {
   if (k >= list.start_id && r < list.total_gh) {
     list.item.push(new item(list.hlist[r], k, r));
     r++
   } else {
     list.item.push(new item(-1, k, -1))
   }
  };
  if (scrollbar.show) {
   if (list.total_gh < 2) scrollbar.visible = false;
   else scrollbar.visible = true
  } else {
   scrollbar.visible = false
  };
  if (panel.vertical_mode) {
   cursor.h = Math.round(vscrollbar.h / list.total_gh);
   if (cursor.h > vscrollbar.h) cursor.h = vscrollbar.h;
   if (cursor.h < cursor.default_w) cursor.h = cursor.default_w
  } else {
   cursor.w = Math.round(hscrollbar.w / list.total_gh);
   if (cursor.w > hscrollbar.w) cursor.w = hscrollbar.w;
   if (cursor.w < cursor.default_w) cursor.w = cursor.default_w
  };
  set_scroller();
  setcursorx()
};

function get_gh_id(a) {
  var b = Math.floor(list.total_gh / 2);
  if (a < list.hlist) {
   var c = 0
  } else {
   var c = b
  };
  for (var i = c; i < list.total_gh; i++) {
   if (i < list.total_gh - 1) {
     if (a >= list.hlist && a < list.hlist[i + 1]) {
       return i
     }
   } else {
     if (a >= list.hlist) {
       return i
     } else {
       return null
     }
   }
  }
};

function setcursorx() {
  if (list.item.length > 0) {
   var a = Math.floor(list.item.length / 2);
   var b = list.item[a].gh_id;
   var c = b / (list.total_gh - 1);
   if (panel.vertical_mode) {
     cursor.y = vscrollbar.y + Math.round(c * (vscrollbar.h - cursor.h))
   } else {
     cursor.x = hscrollbar.x + Math.round(c * (hscrollbar.w - cursor.w))
   }
  } else {
   if (panel.vertical_mode) {
     cursor.y = vscrollbar.y
   } else {
     cursor.x = hscrollbar.x
   }
  }
};

function init_active_pls() {
  var a;
  var b;
  var c;
  list.hlist.splice(0, list.hlist.length);
  list.handlelist = plman.GetPlaylistItems(panel.active_playlist);
  list.total = list.handlelist.Count;
  for (var i = 0; i < list.total; i++) {
   if (i > 0 && i < list.total - 1) {
     i++;
     b = tf_group_key.EvalWithMetadb(list.handlelist.Item(i));
     if (a != b) {
       if (i > 0) {
         c = tf_group_key.EvalWithMetadb(list.handlelist.Item(i - 1));
         if (a != c) {
           list.hlist.push(i - 1)
         };
         if (c != b) {
           list.hlist.push(i)
         }
       } else {
         list.hlist.push(i)
       };
       a = b
     }
   } else {
     b = tf_group_key.EvalWithMetadb(list.handlelist.Item(i));
     if (a != b) {
       list.hlist.push(i);
       a = b
     }
   }
  };
  list.total_gh = list.hlist.length
};

function old_init_active_pls() {
  var a;
  var b;
  list.hlist.splice(0, list.hlist.length);
  list.handlelist = plman.GetPlaylistItems(panel.active_playlist);
  list.total = list.handlelist.Count;
  for (var i = 0; i < list.total; i++) {
   b = tf_group_key.EvalWithMetadb(list.handlelist.Item(i));
   if (a != b) {
     list.hlist.push(i);
     a = b
   }
  };
  list.total_gh = list.hlist.length
};

function on_font_changed() {
  get_font();
  on_playlist_switch()
};

function on_colors_changed() {
  get_colors();
  init_icons();
  redraw_stub_images();
  init_hscrollbar_buttons();
  set_scroller();
  g_image_cache = new image_cache;
  CollectGarbage();
  on_playlist_switch()
};

function on_init() {};

function on_size() {
  if (!window.Width || !window.Height) return;
  window.DlgCode = DLGC_WANTALLKEYS;
  bool_on_size = true;
  if (g_instancetype == 0) {
   window.MinWidth = 170;
   window.MinHeight = 170
  } else if (g_instancetype == 1) {
   window.MinWidth = 170;
   window.MinHeight = 170
  };
  ww = window.Width;
  wh = window.Height;
  if (ww > wh) {
   panel.vertical_mode = false;
   window.MaxHeight = panel.max_height;
   window.MaxWidth = 2000;
   if (wh < 170) wh = 170
  } else {
   panel.vertical_mode = true;
   window.MaxWidth = panel.max_width;
   window.MaxHeight = 2000;
   if (ww < 170) ww = 170
  };
  var a = window.GetProperty("_group TF text info", "%album artist%[ | %album%][ | %date%]");
  if (a == "") window.SetProperty("_group TF text info", "%album artist%[ | %album%][ | %date%]");
  tf_group_info = fb.TitleFormat(window.GetProperty("_group TF text info", "%album artist%[ | %album%][ | %date%]"));
  get_font();
  get_colors();
  init_icons();
  if (panel.vertical_mode) {
   if (scrollbar.show) {
     cover.pad_right_mid = cover.default_pad_right_mid
   } else {
     cover.pad_right_mid = cover.default_pad_right_mid - vscrollbar.default_w
   }
   cover.h = ww - cover.pad_left_mid - cover.pad_right_mid;
   cover.w = cover.h;
   list.nbvis = Math.floor(wh / (cover.h - cover.normal_delta * 2)) + 2;
   if (list.nbvis / 2 == Math.floor(list.nbvis / 2)) {
     list.nbvis--
   }
   list.mid = Math.floor(list.nbvis / 2);
   list.nb_cover_to_draw = Math.floor(wh / (cover.h - cover.normal_delta * 2)) + 2;
   if (scrollbar.themed) {
     scrollbar.theme = window.CreateThemeManager("scrollbar")
   } else {
     scrollbar.theme = false
   };
   init_vscrollbar_buttons();
   button_up.x = ww - button_up.w;
   button_up.y = 0;
   button_down.x = ww - button_down.w;
   button_down.y = wh - button_down.h;
   vscrollbar.y = button_up.h;
   vscrollbar.h = wh - button_up.h - button_down.h;
   cursor.x = ww - vscrollbar.w;
   cursor.y = vscrollbar.y;
   cursor.w = vscrollbar.w
  } else {
   if (scrollbar.show) {
     cover.pad_bot_mid = cover.default_pad_bot_mid
   } else {
     cover.pad_bot_mid = cover.default_pad_bot_mid - hscrollbar.default_h
   }
   if (panel.show_text) {
     cover.pad_top_mid = cover.default_pad_top_mid
   } else {
     cover.pad_top_mid = cover.default_pad_top_mid - 16
   };
   cover.w = wh - cover.pad_top_mid - cover.pad_bot_mid;
   cover.h = cover.w;
   list.nbvis = Math.floor(ww / (cover.w - cover.normal_delta * 2)) + 2;
   if (list.nbvis / 2 == Math.floor(list.nbvis / 2)) {
     list.nbvis--
   }
   list.mid = Math.floor(list.nbvis / 2);
   list.nb_cover_to_draw = Math.floor(ww / (cover.w - cover.normal_delta * 2)) + 2;
   if (scrollbar.themed) {
     scrollbar.theme = window.CreateThemeManager("scrollbar")
   } else {
     scrollbar.theme = false
   };
   init_hscrollbar_buttons();
   button_up.x = 0;
   button_up.y = wh - hscrollbar.h;
   button_down.x = ww - button_down.w;
   button_down.y = wh - hscrollbar.h;
   hscrollbar.x = button_up.w;
   hscrollbar.w = ww - button_up.w - button_down.w;
   cursor.y = wh - hscrollbar.h;
   cursor.x = hscrollbar.x;
   cursor.h = hscrollbar.h
  };
  redraw_stub_images();
  if (list.first_launch) {
   list.first_launch = false;
   on_playlist_switch()
  } else {
   g_image_cache = new image_cache;
   CollectGarbage();
   refresh_spv(panel.active_playlist, true)
  }
};

function on_paint(a) {
  a.FillSolidRect(0, 0, ww, wh, g_backcolor);
  if (list.item.length > 0) {
   var b, mid2;
   list.item[list.mid].draw(a, list.item[list.mid].id, list.mid, 0, true);
   for (var c = 1; c < list.mid + 1; c++) {
     if (c > 1 && c <= list.mid) {
       b = true
     } else {
       b = false
     };
     mid2 = list.mid - c;
     if (mid2 >= 0 && mid2 <= list.item.length - 1) {
       list.item[mid2].draw(a, list.item[mid2].id, mid2, c, b)
     }
     mid2 = list.mid + c;
     if (mid2 >= 0 && mid2 <= list.item.length - 1) {
       list.item[mid2].draw(a, list.item[mid2].id, mid2, c * -1, b)
     }
   };
   mid2 = list.mid - 1;
   if (mid2 >= 0 && mid2 <= list.item.length - 1) {
     list.item[mid2].draw(a, list.item[mid2].id, mid2, 1, true)
   }
   mid2 = list.mid + 1;
   if (mid2 >= 0 && mid2 <= list.item.length - 1) {
     list.item[mid2].draw(a, list.item[mid2].id, mid2, -1, true)
   }
   list.item[list.mid].draw(a, list.item[list.mid].id, list.mid, 0, true);
   if (!panel.vertical_mode) {
     if (panel.show_text) {
       var d = panel.lock_playlist ? 32 : 60;
       var f = panel.lock_playlist ? ww - 64 : ww - 120;
       if (list.item[list.mid].id >= 0) {
         a.GdiDrawText(list.item[list.mid].group_info, g_font, g_textcolor, d, 0, f, cover.pad_top_mid - 4, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX)
       }
     }
   }
  };
  if (list.total_gh > 0 && scrollbar.visible && scrollbar.show) {
   if (panel.vertical_mode) {
     try {
       scrollbar.theme.SetPartAndStateId(6, 1);
       scrollbar.theme.DrawThemeBackground(a, ww - vscrollbar.w, 0, vscrollbar.w, wh)
     } catch (e) {
       a.FillSolidRect(ww - vscrollbar.w, 0, vscrollbar.w, wh, g_backcolor & 0x77ffffff);
       a.FillSolidRect(ww - vscrollbar.w, 0, 1, wh, RGBA(0, 0, 0, 20))
     };
     cursor.bt.draw(a, ww - vscrollbar.w, cursor.y, 255);
     try {
       scrollbar.theme.SetPartAndStateId(9, 1);
       scrollbar.theme.DrawThemeBackground(a, ww - vscrollbar.w, cursor.y, cursor.w, cursor.h)
     } catch (e) {};
     for (i = 0; i < scrollbar.arr_buttons.length; i++) {
       switch (i) {
       case 0:
         scrollbar.arr_buttons.draw(a, ww - vscrollbar.w, button_up.y, 255);
         break;
       case 1:
         scrollbar.arr_buttons.draw(a, ww - vscrollbar.w, button_down.y, 255);
         break
       }
     };
     if (cursor.drag) {
       scrollbar.letter = list.item[Math.floor(list.nbvis / 2)].albumartist.substring(0, 1).toUpperCase();
       cursor.popup && a.DrawImage(cursor.popup, ww - vscrollbar.w - cursor.popup.Width - 00, cursor.y + Math.floor(cursor.h / 2) - Math.floor(cursor.popup.Height / 2), cursor.popup.Width, cursor.popup.Height, 0, 0, cursor.popup.Width, cursor.popup.Height, 0, 155);
       cursor.popup && a.GdiDrawText(scrollbar.letter, gdi.Font("segoe ui", 14, 0), g_backcolor, ww - vscrollbar.w - cursor.popup.Width - 00, cursor.y + Math.floor(cursor.h / 2) - Math.floor(cursor.popup.Height / 2), cursor.popup.Width - 5, cursor.popup.Height, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX)
     }
   } else {
     try {
       scrollbar.theme.SetPartAndStateId(4, 1);
       scrollbar.theme.DrawThemeBackground(a, 0, wh - hscrollbar.h, ww, hscrollbar.h);
       a.FillSolidRect(0, wh - hscrollbar.h - 1, ww, 1, RGBA(0, 0, 0, 10))
     } catch (e) {
       a.FillSolidRect(0, wh - hscrollbar.h, ww, hscrollbar.h, g_backcolor & 0x77ffffff);
       a.FillSolidRect(0, wh - hscrollbar.h, ww, 1, RGBA(0, 0, 0, 20))
     };
     try {
       cursor.bt.draw(a, cursor.x, cursor.y, 255)
     } catch (e) {};
     try {
       scrollbar.theme.SetPartAndStateId(8, 1);
       scrollbar.theme.DrawThemeBackground(a, cursor.x, wh - hscrollbar.h + 0, cursor.w, cursor.h)
     } catch (e) {};
     for (i = 0; i < scrollbar.arr_buttons.length; i++) {
       switch (i) {
       case 0:
         scrollbar.arr_buttons.draw(a, button_up.x, button_up.y, 255);
         break;
       case 1:
         scrollbar.arr_buttons.draw(a, button_down.x, button_down.y, 255);
         break
       }
     };
     if (cursor.drag) {
       scrollbar.letter = list.item[Math.floor(list.nbvis / 2)].albumartist.substring(0, 1).toUpperCase();
       cursor.popup && a.DrawImage(cursor.popup, cursor.x + Math.floor(cursor.w / 2) - Math.floor(cursor.popup.Width / 2), wh - hscrollbar.h - cursor.popup.Height, cursor.popup.Width, cursor.popup.Height, 0, 0, cursor.popup.Width, cursor.popup.Height, 0, 155);
       cursor.popup && a.GdiDrawText(scrollbar.letter, gdi.Font("segoe ui", 14, 0), g_backcolor, cursor.x + Math.floor(cursor.w / 2) - Math.floor(cursor.popup.Width / 2), wh - hscrollbar.h - cursor.popup.Height, cursor.popup.Width, cursor.popup.Height - 5, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX)
     }
   }
  };
  for (i = 0; i < panel.arr_buttons.length; i++) {
   switch (i) {
   case 0:
     if (!panel.lock_playlist) {
       if (panel.vertical_mode) {
         panel.arr_buttons.draw(a, 5, 30, 255)
       } else {
         panel.arr_buttons.draw(a, 30, 5, 255)
       }
     };
     break;
   case 1:
     if (panel.vertical_mode) {
       panel.arr_buttons.draw(a, 5, wh - 22 - 5, 255)
     } else {
       panel.arr_buttons.draw(a, ww - 22 - 5, 5, 255)
     };
     break;
   case 2:
     panel.arr_buttons.draw(a, 5, 5, 255);
     break
   }
  };
  if (!panel.vertical_mode) {
   a.FillGradRect(0, 0, ww, 1, 0, 0, g_textcolor & 0x15ffffff, 0.5)
  }
};

function on_mouse_lbtn_down(x, y) {
  bool_on_size = false;
  var a = list.item.length;
  for (var i = 0; i < a; i++) {
   list.item.checkstate("down", x, y, i)
  };
  if (list.total_gh > 0 && scrollbar.visible && scrollbar.show) {
   if (panel.vertical_mode) {
     if (cursor.bt.checkstate("down", x, y) == ButtonStates.down) {
       cursor.drag = true;
       cursor.grap_y = y - cursor.y;
       cursor.last_y = cursor.y
     };
     if (vscrollbar.hover && !cursor.drag) {
       scrollbar.step = Math.floor(list.nb_cover_to_draw / 2);
       if (scrollbar.step < 1) scrollbar.step = 1;
       if (y < cursor.y) {
         if (!list.buttonclicked) {
           list.buttonclicked = true;
           on_mouse_wheel(scrollbar.step);
           scrollbarbt.timerID1 = window.SetTimeout(function () {
             on_mouse_wheel(scrollbar.step);
             scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
             scrollbarbt.timerID1 = false;
             scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
             scrollbarbt.timerID2 = window.SetInterval(function () {
               if (hscrollbar.hover) {
                 if (mouse_x > ww - vscrollbar.w && cursor.y > mouse_y) {
                   on_mouse_wheel(scrollbar.step)
                 }
               }
             }, scrollbarbt.timer2_value)
           }, scrollbarbt.timer1_value)
         }
       } else {
         if (!list.buttonclicked) {
           list.buttonclicked = true;
           on_mouse_wheel(-1 * scrollbar.step);
           scrollbarbt.timerID1 = window.SetTimeout(function () {
             on_mouse_wheel(-1 * scrollbar.step);
             scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
             scrollbarbt.timerID1 = false;
             scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
             scrollbarbt.timerID2 = window.SetInterval(function () {
               if (hscrollbar.hover) {
                 if (mouse_x > ww - vscrollbar.w && cursor.y + cursor.h < mouse_y) {
                   on_mouse_wheel(-1 * scrollbar.step)
                 }
               }
             }, scrollbarbt.timer2_value)
           }, scrollbarbt.timer1_value)
         }
       }
     }
   } else {
     if (cursor.bt.checkstate("down", x, y) == ButtonStates.down) {
       cursor.drag = true;
       cursor.grap_x = x - cursor.x;
       cursor.last_x = cursor.x
     };
     if (hscrollbar.hover && !cursor.drag) {
       scrollbar.step = Math.floor(list.nb_cover_to_draw / 2);
       if (scrollbar.step < 1) scrollbar.step = 1;
       if (x < cursor.x) {
         if (!list.buttonclicked) {
           list.buttonclicked = true;
           on_mouse_wheel(scrollbar.step);
           scrollbarbt.timerID1 = window.SetTimeout(function () {
             on_mouse_wheel(scrollbar.step);
             scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
             scrollbarbt.timerID1 = false;
             scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
             scrollbarbt.timerID2 = window.SetInterval(function () {
               if (hscrollbar.hover) {
                 if (mouse_y > wh - hscrollbar.h && cursor.x > mouse_x) {
                   on_mouse_wheel(scrollbar.step)
                 }
               }
             }, scrollbarbt.timer2_value)
           }, scrollbarbt.timer1_value)
         }
       } else {
         if (!list.buttonclicked) {
           list.buttonclicked = true;
           on_mouse_wheel(-1 * scrollbar.step);
           scrollbarbt.timerID1 = window.SetTimeout(function () {
             on_mouse_wheel(-1 * scrollbar.step);
             scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
             scrollbarbt.timerID1 = false;
             scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
             scrollbarbt.timerID2 = window.SetInterval(function () {
               if (hscrollbar.hover) {
                 if (mouse_y > wh - hscrollbar.h && cursor.x + cursor.w < mouse_x) {
                   on_mouse_wheel(-1 * scrollbar.step)
                 }
               }
             }, scrollbarbt.timer2_value)
           }, scrollbarbt.timer1_value)
         }
       }
     }
   };
   for (i = 0; i < scrollbar.arr_buttons.length; i++) {
     switch (i) {
     case 0:
       if (scrollbar.arr_buttons.checkstate("down", x, y) == ButtonStates.down) {
         if (!list.buttonclicked) {
           list.buttonclicked = true;
           on_mouse_wheel(1);
           scrollbarbt.timerID1 = window.SetTimeout(function () {
             reset_cover_timers();
             scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
             scrollbarbt.timerID1 = false;
             scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
             scrollbarbt.timerID2 = window.SetInterval(function () {
               on_mouse_wheel(1)
             }, scrollbarbt.timer2_value)
           }, scrollbarbt.timer1_value)
         }
       };
       break;
     case 1:
       if (scrollbar.arr_buttons.checkstate("down", x, y) == ButtonStates.down) {
         if (!list.buttonclicked) {
           list.buttonclicked = true;
           on_mouse_wheel(-1);
           scrollbarbt.timerID1 = window.SetTimeout(function () {
             reset_cover_timers();
             scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
             scrollbarbt.timerID1 = false;
             scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
             scrollbarbt.timerID2 = window.SetInterval(function () {
               on_mouse_wheel(-1)
             }, scrollbarbt.timer2_value)
           }, scrollbarbt.timer1_value)
         }
       };
       break
     }
   }
  };
  for (var i = 0; i < panel.arr_buttons.length; i++) {
   panel.arr_buttons.checkstate("down", x, y)
  }
};

function on_mouse_lbtn_dblclk(x, y, a) {
  if (panel.vertical_mode) {
   if (x < cover.pad_left_mid) {} else if (x < ww - cover.pad_right_mid) {
     var b = list.item.length;
     for (var i = 0; i < b; i++) {
       list.item.checkstate("dblclk", x, y, i)
     }
   } else {
     on_mouse_lbtn_down(x, y)
   }
  } else {
   if (y < cover.pad_top_mid) {} else if (y < wh - cover.pad_bot_mid) {
     var b = list.item.length;
     for (var i = 0; i < b; i++) {
       list.item.checkstate("dblclk", x, y, i)
     }
   } else {
     on_mouse_lbtn_down(x, y)
   }
  }
};

function on_mouse_lbtn_up(x, y) {
  list.buttonclicked = false;
  scrollbar.timerID && window.ClearTimeout(scrollbar.timerID);
  scrollbar.timerID = false;
  scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
  scrollbarbt.timerID1 = false;
  scrollbarbt.timerID2 && window.ClearTimeout(scrollbarbt.timerID2);
  scrollbarbt.timerID2 = false;
  if (list.drag_timer) {
   window.ClearTimeout(list.drag_timer);
   list.drag_timer = false;
   list.drag_stop = true
  }
  if (list.total_gh > 0) {
   cursor.bt.checkstate("up", x, y);
   for (var i = 0; i < scrollbar.arr_buttons.length; i++) {
     scrollbar.arr_buttons.checkstate("up", x, y)
   };
   for (i = 0; i < panel.arr_buttons.length; i++) {
     switch (i) {
     case 0:
       if (panel.arr_buttons.checkstate("up", x, y) == ButtonStates.hover) {
         ShowNowPlaying()
       };
       break;
     case 1:
       if (panel.arr_buttons.checkstate("up", x, y) == ButtonStates.hover) {
         settings_menu(x, y)
       };
       break;
     case 2:
       if (panel.arr_buttons.checkstate("up", x, y) == ButtonStates.hover) {
         if (panel.lock_playlist) {
           panel.lock_playlist = false;
           window.SetProperty("panel.lock.playlist.enabled", panel.lock_playlist);
           plman.ActivePlaylist = panel.active_playlist
         } else {
           panel.lock_playlist = true;
           window.SetProperty("panel.lock.playlist.enabled", panel.lock_playlist);
           panel.active_playlist = plman.ActivePlaylist;
           window.SetProperty("panel.active.playlist", panel.active_playlist);
           var a = Math.floor(list.nbvis / 2);
           a = list.focus_id_item_idx;
           list.item[a].checkstate("mid", list.item[a].x + 5, list.item[a].y + 5, a)
         };
         if (panel.lock_playlist) {
           panel.arr_buttons[2].update(lock_button_normal, lock_button_hover, lock_button_down)
         } else {
           panel.arr_buttons[2].update(unlock_button_normal, unlock_button_hover, unlock_button_down)
         }
       };
       break
     }
   };
   if (cursor.drag) {
     window.RepaintRect(0, wh - hscrollbar.h, ww, hscrollbar.h);
     cursor.drag = false
   } else {
     var b = list.item.length;
     for (i = 0; i < b; i++) {
       list.item.checkstate("up", x, y, i)
     }
   };
   setcursorx();
   window.Repaint()
  }
};

function on_mouse_mbtn_down(x, y, a) {
  bool_on_size = false;
  var b = list.item.length;
  for (var i = 0; i < b; i++) {
   list.item.checkstate("mid", x, y, i)
  }
};

function on_mouse_rbtn_down(x, y) {
  bool_on_size = false;
  var a = list.item.length;
  for (var i = 0; i < a; i++) {
   list.item.checkstate("right", x, y, i)
  }
};

function on_mouse_move(x, y) {
  if (x == mouse_x && y == mouse_y) return true;
  if (cursor.drag) {
   list.drag_stop = false;
   if (list.drag_timer) {
     window.ClearTimeout(list.drag_timer);
     list.drag_timer = false
   }
   list.drag_timer = window.SetTimeout(function () {
     list.drag_stop = true;
     window.ClearTimeout(list.drag_timer);
     list.drag_timer = false;
     window.Repaint()
   }, 25)
  } else {
   list.drag_stop = true
  };
  if (list.total_gh > 0 && scrollbar.visible && scrollbar.show) {
   if (panel.vertical_mode) {
     vscrollbar.hover = (x >= ww - vscrollbar.w && x <= ww && y >= vscrollbar.y && y <= vscrollbar.y + vscrollbar.h);
     cursor.hover = (x >= cursor.x && x <= cursor.x + cursor.w && y >= cursor.y && y <= cursor.y + cursor.h);
     cursor.bt.checkstate("move", x, y);
     for (var i = 0; i < scrollbar.arr_buttons.length; i++) {
       scrollbar.arr_buttons.checkstate("move", x, y)
     };
     if (cursor.drag && mouse_y != y) {
       reset_cover_timers();
       cursor.y = y - cursor.grap_y;
       if (cursor.y < vscrollbar.y) cursor.y = vscrollbar.y;
       if (cursor.y > vscrollbar.y + vscrollbar.h - cursor.h) cursor.y = vscrollbar.y + vscrollbar.h - cursor.h;
       if (!cursor.timerID) {
         cursor.timerID = window.SetTimeout(function () {
           refresh_spv_cursor(fb.ActivePlaylist);
           window.Repaint();
           cursor.timerID = false
         }, 30)
       }
     }
   } else {
     hscrollbar.hover = (y >= wh - hscrollbar.h && y <= wh && x >= hscrollbar.x && x <= hscrollbar.x + hscrollbar.w);
     cursor.hover = (x >= cursor.x && x <= cursor.x + cursor.w && y >= cursor.y && y <= cursor.y + cursor.h);
     cursor.bt.checkstate("move", x, y);
     for (var i = 0; i < scrollbar.arr_buttons.length; i++) {
       scrollbar.arr_buttons.checkstate("move", x, y)
     };
     if (cursor.drag && mouse_x != x) {
       reset_cover_timers();
       cursor.x = x - cursor.grap_x;
       if (cursor.x < hscrollbar.x) cursor.x = hscrollbar.x;
       if (cursor.x > hscrollbar.x + hscrollbar.w - cursor.w) cursor.x = hscrollbar.x + hscrollbar.w - cursor.w;
       if (!cursor.timerID) {
         cursor.timerID = window.SetTimeout(function () {
           refresh_spv_cursor(panel.active_playlist);
           window.Repaint();
           cursor.timerID && window.ClearTimeout(cursor.timerID);
           cursor.timerID = false
         }, 30)
       }
     }
   }
  };
  for (var j = 0; j < panel.arr_buttons.length; j++) {
   panel.arr_buttons[j].checkstate("move", x, y)
  };
  mouse_x = x;
  mouse_y = y
};

function on_mouse_wheel(a) {
  var b = Math.abs(a);
  reset_cover_timers();
  if (!scrollbar.timerID) {
   if (b >= 1) {
     if (a > 0) {
       for (var i = 0; i < b; i++) {
         scrollup_spv(panel.active_playlist)
       };
       scrollbar.timerID = window.SetTimeout(function () {
         window.Repaint();
         scrollbar.timerID && window.ClearTimeout(scrollbar.timerID);
         scrollbar.timerID = false
       }, list.mousewheel_timer_value)
     } else {
       for (var i = 0; i < b; i++) {
         scrolldown_spv(panel.active_playlist)
       }
       scrollbar.timerID = window.SetTimeout(function () {
         window.Repaint();
         scrollbar.timerID && window.ClearTimeout(scrollbar.timerID);
         scrollbar.timerID = false
       }, list.mousewheel_timer_value)
     }

  • Falstaff
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #1414
WSH CoverFlow v1 beta7


[!--sizeo:1--][span style=\"font-size:8pt;line-height:100%\"][!--/sizeo--]click me![/size]

[code]// ==PREPROCESSOR==
// @name "CoverFlow View v1 beta7"
// @version "0.0.7.20120401.1646"
// @author "Br3tt"
// @feature "v1.4"
// @feature "watch-metadb"
// @feature "dragdrop"
// ==/PREPROCESSOR==

// [Requirements]
// * foobar2000 v1.1 or better  >> http://foobar2000.org
// * WSH panel Mod v1.5.2 or better  >> http://code.google.com/p/foo-wsh-panel-mod/downloads/list
// [/Requirements]

// * !!! Keep a reasonable size for the panel to avoid bad perf!

// [Informations]
// * change colors and fonts in foobar2000 Preferences > DefaultUI or ColumsUI
// * Some Settings can be changed in window Properties (right click empty space > Properties)
//  e.g. for custom colors in Properties, use e.g. RGB(255,255,255) for white color, RGB(0,0,0) for black color, ...
// * middle click on cover > Send album tracks to specific playlist "CoverFlow View"
// * keyboard keys : left/right arrows, Home/End, page up/down, spacebar to set focus on the centered album, Return key to play ...
// [/Informations]

SM_CXVSCROLL = 2;
SM_CYHSCROLL = 3;
DLGC_WANTARROWS = 0x0001;
DLGC_WANTALLKEYS = 0x0004;
MF_STRING = 0x00000000;
MF_SEPARATOR = 0x00000800;
MF_GRAYED = 0x00000001;
MF_DISABLED = 0x00000002;
MF_POPUP = 0x00000010;
IDC_ARROW = 32512;
IDC_IBEAM = 32513;
IDC_WAIT = 32514;
IDC_CROSS = 32515;
IDC_UPARROW = 32516;
IDC_SIZE = 32640;
IDC_ICON = 32641;
IDC_SIZENWSE = 32642;
IDC_SIZENESW = 32643;
IDC_SIZEWE = 32644;
IDC_SIZENS = 32645;
IDC_SIZEALL = 32646;
IDC_NO = 32648;
IDC_APPSTARTING = 32650;
IDC_HAND = 32649;
IDC_HELP = 32651;
var DT_LEFT = 0x00000000;
var DT_RIGHT = 0x00000002;
var DT_TOP = 0x00000000;
var DT_CENTER = 0x00000001;
var DT_VCENTER = 0x00000004;
var DT_WORDBREAK = 0x00000010;
var DT_SINGLELINE = 0x00000020;
var DT_CALCRECT = 0x00000400;
var DT_NOPREFIX = 0x00000800;
var DT_EDITCONTROL = 0x00002000;
var DT_END_ELLIPSIS = 0x00008000;
var VK_BACK = 0x08;
var VK_RETURN = 0x0D;
var VK_SHIFT = 0x10;
var VK_CONTROL = 0x11;
var VK_ALT = 0x12;
var VK_ESCAPE = 0x1B;
var VK_PGUP = 0x21;
var VK_PGDN = 0x22;
var VK_END = 0x23;
var VK_HOME = 0x24;
var VK_LEFT = 0x25;
var VK_UP = 0x26;
var VK_RIGHT = 0x27;
var VK_DOWN = 0x28;
var VK_INSERT = 0x2D;
var VK_DELETE = 0x2E;
var VK_SPACEBAR = 0x20;
var KMask = {
  none: 0,
  ctrl: 1,
  shift: 2,
  ctrlshift: 3,
  ctrlalt: 4,
  ctrlaltshift: 5,
  alt: 6
};

function GetKeyboardMask() {
  var c = utils.IsKeyPressed(VK_CONTROL) ? true : false;
  var a = utils.IsKeyPressed(VK_ALT) ? true : false;
  var s = utils.IsKeyPressed(VK_SHIFT) ? true : false;
  var b = KMask.none;
  if (c && !a && !s) b = KMask.ctrl;
  if (!c && !a && s) b = KMask.shift;
  if (c && !a && s) b = KMask.ctrlshift;
  if (c && a && !s) b = KMask.ctrlalt;
  if (c && a && s) b = KMask.ctrlaltshift;
  if (!c && a && !s) b = KMask.alt;
  return b
};
ColorTypeCUI = {
  text: 0,
  selection_text: 1,
  inactive_selection_text: 2,
  background: 3,
  selection_background: 4,
  inactive_selection_background: 5,
  active_item_frame: 6
};
FontTypeCUI = {
  items: 0,
  labels: 1
};
ColorTypeDUI = {
  text: 0,
  background: 1,
  highlight: 2,
  selection: 3
};
FontTypeDUI = {
  defaults: 0,
  tabs: 1,
  lists: 2,
  playlists: 3,
  statusbar: 4,
  console: 5
};

function StringFormat() {
  var a = 0,
   v_align = 0,
   trimming = 0,
   flags = 0;
  switch (arguments.length) {
  case 3:
   trimming = arguments[2];
  case 2:
   v_align = arguments[1];
  case 1:
   a = arguments[0];
   break;
  default:
   return 0
  };
  return ((a << 28) | (v_align << 24) | (trimming << 20) | flags)
};
StringAlignment = {
  Near: 0,
  Centre: 1,
  Far: 2
};
var lt_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Near);
var ct_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Near);
var rt_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Near);
var lc_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Centre);
var cc_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Centre);
var rc_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Centre);
var lb_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Far);
var cb_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Far);
var rb_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Far);

function RGB(r, g, b) {
  return (0xff000000 | (r << 16) | (g << 8) | (b))
};

function RGBA(r, g, b, a) {
  return ((a << 24) | (r << 16) | (g << 8) | (b))
};

function getAlpha(a) {
  return ((a >> 24) & 0xff)
}
function getRed(a) {
  return ((a >> 16) & 0xff)
}
function getGreen(a) {
  return ((a >> 8) & 0xff)
}
function getBlue(a) {
  return (a & 0xff)
}
function num(a, b) {
  var i;
  var c = a.toString();
  var k = b - c.length;
  if (k > 0) {
   for (i = 0; i < k; i++) {
     c = "0" + c
   }
  };
  return c.toString()
};

function TrackType(a) {
  var b;
  var c;
  switch (a) {
  case "file":
   b = 1;
   c = 0;
   break;
  case "cdda":
   b = 1;
   c = 1;
   break;
  case "FOO_":
   b = 0;
   c = 2;
   break;
  case "http":
   b = 0;
   c = 3;
   break;
  case "mms:":
   b = 0;
   c = 3;
   break;
  case "unpa":
   b = 0;
   c = 4;
   break;
  default:
   b = 0;
   c = 5
  };
  return c
};
ButtonStates = {
  normal: 0,
  hover: 1,
  down: 2
};
button = function (d, e, f) {
  this.img = Array(d, e, f);
  this.w = this.img[0].Width;
  this.h = this.img[0].Height;
  this.state = ButtonStates.normal;
  this.update = function (a, b, c) {
   this.img = Array(a, b, c)
  };
  this.draw = function (a, x, y, b) {
   this.x = x;
   this.y = y;
   this.img[this.state] && a.DrawImage(this.img[this.state], this.x, this.y, this.w, this.h, 0, 0, this.w, this.h, 0, b)
  };
  this.display_context_menu = function (x, y, a) {};
  this.repaint = function () {
   window.RepaintRect(this.x, this.y, this.w, this.h)
  };
  this.checkstate = function (a, x, y) {
   this.ishover = (x > this.x && x < this.x + this.w - 1 && y > this.y && y < this.y + this.h - 1);
   this.old = this.state;
   switch (a) {
   case "down":
     switch (this.state) {
     case ButtonStates.normal:
     case ButtonStates.hover:
       this.state = this.ishover ? ButtonStates.down : ButtonStates.normal;
       break
     };
     break;
   case "up":
     this.state = this.ishover ? ButtonStates.hover : ButtonStates.normal;
     break;
   case "right":
     if (this.ishover) this.display_context_menu(x, y, id);
     break;
   case "move":
     switch (this.state) {
     case ButtonStates.normal:
     case ButtonStates.hover:
       this.state = this.ishover ? ButtonStates.hover : ButtonStates.normal;
       break
     };
     break;
   case "leave":
     this.state = this.isdown ? ButtonStates.down : ButtonStates.normal;
     break
   };
   if (this.state != this.old) this.repaint();
   return this.state
  }
};

function get_system_scrollbar_width() {
  var a = utils.GetSystemMetrics(SM_CXVSCROLL);
  return a
};

function get_system_scrollbar_height() {
  var a = utils.GetSystemMetrics(SM_CYHSCROLL);
  return a
};
var nocover;
var nocover_img;
var streamcover;
var streamcover_img;
var loading;
var loading_img;
var star_img_off;
var star_img_on;
var star_img_hov;
var star_img_kill;
var toggle_scrollbar;
var menu_button;
image_cache = function () {
  this._cachelist = {};
  this.hit = function (a) {
   var b = this._cachelist[a.metadb.Path];
   if (list.drag_stop && typeof b == "undefined") {
     if (!cover.load_timer) {
       cover.load_timer = window.SetTimeout(function () {
         utils.GetAlbumArtAsync(window.ID, a.metadb, 0, true, false, false);
         cover.load_timer && window.ClearTimeout(cover.load_timer);
         cover.load_timer = false
       }, 35)
     }
   };
   return b
  };
  this.getit = function (a, b) {
   var c;
   var d = (cover.w - cover.margin * 2) * cover.quality / 100;
   var e = (cover.h - cover.margin * 2) * cover.quality / 100;
   if (a.track_type != 3) {
     if (a.metadb) {
       c = FormatCover(b, d, e);
       if (!c) {
         c = nocover_img;
         a.cover_type = 0
       } else {
         a.cover_type = 1
       }
     }
   } else {
     c = streamcover_img;
     a.cover_type = 3
   };
   this._cachelist[a.metadb.Path] = c;
   return c
  }
};
var g_image_cache = new image_cache;

function FormatCover(a, w, h) {
  if (!a || w <= 0 || h <= 0) return a;
  if (cover.draw_glass_effect) {
   var b = a.Resize(w, h, 2);
   var c = b.GetGraphics();
   c.FillGradRect(0, 0, w, h, 90, RGBA(255, 255, 255, 60), RGBA(255, 255, 255, 10), 1.0);
   c.SetSmoothingMode(2);
   c.FillEllipse(-20, 25, w * 2 + 40, h * 2, RGBA(0, 0, 0, 30));
   b.ReleaseGraphics©;
   return b
  } else {
   var b = a.Resize(w, h, 2);
   var c = b.GetGraphics();
   c.DrawRect(0, 0, w, h, 2.0, g_backcolor);
   c.DrawRect(0, 0, w, h, 2.0, g_textcolor & 0x33ffffff);
   b.ReleaseGraphics©;
   return b
  }
};

function reset_cover_timers() {
  cover.load_timer && window.ClearTimeout(cover.load_timer);
  cover.load_timer = false
};

function on_get_album_art_done(a, b, c, d) {
  var e = list.item.length;
  for (var i = 0; i < e; i++) {
   if (list.item.metadb) {
     if (list.item.metadb.Compare(a)) {
       list.item.cover_img = g_image_cache.getit(list.item, c);
       if (list.item.show) {
         if (panel.vertical_mode) {
           window.RepaintRect(cover.pad_left_mid, list.item.y - 2, ww - cover.pad_left_mid, list.item.h + 4)
         } else {
           window.RepaintRect(list.item.x - 2, cover.pad_top_mid, list.item.w + 4, wh - cover.pad_top_mid)
         }
       } else {
         list.item.show = true
       };
       break
     }
   }
  }
};
ItemStates = {
  normal: 0,
  hover: 1,
  selected: 2
};
item = function (h, k, l) {
  var i;
  if (typeof this.id == "undefined") {
   if (h < 0) {
     this.id = h;
     this.idx = k;
     this.gh_id = l;
     this.metadb = false;
     this.albumartist = "";
     this.track_type = null;
     this.group_info = ""
   } else {
     this.id = h;
     this.idx = k;
     this.gh_id = l;
     this.metadb = list.handlelist.Item(this.id);
     if (this.metadb) {
       this.albumartist = tf_albumartist.EvalWithMetadb(this.metadb);
       this.track_type = TrackType(this.metadb.rawpath.substring(0, 4));
       this.group_info = tf_group_info.EvalWithMetadb(this.metadb)
     }
   }
  };
  this.update_infos = function () {
   if (this.metadb) {
     this.albumartist = tf_albumartist.EvalWithMetadb(this.metadb);
     this.track_type = TrackType(this.metadb.rawpath.substring(0, 4));
     this.group_info = tf_group_info.EvalWithMetadb(this.metadb)
   } else {
     this.albumartist = "";
     this.track_type = null;
     this.group_info = ""
   }
  };
  this.draw = function (a, b, c, d, e) {
   if (panel.vertical_mode) {
     this.show = e;
     if (list.mid == c) {
       this.h = cover.h;
       this.w = cover.h;
       this.x = cover.pad_left_mid;
       this.y = Math.floor((wh / 2) - (cover.h / 2));
       this.cut = 1
     } else {
       this.h = Math.abs(d) == 1 ? cover.h - cover.normal_delta * 1 : cover.h - cover.normal_delta * 2;
       this.w = this.h;
       this.y = Math.abs(d) == 1 ? Math.floor((wh / 2) - (this.h / 2)) - (d * (this.h - 5)) : Math.floor((wh / 2) - (this.h / 2)) - (d * this.h);
       this.x = Math.abs(d) == 1 ? cover.pad_left_mid + Math.ceil(cover.normal_delta / 2) : cover.pad_left_mid + cover.normal_delta;
       this.cut = Math.abs(d) == 1 ? 1 : 0
     };
     a.FillSolidRect(this.x + 1, this.y + 1, this.w - 4, this.h - 4, g_backcolor);
     if (this.id >= 0) {
       this.cover_img = g_image_cache.hit(this);
       if (this.show && typeof (this.cover_img) != "undefined") {
         if (cover.draw_shadows) {
           if (d == 0 || d == 1 || d == -1) {
             for (var j = 0; j < 7; j++) {
               if (d != -1 && this.gh_id > 0) {
                 a.FillSolidRect(this.x + cover.normal_delta / 2, Math.floor(cover.margin / 2) + this.y - j - cover.margin + 1, this.w - cover.normal_delta - cover.margin - 1, 1, RGBA(0, 0, 0, 150 - j * 25))
               };
               if (d != 1 && this.gh_id < list.total_gh - 1) {
                 a.FillSolidRect(this.x + cover.normal_delta / 2, Math.floor(cover.margin / 2) + this.y + this.h - cover.margin + j - 2, this.w - cover.normal_delta - cover.margin - 1, 1, RGBA(0, 0, 0, 150 - j * 25))
               }
             }
           }
         };
         a.DrawImage(this.cover_img, this.x, Math.floor(cover.margin / 2) + this.y, this.w, this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255)
       } else {
         if (cover.draw_shadows) {
           if (d == 0 || d == 1 || d == -1) {
             for (var j = 0; j < 7; j++) {
               if (d != -1 && this.gh_id > 0) {
                 a.FillSolidRect(this.x + cover.normal_delta / 2, Math.floor(cover.margin / 2) + this.y - j - cover.margin + 1, this.w - cover.normal_delta - cover.margin - 1, 1, RGBA(0, 0, 0, 150 - j * 25))
               };
               if (d != 1 && this.gh_id < list.total_gh - 1) {
                 a.FillSolidRect(this.x + cover.normal_delta / 2, Math.floor(cover.margin / 2) + this.y + this.h - cover.margin + j - 2, this.w - cover.normal_delta - cover.margin - 1, 1, RGBA(0, 0, 0, 150 - j * 25))
               }
             }
           }
         };
         a.DrawImage(loading_img, this.x, Math.floor(cover.margin / 2) + this.y, this.w, this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255)
       };
       if (this.gh_id == list.selected_gh_id) {
         list.focus_id_item_idx = this.idx;
         if (cover.draw_focus_border) {
           a.SetSmoothingMode(2);
           a.DrawRoundRect(this.x - 1, Math.floor(cover.margin / 2) + this.y - 1, this.w - cover.margin * 2 + 2, this.h - cover.margin * 2 + 2, 2, 2, 3.0, g_backcolor_sel);
           a.DrawRoundRect(this.x - 2, Math.floor(cover.margin / 2) + this.y - 2, this.w - cover.margin * 2 + 4, this.h - cover.margin * 2 + 4, 3, 3, 1.0, RGBA(255, 255, 255, 60));
           a.SetSmoothingMode(0);
           a.DrawRect(this.x + 1, Math.floor(cover.margin / 2) + this.y + 1, this.w - cover.margin * 2 - 2, this.h - cover.margin * 2 - 2, 1.0, g_backcolor_sel);
           a.DrawRect(this.x + 1, Math.floor(cover.margin / 2) + this.y + 1, this.w - cover.margin * 2 - 2, this.h - cover.margin * 2 - 2, 1.0, RGBA(0, 0, 0, 40))
         }
       }
     }
   } else {
     this.show = e;
     if (list.mid == c) {
       this.w = cover.w;
       this.h = cover.w;
       this.y = cover.pad_top_mid;
       this.x = Math.floor((ww / 2) - (cover.w / 2));
       this.cut = 1
     } else {
       this.w = Math.abs(d) == 1 ? cover.w - cover.normal_delta * 1 : cover.w - cover.normal_delta * 2;
       this.h = this.w;
       this.x = Math.abs(d) == 1 ? Math.floor((ww / 2) - (this.w / 2)) - (d * (this.w - 5)) : Math.floor((ww / 2) - (this.w / 2)) - (d * this.w);
       this.y = Math.abs(d) == 1 ? cover.pad_top_mid + Math.ceil(cover.normal_delta / 2) : cover.pad_top_mid + cover.normal_delta;
       this.cut = Math.abs(d) == 1 ? 1 : 0
     };
     a.FillSolidRect(this.x + 1, this.y + 1, this.w - 4, this.h - 4, g_backcolor);
     if (this.id >= 0) {
       this.cover_img = g_image_cache.hit(this);
       if (this.show && typeof (this.cover_img) != "undefined") {
         var f = 255 - Math.floor(cover.reflect_strength_percent * 2.55);
         if (cover.draw_reflection && f > 0 && cover.reflect_strength_percent > 0) {
           a.DrawImage(this.cover_img, Math.floor(cover.margin / 2) + this.x + this.w, this.y + this.h - cover.margin - 1, -1 * this.w, this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 180, 255);
           a.FillGradRect(Math.floor(cover.margin / 2) + this.x, this.y + this.h, this.w - cover.margin * 2 + 2, this.h + 1, 90, RGBA(g_backcolor_R, g_backcolor_G, g_backcolor_B, f), g_backcolor, 1.0)
         };
         if (cover.draw_shadows) {
           if (d == 0 || d == 1 || d == -1) {
             for (var j = 0; j < 7; j++) {
               if (d != -1 && this.gh_id > 0) {
                 a.FillSolidRect(Math.floor(cover.margin / 2) + this.x - j - cover.margin + 1, this.y + cover.normal_delta / 2, 1, this.h - cover.normal_delta - cover.margin - 1, RGBA(0, 0, 0, 150 - j * 25))
               };
               if (d != 1 && this.gh_id < list.total_gh - 1) {
                 a.FillSolidRect(Math.floor(cover.margin / 2) + this.x + this.w - cover.margin + j - 2, this.y + cover.normal_delta / 2, 1, this.h - cover.normal_delta - cover.margin - 1, RGBA(0, 0, 0, 150 - j * 25))
               }
             }
           }
         };
         a.DrawImage(this.cover_img, Math.floor(cover.margin / 2) + this.x, this.y, this.w, this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255)
       } else {
         var f = 255 - Math.floor(cover.reflect_strength_percent * 2.55);
         if (cover.draw_reflection && f > 0 && cover.reflect_strength_percent > 0) {
           a.DrawImage(loading_img, Math.floor(cover.margin / 2) + this.x + this.w, this.y + this.h - cover.margin - 1, -1 * this.w, this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 180, 255);
           a.FillGradRect(Math.floor(cover.margin / 2) + this.x, this.y + this.h, this.w - cover.margin * 2 + 2, this.h + 1, 90, RGBA(g_backcolor_R, g_backcolor_G, g_backcolor_B, f), g_backcolor, 1.0)
         };
         if (cover.draw_shadows) {
           if (d == 0 || d == 1 || d == -1) {
             for (var j = 0; j < 7; j++) {
               if (d != -1 && this.gh_id > 0) {
                 a.FillSolidRect(Math.floor(cover.margin / 2) + this.x - j - cover.margin + 1, this.y + cover.normal_delta / 2, 1, this.h - cover.normal_delta - cover.margin - 1, RGBA(0, 0, 0, 150 - j * 25))
               };
               if (d != 1 && this.gh_id < list.total_gh - 1) {
                 a.FillSolidRect(Math.floor(cover.margin / 2) + this.x + this.w - cover.margin + j - 2, this.y + cover.normal_delta / 2, 1, this.h - cover.normal_delta - cover.margin - 1, RGBA(0, 0, 0, 150 - j * 25))
               }
             }
           }
         };
         a.DrawImage(loading_img, Math.floor(cover.margin / 2) + this.x, this.y, this.w, this.h, 0, 0, cover.w * cover.quality / 100, cover.h * cover.quality / 100, 0, 255)
       };
       if (this.gh_id == list.selected_gh_id) {
         list.focus_id_item_idx = this.idx;
         if (cover.draw_focus_border) {
           a.SetSmoothingMode(2);
           a.DrawRoundRect(Math.floor(cover.margin / 2) + this.x - 1, this.y - 1, this.w - cover.margin * 2 + 2, this.h - cover.margin * 2 + 2, 2, 2, 3.0, g_backcolor_sel);
           a.DrawRoundRect(Math.floor(cover.margin / 2) + this.x - 2, this.y - 2, this.w - cover.margin * 2 + 4, this.h - cover.margin * 2 + 4, 3, 3, 1.0, RGBA(255, 255, 255, 60));
           a.SetSmoothingMode(0);
           a.DrawRect(Math.floor(cover.margin / 2) + this.x + 1, this.y + 1, this.w - cover.margin * 2 - 2, this.h - cover.margin * 2 - 2, 1.0, g_backcolor_sel);
           a.DrawRect(Math.floor(cover.margin / 2) + this.x + 1, this.y + 1, this.w - cover.margin * 2 - 2, this.h - cover.margin * 2 - 2, 1.0, RGBA(0, 0, 0, 40))
         }
       }
     }
   }
  };
  this.checkstate = function (a, x, y, b) {
   if (this.id >= 0) {
     this.ishover = (x > this.x && x < this.x + this.w && y >= this.y && y < this.y + this.h)
   } else {
     this.ishover = false
   };
   switch (a) {
   case "down":
     if (this.id >= 0) {
       if (plman.IsPlaylistItemSelected(panel.active_playlist, this.id)) {
         if (this.ishover) {
           if (panel.lock_playlist) {
             this.checkstate("mid", x, y, b)
           } else {
             SelectGroupItems(this.id, this.gh_id, true)
           };
           g_saved = this;
           refresh_spv(panel.active_playlist, bool_on_size)
         }
       } else {
         if (this.ishover) {
           if (utils.IsKeyPressed(VK_SHIFT)) {
             if (list.focus_id != this.id) {
               if (list.SHIFT_start_id != null) {} else {}
             }
           } else if (utils.IsKeyPressed(VK_CONTROL)) {
             if (panel.lock_playlist) {
               this.checkstate("mid", x, y, b)
             } else {
               SelectGroupItems(this.id, this.gh_id, true)
             }
           } else {
             SelectGroupItems(this.id, this.gh_id, true);
             g_saved = this;
             if (panel.lock_playlist) {
               g_saved.checkstate("mid", x, y, b)
             }
           }
         }
       }
     };
     break;
   case "dblclk":
     if (this.id >= 0 && g_saved != null) {
       if (plman.IsPlaylistItemSelected(panel.active_playlist, this.id)) {
         if (panel.lock_playlist) {
           if (this.id == g_saved.id) {
             plman.ExecutePlaylistDefaultAction(panel.active_playlist, list.hlist[g_saved.gh_id]);
             g_saved = null
           }
         } else {
           if (this.id == g_saved.id) {
             plman.ExecutePlaylistDefaultAction(panel.active_playlist, list.hlist[g_saved.gh_id]);
             g_saved = null;
             window.Repaint()
           }
         }
       }
     };
     break;
   case "mid":
     if (this.ishover) {
       if (plman.GetPlaylistName(panel.active_playlist) != "CoverFlow View") {
         SelectGroupItems(this.id, this.gh_id, true);
         var c = false;
         var d = 0;
         var e = panel.active_playlist;
         var f = plman.PlaylistCount;
         for (var i = 0; i < f; i++) {
           if (plman.GetPlaylistName(i) == "CoverFlow View") {
             c = true;
             d = i;
             break
           }
         };
         if (!c) {
           bypass.on_playlists_changed = true;
           d = plman.PlaylistCount;
           plman.CreatePlaylist(plman.PlaylistCount, "CoverFlow View")
         };
         plman.ActivePlaylist = d;
         fb.ClearPlaylist();
         var g = fb.PlaylistItemCount(d);
         plman.InsertPlaylistItems(d, g, plman.GetPlaylistSelectedItems(e), false);
         plman.SetPlaylistFocusItem(d, 0)
       }
     };
     break;
   case "right":
     if (this.ishover) {
       if (panel.lock_playlist) {
         list.selected_gh_id = this.gh_id;
         list.focus_id = this.id;
         bypass.on_item_focus_change = true;
         this.checkstate("mid", x, y, b)
       } else {
         list.selected_gh_id = this.gh_id;
         list.focus_id = this.id;
         bypass.on_item_focus_change = true;
         SelectGroupItems(this.id, this.gh_id, true)
       }
     };
     break;
   case "up":
     break;
   case "move":
     break;
   case "leave":
     break
   };
   return this.ishover
  }
};
var tf_path = fb.TitleFormat("$left(%_path_raw%,4)");
var tf_albumartist = fb.TitleFormat("$if(%length%,%album artist%,'Stream')");
var tf_album = fb.TitleFormat("$if2(%album%,$if(%length%,'Single','web radios'))");
var tf_group_key = fb.TitleFormat(window.GetProperty("_group Key", "%album artist%%album%"));
var tf_group_info = fb.TitleFormat(window.GetProperty("_group TF text info", "%album artist%[ | %album%][ | %date%]"));
var g_instancetype = window.InstanceType;
var g_font = null;
var g_font_headers = null;
var ww = 0,
  wh = 0;
var mouse_x = 0,
  mouse_y = 0;
var g_textcolor = 0,
  g_textcolor_sel = 0,
  g_textcolor_hl = 0,
  g_backcolor = 0,
  g_backcolor_sel = 0;
var g_metadb;
var bool_on_size = false;
var g_search_string = "";
var incsearch_font = gdi.Font("lucida console", 9, 0);
var incsearch_font_big = gdi.Font("lucida console", 20, 1);
var clear_incsearch_timer = false;
var incsearch_timer = false;
var incsearch_timer_lock = false;
var g_saved = null;
var hand = false;
bypass = {
  on_item_focus_change: false,
  on_playlists_changed: false
};
panel = {
  max_width: 250,
  max_height: 250,
  arr_buttons: Array(),
  button_total: 3,
  show_text: window.GetProperty("panel.album.info.visible", true),
  custom_textcolor: window.GetProperty("panel.custom.text.color.normal", ""),
  custom_textcolor_selection: window.GetProperty("panel.custom.text.color.selection", ""),
  custom_backcolor: window.GetProperty("panel.custom.background.color", ""),
  lock_playlist: window.GetProperty("panel.lock.playlist.enabled", false),
  active_playlist: window.GetProperty("panel.active.playlist", 0),
  vertical_mode: false
};
list = {
  first_launch: true,
  total: 0,
  total_gh: 0,
  start_id: 0,
  nbvis: 0,
  mid: 0,
  item: Array(),
  hlist: Array(),
  handlelist: null,
  metadblist_selection: plman.GetPlaylistSelectedItems(panel.active_playlist),
  focus_id: 0,
  focus_id_item_idx: 0,
  selected_gh_id: 0,
  marker_id: 0,
  gh_id: 0,
  mousewheel_timer_value: 20,
  key_timer_value: 60,
  nowplaying: 0,
  SHIFT_start_id: null,
  SHIFT_count: 0,
  inc_search_noresult: false,
  nb_cover_to_draw: 0,
  buttonclicked: false,
  drag_stop: true,
  drag_timer: false
};
scrollbar = {
  theme: false,
  themed: window.GetProperty("list.scrollbar.themed", false),
  show: window.GetProperty("list.scrollbar.visible", true),
  visible: true,
  default_step: window.GetProperty("list.scrollbar.step", 3),
  step: 3,
  letter: null,
  button_total: 2,
  arr_buttons: Array(),
  timerID: false
}
hscrollbar = {
  hover: false,
  x: 0,
  y: 0,
  default_h: get_system_scrollbar_height(),
  h: get_system_scrollbar_height(),
  w: 0
};
vscrollbar = {
  hover: false,
  x: 0,
  y: 0,
  default_w: get_system_scrollbar_width(),
  w: get_system_scrollbar_width(),
  h: 0
};
scrollbarbt = {
  timerID1: false,
  timerID2: false,
  timer1_value: 400,
  timer2_value: 60
};
button_up = {
  img_normal: null,
  img_hover: null,
  img_down: null,
  x: 0,
  y: 0,
  w: hscrollbar.default_h,
  h: hscrollbar.default_h
};
button_down = {
  img_normal: null,
  img_hover: null,
  img_down: null,
  x: 0,
  y: 0,
  w: hscrollbar.default_h,
  h: hscrollbar.default_h
};
cursor = {
  bt: null,
  img_normal: null,
  img_hover: null,
  img_down: null,
  popup: null,
  x: 0,
  y: 0,
  w: hscrollbar.default_h,
  h: hscrollbar.default_h,
  default_w: hscrollbar.default_h + 3,
  hover: false,
  drag: false,
  grap_x: 0,
  timerID: false,
  last_x: 0
};
cover = {
  margin: 2,
  w: 0,
  h: 0,
  top_offset: 0,
  default_pad_top_mid: 35,
  default_pad_bot_mid: 30,
  pad_top_mid: 35,
  pad_bot_mid: 30,
  default_pad_left_mid: 24,
  default_pad_right_mid: 20,
  pad_left_mid: 24,
  pad_right_mid: 20,
  normal_delta: 20,
  quality: window.GetProperty("list.covers.quality.percent", 100),
  draw_reflection: window.GetProperty("cover.draw.ground.reflection", true),
  reflect_strength_percent: window.GetProperty("cover.ground.reflection.percent", 20),
  draw_shadows: window.GetProperty("cover.draw.shadows", true),
  draw_focus_border: window.GetProperty("cover.draw.focus.border", true),
  draw_glass_effect: window.GetProperty("cover.draw.glass.effect", false),
  load_timer: false
};

function refresh_spv_cursor(a) {
  if (panel.vertical_mode) {
   var b = (cursor.y - vscrollbar.y) / (vscrollbar.h - cursor.h)
  } else {
   var b = (cursor.x - hscrollbar.x) / (hscrollbar.w - cursor.w)
  }
  if (b > 1) b = 1;
  if (b < 0) b = 0;
  var r = Math.round(b * list.total_gh);
  set_gh_id(a, list.hlist[r - 1]);
  window.Repaint()
}
function set_gh_id(a, b) {
  reset_cover_timers();
  list.item.splice(0, list.item.length);
  if (list.total_gh <= 0) return true;
  list.gh_id = get_gh_id(b);
  if (list.gh_id == null) {
   list.gh_id = 0
  }
  var r = list.gh_id - list.mid;
  if (r < 0) {
   list.start_id = Math.abs®;
   r = 0
  } else {
   list.start_id = 0
  };
  for (var k = 0; k < list.nbvis; k++) {
   if (k >= list.start_id && r < list.total_gh) {
     list.item.push(new item(list.hlist[r], k, r));
     r++
   } else {
     list.item.push(new item(-1, k, -1))
   }
  }
};

function scrollup_spv(a) {
  var r = list.item[list.mid].gh_id;
  if (r > 0) {
   var s = list.item[0].gh_id;
   if (s > 0) {
     list.item.unshift(new item(list.hlist[s - 1], 0, s - 1))
   } else {
     list.item.unshift(new item(-1, 0, -1))
   };
   list.item.pop()
  };
  var b = list.item.length;
  for (var i = 0; i < b; i++) {
   list.item.idx = i
  };
  setcursorx()
};

function scrolldown_spv(a) {
  var r = list.item[list.mid].gh_id;
  if (r < list.total_gh - 1) {
   var s = list.item[list.item.length - 1].gh_id;
   if (s > 0 && s < list.total_gh - 1) {
     list.item.push(new item(list.hlist[s + 1], 0, s + 1))
   } else {
     list.item.push(new item(-1, 0, -1))
   };
   list.item.shift()
  };
  var b = list.item.length;
  for (var i = 0; i < b; i++) {
   list.item.idx = i
  };
  setcursorx()
};

function refresh_spv(a, b) {
  reset_cover_timers();
  list.item.splice(0, list.item.length);
  if (list.total_gh <= 0) return true;
  list.gh_id = get_gh_id(list.focus_id);
  if (list.gh_id == null) {
   init_active_pls();
   return true
  }
  list.selected_gh_id = list.gh_id;
  var r = list.gh_id - list.mid;
  if (r < 0) {
   list.start_id = Math.abs®;
   r = 0
  } else {
   list.start_id = 0
  };
  for (var k = 0; k < list.nbvis; k++) {
   if (k >= list.start_id && r < list.total_gh) {
     list.item.push(new item(list.hlist[r], k, r));
     r++
   } else {
     list.item.push(new item(-1, k, -1))
   }
  };
  if (scrollbar.show) {
   if (list.total_gh < 2) scrollbar.visible = false;
   else scrollbar.visible = true
  } else {
   scrollbar.visible = false
  };
  if (panel.vertical_mode) {
   cursor.h = Math.round(vscrollbar.h / list.total_gh);
   if (cursor.h > vscrollbar.h) cursor.h = vscrollbar.h;
   if (cursor.h < cursor.default_w) cursor.h = cursor.default_w
  } else {
   cursor.w = Math.round(hscrollbar.w / list.total_gh);
   if (cursor.w > hscrollbar.w) cursor.w = hscrollbar.w;
   if (cursor.w < cursor.default_w) cursor.w = cursor.default_w
  };
  set_scroller();
  setcursorx()
};

function get_gh_id(a) {
  var b = Math.floor(list.total_gh / 2);
  if (a < list.hlist) {
   var c = 0
  } else {
   var c = b
  };
  for (var i = c; i < list.total_gh; i++) {
   if (i < list.total_gh - 1) {
     if (a >= list.hlist && a < list.hlist[i + 1]) {
       return i
     }
   } else {
     if (a >= list.hlist) {
       return i
     } else {
       return null
     }
   }
  }
};

function setcursorx() {
  if (list.item.length > 0) {
   var a = Math.floor(list.item.length / 2);
   var b = list.item[a].gh_id;
   var c = b / (list.total_gh - 1);
   if (panel.vertical_mode) {
     cursor.y = vscrollbar.y + Math.round(c * (vscrollbar.h - cursor.h))
   } else {
     cursor.x = hscrollbar.x + Math.round(c * (hscrollbar.w - cursor.w))
   }
  } else {
   if (panel.vertical_mode) {
     cursor.y = vscrollbar.y
   } else {
     cursor.x = hscrollbar.x
   }
  }
};

function init_active_pls() {
  var a;
  var b;
  var c;
  list.hlist.splice(0, list.hlist.length);
  list.handlelist = plman.GetPlaylistItems(panel.active_playlist);
  list.total = list.handlelist.Count;
  for (var i = 0; i < list.total; i++) {
   if (i > 0 && i < list.total - 1) {
     i++;
     b = tf_group_key.EvalWithMetadb(list.handlelist.Item(i));
     if (a != b) {
       if (i > 0) {
         c = tf_group_key.EvalWithMetadb(list.handlelist.Item(i - 1));
         if (a != c) {
           list.hlist.push(i - 1)
         };
         if (c != b) {
           list.hlist.push(i)
         }
       } else {
         list.hlist.push(i)
       };
       a = b
     }
   } else {
     b = tf_group_key.EvalWithMetadb(list.handlelist.Item(i));
     if (a != b) {
       list.hlist.push(i);
       a = b
     }
   }
  };
  list.total_gh = list.hlist.length
};

function old_init_active_pls() {
  var a;
  var b;
  list.hlist.splice(0, list.hlist.length);
  list.handlelist = plman.GetPlaylistItems(panel.active_playlist);
  list.total = list.handlelist.Count;
  for (var i = 0; i < list.total; i++) {
   b = tf_group_key.EvalWithMetadb(list.handlelist.Item(i));
   if (a != b) {
     list.hlist.push(i);
     a = b
   }
  };
  list.total_gh = list.hlist.length
};

function on_font_changed() {
  get_font();
  on_playlist_switch()
};

function on_colors_changed() {
  get_colors();
  init_icons();
  redraw_stub_images();
  init_hscrollbar_buttons();
  set_scroller();
  g_image_cache = new image_cache;
  CollectGarbage();
  on_playlist_switch()
};

function on_init() {};

function on_size() {
  if (!window.Width || !window.Height) return;
  window.DlgCode = DLGC_WANTALLKEYS;
  bool_on_size = true;
  if (g_instancetype == 0) {
   window.MinWidth = 170;
   window.MinHeight = 170
  } else if (g_instancetype == 1) {
   window.MinWidth = 170;
   window.MinHeight = 170
  };
  ww = window.Width;
  wh = window.Height;
  if (ww > wh) {
   panel.vertical_mode = false;
   window.MaxHeight = panel.max_height;
   window.MaxWidth = 2000;
   if (wh < 170) wh = 170
  } else {
   panel.vertical_mode = true;
   window.MaxWidth = panel.max_width;
   window.MaxHeight = 2000;
   if (ww < 170) ww = 170
  };
  var a = window.GetProperty("_group TF text info", "%album artist%[ | %album%][ | %date%]");
  if (a == "") window.SetProperty("_group TF text info", "%album artist%[ | %album%][ | %date%]");
  tf_group_info = fb.TitleFormat(window.GetProperty("_group TF text info", "%album artist%[ | %album%][ | %date%]"));
  get_font();
  get_colors();
  init_icons();
  if (panel.vertical_mode) {
   if (scrollbar.show) {
     cover.pad_right_mid = cover.default_pad_right_mid + vscrollbar.default_w
   } else {
     cover.pad_right_mid = cover.default_pad_right_mid
   }
   cover.h = ww - cover.pad_left_mid - cover.pad_right_mid;
   cover.w = cover.h;
   list.nbvis = Math.floor(wh / (cover.h - cover.normal_delta * 2)) + 2 + 10;
   if (list.nbvis / 2 == Math.floor(list.nbvis / 2)) {
     list.nbvis--
   }
   list.mid = Math.floor(list.nbvis / 2);
   list.nb_cover_to_draw = Math.floor(wh / (cover.h - cover.normal_delta * 2)) + 2;
   if (scrollbar.themed) {
     scrollbar.theme = window.CreateThemeManager("scrollbar")
   } else {
     scrollbar.theme = false
   };
   init_vscrollbar_buttons();
   button_up.x = ww - button_up.w;
   button_up.y = 0;
   button_down.x = ww - button_down.w;
   button_down.y = wh - button_down.h;
   vscrollbar.y = button_up.h;
   vscrollbar.h = wh - button_up.h - button_down.h;
   cursor.x = ww - vscrollbar.w;
   cursor.y = vscrollbar.y;
   cursor.w = vscrollbar.w
  } else {
   if (scrollbar.show) {
     cover.pad_bot_mid = cover.default_pad_bot_mid
   } else {
     cover.pad_bot_mid = cover.default_pad_bot_mid - hscrollbar.default_h
   }
   if (panel.show_text) {
     cover.pad_top_mid = cover.default_pad_top_mid
   } else {
     cover.pad_top_mid = cover.default_pad_top_mid - 16
   };
   cover.w = wh - cover.pad_top_mid - cover.pad_bot_mid;
   cover.h = cover.w;
   list.nbvis = Math.floor(ww / (cover.w - cover.normal_delta * 2)) + 2 + 10;
   if (list.nbvis / 2 == Math.floor(list.nbvis / 2)) {
     list.nbvis--
   }
   list.mid = Math.floor(list.nbvis / 2);
   list.nb_cover_to_draw = Math.floor(ww / (cover.w - cover.normal_delta * 2)) + 2;
   if (scrollbar.themed) {
     scrollbar.theme = window.CreateThemeManager("scrollbar")
   } else {
     scrollbar.theme = false
   };
   init_hscrollbar_buttons();
   button_up.x = 0;
   button_up.y = wh - hscrollbar.h;
   button_down.x = ww - button_down.w;
   button_down.y = wh - hscrollbar.h;
   hscrollbar.x = button_up.w;
   hscrollbar.w = ww - button_up.w - button_down.w;
   cursor.y = wh - hscrollbar.h;
   cursor.x = hscrollbar.x;
   cursor.h = hscrollbar.h
  };
  redraw_stub_images();
  if (list.first_launch) {
   list.first_launch = false;
   on_playlist_switch()
  } else {
   g_image_cache = new image_cache;
   CollectGarbage();
   refresh_spv(panel.active_playlist, true)
  }
};

function on_paint(a) {
  a.FillSolidRect(0, 0, ww, wh, g_backcolor);
  if (list.item.length > 0) {
   var b, mid2;
   list.item[list.mid].draw(a, list.item[list.mid].id, list.mid, 0, true);
   for (var c = 1; c < list.mid + 1; c++) {
     if (c > 1 && c <= list.mid) {
       b = true
     } else {
       b = false
     };
     mid2 = list.mid - c;
     if (mid2 >= 0 && mid2 <= list.item.length - 1) {
       list.item[mid2].draw(a, list.item[mid2].id, mid2, c, b)
     }
     mid2 = list.mid + c;
     if (mid2 >= 0 && mid2 <= list.item.length - 1) {
       list.item[mid2].draw(a, list.item[mid2].id, mid2, c * -1, b)
     }
   };
   mid2 = list.mid - 1;
   if (mid2 >= 0 && mid2 <= list.item.length - 1) {
     list.item[mid2].draw(a, list.item[mid2].id, mid2, 1, true)
   }
   mid2 = list.mid + 1;
   if (mid2 >= 0 && mid2 <= list.item.length - 1) {
     list.item[mid2].draw(a, list.item[mid2].id, mid2, -1, true)
   }
   list.item[list.mid].draw(a, list.item[list.mid].id, list.mid, 0, true);
   if (!panel.vertical_mode) {
     if (panel.show_text) {
       var d = 32;
       var f = ww - 64;
       if (list.item[list.mid].id >= 0) {
         a.GdiDrawText(list.item[list.mid].group_info, g_font, g_textcolor, d, 0, f, cover.pad_top_mid - 4, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX)
       }
     }
   }
  } else {
   if (fb.PlaylistCount > 0) {
     var g = fb.GetPlaylistName(fb.ActivePlaylist);
     var h = "This playlist is empty"
   } else {
     var g = "Br3tt's WSH CoverFlow";
     var h = "Create a playlist to start!"
   };
   a.SetTextRenderingHint(5);
   a.DrawString(g, gdi.Font("Tahoma", 17, 0), g_textcolor, 0, -20, ww, wh, cc_stringformat);
   a.DrawString(h, gdi.Font("Tahoma", 13, 0), g_textcolor, 0, 20, ww, wh, cc_stringformat);
   a.FillGradRect(40, Math.floor(wh / 2), ww - 80, 1, 0, 0, g_textcolor, 0.5);
   a.FillSolidRect(0, 0, ww, wh, g_backcolor & 0xbbffffff)
  };
  if (list.total_gh > 0 && scrollbar.visible && scrollbar.show) {
   if (panel.vertical_mode) {
     try {
       scrollbar.theme.SetPartAndStateId(6, 1);
       scrollbar.theme.DrawThemeBackground(a, ww - vscrollbar.w, 0, vscrollbar.w, wh)
     } catch (e) {
       a.FillSolidRect(ww - vscrollbar.w, 0, vscrollbar.w, wh, g_backcolor & 0x77ffffff);
       a.FillSolidRect(ww - vscrollbar.w, 0, 1, wh, RGBA(0, 0, 0, 20))
     };
     cursor.bt.draw(a, ww - vscrollbar.w, cursor.y, 255);
     try {
       scrollbar.theme.SetPartAndStateId(9, 1);
       scrollbar.theme.DrawThemeBackground(a, ww - vscrollbar.w, cursor.y, cursor.w, cursor.h)
     } catch (e) {};
     for (i = 0; i < scrollbar.arr_buttons.length; i++) {
       switch (i) {
       case 0:
         scrollbar.arr_buttons.draw(a, ww - vscrollbar.w, button_up.y, 255);
         break;
       case 1:
         scrollbar.arr_buttons.draw(a, ww - vscrollbar.w, button_down.y, 255);
         break
       }
     };
     if (cursor.drag) {
       scrollbar.letter = list.item[Math.floor(list.nbvis / 2)].albumartist.substring(0, 1).toUpperCase();
       cursor.popup && a.DrawImage(cursor.popup, ww - vscrollbar.w - cursor.popup.Width - 00, cursor.y + Math.floor(cursor.h / 2) - Math.floor(cursor.popup.Height / 2), cursor.popup.Width, cursor.popup.Height, 0, 0, cursor.popup.Width, cursor.popup.Height, 0, 155);
       cursor.popup && a.GdiDrawText(scrollbar.letter, gdi.Font("segoe ui", 14, 0), g_backcolor, ww - vscrollbar.w - cursor.popup.Width - 00, cursor.y + Math.floor(cursor.h / 2) - Math.floor(cursor.popup.Height / 2), cursor.popup.Width - 5, cursor.popup.Height, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX)
     }
   } else {
     try {
       scrollbar.theme.SetPartAndStateId(4, 1);
       scrollbar.theme.DrawThemeBackground(a, 0, wh - hscrollbar.h, ww, hscrollbar.h);
       a.FillSolidRect(0, wh - hscrollbar.h - 1, ww, 1, RGBA(0, 0, 0, 10))
     } catch (e) {
       a.FillSolidRect(0, wh - hscrollbar.h, ww, hscrollbar.h, g_backcolor & 0x77ffffff);
       a.FillSolidRect(0, wh - hscrollbar.h, ww, 1, RGBA(0, 0, 0, 20))
     };
     try {
       cursor.bt.draw(a, cursor.x, cursor.y, 255)
     } catch (e) {};
     try {
       scrollbar.theme.SetPartAndStateId(8, 1);
       scrollbar.theme.DrawThemeBackground(a, cursor.x, wh - hscrollbar.h + 0, cursor.w, cursor.h)
     } catch (e) {};
     for (i = 0; i < scrollbar.arr_buttons.length; i++) {
       switch (i) {
       case 0:
         scrollbar.arr_buttons.draw(a, button_up.x, button_up.y, 255);
         break;
       case 1:
         scrollbar.arr_buttons.draw(a, button_down.x, button_down.y, 255);
         break
       }
     };
     if (cursor.drag) {
       scrollbar.letter = list.item[Math.floor(list.nbvis / 2)].albumartist.substring(0, 1).toUpperCase();
       cursor.popup && a.DrawImage(cursor.popup, cursor.x + Math.floor(cursor.w / 2) - Math.floor(cursor.popup.Width / 2), wh - hscrollbar.h - cursor.popup.Height, cursor.popup.Width, cursor.popup.Height, 0, 0, cursor.popup.Width, cursor.popup.Height, 0, 155);
       cursor.popup && a.GdiDrawText(scrollbar.letter, gdi.Font("segoe ui", 14, 0), g_backcolor, cursor.x + Math.floor(cursor.w / 2) - Math.floor(cursor.popup.Width / 2), wh - hscrollbar.h - cursor.popup.Height, cursor.popup.Width, cursor.popup.Height - 5, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX)
     }
   }
  };
  for (i = 0; i < panel.arr_buttons.length; i++) {
   switch (i) {
   case 0:
     if (!panel.lock_playlist) {
       panel.arr_buttons.draw(a, 4, 4, (list.total_gh > 0) ? 255 : 80)
     };
     break;
   case 1:
     if (panel.vertical_mode) {
       panel.arr_buttons.draw(a, 4, wh - 22 - 4, (list.total_gh > 0) ? 255 : 80)
     } else {
       panel.arr_buttons.draw(a, ww - 22 - 4, 4, (list.total_gh > 0) ? 255 : 80)
     };
     break;
   case 2:
     if (panel.lock_playlist) {
       if (panel.vertical_mode) {
         panel.arr_buttons.draw(a, 4, 4, 255)
       } else {
         panel.arr_buttons.draw(a, 4, 4, 255)
       }
     };
     break
   }
  };
  if (!panel.vertical_mode) {
   a.FillGradRect(0, 0, ww, 1, 0, 0, g_textcolor & 0x15ffffff, 0.5)
  };
  if (g_search_string.length > 0) {
   a.SetSmoothingMode(2);
   var j = Math.floor((ww / 2) - ((g_search_string.length * 13) + (10 * 2)) / 2);
   var k = Math.floor(wh / 2) - 30;
   var l = ((g_search_string.length * 13) + (10 * 2));
   var m = 60;
   a.FillRoundRect(j, k, l, m, 5, 5, RGBA(0, 0, 0, 150));
   a.DrawRoundRect(j, k, l, m, 5, 5, 2.0, RGBA(255, 255, 255, 200));
   a.DrawRoundRect(j + 2, k + 2, l - 4, m - 4, 3, 3, 1.0, RGBA(0, 0, 0, 150));
   a.GdiDrawText(g_search_string, incsearch_font_big, RGB(0, 0, 0), j + 1, k + 1, l, m, DT_CENTER | DT_NOPREFIX | DT_CALCRECT | DT_VCENTER);
   a.GdiDrawText(g_search_string, incsearch_font_big, list.inc_search_noresult ? RGB(255, 75, 75) : RGB(250, 250, 250), j, k, l, m, DT_CENTER | DT_NOPREFIX | DT_CALCRECT | DT_VCENTER)
  }
};

function on_mouse_lbtn_down(x, y) {
  bool_on_size = false;
  var a = list.item.length;
  var b = 0;
  if (!list.item[list.mid].checkstate("down", x, y, list.mid)) {
   for (var i = 1; i < list.mid + 1; i++) {
     b = list.mid - i;
     if (b >= 0 && b <= a - 1) {
       if (list.item.checkstate("down", x, y, b)) {
         break
       }
     };
     b = list.mid + i;
     if (b >= 0 && b <= a - 1) {
       if (list.item.checkstate("down", x, y, b)) {
         break
       }
     }
   }
  };
  if (list.total_gh > 0 && scrollbar.visible && scrollbar.show) {
   if (panel.vertical_mode) {
     if (cursor.bt.checkstate("down", x, y) == ButtonStates.down) {
       cursor.drag = true;
       cursor.grap_y = y - cursor.y;
       cursor.last_y = cursor.y
     };
     if (vscrollbar.hover && !cursor.drag) {
       scrollbar.step = Math.floor(list.nb_cover_to_draw / 2);
       if (scrollbar.step < 1) scrollbar.step = 1;
       if (y < cursor.y) {
         if (!list.buttonclicked) {
           list.buttonclicked = true;
           on_mouse_wheel(scrollbar.step);
           scrollbarbt.timerID1 = window.SetTimeout(function () {
             on_mouse_wheel(scrollbar.step);
             scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
             scrollbarbt.timerID1 = false;
             scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
             scrollbarbt.timerID2 = window.SetInterval(function () {
               if (hscrollbar.hover) {
                 if (mouse_x > ww - vscrollbar.w && cursor.y > mouse_y) {
                   on_mouse_wheel(scrollbar.step)
                 }
               }
             }, scrollbarbt.timer2_value)
           }, scrollbarbt.timer1_value)
         }
       } else {
         if (!list.buttonclicked) {
           list.buttonclicked = true;
           on_mouse_wheel(-1 * scrollbar.step);
           scrollbarbt.timerID1 = window.SetTimeout(function () {
             on_mouse_wheel(-1 * scrollbar.step);
             scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
             scrollbarbt.timerID1 = false;
             scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
             scrollbarbt.timerID2 = window.SetInterval(function () {
               if (hscrollbar.hover) {
                 if (mouse_x > ww - vscrollbar.w && cursor.y + cursor.h < mouse_y) {
                   on_mouse_wheel(-1 * scrollbar.step)
                 }
               }
             }, scrollbarbt.timer2_value)
           }, scrollbarbt.timer1_value)
         }
       }
     }
   } else {
     if (cursor.bt.checkstate("down", x, y) == ButtonStates.down) {
       cursor.drag = true;
       cursor.grap_x = x - cursor.x;
       cursor.last_x = cursor.x
     };
     if (hscrollbar.hover && !cursor.drag) {
       scrollbar.step = Math.floor(list.nb_cover_to_draw / 2);
       if (scrollbar.step < 1) scrollbar.step = 1;
       if (x < cursor.x) {
         if (!list.buttonclicked) {
           list.buttonclicked = true;
           on_mouse_wheel(scrollbar.step);
           scrollbarbt.timerID1 = window.SetTimeout(function () {
             on_mouse_wheel(scrollbar.step);
             scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
             scrollbarbt.timerID1 = false;
             scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
             scrollbarbt.timerID2 = window.SetInterval(function () {
               if (hscrollbar.hover) {
                 if (mouse_y > wh - hscrollbar.h && cursor.x > mouse_x) {
                   on_mouse_wheel(scrollbar.step)
                 }
               }
             }, scrollbarbt.timer2_value)
           }, scrollbarbt.timer1_value)
         }
       } else {
         if (!list.buttonclicked) {
           list.buttonclicked = true;
           on_mouse_wheel(-1 * scrollbar.step);
           scrollbarbt.timerID1 = window.SetTimeout(function () {
             on_mouse_wheel(-1 * scrollbar.step);
             scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
             scrollbarbt.timerID1 = false;
             scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
             scrollbarbt.timerID2 = window.SetInterval(function () {
               if (hscrollbar.hover) {
                 if (mouse_y > wh - hscrollbar.h && cursor.x + cursor.w < mouse_x) {
                   on_mouse_wheel(-1 * scrollbar.step)
                 }
               }
             }, scrollbarbt.timer2_value)
           }, scrollbarbt.timer1_value)
         }
       }
     }
   };
   for (i = 0; i < scrollbar.arr_buttons.length; i++) {
     switch (i) {
     case 0:
       if (scrollbar.arr_buttons.checkstate("down", x, y) == ButtonStates.down) {
         if (!list.buttonclicked) {
           list.buttonclicked = true;
           on_mouse_wheel(1);
           scrollbarbt.timerID1 = window.SetTimeout(function () {
             reset_cover_timers();
             scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
             scrollbarbt.timerID1 = false;
             scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
             scrollbarbt.timerID2 = window.SetInterval(function () {
               on_mouse_wheel(1)
             }, scrollbarbt.timer2_value)
           }, scrollbarbt.timer1_value)
         }
       };
       break;
     case 1:
       if (scrollbar.arr_buttons.checkstate("down", x, y) == ButtonStates.down) {
         if (!list.buttonclicked) {
           list.buttonclicked = true;
           on_mouse_wheel(-1);
           scrollbarbt.timerID1 = window.SetTimeout(function () {
             reset_cover_timers();
             scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
             scrollbarbt.timerID1 = false;
             scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
             scrollbarbt.timerID2 = window.SetInterval(function () {
               on_mouse_wheel(-1)
             }, scrollbarbt.timer2_value)
           }, scrollbarbt.timer1_value)
         }
       };
       break
     }
   }
  };
  if (list.total_gh > 0) {
   for (var i = 0; i < panel.arr_buttons.length; i++) {
     switch (i) {
     case 0:
       if (!panel.lock_playlist) {
         panel.arr_buttons.checkstate("down", x, y)
       };
       break;
     default:
       panel.arr_buttons.checkstate("down", x, y)
     }
   }
  }
};

function on_mouse_lbtn_dblclk(x, y, a) {
  if (panel.vertical_mode) {
   if (x < cover.pad_left_mid) {} else if (x < ww - cover.pad_right_mid) {
     var b = list.item.length;
     for (var i = 0; i < b; i++) {
       list.item.checkstate("dblclk", x, y, i)
     }
   } else {
     on_mouse_lbtn_down(x, y)
   }
  } else {
   if (y < cover.pad_top_mid) {} else if (y < wh - cover.pad_bot_mid) {
     var b = list.item.length;
     for (var i = 0; i < b; i++) {
       list.item.checkstate("dblclk", x, y, i)
     }
   } else {
     on_mouse_lbtn_down(x, y)
   }
  }
};

function on_mouse_lbtn_up(x, y) {
  list.buttonclicked = false;
  scrollbar.timerID && window.ClearTimeout(scrollbar.timerID);
  scrollbar.timerID = false;
  scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
  scrollbarbt.timerID1 = false;
  scrollbarbt.timerID2 && window.ClearTimeout(scrollbarbt.timerID2);
  scrollbarbt.timerID2 = false;
  if (list.drag_timer) {
   window.ClearTimeout(list.drag_timer);
   list.drag_timer = false;
   list.drag_stop = true
  }
  if (list.total_gh > 0) {
   cursor.bt.checkstate("up", x, y);
   for (var i = 0; i < scrollbar.arr_buttons.length; i++) {
     scrollbar.arr_buttons.checkstate("up", x, y)
   };
   for (i = 0; i < panel.arr_buttons.length; i++) {
     switch (i) {
     case 0:
       if (!panel.lock_playlist) {
         if (panel.arr_buttons.checkstate("up", x, y) == ButtonStates.hover) {
           ShowNowPlaying()
         }
       };
       break;
     case 1:
       if (panel.arr_buttons.checkstate("up", x, y) == ButtonStates.hover) {
         settings_menu(x, y)
       };
       break;
     case 2:
       if (panel.lock_playlist) {
         if (panel.arr_buttons.checkstate("up", x, y) == ButtonStates.hover) {
           panel.lock_playlist = false;
           window.SetProperty("panel.lock.playlist.enabled", panel.lock_playlist);
           plman.ActivePlaylist = panel.active_playlist
         }
       };
       break
     }
   };
   if (cursor.drag) {
     window.RepaintRect(0, wh - hscrollbar.h, ww, hscrollbar.h);
     cursor.drag = false
   } else {
     var a = list.item.length;
     for (i = 0; i < a; i++) {
       list.item.checkstate("up", x, y, i)
     }
   };
   setcursorx();
   window.Repaint()
  }
};

function on_mouse_mbtn_down(x, y, a) {
  bool_on_size = false;
  var b = list.item.length;
  for (var i = 0; i < b; i++) {
   list.item.checkstate("mid", x, y, i)
  }
};

function on_mouse_rbtn_down(x, y) {
  bool_on_size = false;
  var a = list.item.length;
  var b = false;
  var c = list.mid;
  if (list.item[list.mid].checkstate("right", x, y, list.mid)) {
   b = true
  } else {
   for (var i = 1; i < list.mid + 1; i++) {
     c = list.mid - i;
     if (c >= 0 && c <= a - 1) {
       if (list.item[c].checkstate("right", x, y, c) == true) {
         b = true;
         break
       }
     };
     c = list.mid + i;
     if (c >= 0 && c <= a - 1) {
       if (list.item[c].checkstate("right", x, y, c) == true) {
         b = true;
         break
       }
     }
   }
  };
  if (b) {
   new_context_menu(x, y, list.item[c].id, list.item[c].idx)
  }
};

function on_mouse_rbtn_up(x, y) {
  if (!utils.IsKeyPressed(VK_SHIFT)) {
   return true
  }
};

function on_mouse_move(x, y) {
  if (x == mouse_x && y == mouse_y) return true;
  hand = false;
  if (cursor.drag) {
   list.drag_stop = false;
   if (list.drag_timer) {
     window.ClearTimeout(list.drag_timer);
     list.drag_timer = false
   }
   list.drag_timer = window.SetTimeout(function () {
     list.drag_stop = true;
     window.ClearTimeout(list.drag_timer);
     list.drag_timer = false;
     window.Repaint()
   }, 25)
  } else {
   list.drag_stop = true
  };
  if (list.total_gh > 0 && scrollbar.visible && scrollbar.show) {
   if (panel.vertical_mode) {
     vscrollbar.hover = (x >= ww - vscrollbar.w && x <= ww && y >= vscrollbar.y && y <= vscrollbar.y + vscrollbar.h);
     cursor.hover = (x >= cursor.x && x <= cursor.x + cursor.w && y >= cursor.y && y <= cursor.y + cursor.h);
     cursor.bt.checkstate("move", x, y);
     for (var i = 0; i < scrollbar.arr_buttons.length; i++) {
       scrollbar.arr_buttons
  • Last Edit: 01 April, 2012, 01:43:03 PM by Falstaff

WSH Panel Mod script discussion/help
Reply #1415
The panel crashes when 1. playlist is empty and 2. the option button (upper right corner) is pressed.

Edit
The size of the ui-elemnt is locked when it reaches a certain size: i can't make it bigger. Therefore (when it is placed in a tabstack) all other tabs are limited to coverflow maximum size. Somehow annoying!
  • Last Edit: 01 April, 2012, 04:02:03 PM by q-stankovic
german support forum: www.foobar-users.de / user: qwert73

  • Falstaff
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #1416
The panel crashes when 1. playlist is empty and 2. the option button (upper right corner) is pressed.

Edit
The size of the ui-elemnt is locked when it reaches a certain size: i can't make it bigger. Therefore (when it is placed in a tabstack) all other tabs are limited to coverflow maximum size. Somehow annoying!


it seems the paste in this forum has added unwanted characters, that's weird, so, download this script from here: http://fav.me/d4t4lh7

e.g: "if ( c ) {" is translated "if © {", that make the script crashing of course.

all is fine there.

yep, i've limited size to 300 pixel height.
  • Last Edit: 01 April, 2012, 04:28:41 PM by Falstaff

  • Falstaff
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #1417
The panel crashes when 1. playlist is empty and 2. the option button (upper right corner) is pressed.

Edit
The size of the ui-elemnt is locked when it reaches a certain size: i can't make it bigger. Therefore (when it is placed in a tabstack) all other tabs are limited to coverflow maximum size. Somehow annoying!


it seems the paste in this forum has added unwanted characters, that's weird, so, download this script from here: http://fav.me/d4t4lh7

e.g: "if ( c ) {" is translated "if © {", that make the script crashing of course.

all is fine there.

yep, i've limited size to 300 pixel height.


WSH Panel Mod script discussion/help
Reply #1418
I downloaded it from your link and did it once again, but still crashes!

edit
Any chance to make the panel sizeable again but without making the thumbnails larger than necessary, means: than in 300 pixel panel? I have no space to place it outside a tabstack.
  • Last Edit: 01 April, 2012, 04:36:10 PM by q-stankovic
german support forum: www.foobar-users.de / user: qwert73

  • WilB
  • [*][*][*][*]
WSH Panel Mod script discussion/help
Reply #1419
I seem to get a lot of crashes on line 378 (vertical mode) and line 380 (horizontal mode) in CUI when switching between layouts with and without the panel. But I haven't encountered them yet in DUI when switching between tabs. Otherwise it's excellent work & fast too.

Code: [Select]
Error: WSH Panel Mod (CoverFlow View v1 beta7 v0.0.7.20120401.1646 by Br3tt): Microsoft JScript runtime error:
Overflow
File: <main>
Ln: 378, Col: 13
<source text only available at compile time>

Error: WSH Panel Mod (CoverFlow View v1 beta7 v0.0.7.20120401.1646 by Br3tt): Microsoft JScript runtime error:
Overflow
File: <main>
Ln: 380, Col: 13
<source text only available at compile time>

***EDIT***
Also it doesn't always identify the correct now playing cover, especially if minimise foobar2000, use another program and then return to foobar2000 after a track change. It sometimes gets stuck on the previous track's cover. Even pressing the music note button causes it to highlight the wrong cover.  Again CUI & seen in horizontal mode.
  • Last Edit: 01 April, 2012, 05:34:54 PM by WilB

WSH Panel Mod script discussion/help
Reply #1420
Ah, sorry: forgot the console output

Code: [Select]
Error: WSH Panel Mod (CoverFlow View v1 beta7 v0.0.7.20120401.1646 by Br3tt): Laufzeitfehler in Microsoft JScript:
'list.item[...]' ist Null oder kein Objekt
File: <main>
Ln: 1329, Col: 3
<source text only available at compile time>
german support forum: www.foobar-users.de / user: qwert73

  • Falstaff
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #1421
thanx for feedback, i've mainly tested it on DUI, i'll check your reports to see what's the issue.

EDIT: with the paste problem on this topic, i'd be sure every use the same script, so, please, thanx to test it again from here this time (i've made a little fix about the lines pointed by WilB):

http://pastebin.com/X8xdSZkA

btw, i can't reproduce any crash on DUI or CUI from my side.

thanx by advance.

Any chance to make the panel sizeable again but without making the thumbnails larger than necessary, means: than in 300 pixel panel? I have no space to place it outside a tabstack.

i will remove this limitation, asap all your issues will be fixed
  • Last Edit: 01 April, 2012, 05:32:09 PM by Falstaff

  • WilB
  • [*][*][*][*]
WSH Panel Mod script discussion/help
Reply #1422
Thanks for your fast response. Unfortunately, the crashes are still occurring (e.g. line 380 when in vertical mode). I also spotted another issue added as an edit to my previous post.
  • Last Edit: 01 April, 2012, 05:46:18 PM by WilB

  • Falstaff
  • [*][*][*][*][*]
WSH Panel Mod script discussion/help
Reply #1423
Thanks for your fast response. Unfortunately, the crashes are still occurring (e.g. line 380 when in vertical mode). I also spotted another issue added as an edit to my previous post.


before getting further, i'd like to know if you test my panel in a config that conatins other WSH panels? i ask that because if timers are badly handled in them, it can (often) affect other WSH panels as the CoverFlow panel that use timers too.

could you tell me what's your situation please?

btw, replacing line 380 by these 3 lines:
Code: [Select]
                        try {
                            window.RepaintRect(cover.pad_left_mid, list.item[i].y - 2, ww - cover.pad_left_mid, list.item[i].h + 4);
                        } catch(e) {};

and line 384 by these 3 lines:
Code: [Select]
                        try {
                            window.RepaintRect(list.item[i].x - 2, cover.pad_top_mid, list.item[i].w + 4, wh - cover.pad_top_mid);
                        } catch (e) {};


should avoid crash for you... at least at these lines

EDIT: any other feedback from new user would be really appreciated, especially when it works fine too. So thanx by advance.
  • Last Edit: 01 April, 2012, 06:06:38 PM by Falstaff

WSH Panel Mod script discussion/help
Reply #1424
here the console output with the script from pastebin:

Error: WSH Panel Mod (CoverFlow View v1 beta7.1 v0.0.7.20120401.2320 by Br3tt): Laufzeitfehler in Microsoft JScript:
'list.item[...]' ist Null oder kein Objekt
File: <main>
Ln: 1333, Col: 2
<source text only available at compile time>
german support forum: www.foobar-users.de / user: qwert73