Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: WSH Panel Mod script discussion/help (Read 1377042 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

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.


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%,)*.*\*.*  ..........)

 

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

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

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.

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?

WSH Panel Mod script discussion/help

Reply #1408
only horizontal for now. maybe a vertical one later, i can't say when.

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

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?

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.

WSH Panel Mod script discussion/help

Reply #1412
That was simple. Thanks.

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)
      }

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

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!

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.

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.

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.

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>

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

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.

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.

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>