diff --git a/js/georgia-main.js b/js/georgia-main.js
index f268c301..32853bc0 100644
--- a/js/georgia-main.js
+++ b/js/georgia-main.js
@@ -1,1120 +1,1120 @@
-///
-
-//
-// Georgia
-//
-// Description a fullscreen now-playing script for foo_jscript_panel
-// Author Mordred
-// Version 0.9.0
-// Dev. Started 2017-12-22
-// Last change 2018-04-18
-// --------------------------------------------------------------------------------------
-
-// CONFIGURATION //////////////////////////////////////
-
-var themeBaseName = "Georgia"; // this is the base name of the theme, and will be used for finding some of the theme's files in the configuration folder.
-
-var ft = {}; // fonts
-var col = {}; // colors
-var geo = {}; // sizes
-
-var is_4k = false;
-
-// FONTS
-testFont('HelveticaNeueLT Std');
-testFont('HelveticaNeueLT Std Thin');
-testFont('HelveticaNeueLT Std Med');
-testFont('HelveticaNeueLT Std Lt');
-testFont('Guifx v2 Transports');
-
-var useNeue = false;
-var fontsCreated = null;
-
-function createFonts() {
- var font_size = is_4k.toString();
- if (fontsCreated && fontsCreated == font_size) {
- return; // don't redo fonts
- }
-
- function font(name, size, style) {
- var font;
- try {
- font = gdi.Font(name, font_size === 'true' ? Math.min(size * 2) : size, style);
- } catch (e) {
- console.log('Failed to load font >>>', name, size, style);
- }
- return font;
- }
- ft.album_lrg = font('HelveticaNeueLT Std Med', 36, 0);
- ft.album_med = font('HelveticaNeueLT Std Med', 32, 0);
- ft.album_sml = font('HelveticaNeueLT Std Med', 28, 0);
- ft.album_substitle_lrg = font('HelveticaNeueLT Std Med', 36, g_font_style.italic);
- ft.album_substitle_med = font('HelveticaNeueLT Std Med', 32, g_font_style.italic);
- ft.album_substitle_sml = font('HelveticaNeueLT Std Med', 28, g_font_style.italic);
- ft.title_lrg = font('HelveticaNeueLT Std Thin', 34, 0);
- ft.title_med = font('HelveticaNeueLT Std Thin', 30, 0);
- ft.title_sml = font('HelveticaNeueLT Std Thin', 26, 0);
- ft.tracknum_lrg = font('HelveticaNeueLT Std Lt', 34, g_font_style.bold);
- ft.tracknum_med = font('HelveticaNeueLT Std Lt', 30, g_font_style.bold);
- ft.tracknum_sml = font('HelveticaNeueLT Std Lt', 26, g_font_style.bold);
- ft.year = font('HelveticaNeueLT Std', 48, g_font_style.bold);
+///
+
+//
+// Georgia
+//
+// Description a fullscreen now-playing script for foo_jscript_panel
+// Author Mordred
+// Version 1.0.1
+// Dev. Started 2017-12-22
+// Last change 2019-01-23
+// --------------------------------------------------------------------------------------
+
+// CONFIGURATION //////////////////////////////////////
+
+var themeBaseName = "Georgia"; // this is the base name of the theme, and will be used for finding some of the theme's files in the configuration folder.
+
+var ft = {}; // fonts
+var col = {}; // colors
+var geo = {}; // sizes
+
+var is_4k = false;
+
+// FONTS
+testFont('HelveticaNeueLT Std');
+testFont('HelveticaNeueLT Std Thin');
+testFont('HelveticaNeueLT Std Med');
+testFont('HelveticaNeueLT Std Lt');
+testFont('Guifx v2 Transports');
+
+var useNeue = false;
+var fontsCreated = null;
+
+function createFonts() {
+ var font_size = is_4k.toString();
+ if (fontsCreated && fontsCreated == font_size) {
+ return; // don't redo fonts
+ }
+
+ function font(name, size, style) {
+ var font;
+ try {
+ font = gdi.Font(name, font_size === 'true' ? Math.min(size * 2) : size, style);
+ } catch (e) {
+ console.log('Failed to load font >>>', name, size, style);
+ }
+ return font;
+ }
+ ft.album_lrg = font('HelveticaNeueLT Std Med', 36, 0);
+ ft.album_med = font('HelveticaNeueLT Std Med', 32, 0);
+ ft.album_sml = font('HelveticaNeueLT Std Med', 28, 0);
+ ft.album_substitle_lrg = font('HelveticaNeueLT Std Med', 36, g_font_style.italic);
+ ft.album_substitle_med = font('HelveticaNeueLT Std Med', 32, g_font_style.italic);
+ ft.album_substitle_sml = font('HelveticaNeueLT Std Med', 28, g_font_style.italic);
+ ft.title_lrg = font('HelveticaNeueLT Std Thin', 34, 0);
+ ft.title_med = font('HelveticaNeueLT Std Thin', 30, 0);
+ ft.title_sml = font('HelveticaNeueLT Std Thin', 26, 0);
+ ft.tracknum_lrg = font('HelveticaNeueLT Std Lt', 34, g_font_style.bold);
+ ft.tracknum_med = font('HelveticaNeueLT Std Lt', 30, g_font_style.bold);
+ ft.tracknum_sml = font('HelveticaNeueLT Std Lt', 26, g_font_style.bold);
+ ft.year = font('HelveticaNeueLT Std', 48, g_font_style.bold);
ft.artist_lrg = font('HelveticaNeueLT Std Med', 40, 0);
ft.artist_med = font('HelveticaNeueLT Std Med', 36, 0);
ft.artist_sml = font('HelveticaNeueLT Std Med', 30, 0);
- ft.track_info = font('HelveticaNeueLT Std Thin', 18, 0);
- ft.grd_key_lrg = font('HelveticaNeueLT Std', 24, 0); // used instead of ft.grd_key if ww > 1280
- ft.grd_val_lrg = font('HelveticaNeueLT Std Lt', 24, 0); // used instead of ft.grd_val if ww > 1280
- ft.grd_key_med = font('HelveticaNeueLT Std', 20, 0);
- ft.grd_val_med = font('HelveticaNeueLT Std Lt', 20, 0);
- ft.grd_key_sml = font('HelveticaNeueLT Std', 18, 0);
- ft.grd_val_sml = font('HelveticaNeueLT Std Lt', 18, 0);
- ft.lower_bar = font('HelveticaNeueLT Std Lt', 30, 0);
- ft.lower_bar_bold = font('HelveticaNeueLT Std Med', 30, 0);
- ft.lower_bar_sml = font('HelveticaNeueLT Std Lt', 26, 0);
- ft.lower_bar_sml_bold = font('HelveticaNeueLT Std Med', 26, 0);
- if (utils.checkFont('NeueHaasGroteskDisp Pro XLt')) {
- useNeue = true;
- ft.lower_bar_artist = font('NeueHaasGroteskDisp Pro XLt', 31, g_font_style.italic);
- ft.lower_bar_artist_sml = font('NeueHaasGroteskDisp Pro XLt', 27, g_font_style.italic);
- } else {
- ft.lower_bar_artist = font('HelveticaNeueLT Std Thin', 31, g_font_style.italic);
- ft.lower_bar_artist_sml = font('HelveticaNeueLT Std Thin', 27, g_font_style.italic);
- }
- ft.small_font = font('HelveticaNeueLT Std', 14, 0);
- ft.guifx = font('Guifx v2 Transports', 16, 0);
- ft.Marlett = font('Marlett', 13, 0);
- ft.SegoeUi = font('Segoe Ui Semibold', 12, 0);
- ft.library_tree = font('Segoe UI', libraryProps.baseFontSize, 0);
- ft.lyrics = font('HelveticaNeueLT Std', pref.lyrics_font_size || 20, 1);
-}
-
-
-// COLORS
-col.progres_bar_text = RGB(0, 0, 0);
-col.artist = RGB(255, 255, 255);
-col.info_text = RGB(255, 255, 255);
-col.now_playing = RGB(0, 0, 0); // tracknumber, title, and time
-
-col.bg = RGB(205, 205, 205);
-col.menu_bg = RGB(58, 58, 58);
-col.rating = RGB(255, 170, 032);
-col.mood = RGB(000, 128, 255);
-col.hotness = RGB(192, 192, 000);
-
-col.playcount = RGB(000, 153, 153);
-col.dark_grey = RGB(128, 128, 128);
-col.progress_fill = RGB(235, 59, 70);
-col.progress_bar = RGB(125, 125, 125);
-
-col.tl_added = RGB(15, 51, 65);
-col.tl_played = RGB(44, 66, 75);
-col.tl_unplayed = RGB(126, 173, 195);
-col.tl_play = RGB(255, 255, 255); // each individual play
-
-// ALBUM ART DISPLAY PROPERTIES
-col.aa_border = RGBA(060, 060, 060, 128);
-col.aa_shadow = RGBA(000, 000, 000, 64);
-
-function setGeometry() {
- geo.aa_shadow = is_4k ? 16 : 8; // size of albumart shadow
- geo.pause_size = is_4k ? 300 : 150;
- geo.prog_bar_h = is_4k ? 24 : (ww > 1920 ? 14 : 12); // height of progress bar
- geo.lower_bar_h = is_4k ? 160 : 80; // height of song title and time + progress bar area
- geo.top_art_spacing = is_4k ? 192 : 96; // space between top of theme and artwork
- geo.top_bg_h = is_4k ? 320 : 160; // height of offset color background
- geo.timeline_h = is_4k ? 36 : 18; // height of timeline
- if (!pref.show_progress_bar) {
- geo.lower_bar_h -= geo.prog_bar_h * 2;
- }
-
- if (is_4k) {
- settingsImg = gdi.Image(pref.setting_4k_img); // settings image
- propertiesImg = gdi.Image(pref.prop_4k_img); // properties image
- ratingsImg = gdi.Image(pref.rating_4k_img); // rating image
- playlistImg = gdi.Image(pref.list_4k_img); // playlist image
- libraryImg = gdi.Image(pref.library_4k_img); // library image
- lyricsImg = gdi.Image(pref.lyrics_4k_img); // lyrics image
- } else {
- settingsImg = gdi.Image(pref.settng_img); // settings image
- propertiesImg = gdi.Image(pref.prop_img); // properties image
- ratingsImg = gdi.Image(pref.rating_img); // rating image
- playlistImg = gdi.Image(pref.list_img); // playlist image
- libraryImg = gdi.Image(pref.library_img); // library image
- lyricsImg = gdi.Image(pref.lyrics_img); // lyrics image
- }
-}
-
-var playedTimesRatios = [];
-var lfmPlayedTimesRatios = []; // remove this
-
-// PATHS
-pref.bg_image = fb.ProfilePath + 'georgia/images/wallpaper-blueish.jpg';
-pref.settng_img = fb.ProfilePath + 'georgia/images/settings.png';
-pref.prop_img = fb.ProfilePath + 'georgia/images/properties.png';
-pref.list_img = fb.ProfilePath + 'georgia/images/playlist.png';
-pref.library_img = fb.ProfilePath + 'georgia/images/library.png';
-pref.lyrics_img = fb.ProfilePath + 'georgia/images/lyrics.png';
-pref.rating_img = fb.ProfilePath + 'georgia/images/star.png';
-
-pref.setting_4k_img = fb.ProfilePath + 'georgia/images/4k/settings.png';
-pref.prop_4k_img = fb.ProfilePath + 'georgia/images/4k/properties.png';
-pref.list_4k_img = fb.ProfilePath + 'georgia/images/4k/playlist.png';
-pref.library_4k_img = fb.ProfilePath + 'georgia/images/4k/library.png';
-pref.lyrics_4k_img = fb.ProfilePath + 'georgia/images/4k/lyrics.png';
-pref.rating_4k_img = fb.ProfilePath + 'georgia/images/4k/star.png';
-
-pref.divider_img = fb.ProfilePath + 'georgia/images/divider.png';
-pref.last_fm_img = fb.ProfilePath + 'georgia/images/last-fm-red-36.png';
-pref.last_fmw_img = fb.ProfilePath + 'georgia/images/last-fm-36.png';
-pref.label_base = fb.ProfilePath + 'images/recordlabel/'; // location of the record label logos for the bottom right corner
-pref.logo_hq = fb.ProfilePath + 'images/artistlogos/'; // location of High-Qualiy band logos for the bottom left corner
-pref.logo_color = fb.ProfilePath + 'images/artistlogos color/';
-pref.codec_base = fb.ProfilePath + 'images/codec logos/';
-pref.flags_base = fb.ProfilePath + 'images/flags/'; // location of artist country flags
-
-// MOUSE WHEEL SEEKING SPEED
-pref.mouse_wheel_seek_speed = 5; // seconds per wheel step
-
-// DEBUG
-// var pref.show_debug_log = window.GetProperty("Debug: Show Debug Output", false);
-var showDebugTiming = false; // spam console with debug timings
-var showDrawTiming = false; // spam console with draw times
-var showExtraDrawTiming = false; // spam console with every section of the draw code to determine bottlenecks
-var showLyricsTiming = true; // spam console with timing for lyrics loading
-
-// Lyrics Constants
-var DEFAULT_OFFSET = 29;
-var SCROLL_STEP = 1; // do not modify this value
-var PLAYTIMER_VALUE = 01; // do not modify this value
-
-
-// PLAYLIST JUNK
-var listLeft = 15;
-var listTop = 15;
-var listRight = 15;
-var listBottom = 15;
-var showNowPlayingCalled = false; //TODO: Remove?
-
-//--->
-var listLength = maxRows = listX = listY = listW = listH = 0;
-var listStep = [];
-var rowDrag = fileDrag = makeSelectionDrag = linkToLastItem = false;
-var nowPlayingGroupNr = -1;
-var focusGroupNr = -1;
-var keyPressed = false;
-var guiInstanceType = window.InstanceType;
-var tempFocusItemIndex;
-var btns = [];
-var hyperlinks = [];
-//--->
-AlbumArtId = {
- front: 0,
- back: 1,
- disc: 2,
- icon: 3,
- artist: 4
-};
-// =================================================== //
-//--->
-var thisPanelName = "Playlist"; //Don't change!! needed in Scrollbar.txt.
-//---> Fonts
-var playlistFontSize = window.GetProperty("Playlist: Font Size", 12);
-if (playlistFontSize < 7) {
- playlistFontSize = 7;
- window.SetProperty("Playlist: Font Size", playlistFontSize);
-}
-
-// END OF CONFIGURATION /////////////////////////////////
-
-
-
-// VARIABLES
-// Artwork
-var albumart = null; // albumart image
-var albumart_size = new ImageSize(0, 0, 0, 0); // position (big image)
-var cdart = null; // cdart image
-var cdart_size = new ImageSize(0, 0, 0, 0); // cdart position (offset from albumart_size)
-var image_bg = gdi.Image(pref.bg_image); // background image
-var albumart_scaled = null; // pre-scaled album art to speed up drawing considerably
-var recordLabels = []; // array of record label images
-var bandLogo = null; // band logo image
-var settingsImg = null; // settings image
-var propertiesImg = null; // properties image
-var ratingsImg = null; // rating image
-var playlistImg = null; // playlist image
-var libraryImg = null; // library image
-var lyricsImg = null; // lyrics image
-var dividerImg = gdi.Image(pref.divider_img); // end lyrics image
-var lastFmImg = gdi.Image(pref.last_fm_img); // Last.fm logo image
-var lastFmWhiteImg = gdi.Image(pref.last_fmw_img); // white Last.fm logo image
-var shadow_image = null; // shadow behind the artwork + discart
-var labelShadowImg = null; // shadow behind labels
-var playlist_shadow = null; // shadow behind the playlist
-var flagImgs = []; // array of flag images
-var rotatedCD = null; // drawing cdArt rotated is slow, so first draw it rotated into the rotatedCD image, and then draw rotatedCD image unrotated
-var disc_art_loading; // for on_load_image_done()
-var album_art_loading; // for on_load_image_done()
-var isStreaming = false; // is the song from a streaming source?
-var retrieveThemeColorsWhenLoaded = false; // only load theme colors on first image in aa_array
-var newTrackFetchingArtwork = false; // only load theme colors when newTrackFetchingArtwork = true
-var noArtwork = false; // only use default theme when noArtwork was found
-var themeColorSet = false; // when no artwork, don't set themeColor every redraw
-var playCountVerifiedByLastFm = false; // show Last.fm image when we %lastfm_play_count% > 0
-var art_off_center = false; // if true, album art has been shifted 40 pixels to the right
-var loadFromCache = true; // always load art from cache unless this is set
-
-//var inShowMenuEntry = false;
-
-var str = new Object();
-var state = new Object(); // panel state
-
-var metadb_handle = null; // watch db for tag changes
-// TIMERS
-var progressTimer; // 40ms repaint of progress bar
-var globTimer; // Timer for rotating globs
-var slideTimer; // Timer for CD Slide out
-var hideCursor; // Timer for hiding cursor
-
-// STATUS VARIABLES
-var ww = 0,
- wh = 0; // size of panel
-var progressLength = 0; // fixing jumpiness in progressBar
-var progressMoved = false; // playback position changed, so reset progressLength
-var last_pb; // saves last playback order
-var g_drag = 0; // status variable for clickable progress bar
-var just_dblclicked = false;
-var aa_list = new Array();
-var albumArtIndex = 0; // index of currently displayed album art if more than 1
-var fadeAlpha = 255; // full alpha which will be decremented
-var nextPrevAlpha = 255; // full alpha for next/prev icons which will be decremented
-var bandLogoHQ = false; // if true will partially remove the 10 pixel "gutter" around the image that fanart.tv requires around their high-rez images so that logos use more of the available space.
-var t_interval; // milliseconds between screen updates
-// var settingsY = 0; // location of settings button
-var lastLeftEdge = 0; // the left edge of the record labels. Saved so we don't have to recalculate every on every on_paint unless size has changed
-var displayPlaylist = pref.start_Playlist;
-var displayLibrary = false;
-var displayLyrics = false;
-var showLibraryButton = true; // TODO: Remove once library goes live
-
-var tl_firstPlayedRatio = 0;
-var tl_lastPlayedRatio = 0;
-
-var current_path;
-var last_path;
-var lastDiscNumber;
-var lastVinylSide;
-var currentLastPlayed = '';
-
-// Lyrics Variables
-var len_seconds = fb.Titleformat("%length_seconds%");
-var elap_seconds = fb.TitleFormat("%playback_time_seconds%");
-
-var g_playtimer = null;
-var g_timer_abs;
-
-// TODO change these variable names
-var g_tab = Array();
-var g_scroll = 0;
-var g_lyrics_path;
-var g_lyrics_filename;
-var g_lyrics_status;
-var focus = 0;
-var focus_next = 0;
-var hundredth = 0;
-var g_is_scrolling = false;
-var g_tab_length;
-
-var midpoint; // this is the center of the lyrics, where the highlighted line will display
-var lyrPos; // this is the absolute yPosition of the very first line in the lyrics. It will start at midpoint and then move up and off the screen
-var lyricsWidth = 0; // minimum width needed to display the lyrics to speed up drawing
-
-
-// MENU STUFF
-var pad_x = 4;
-var pad_y = 2;
-var mymenu = Array(7);
-var menu_img = new Array(7);
-var menu_down = false;
-var menu_padx = pad_x;
-var menu_pady = pad_y + 4;
-var menu_width = 250; // this will get sized based on the font later
-
-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);
-
-// Flags, used with GdiDrawText()
-// For more information, see: http://msdn.microsoft.com/en-us/library/dd162498(VS.85).aspx
-DT_TOP = 0x00000000;
-DT_LEFT = 0x00000000;
-DT_CENTER = 0x00000001;
-DT_RIGHT = 0x00000002;
-DT_VCENTER = 0x00000004;
-DT_BOTTOM = 0x00000008;
-DT_WORDBREAK = 0x00000010;
-DT_SINGLELINE = 0x00000020;
-DT_EXPANDTABS = 0x00000040;
-DT_TABSTOP = 0x00000080;
-DT_NOCLIP = 0x00000100;
-DT_EXTERNALLEADING = 0x00000200;
-DT_CALCRECT = 0x00000400; // [1.2.1] Handles well
-DT_NOPREFIX = 0x00000800; // NOTE: Please use this flag, or a '&' character will become an underline '_'
-DT_INTERNAL = 0x00001000;
-DT_EDITCONTROL = 0x00002000;
-DT_PATH_ELLIPSIS = 0x00004000;
-DT_END_ELLIPSIS = 0x00008000;
-DT_MODIFYSTRING = 0x00010000; // do not use
-DT_RTLREADING = 0x00020000;
-DT_WORD_ELLIPSIS = 0x00040000;
-DT_NOFULLWIDTHCHARBREAK = 0x00080000;
-DT_HIDEPREFIX = 0x00100000;
-DT_PREFIXONLY = 0x00200000;
-
-// File IO Modes
-var ForReading = 1;
-var ForWriting = 2;
-var ForAppending = 8;
-
-///////// OBJECTS
-
-var fso = new ActiveXObject("Scripting.FileSystemObject");
-
-var art_cache = new ArtCache(10);
-var cdartPath = '';
-var album_art_path = '';
-
-var pauseBtn = new PauseButton();
-
-var last_accent_col = undefined;
-var progressAlphaCol = undefined;
-
-// Call initialization function
-on_init();
-
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-function on_paint(gr) {
- if (showDrawTiming) drawStuff = fb.CreateProfiler("on_paint");
- gr.SetTextRenderingHint(TextRenderingHint.AntiAlias);
- gr.SetSmoothingMode(SmoothingMode.None);
-
- // Background
- if (!albumart && noArtwork) { // we use noArtwork to prevent flashing of blue default theme
- albumart_size.x = Math.floor(ww * 0.33); // if there's no album art info panel takes up 1/3 screen
- albumart_size.y = geo.top_art_spacing;
- albumart_size.h = wh - albumart_size.y - geo.lower_bar_h - 32;
- if (!themeColorSet) {
- setTheme(blueTheme.colors);
- themeColorSet = true;
- }
- }
- gr.FillSolidRect(0, geo.top_bg_h, ww, wh - geo.top_bg_h, col.bg);
- gr.FillSolidRect(0, 0, ww, geo.top_bg_h, col.menu_bg);
- if ((fb.IsPaused || fb.IsPlaying) && (!albumart && cdart)) {
- gr.SetSmoothingMode(SmoothingMode.None);
- gr.FillSolidRect(0, albumart_size.y, albumart_size.x, albumart_size.h, col.info_bg);
- gr.DrawRect(-1, albumart_size.y, albumart_size.x, albumart_size.h - 1, 1, col.accent);
- gr.SetSmoothingMode(SmoothingMode.AntiAlias);
- }
-
- gr.SetSmoothingMode(SmoothingMode.AntiAlias);
- gr.SetInterpolationMode(InterpolationMode.HighQualityBicubic);
-
- // BIG ALBUMART
- if (fb.IsPlaying) {
- if (albumart && albumart_scaled) {
- if (showExtraDrawTiming) drawArt = fb.CreateProfiler('on_paint -> artwork');
- if (!shadow_image) { // when switching views, the drop shadow won't get created initially which is very jarring when it suddenly appears later, so create it if we don't have it.
- createDropShadow();
- }
- shadow_image && gr.DrawImage(shadow_image, -geo.aa_shadow, albumart_size.y - geo.aa_shadow, shadow_image.Width, shadow_image.Height,
- 0, 0, shadow_image.Width, shadow_image.Height);
- // gr.DrawRect(-geo.aa_shadow, albumart_size.y - geo.aa_shadow, shadow_image.Width, shadow_image.Height, 1, RGBA(0,0,255,125)); // viewing border line
- if (cdart && !rotatedCD && !displayPlaylist && !displayLibrary && pref.display_cdart) {
- CreateRotatedCDImage();
- }
- if (!pref.cdart_ontop || displayLyrics) {
- if (rotatedCD && !displayPlaylist && !displayLibrary && pref.display_cdart) {
- if (showExtraDrawTiming) drawCD = fb.CreateProfiler('cdart');
- gr.DrawImage(rotatedCD, cdart_size.x, cdart_size.y, cdart_size.w, cdart_size.h, 0, 0, rotatedCD.width, rotatedCD.height, 0);
- if (showExtraDrawTiming) drawCD.Print();
- }
- gr.DrawImage(albumart_scaled, albumart_size.x, albumart_size.y, albumart_size.w, albumart_size.h, 0, 0, albumart_scaled.width, albumart_scaled.height);
- } else { // draw cdart on top of front cover
- gr.DrawImage(albumart_scaled, albumart_size.x, albumart_size.y, albumart_size.w, albumart_size.h, 0, 0, albumart_scaled.width, albumart_scaled.height);
- if (rotatedCD && !displayPlaylist && !displayLibrary && pref.display_cdart) {
- if (showExtraDrawTiming) drawCD = fb.CreateProfiler('cdart');
- gr.DrawImage(rotatedCD, cdart_size.x, cdart_size.y, cdart_size.w, cdart_size.h, 0, 0, rotatedCD.width, rotatedCD.height, 0);
- if (showExtraDrawTiming) drawCD.Print();
- }
- }
- if (displayLyrics && albumart_scaled && fb.IsPlaying) {
- gr.FillSolidRect(albumart_size.x - 1, albumart_size.y - 1, albumart_size.w + 1, albumart_size.h + 1, RGBA(0, 0, 0, 155));
- show_lyrics(gr, g_tab, Math.floor(lyrPos - pref.lyrics_h_padding));
- }
- if (showExtraDrawTiming) drawArt.Print();
- } else {
- if (cdart && !rotatedCD && !displayPlaylist && !displayLibrary && pref.display_cdart) {
- CreateRotatedCDImage();
- }
- if (!shadow_image) { // when switching views, the drop shadow won't get created initially which is very jarring when it suddenly appears later, so create it if we don't have it.
- createDropShadow();
- }
- if (rotatedCD && pref.display_cdart) {
- if (showExtraDrawTiming) drawCD = fb.CreateProfiler('cdart');
- shadow_image && gr.DrawImage(shadow_image, -geo.aa_shadow, albumart_size.y - geo.aa_shadow, shadow_image.Width, shadow_image.Height,
- 0, 0, shadow_image.Width, shadow_image.Height);
- gr.DrawImage(rotatedCD, cdart_size.x, cdart_size.y, cdart_size.w, cdart_size.h, 0, 0, rotatedCD.width, rotatedCD.height, 0);
- if (showExtraDrawTiming) drawCD.Print();
- }
- }
- }
- if (fb.IsPlaying && (albumart || !cdart)) {
- gr.SetSmoothingMode(SmoothingMode.None);
- gr.FillSolidRect(0, albumart_size.y, albumart_size.x, albumart_size.h, col.info_bg); // info bg -- must be drawn after shadow
- gr.DrawRect(-1, albumart_size.y, albumart_size.x, albumart_size.h - 1, 1, col.accent);
- gr.SetSmoothingMode(SmoothingMode.AntiAlias);
- }
- if (fb.IsPaused) {
- pauseBtn.draw(gr);
- }
-
- var textLeft = Math.round(Math.min(0.015 * ww, is_4k ? 40 : 20));
- if (str.artist) {
+ ft.track_info = font('HelveticaNeueLT Std Thin', 18, 0);
+ ft.grd_key_lrg = font('HelveticaNeueLT Std', 24, 0); // used instead of ft.grd_key if ww > 1280
+ ft.grd_val_lrg = font('HelveticaNeueLT Std Lt', 24, 0); // used instead of ft.grd_val if ww > 1280
+ ft.grd_key_med = font('HelveticaNeueLT Std', 20, 0);
+ ft.grd_val_med = font('HelveticaNeueLT Std Lt', 20, 0);
+ ft.grd_key_sml = font('HelveticaNeueLT Std', 18, 0);
+ ft.grd_val_sml = font('HelveticaNeueLT Std Lt', 18, 0);
+ ft.lower_bar = font('HelveticaNeueLT Std Lt', 30, 0);
+ ft.lower_bar_bold = font('HelveticaNeueLT Std Med', 30, 0);
+ ft.lower_bar_sml = font('HelveticaNeueLT Std Lt', 26, 0);
+ ft.lower_bar_sml_bold = font('HelveticaNeueLT Std Med', 26, 0);
+ if (utils.checkFont('NeueHaasGroteskDisp Pro XLt')) {
+ useNeue = true;
+ ft.lower_bar_artist = font('NeueHaasGroteskDisp Pro XLt', 31, g_font_style.italic);
+ ft.lower_bar_artist_sml = font('NeueHaasGroteskDisp Pro XLt', 27, g_font_style.italic);
+ } else {
+ ft.lower_bar_artist = font('HelveticaNeueLT Std Thin', 31, g_font_style.italic);
+ ft.lower_bar_artist_sml = font('HelveticaNeueLT Std Thin', 27, g_font_style.italic);
+ }
+ ft.small_font = font('HelveticaNeueLT Std', 14, 0);
+ ft.guifx = font('Guifx v2 Transports', 16, 0);
+ ft.Marlett = font('Marlett', 13, 0);
+ ft.SegoeUi = font('Segoe Ui Semibold', 12, 0);
+ ft.library_tree = font('Segoe UI', libraryProps.baseFontSize, 0);
+ ft.lyrics = font('HelveticaNeueLT Std', pref.lyrics_font_size || 20, 1);
+}
+
+
+// COLORS
+col.progres_bar_text = RGB(0, 0, 0);
+col.artist = RGB(255, 255, 255);
+col.info_text = RGB(255, 255, 255);
+col.now_playing = RGB(0, 0, 0); // tracknumber, title, and time
+
+col.bg = RGB(205, 205, 205);
+col.menu_bg = RGB(58, 58, 58);
+col.rating = RGB(255, 170, 032);
+col.mood = RGB(000, 128, 255);
+col.hotness = RGB(192, 192, 000);
+
+col.playcount = RGB(000, 153, 153);
+col.dark_grey = RGB(128, 128, 128);
+col.progress_fill = RGB(235, 59, 70);
+col.progress_bar = RGB(125, 125, 125);
+
+col.tl_added = RGB(15, 51, 65);
+col.tl_played = RGB(44, 66, 75);
+col.tl_unplayed = RGB(126, 173, 195);
+col.tl_play = RGB(255, 255, 255); // each individual play
+
+// ALBUM ART DISPLAY PROPERTIES
+col.aa_border = RGBA(060, 060, 060, 128);
+col.aa_shadow = RGBA(000, 000, 000, 64);
+
+function setGeometry() {
+ geo.aa_shadow = is_4k ? 16 : 8; // size of albumart shadow
+ geo.pause_size = is_4k ? 300 : 150;
+ geo.prog_bar_h = is_4k ? 24 : (ww > 1920 ? 14 : 12); // height of progress bar
+ geo.lower_bar_h = is_4k ? 160 : 80; // height of song title and time + progress bar area
+ geo.top_art_spacing = is_4k ? 192 : 96; // space between top of theme and artwork
+ geo.top_bg_h = is_4k ? 320 : 160; // height of offset color background
+ geo.timeline_h = is_4k ? 36 : 18; // height of timeline
+ if (!pref.show_progress_bar) {
+ geo.lower_bar_h -= geo.prog_bar_h * 2;
+ }
+
+ if (is_4k) {
+ settingsImg = gdi.Image(pref.setting_4k_img); // settings image
+ propertiesImg = gdi.Image(pref.prop_4k_img); // properties image
+ ratingsImg = gdi.Image(pref.rating_4k_img); // rating image
+ playlistImg = gdi.Image(pref.list_4k_img); // playlist image
+ libraryImg = gdi.Image(pref.library_4k_img); // library image
+ lyricsImg = gdi.Image(pref.lyrics_4k_img); // lyrics image
+ } else {
+ settingsImg = gdi.Image(pref.settng_img); // settings image
+ propertiesImg = gdi.Image(pref.prop_img); // properties image
+ ratingsImg = gdi.Image(pref.rating_img); // rating image
+ playlistImg = gdi.Image(pref.list_img); // playlist image
+ libraryImg = gdi.Image(pref.library_img); // library image
+ lyricsImg = gdi.Image(pref.lyrics_img); // lyrics image
+ }
+}
+
+var playedTimesRatios = [];
+var lfmPlayedTimesRatios = []; // remove this
+
+// PATHS
+pref.bg_image = fb.ProfilePath + 'georgia/images/wallpaper-blueish.jpg';
+pref.settng_img = fb.ProfilePath + 'georgia/images/settings.png';
+pref.prop_img = fb.ProfilePath + 'georgia/images/properties.png';
+pref.list_img = fb.ProfilePath + 'georgia/images/playlist.png';
+pref.library_img = fb.ProfilePath + 'georgia/images/library.png';
+pref.lyrics_img = fb.ProfilePath + 'georgia/images/lyrics.png';
+pref.rating_img = fb.ProfilePath + 'georgia/images/star.png';
+
+pref.setting_4k_img = fb.ProfilePath + 'georgia/images/4k/settings.png';
+pref.prop_4k_img = fb.ProfilePath + 'georgia/images/4k/properties.png';
+pref.list_4k_img = fb.ProfilePath + 'georgia/images/4k/playlist.png';
+pref.library_4k_img = fb.ProfilePath + 'georgia/images/4k/library.png';
+pref.lyrics_4k_img = fb.ProfilePath + 'georgia/images/4k/lyrics.png';
+pref.rating_4k_img = fb.ProfilePath + 'georgia/images/4k/star.png';
+
+pref.divider_img = fb.ProfilePath + 'georgia/images/divider.png';
+pref.last_fm_img = fb.ProfilePath + 'georgia/images/last-fm-red-36.png';
+pref.last_fmw_img = fb.ProfilePath + 'georgia/images/last-fm-36.png';
+pref.label_base = fb.ProfilePath + 'images/recordlabel/'; // location of the record label logos for the bottom right corner
+pref.logo_hq = fb.ProfilePath + 'images/artistlogos/'; // location of High-Qualiy band logos for the bottom left corner
+pref.logo_color = fb.ProfilePath + 'images/artistlogos color/';
+pref.codec_base = fb.ProfilePath + 'images/codec logos/';
+pref.flags_base = fb.ProfilePath + 'images/flags/'; // location of artist country flags
+
+// MOUSE WHEEL SEEKING SPEED
+pref.mouse_wheel_seek_speed = 5; // seconds per wheel step
+
+// DEBUG
+// var pref.show_debug_log = window.GetProperty("Debug: Show Debug Output", false);
+var showDebugTiming = false; // spam console with debug timings
+var showDrawTiming = false; // spam console with draw times
+var showExtraDrawTiming = false; // spam console with every section of the draw code to determine bottlenecks
+var showLyricsTiming = true; // spam console with timing for lyrics loading
+
+// Lyrics Constants
+var DEFAULT_OFFSET = 29;
+var SCROLL_STEP = 1; // do not modify this value
+var PLAYTIMER_VALUE = 01; // do not modify this value
+
+
+// PLAYLIST JUNK
+var listLeft = 15;
+var listTop = 15;
+var listRight = 15;
+var listBottom = 15;
+var showNowPlayingCalled = false; //TODO: Remove?
+
+//--->
+var listLength = maxRows = listX = listY = listW = listH = 0;
+var listStep = [];
+var rowDrag = fileDrag = makeSelectionDrag = linkToLastItem = false;
+var nowPlayingGroupNr = -1;
+var focusGroupNr = -1;
+var keyPressed = false;
+var guiInstanceType = window.InstanceType;
+var tempFocusItemIndex;
+var btns = [];
+var hyperlinks = [];
+//--->
+AlbumArtId = {
+ front: 0,
+ back: 1,
+ disc: 2,
+ icon: 3,
+ artist: 4
+};
+// =================================================== //
+//--->
+var thisPanelName = "Playlist"; //Don't change!! needed in Scrollbar.txt.
+//---> Fonts
+var playlistFontSize = window.GetProperty("Playlist: Font Size", 12);
+if (playlistFontSize < 7) {
+ playlistFontSize = 7;
+ window.SetProperty("Playlist: Font Size", playlistFontSize);
+}
+
+// END OF CONFIGURATION /////////////////////////////////
+
+
+
+// VARIABLES
+// Artwork
+var albumart = null; // albumart image
+var albumart_size = new ImageSize(0, 0, 0, 0); // position (big image)
+var cdart = null; // cdart image
+var cdart_size = new ImageSize(0, 0, 0, 0); // cdart position (offset from albumart_size)
+var image_bg = gdi.Image(pref.bg_image); // background image
+var albumart_scaled = null; // pre-scaled album art to speed up drawing considerably
+var recordLabels = []; // array of record label images
+var bandLogo = null; // band logo image
+var settingsImg = null; // settings image
+var propertiesImg = null; // properties image
+var ratingsImg = null; // rating image
+var playlistImg = null; // playlist image
+var libraryImg = null; // library image
+var lyricsImg = null; // lyrics image
+var dividerImg = gdi.Image(pref.divider_img); // end lyrics image
+var lastFmImg = gdi.Image(pref.last_fm_img); // Last.fm logo image
+var lastFmWhiteImg = gdi.Image(pref.last_fmw_img); // white Last.fm logo image
+var shadow_image = null; // shadow behind the artwork + discart
+var labelShadowImg = null; // shadow behind labels
+var playlist_shadow = null; // shadow behind the playlist
+var flagImgs = []; // array of flag images
+var rotatedCD = null; // drawing cdArt rotated is slow, so first draw it rotated into the rotatedCD image, and then draw rotatedCD image unrotated
+var disc_art_loading; // for on_load_image_done()
+var album_art_loading; // for on_load_image_done()
+var isStreaming = false; // is the song from a streaming source?
+var retrieveThemeColorsWhenLoaded = false; // only load theme colors on first image in aa_array
+var newTrackFetchingArtwork = false; // only load theme colors when newTrackFetchingArtwork = true
+var noArtwork = false; // only use default theme when noArtwork was found
+var themeColorSet = false; // when no artwork, don't set themeColor every redraw
+var playCountVerifiedByLastFm = false; // show Last.fm image when we %lastfm_play_count% > 0
+var art_off_center = false; // if true, album art has been shifted 40 pixels to the right
+var loadFromCache = true; // always load art from cache unless this is set
+
+//var inShowMenuEntry = false;
+
+var str = new Object();
+var state = new Object(); // panel state
+
+var metadb_handle = null; // watch db for tag changes
+// TIMERS
+var progressTimer; // 40ms repaint of progress bar
+var globTimer; // Timer for rotating globs
+var slideTimer; // Timer for CD Slide out
+var hideCursor; // Timer for hiding cursor
+
+// STATUS VARIABLES
+var ww = 0,
+ wh = 0; // size of panel
+var progressLength = 0; // fixing jumpiness in progressBar
+var progressMoved = false; // playback position changed, so reset progressLength
+var last_pb; // saves last playback order
+var g_drag = 0; // status variable for clickable progress bar
+var just_dblclicked = false;
+var aa_list = new Array();
+var albumArtIndex = 0; // index of currently displayed album art if more than 1
+var fadeAlpha = 255; // full alpha which will be decremented
+var nextPrevAlpha = 255; // full alpha for next/prev icons which will be decremented
+var bandLogoHQ = false; // if true will partially remove the 10 pixel "gutter" around the image that fanart.tv requires around their high-rez images so that logos use more of the available space.
+var t_interval; // milliseconds between screen updates
+// var settingsY = 0; // location of settings button
+var lastLeftEdge = 0; // the left edge of the record labels. Saved so we don't have to recalculate every on every on_paint unless size has changed
+var displayPlaylist = pref.start_Playlist;
+var displayLibrary = false;
+var displayLyrics = false;
+var showLibraryButton = true; // TODO: Remove once library goes live
+
+var tl_firstPlayedRatio = 0;
+var tl_lastPlayedRatio = 0;
+
+var current_path;
+var last_path;
+var lastDiscNumber;
+var lastVinylSide;
+var currentLastPlayed = '';
+
+// Lyrics Variables
+var len_seconds = fb.Titleformat("%length_seconds%");
+var elap_seconds = fb.TitleFormat("%playback_time_seconds%");
+
+var g_playtimer = null;
+var g_timer_abs;
+
+// TODO change these variable names
+var g_tab = Array();
+var g_scroll = 0;
+var g_lyrics_path;
+var g_lyrics_filename;
+var g_lyrics_status;
+var focus = 0;
+var focus_next = 0;
+var hundredth = 0;
+var g_is_scrolling = false;
+var g_tab_length;
+
+var midpoint; // this is the center of the lyrics, where the highlighted line will display
+var lyrPos; // this is the absolute yPosition of the very first line in the lyrics. It will start at midpoint and then move up and off the screen
+var lyricsWidth = 0; // minimum width needed to display the lyrics to speed up drawing
+
+
+// MENU STUFF
+var pad_x = 4;
+var pad_y = 2;
+var mymenu = Array(7);
+var menu_img = new Array(7);
+var menu_down = false;
+var menu_padx = pad_x;
+var menu_pady = pad_y + 4;
+var menu_width = 250; // this will get sized based on the font later
+
+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);
+
+// Flags, used with GdiDrawText()
+// For more information, see: http://msdn.microsoft.com/en-us/library/dd162498(VS.85).aspx
+DT_TOP = 0x00000000;
+DT_LEFT = 0x00000000;
+DT_CENTER = 0x00000001;
+DT_RIGHT = 0x00000002;
+DT_VCENTER = 0x00000004;
+DT_BOTTOM = 0x00000008;
+DT_WORDBREAK = 0x00000010;
+DT_SINGLELINE = 0x00000020;
+DT_EXPANDTABS = 0x00000040;
+DT_TABSTOP = 0x00000080;
+DT_NOCLIP = 0x00000100;
+DT_EXTERNALLEADING = 0x00000200;
+DT_CALCRECT = 0x00000400; // [1.2.1] Handles well
+DT_NOPREFIX = 0x00000800; // NOTE: Please use this flag, or a '&' character will become an underline '_'
+DT_INTERNAL = 0x00001000;
+DT_EDITCONTROL = 0x00002000;
+DT_PATH_ELLIPSIS = 0x00004000;
+DT_END_ELLIPSIS = 0x00008000;
+DT_MODIFYSTRING = 0x00010000; // do not use
+DT_RTLREADING = 0x00020000;
+DT_WORD_ELLIPSIS = 0x00040000;
+DT_NOFULLWIDTHCHARBREAK = 0x00080000;
+DT_HIDEPREFIX = 0x00100000;
+DT_PREFIXONLY = 0x00200000;
+
+// File IO Modes
+var ForReading = 1;
+var ForWriting = 2;
+var ForAppending = 8;
+
+///////// OBJECTS
+
+var fso = new ActiveXObject("Scripting.FileSystemObject");
+
+var art_cache = new ArtCache(10);
+var cdartPath = '';
+var album_art_path = '';
+
+var pauseBtn = new PauseButton();
+
+var last_accent_col = undefined;
+var progressAlphaCol = undefined;
+
+// Call initialization function
+on_init();
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function on_paint(gr) {
+ if (showDrawTiming) drawStuff = fb.CreateProfiler("on_paint");
+ gr.SetTextRenderingHint(TextRenderingHint.AntiAlias);
+ gr.SetSmoothingMode(SmoothingMode.None);
+
+ // Background
+ if (!albumart && noArtwork) { // we use noArtwork to prevent flashing of blue default theme
+ albumart_size.x = Math.floor(ww * 0.33); // if there's no album art info panel takes up 1/3 screen
+ albumart_size.y = geo.top_art_spacing;
+ albumart_size.h = wh - albumart_size.y - geo.lower_bar_h - 32;
+ if (!themeColorSet) {
+ setTheme(blueTheme.colors);
+ themeColorSet = true;
+ }
+ }
+ gr.FillSolidRect(0, geo.top_bg_h, ww, wh - geo.top_bg_h, col.bg);
+ gr.FillSolidRect(0, 0, ww, geo.top_bg_h, col.menu_bg);
+ if ((fb.IsPaused || fb.IsPlaying) && (!albumart && cdart)) {
+ gr.SetSmoothingMode(SmoothingMode.None);
+ gr.FillSolidRect(0, albumart_size.y, albumart_size.x, albumart_size.h, col.info_bg);
+ gr.DrawRect(-1, albumart_size.y, albumart_size.x, albumart_size.h - 1, 1, col.accent);
+ gr.SetSmoothingMode(SmoothingMode.AntiAlias);
+ }
+
+ gr.SetSmoothingMode(SmoothingMode.AntiAlias);
+ gr.SetInterpolationMode(InterpolationMode.HighQualityBicubic);
+
+ // BIG ALBUMART
+ if (fb.IsPlaying) {
+ if (albumart && albumart_scaled) {
+ if (showExtraDrawTiming) drawArt = fb.CreateProfiler('on_paint -> artwork');
+ if (!shadow_image) { // when switching views, the drop shadow won't get created initially which is very jarring when it suddenly appears later, so create it if we don't have it.
+ createDropShadow();
+ }
+ shadow_image && gr.DrawImage(shadow_image, -geo.aa_shadow, albumart_size.y - geo.aa_shadow, shadow_image.Width, shadow_image.Height,
+ 0, 0, shadow_image.Width, shadow_image.Height);
+ // gr.DrawRect(-geo.aa_shadow, albumart_size.y - geo.aa_shadow, shadow_image.Width, shadow_image.Height, 1, RGBA(0,0,255,125)); // viewing border line
+ if (cdart && !rotatedCD && !displayPlaylist && !displayLibrary && pref.display_cdart) {
+ CreateRotatedCDImage();
+ }
+ if (!pref.cdart_ontop || displayLyrics) {
+ if (rotatedCD && !displayPlaylist && !displayLibrary && pref.display_cdart) {
+ if (showExtraDrawTiming) drawCD = fb.CreateProfiler('cdart');
+ gr.DrawImage(rotatedCD, cdart_size.x, cdart_size.y, cdart_size.w, cdart_size.h, 0, 0, rotatedCD.width, rotatedCD.height, 0);
+ if (showExtraDrawTiming) drawCD.Print();
+ }
+ gr.DrawImage(albumart_scaled, albumart_size.x, albumart_size.y, albumart_size.w, albumart_size.h, 0, 0, albumart_scaled.width, albumart_scaled.height);
+ } else { // draw cdart on top of front cover
+ gr.DrawImage(albumart_scaled, albumart_size.x, albumart_size.y, albumart_size.w, albumart_size.h, 0, 0, albumart_scaled.width, albumart_scaled.height);
+ if (rotatedCD && !displayPlaylist && !displayLibrary && pref.display_cdart) {
+ if (showExtraDrawTiming) drawCD = fb.CreateProfiler('cdart');
+ gr.DrawImage(rotatedCD, cdart_size.x, cdart_size.y, cdart_size.w, cdart_size.h, 0, 0, rotatedCD.width, rotatedCD.height, 0);
+ if (showExtraDrawTiming) drawCD.Print();
+ }
+ }
+ if (displayLyrics && albumart_scaled && fb.IsPlaying) {
+ gr.FillSolidRect(albumart_size.x - 1, albumart_size.y - 1, albumart_size.w + 1, albumart_size.h + 1, RGBA(0, 0, 0, 155));
+ show_lyrics(gr, g_tab, Math.floor(lyrPos - pref.lyrics_h_padding));
+ }
+ if (showExtraDrawTiming) drawArt.Print();
+ } else {
+ if (cdart && !rotatedCD && !displayPlaylist && !displayLibrary && pref.display_cdart) {
+ CreateRotatedCDImage();
+ }
+ if (!shadow_image) { // when switching views, the drop shadow won't get created initially which is very jarring when it suddenly appears later, so create it if we don't have it.
+ createDropShadow();
+ }
+ if (rotatedCD && pref.display_cdart) {
+ if (showExtraDrawTiming) drawCD = fb.CreateProfiler('cdart');
+ shadow_image && gr.DrawImage(shadow_image, -geo.aa_shadow, albumart_size.y - geo.aa_shadow, shadow_image.Width, shadow_image.Height,
+ 0, 0, shadow_image.Width, shadow_image.Height);
+ gr.DrawImage(rotatedCD, cdart_size.x, cdart_size.y, cdart_size.w, cdart_size.h, 0, 0, rotatedCD.width, rotatedCD.height, 0);
+ if (showExtraDrawTiming) drawCD.Print();
+ }
+ }
+ }
+ if (fb.IsPlaying && (albumart || !cdart)) {
+ gr.SetSmoothingMode(SmoothingMode.None);
+ gr.FillSolidRect(0, albumart_size.y, albumart_size.x, albumart_size.h, col.info_bg); // info bg -- must be drawn after shadow
+ gr.DrawRect(-1, albumart_size.y, albumart_size.x, albumart_size.h - 1, 1, col.accent);
+ gr.SetSmoothingMode(SmoothingMode.AntiAlias);
+ }
+ if (fb.IsPaused) {
+ pauseBtn.draw(gr);
+ }
+
+ var textLeft = Math.round(Math.min(0.015 * ww, is_4k ? 40 : 20));
+ if (str.artist) {
var availableWidth = displayPlaylist || displayLibrary ? Math.min(ww / 2 - 20, btns.playlist.x - textLeft) : btns.playlist.x - textLeft;
var artistFont = chooseFontForWidth(gr, availableWidth, str.artist, [ft.artist_lrg, ft.artist_med, ft.artist_sml]);
height = gr.CalcTextHeight(str.artist, artistFont);
- var artistY = albumart_size.y - height - (is_4k ? 16 : 8);
+ var artistY = albumart_size.y - height - (is_4k ? 16 : 8);
gr.DrawString(str.artist, artistFont, col.artist, textLeft, artistY, availableWidth, height, StringFormat(0, 0, 4));
width = gr.MeasureString(str.artist, artistFont, 0, 0, 0, 0).Width;
if (pref.show_flags && flagImgs.length && width + flagImgs[0].width * flagImgs.length < availableWidth) {
- var flagWidths = 0;
- var flagsLeft = textLeft + width + (is_4k ? 30 : 15);
- for (i = 0; i < flagImgs.length; i++) {
- gr.DrawImage(flagImgs[i], flagsLeft, Math.round(artistY + 1 + height / 2 - flagImgs[i].height / 2),
- flagImgs[i].width, flagImgs[i].height, 0, 0, flagImgs[i].width, flagImgs[i].height)
- flagsLeft += flagImgs[i].width + (is_4k ? 10 : 5);
- }
- }
- }
-
- if (((!displayPlaylist && !displayLibrary) || (!albumart && noArtwork)) && fb.IsPlaying) {
- if (!albumart && cdart) {
- gridSpace = Math.round(cdart_size.x - geo.aa_shadow - textLeft);
- } else {
- gridSpace = Math.round(albumart_size.x - geo.aa_shadow - textLeft);
- }
- text_width = gridSpace;
-
- if (showExtraDrawTiming) drawTextGrid = fb.CreateProfiler('on_paint -> textGrid');
-
- var trackInfoHeight = 0;
- if (str.trackInfo) {
- gr.SetTextRenderingHint(TextRenderingHint.ClearTypeGridFit);
- trackInfoHeight = gr.MeasureString(str.trackInfo, ft.track_info, 0, 0, 0, 0).Height;
- gr.DrawString(str.trackInfo, ft.track_info, col.artist, ww - textLeft * 2 - text_width, geo.top_bg_h - trackInfoHeight - 15, text_width, trackInfoHeight, StringFormat(StringAlignment.Far));
- gr.SetTextRenderingHint(TextRenderingHint.AntiAlias);
- }
- if (str.year) {
- height = gr.MeasureString(str.year, ft.year, 0, 0, 0, 0).Height;
- gr.DrawString(str.year, ft.year, col.artist, ww - textLeft * 2 - text_width, geo.top_bg_h - trackInfoHeight - height - 20, text_width, height, StringFormat(StringAlignment.Far));
- }
-
- var top = (albumart_size.y ? albumart_size.y : geo.top_art_spacing) + (is_4k ? 30 : 15);
- if (gridSpace > 120) {
- if (str.title) {
- ft.title = ft.title_lrg;
- ft.tracknum = ft.tracknum_lrg;
- var title_spacing = is_4k ? 16 : 8;
- var trackNumWidth = 0;
- if (str.tracknum) {
- trackNumWidth = gr.MeasureString(str.tracknum, ft.tracknum, 0, 0, 0, 0).Width + title_spacing;
- }
- txtRec = gr.MeasureString(str.title, ft.title, 0, 0, text_width - trackNumWidth, wh);
- if (txtRec.lines > 2) {
- ft.title = ft.title_med;
- ft.tracknum = ft.tracknum_med;
- if (str.tracknum) {
- trackNumWidth = gr.MeasureString(str.tracknum, ft.tracknum, 0, 0, 0, 0).Width + title_spacing;
- }
- txtRec = gr.MeasureString(str.title, ft.title, 0, 0, text_width - trackNumWidth, wh);
- if (txtRec.lines > 2) {
- ft.title = ft.title_sml;
- ft.tracknum = ft.tracknum_sml;
- if (str.tracknum) {
- trackNumWidth = gr.MeasureString(str.tracknum, ft.tracknum, 0, 0, 0, 0).Width + title_spacing;
- }
- txtRec = gr.MeasureString(str.title, ft.title, 0, 0, text_width - trackNumWidth, wh);
- }
- }
- var tracknumHeight = gr.MeasureString(str.tracknum, ft.tracknum, 0, 0, 0, 0).Height;
- var heightAdjustment = Math.ceil((tracknumHeight - gr.MeasureString(str.title, ft.title, 0, 0, 0, 0).Height) / 2);
- var numLines = Math.min(2, txtRec.lines);
- height = gr.CalcTextHeight(str.title, ft.title) * numLines + 3;
-
- trackNumWidth = Math.ceil(trackNumWidth);
- gr.DrawString(str.tracknum, ft.tracknum, col.info_text, textLeft, top - heightAdjustment, trackNumWidth, height);
- // gr.DrawRect(textLeft, top, trackNumWidth, height, 1, rgb(255,0,0));
- gr.SetTextRenderingHint(TextRenderingHint.ClearTypeGridFit); // thicker fonts can use anti-alias
- gr.DrawString(str.title, ft.title, col.info_text, textLeft + trackNumWidth, top, text_width - trackNumWidth, height, g_string_format.trim_ellipsis_word);
- // gr.DrawRect(textLeft, top, text_width - trackNumWidth, height, 1, rgb(255,0,0));
-
- top += height + (is_4k ? 20 : 12);
- gr.SetTextRenderingHint(TextRenderingHint.AntiAlias);
- }
-
- //Timeline playcount bars
- if (fb.IsPlaying) {
- var extraLeftSpace = is_4k ? 6 : 3; // add a little space to the left so songs that were played a long time ago show more in the "added" stage
- gr.SetSmoothingMode(SmoothingMode.None); // disable smoothing
- width = albumart_size.x - extraLeftSpace - 1; // albumart_size.x set even if no art. Subtract 1 because we want the timeline stop 1 pixel short of art
-
- gr.FillSolidRect(0, top, width + extraLeftSpace, geo.timeline_h, col.tl_added);
- if (tl_firstPlayedRatio >= 0 && tl_lastPlayedRatio >= 0) {
- x1 = Math.floor(width * tl_firstPlayedRatio) + extraLeftSpace;
- x2 = Math.floor(width * tl_lastPlayedRatio) + extraLeftSpace;
- gr.FillSolidRect(x1, top, width - x1 + extraLeftSpace, geo.timeline_h, col.tl_played);
- gr.FillSolidRect(x2, top, width - x2 + extraLeftSpace, geo.timeline_h, col.tl_unplayed);
- }
- for (i = 0; i < playedTimesRatios.length; i++) {
- x = Math.floor(width * playedTimesRatios[i]) + extraLeftSpace;
- if (!isNaN(x)) {
- gr.DrawLine(x, top, x, top + geo.timeline_h, is_4k ? 3 : 2, col.tl_play);
- } else {
- // console.log('Played Times Error! ratio: ' + playedTimesRatios[i], 'x: ' + x);
- }
- }
- gr.SetSmoothingMode(SmoothingMode.AntiAlias);
- }
-
- top += geo.timeline_h + (is_4k ? 20 : 12);
-
- if (str.album) {
- var drawSubtitle = !!str.album_subtitle.length;
- ft_album = ft.album_lrg;
- ft_subtitle = ft.album_substitle_lrg;
- txtRec = gr.MeasureString(str.album, ft_album, 0, 0, text_width, wh);
- subtitleRec = gr.MeasureString(str.album_subtitle, ft_subtitle, 0, 0, text_width, wh);
- if (txtRec.lines > 2 || subtitleRec.lines > 2) {
- ft_album = ft.album_med;
- txtRec = gr.MeasureString(str.album, ft_album, 0, 0, text_width, wh);
- if (txtRec.lines > 2) {
- ft.album = ft.album_sml;
- }
- album_text = str.album + str.album_subtitle;
- drawSubtitle = false;
- } else if (txtRec.width + subtitleRec.width > text_width) {
- album_text = str.album + str.album_subtitle;
- drawSubtitle = false;
- } else {
- // draw subtitle separately
- album_text = str.album;
- }
- var numLines = Math.min(2, txtRec.lines);
- height = gr.CalcTextHeight(album_text, ft_album) * numLines;
-
- gr.DrawString(album_text, ft_album, col.info_text, textLeft, top, text_width, height, g_string_format.trim_ellipsis_word);
- // console.log(drawSubtitle, str.album_subtitle, txtRec.width, subtitleRec.width, text_width);
- if (drawSubtitle) {
- gr.DrawString(str.album_subtitle, ft_subtitle, col.info_text,
- textLeft + Math.ceil(txtRec.width), top, text_width - Math.ceil(txtRec.width), height, g_string_format.trim_ellipsis_word);
- }
-
- top += height + (is_4k ? 20 : 10);
- }
-
- // Tag grid
- grid_key_ft = ft.grd_key_lrg;
- col1_width = calculateGridMaxTextWidth(gr, str.grid, grid_key_ft);
- if (col1_width < text_width / 3) {
- grid_val_ft = ft.grd_val_lrg;
- } else {
- grid_key_ft = ft.grd_key_med;
- col1_width = calculateGridMaxTextWidth(gr, str.grid, grid_key_ft);
- if (col1_width < text_width / 3) {
- grid_val_ft = ft.grd_val_med;
- } else {
- grid_key_ft = ft.grd_key_sml;
- grid_val_ft = ft.grd_val_sml;
- col1_width = calculateGridMaxTextWidth(gr, str.grid, grid_key_ft);
- if (col1_width > text_width / 3) {
- col1_width = Math.floor(text_width / 3);
- }
- }
- }
- var column_margin = is_4k ? 20 : 10;
- var col2_width = text_width - column_margin - col1_width;
- var col2_left = textLeft + col1_width + column_margin;
-
- for (k = 0, i = 0; k < str.grid.length; k++) {
- var key = str.grid[k].label;
- var value = str.grid[k].val;
- var showLastFmImage = false;
- var dropShadow = false;
- var grid_val_col = col.info_text;
-
- if (value.length) {
- switch (key) {
- case 'Rating':
- grid_val_col = col.rating;
- dropShadow = true;
- break;
- case 'Mood':
- grid_val_col = col.mood;
- dropShadow = true;
- break;
- case 'Hotness':
- grid_val_col = col.hotness;
- dropShadow = true;
- break;
- case 'Play Count':
- showLastFmImage = true;
- break;
- default:
- break;
- }
- txtRec = gr.MeasureString(value, grid_val_ft, 0, 0, col2_width, wh);
- if (top + txtRec.Height < albumart_size.y + albumart_size.h) {
- cell_height = txtRec.Height + 5;
- if (dropShadow) {
- var border_w = is_4k ? 1 : 0.5;
- gr.DrawString(value, grid_val_ft, col.extraDarkAccent, col2_left + border_w, top + border_w, col2_width, cell_height, StringFormat(0, 0, 4));
- gr.DrawString(value, grid_val_ft, col.extraDarkAccent, col2_left - border_w, top + border_w, col2_width, cell_height, StringFormat(0, 0, 4));
- gr.DrawString(value, grid_val_ft, col.extraDarkAccent, col2_left + border_w, top - border_w, col2_width, cell_height, StringFormat(0, 0, 4));
- gr.DrawString(value, grid_val_ft, col.extraDarkAccent, col2_left - border_w, top - border_w, col2_width, cell_height, StringFormat(0, 0, 4));
- }
- gr.DrawString(key, grid_key_ft, col.info_text, textLeft, top, col1_width, cell_height, g_string_format.trim_ellipsis_char); // key
- gr.DrawString(value, grid_val_ft, grid_val_col, col2_left, top, col2_width, cell_height, StringFormat(0, 0, 4));
-
- if (playCountVerifiedByLastFm && showLastFmImage) {
- var lastFmLogo = lastFmImg;
- if (colorDistance(col.primary, rgb(185, 0, 0), false) < 132) {
- lastFmLogo = lastFmWhiteImg;
- }
- var heightRatio = (cell_height - 12) / lastFmImg.height;
- gr.DrawImage(lastFmLogo, col2_left + txtRec.Width + 20, top + 3, Math.round(lastFmLogo.width * heightRatio), cell_height - 12,
- 0, 0, lastFmLogo.width, lastFmLogo.height);
- }
- top += cell_height + 5;
- }
- }
- }
- }
- if (showExtraDrawTiming) drawTextGrid.Print();
-
- } /* if (!displayPlaylist && !displayLibrary) */
-
- if ((fb.IsPlaying && !displayPlaylist && !displayLibrary) || (!albumart && !cdart && noArtwork)) {
- // BAND LOGO drawing code
- showExtraDrawTiming && (drawBandLogos = fb.CreateProfiler("on_paint -> band logos"));
- availableSpace = albumart_size.y + albumart_size.h - top;
- if (bandLogo && availableSpace > 75) {
- // max width we'll draw is 1/2 the full size because the HQ images are just so big
- logoWidth = Math.min(bandLogoHQ ? (is_4k ? bandLogo.width : bandLogo.width / 2) : bandLogo.width * 1.5, albumart_size.x - ww * 0.05);
- heightScale = logoWidth / bandLogo.width; // width is fixed to logoWidth, so scale height accordingly
- if (bandLogo.height * heightScale > availableSpace) {
- // TODO: could probably do this calc just once, but the logic is complicated
- heightScale = availableSpace / bandLogo.height;
- logoWidth = bandLogo.width * heightScale;
- }
- logoTop = Math.round(albumart_size.y + albumart_size.h - (heightScale * bandLogo.height)) - 4;
- if (!bandLogoHQ || is_4k) {
- logoTop -= 20;
- }
- gr.DrawImage(bandLogo, Math.round(albumart_size.x / 2 - logoWidth / 2), logoTop, Math.round(logoWidth), Math.round(bandLogo.height * heightScale),
- 0, 0, bandLogo.width, bandLogo.height, 0);
- }
- if (showExtraDrawTiming) drawBandLogos.Print();
-
-
- // RECORD LABEL drawing code
- // this section should draw in 3ms or less always
- if (recordLabels.length > 0) {
- var rightSideGap = 20, // how close last label is to right edge
- labelSpacing = 0,
- leftEdgeGap = art_off_center ? 20 : 40, // space between art and label
- maxLabelWidth = is_4k ? 400 : 200;
- leftEdgeWidth = is_4k ? 45 : 30; // how far label background extends on left
- if (showExtraDrawTiming) drawLabelTime = fb.CreateProfiler("on_paint -> record labels");
- totalLabelWidth = 0;
- for (i = 0; i < recordLabels.length; i++) {
- if (recordLabels[i].width > maxLabelWidth) {
- totalLabelWidth += maxLabelWidth;
- } else {
- if (is_4k && recordLabels[i].width < 200) {
- totalLabelWidth += recordLabels[i].width * 2;
- } else {
- totalLabelWidth += recordLabels[i].width;
- }
- }
- }
- if (!lastLeftEdge) { // we don't want to recalculate this every screen refresh
- debugLog('recalculating lastLeftEdge');
- labelShadowImg = disposeImg(labelShadowImg);
- labelWidth = Math.round(totalLabelWidth / recordLabels.length);
- labelHeight = Math.round(recordLabels[0].height * labelWidth / recordLabels[0].width); // might be recalc'd below
- if (albumart) {
- if (cdart && pref.display_cdart) {
- leftEdge = Math.round(Math.max(albumart_size.x + albumart_scaled.Width + 5, ww * 0.975 - totalLabelWidth + 1));
- var cdCenter = {};
- cdCenter.x = Math.round(cdart_size.x + cdart_size.w / 2);
- cdCenter.y = Math.round(cdart_size.y + cdart_size.h / 2);
- var radius = cdCenter.y - cdart_size.y;
-
- while (true) {
- allLabelsWidth = Math.max(Math.min(Math.round((ww - leftEdge - rightSideGap) / recordLabels.length), maxLabelWidth), 50);
- //console.log("leftEdge = " + leftEdge + ", ww-leftEdge-10 = " + (ww-leftEdge-10) + ", allLabelsWidth=" + allLabelsWidth);
- var maxWidth = is_4k && recordLabels[0].width < 200 ? recordLabels[0].width * 2 : recordLabels[0].width;
- labelWidth = (allLabelsWidth > maxWidth) ? maxWidth : allLabelsWidth;
- labelHeight = Math.round(recordLabels[0].height * labelWidth / recordLabels[0].width); // width is based on height scale
- topEdge = Math.round(albumart_size.y + albumart_size.h - labelHeight);
-
- var a = topEdge - cdCenter.y + 1; // adding 1 to a and b so that the border just touches the edge of the cdart
- var b = leftEdge - cdCenter.x + 1;
-
- if ((a * a + b * b) > radius * radius) {
- break;
- }
- leftEdge += 4;
- }
- } else {
- leftEdge = Math.round(Math.max(albumart_size.x + albumart_size.w + leftEdgeWidth + leftEdgeGap, ww * 0.975 - totalLabelWidth + 1));
- }
- } else {
- leftEdge = Math.round(ww * 0.975 - totalLabelWidth);
- }
- labelAreaWidth = ww - leftEdge - rightSideGap;
- lastLeftEdge = leftEdge;
- } else {
- // already calculated
- leftEdge = lastLeftEdge;
- labelAreaWidth = ww - leftEdge - rightSideGap;
- }
- if (labelAreaWidth >= 50) {
- if (recordLabels.length > 1) {
- labelSpacing = Math.min(12, Math.max(3, Math.round((labelAreaWidth / (recordLabels.length - 1)) * 0.048))); // spacing should be proportional, and between 3 and 12 pixels
- }
- // console.log('labelAreaWidth = ' + labelAreaWidth + ", labelSpacing = " + labelSpacing);
- allLabelsWidth = Math.max(Math.min(Math.round((labelAreaWidth - (labelSpacing * (recordLabels.length - 1))) / recordLabels.length), maxLabelWidth), 50); // allLabelsWidth must be between 50 and 200 pixels wide
- var labelX = leftEdge;
- topEdge = albumart_size.y + albumart_size.h - labelHeight - 20;
- var origLabelHeight = labelHeight;
-
- if (!labelShadowImg) {
- labelShadowImg = createShadowRect(ww - labelX + leftEdgeWidth, labelHeight + 40);
- }
- gr.DrawImage(labelShadowImg, labelX - leftEdgeWidth - geo.aa_shadow, topEdge - 20 - geo.aa_shadow, ww - labelX + leftEdgeWidth + 2 * geo.aa_shadow, labelHeight + 40 + 2 * geo.aa_shadow,
- 0, 0, labelShadowImg.width, labelShadowImg.height);
- gr.SetSmoothingMode(SmoothingMode.None); // disable smoothing
- gr.FillSolidRect(labelX - leftEdgeWidth, topEdge - 20, ww - labelX + leftEdgeWidth, labelHeight + 40, col.info_bg);
- gr.DrawRect(labelX - leftEdgeWidth, topEdge - 20, ww - labelX + leftEdgeWidth, labelHeight + 40 - 1, 1, col.accent);
- gr.SetSmoothingMode(SmoothingMode.AntiAlias);
- for (i = 0; i < recordLabels.length; i++) {
- // allLabelsWidth can never be greater than 200, so if a label image is 161 pixels wide, never draw it wider than 161
- var maxWidth = is_4k && recordLabels[i].width < 200 ? recordLabels[i].width * 2 : recordLabels[i].width;
- labelWidth = (allLabelsWidth > maxWidth) ? maxWidth : allLabelsWidth;
- labelHeight = Math.round(recordLabels[i].height * labelWidth / recordLabels[i].width); // width is based on height scale
-
- gr.DrawImage(recordLabels[i], labelX, Math.round(topEdge + origLabelHeight / 2 - labelHeight / 2), labelWidth, labelHeight, 0, 0, recordLabels[i].width, recordLabels[i].height);
- // gr.DrawRect(labelX, topEdge, labelWidth, labelHeight, 1, RGB(255,0,0)); // shows bounding rect of record labels
- labelX += labelWidth + labelSpacing;
- }
- labelHeight = origLabelHeight; // restore
- }
- if (showExtraDrawTiming) drawLabelTime.Print();
- }
- } /* if (!displayPlaylist && !displayLibrary) */
-
- // MENUBAR
- showExtraDrawTiming && (drawMenuBar = fb.CreateProfiler("on_paint -> menu bar"));
- for (var i in btns) {
- var x = btns[i].x,
- y = btns[i].y,
- w = btns[i].w,
- h = btns[i].h,
- img = btns[i].img;
-
- if (img) { // TODO: fix
- gr.DrawImage(img[0], x, y, w, h, 0, 0, w, h, 0, 255); // normal
- gr.DrawImage(img[1], x, y, w, h, 0, 0, w, h, 0, btns[i].hoverAlpha);
- gr.DrawImage(img[2], x, y, w, h, 0, 0, w, h, 0, btns[i].downAlpha);
- }
- }
-
- showExtraDrawTiming && drawMenuBar.Print();
-
- // LOWER BAR
- var lowerBarTop = wh - geo.lower_bar_h;
- var pbLeft = Math.round(0.025 * ww);
-
- // Title & artist
- //if (showExtraDrawTiming) drawLowerBar = fb.CreateProfiler("on_paint -> lowerBar");
- if (ww > 600) {
- if (str.disc != '')
- width = gr.CalcTextWidth(str.disc + ' ' + str.time + ' ' + str.length, ft.lower_bar);
- else
- width = gr.CalcTextWidth(' ' + str.time + ' ' + str.length, ft.lower_bar);
- } else {
- width = 0;
- }
-
- var ft_lower_bold = ft.lower_bar_bold;
- var ft_lower = ft.lower_bar;
- var ft_lower_orig_artist = ft.lower_bar_artist;
- var trackNumWidth = Math.ceil(gr.MeasureString(str.tracknum, ft_lower, 0, 0, 0, 0).Width);
- var titleMeasurements = gr.MeasureString(str.title_lower, ft_lower, 0, 0, 0, 0);
- var titleWidth = titleMeasurements.Width;
- var origArtistWidth = gr.MeasureString(str.original_artist, ft_lower_orig_artist, 0, 0, 0, 0).Width;
- if (width + trackNumWidth + titleWidth + origArtistWidth > 0.95 * ww) {
- // we don't have room for all the text so use a smaller font and recalc size
- ft_lower_bold = ft.lower_bar_sml_bold;
- ft_lower = ft.lower_bar_sml;
- ft_lower_orig_artist = ft.lower_bar_artist_sml;
- titleMeasurements = gr.MeasureString(str.title_lower, ft_lower, 0, 0, 0, 0);
- trackNumWidth = Math.ceil(gr.MeasureString(str.tracknum, ft.lower_bar_sml_bold, 0, 0, 0, 0).Width);
- if (str.disc !== '') {
- width = gr.CalcTextWidth(str.disc + ' ' + str.time + ' ' + str.length, ft_lower);
- } else {
- width = gr.CalcTextWidth(' ' + str.time + ' ' + str.length, ft_lower);
- }
- }
- gr.DrawString(str.tracknum, ft_lower_bold, col.now_playing, pbLeft, lowerBarTop, 0.95 * ww - width, titleMeasurements.Height, StringFormat(0, 0, 4, 0x00001000));
- width += trackNumWidth;
- gr.DrawString(str.title_lower, ft_lower, col.now_playing, pbLeft + trackNumWidth, lowerBarTop, 0.95 * ww - width, titleMeasurements.Height, StringFormat(0, 0, 4, 0x00001000));
- width += Math.ceil(titleMeasurements.Width);
- if (str.original_artist && width < 0.95 * ww) {
- var h_spacing = 0;
- var v_spacing = 0;
- if (useNeue) {
- h_spacing = is_4k ? 8 : 4;
- v_spacing = is_4k ? 2 : 1;
- }
- gr.DrawString(str.original_artist, ft_lower_orig_artist, col.now_playing, pbLeft + trackNumWidth + titleMeasurements.Width + h_spacing, lowerBarTop + v_spacing, 0.95 * ww - width, titleMeasurements.Height, StringFormat(0, 0, 4, 0x00001000));
- }
-
- // Progress bar/Seekbar
- var pbTop = Math.round(lowerBarTop + titleMeasurements.Height) + (is_4k ? 16 : 8);
- gr.SetSmoothingMode(SmoothingMode.None); // disable smoothing
- if (pref.show_progress_bar) {
- gr.FillSolidRect(pbLeft, pbTop, Math.round(0.95 * ww), geo.prog_bar_h, col.progress_bar);
- }
- if (fb.PlaybackLength > 0) {
- if (ww > 600) {
- gr.DrawString(str.length, ft_lower, col.now_playing, 0.725 * ww, lowerBarTop, 0.25 * ww, titleMeasurements.Height, StringFormat(2, 0));
- width = gr.CalcTextWidth(' ' + str.length, ft_lower);
- gr.DrawString(str.time, ft_lower_bold, col.now_playing, 0.725 * ww, lowerBarTop, 0.25 * ww - width, titleMeasurements.Height, StringFormat(2, 0));
- width += gr.CalcTextWidth(' ' + str.time, ft_lower_bold);
- gr.DrawString(str.disc, ft_lower, col.now_playing, 0.725 * ww, lowerBarTop, 0.25 * ww - width, titleMeasurements.Height, StringFormat(2, 0));
- }
-
- if (pref.show_progress_bar) {
- var progressStationary = false;
- /* in some cases the progress bar would move backwards at the end of a song while buffering/streaming was occurring.
- This created strange looking jitter so now the progress bar can only increase unless the user seeked in the track. */
- if (progressMoved || Math.floor(0.95 * ww * (fb.PlaybackTime / fb.PlaybackLength)) > progressLength) {
- progressLength = Math.floor(0.95 * ww * (fb.PlaybackTime / fb.PlaybackLength));
- } else {
- progressStationary = true;
- }
- progressMoved = false;
- gr.FillSolidRect(pbLeft, pbTop, progressLength, geo.prog_bar_h, col.progress_fill);
- gr.DrawLine(progressLength + pbLeft, pbTop, progressLength + pbLeft, pbTop + geo.prog_bar_h - 1, 1, col.accent);
- if (progressStationary && fb.IsPlaying && !fb.IsPaused) {
- if (col.accent !== last_accent_col || progressAlphaCol === undefined) {
- var c = new Color(col.accent);
- progressAlphaCol = rgba(c.r, c.g, c.b, 100); // fake anti-aliased edge so things look a little smoother
- last_accent_col = col.accent;
- }
- gr.DrawLine(progressLength + pbLeft + 1, pbTop, progressLength + pbLeft + 1, pbTop + geo.prog_bar_h - 1, 1, progressAlphaCol);
- }
- }
- } else if (ww > 600) { // streaming, but still want to show time
- gr.DrawString(str.time, ft.lower_bar, col.now_playing, Math.floor(0.725 * ww), lowerBarTop, 0.25 * ww, 0.5 * geo.lower_bar_h, StringFormat(2, 0));
- }
- gr.SetSmoothingMode(SmoothingMode.AntiAlias);
-
- if (displayPlaylist) {
- showExtraDrawTiming && (drawPlaylist = fb.CreateProfiler('on_paint -> playlist'));
- if (!playlist_shadow) {
- playlist_shadow = createShadowRect(playlist.w + 2 * geo.aa_shadow, playlist.h); // extend shadow past edge
- }
- gr.DrawImage(playlist_shadow, playlist.x - geo.aa_shadow, playlist.y - geo.aa_shadow, playlist.w + 2 * geo.aa_shadow, playlist.h + 2 * geo.aa_shadow,
- 0, 0, playlist_shadow.width, playlist_shadow.height);
- playlist.on_paint(gr);
- showExtraDrawTiming && drawPlaylist.Print();
- } else if (displayLibrary) {
- if (typeof libraryPanel !== 'undefined') {
- libraryPanel.on_paint(gr);
- } else {
- // TODO: take this if/else out once this part is done
- displayLibrary = false;
- }
- }
-
- if (showDrawTiming) {
- drawStuff.Print();
- }
-}
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-function show_lyrics(gr, tab, posy) {
- var i, k, text_colour;
- divider_spacing = is_4k ? 80 : 40;
- divider_height = is_4k ? 20 : 10;
-
- if (showDebugTiming)
- show_lyricsTime = fb.CreateProfiler("show_lyrics");
- gr.SetTextRenderingHint(TextRenderingHint.AntiAlias);
- var g_txt_align = cc_stringformat;
-
- if (dividerImg && dividerImg.width < (albumart_size.w - 10) && posy - divider_spacing - dividerImg.height >= albumart_size.y + pref.lyrics_h_padding) {
- gr.FillRoundRect(albumart_size.x + Math.floor(albumart_size.w * .2) - 1, posy - divider_spacing - divider_height + 1, Math.floor(albumart_size.w * 0.6), divider_height, divider_height / 2, divider_height / 2, col.darkAccent);
- gr.FillRoundRect(albumart_size.x + Math.floor(albumart_size.w * .2), posy - divider_spacing - divider_height, Math.floor(albumart_size.w * 0.6), divider_height, divider_height / 2, divider_height / 2, col.info_bg);
- }
- for (i = 0; i < tab.length; i++) {
- if (posy >= albumart_size.y + pref.lyrics_h_padding && posy < albumart_size.h - pref.lyrics_h_padding) {
- if (i == focus && g_lyrics_status == 1) {
- text_colour = g_txt_highlightcolour;
- } else {
- if (g_lyrics_status == 0) {
- text_colour = g_txt_highlightcolour;
- } else {
- text_colour = g_txt_normalcolour;
- }
- }
- lineHeight = tab[i].total_lines * pref.lyrics_line_height;
- // maybe redo this to use albumart_size.x+(albumart_size.w-lyricsWidth)/2 and lyricsWidth
- pref.lyrics_glow && gr.DrawString(tab[i].text, ft.lyrics, g_txt_shadowcolor, albumart_size.x + (albumart_size.w - lyricsWidth) / 2 - 1, posy, lyricsWidth, lineHeight, g_txt_align);
- pref.lyrics_glow && gr.DrawString(tab[i].text, ft.lyrics, g_txt_shadowcolor, albumart_size.x + (albumart_size.w - lyricsWidth) / 2, posy - 1, lyricsWidth, lineHeight, g_txt_align);
- pref.lyrics_text_shadow && gr.DrawString(tab[i].text, ft.lyrics, g_txt_shadowcolor, albumart_size.x + (albumart_size.w - lyricsWidth) / 2 + 2, posy + 2, lyricsWidth, lineHeight, g_txt_align);
- gr.DrawString(tab[i].text, ft.lyrics, text_colour, albumart_size.x + (albumart_size.w - lyricsWidth) / 2, posy, lyricsWidth, lineHeight, g_txt_align);
- }
- posy = Math.floor(posy + pref.lyrics_line_height + ((tab[i].total_lines - 1) * pref.lyrics_line_height));
- }
- posy += divider_spacing;
- if (dividerImg && dividerImg.width < (albumart_size.w - 10) && posy < albumart_size.h - pref.lyrics_h_padding) {
- // gr.DrawImage(dividerImg, albumart_size.x+(albumart_size.w-dividerImg.width)/2, posy, dividerImg.width, dividerImg.height, 0,0,dividerImg.width,dividerImg.height);
- gr.FillRoundRect(albumart_size.x + Math.floor(albumart_size.w * .2) - 1, posy + 1, Math.floor(albumart_size.w * 0.6), divider_height, divider_height / 2, divider_height / 2, col.darkAccent);
- gr.FillRoundRect(albumart_size.x + Math.floor(albumart_size.w * .2), posy, Math.floor(albumart_size.w * 0.6), divider_height, divider_height / 2, divider_height / 2, col.info_bg);
- }
-
- if (showDebugTiming)
- show_lyricsTime.Print();
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-
-function onRatingMenu(x, y) {
- var MF_SEPARATOR = 0x00000800;
- var MF_STRING = 0x00000000;
- var idx;
- var _menu = window.CreatePopupMenu();
-
- menu_down = true;
-
- var rating = fb.TitleFormat("%rating%").Eval();
-
- _menu.AppendMenuItem(MF_STRING, 1, "No rating");
- _menu.CheckMenuItem(1, rating == null ? 1 : 0);
- _menu.AppendMenuItem(MF_STRING, 11, "1 Star");
- _menu.CheckMenuItem(11, rating == 1 ? 1 : 0);
- _menu.AppendMenuItem(MF_STRING, 12, "2 Stars");
- _menu.CheckMenuItem(12, rating == 2 ? 1 : 0);
- _menu.AppendMenuItem(MF_STRING, 13, "3 Stars");
- _menu.CheckMenuItem(13, rating == 3 ? 1 : 0);
- _menu.AppendMenuItem(MF_STRING, 14, "4 Stars");
- _menu.CheckMenuItem(14, rating == 4 ? 1 : 0);
- _menu.AppendMenuItem(MF_STRING, 15, "5 Stars");
- _menu.CheckMenuItem(15, rating == 5 ? 1 : 0);
-
- idx = _menu.TrackPopupMenu(x, y);
- switch (idx) {
- case 1:
- fb.RunContextCommand("Playback Statistics/Rating/");
- break;
- case 11:
- fb.RunContextCommand("Playback Statistics/Rating/1");
- break;
- case 12:
- fb.RunContextCommand("Playback Statistics/Rating/2");
- break;
- case 13:
- fb.RunContextCommand("Playback Statistics/Rating/3");
- break;
- case 14:
- fb.RunContextCommand("Playback Statistics/Rating/4");
- break;
- case 15:
- fb.RunContextCommand("Playback Statistics/Rating/5");
- break;
- }
- _menu.Dispose();
- menu_down = false;
-}
-
-function GetTimezoneMenuItem() {
- var timezone = pref.time_zone.trim();
- var isNegative = timezone[0] === '-' ? true : false;
- timezone = timezone.replace('-', '').replace('+', '');
- timezone = timezone.split(':');
-
- var hours = parseInt(timezone[0]);
- var mins = parseInt(timezone[1]);
-
- if (mins > 0 || hours > 12) { // not in our timezone menu list
- return 0;
- }
- return 140 + 12 + (isNegative ? -hours : hours);
-}
-
-function SetTimezoneFromMenuItem(menu_idx) {
- var index = menu_idx - 140;
- var timezone = '';
-
- if (index > 12) {
- timezone = '+';
- timezone += leftPad(index - 12, 2, '0');
- timezone += ':00';
- } else {
- timezone = '-';
- timezone += leftPad(12 - index, 2, '0');
- timezone += ':00';
- }
-
- console.log('Setting timezone to', timezone);
- pref.time_zone = timezone;
-}
-
-function onSettingsMenu(x, y) {
- var MF_SEPARATOR = 0x00000800;
- var MF_STRING = 0x00000000;
- var MF_GRAYED = 0x00000001;
- var MF_DISABLED = 0x00000002;
- var MF_POPUP = 0x00000010;
- var idx;
-
- menu_down = true;
-
- // Settings
- var _menu = window.CreatePopupMenu();
- var _rotationMenu = window.CreatePopupMenu();
- var _debugMenu = window.CreatePopupMenu();
- var _libraryMenu = window.CreatePopupMenu();
- var _timeZoneMenu = window.CreatePopupMenu();
-
- //var pbo = fb.PlaybackOrder;
+ var flagWidths = 0;
+ var flagsLeft = textLeft + width + (is_4k ? 30 : 15);
+ for (i = 0; i < flagImgs.length; i++) {
+ gr.DrawImage(flagImgs[i], flagsLeft, Math.round(artistY + 1 + height / 2 - flagImgs[i].height / 2),
+ flagImgs[i].width, flagImgs[i].height, 0, 0, flagImgs[i].width, flagImgs[i].height)
+ flagsLeft += flagImgs[i].width + (is_4k ? 10 : 5);
+ }
+ }
+ }
+
+ if (((!displayPlaylist && !displayLibrary) || (!albumart && noArtwork)) && fb.IsPlaying) {
+ if (!albumart && cdart) {
+ gridSpace = Math.round(cdart_size.x - geo.aa_shadow - textLeft);
+ } else {
+ gridSpace = Math.round(albumart_size.x - geo.aa_shadow - textLeft);
+ }
+ text_width = gridSpace;
+
+ if (showExtraDrawTiming) drawTextGrid = fb.CreateProfiler('on_paint -> textGrid');
+
+ var trackInfoHeight = 0;
+ if (str.trackInfo) {
+ gr.SetTextRenderingHint(TextRenderingHint.ClearTypeGridFit);
+ trackInfoHeight = gr.MeasureString(str.trackInfo, ft.track_info, 0, 0, 0, 0).Height;
+ gr.DrawString(str.trackInfo, ft.track_info, col.artist, ww - textLeft * 2 - text_width, geo.top_bg_h - trackInfoHeight - 15, text_width, trackInfoHeight, StringFormat(StringAlignment.Far));
+ gr.SetTextRenderingHint(TextRenderingHint.AntiAlias);
+ }
+ if (str.year) {
+ height = gr.MeasureString(str.year, ft.year, 0, 0, 0, 0).Height;
+ gr.DrawString(str.year, ft.year, col.artist, ww - textLeft * 2 - text_width, geo.top_bg_h - trackInfoHeight - height - 20, text_width, height, StringFormat(StringAlignment.Far));
+ }
+
+ var top = (albumart_size.y ? albumart_size.y : geo.top_art_spacing) + (is_4k ? 30 : 15);
+ if (gridSpace > 120) {
+ if (str.title) {
+ ft.title = ft.title_lrg;
+ ft.tracknum = ft.tracknum_lrg;
+ var title_spacing = is_4k ? 16 : 8;
+ var trackNumWidth = 0;
+ if (str.tracknum) {
+ trackNumWidth = gr.MeasureString(str.tracknum, ft.tracknum, 0, 0, 0, 0).Width + title_spacing;
+ }
+ txtRec = gr.MeasureString(str.title, ft.title, 0, 0, text_width - trackNumWidth, wh);
+ if (txtRec.lines > 2) {
+ ft.title = ft.title_med;
+ ft.tracknum = ft.tracknum_med;
+ if (str.tracknum) {
+ trackNumWidth = gr.MeasureString(str.tracknum, ft.tracknum, 0, 0, 0, 0).Width + title_spacing;
+ }
+ txtRec = gr.MeasureString(str.title, ft.title, 0, 0, text_width - trackNumWidth, wh);
+ if (txtRec.lines > 2) {
+ ft.title = ft.title_sml;
+ ft.tracknum = ft.tracknum_sml;
+ if (str.tracknum) {
+ trackNumWidth = gr.MeasureString(str.tracknum, ft.tracknum, 0, 0, 0, 0).Width + title_spacing;
+ }
+ txtRec = gr.MeasureString(str.title, ft.title, 0, 0, text_width - trackNumWidth, wh);
+ }
+ }
+ var tracknumHeight = gr.MeasureString(str.tracknum, ft.tracknum, 0, 0, 0, 0).Height;
+ var heightAdjustment = Math.ceil((tracknumHeight - gr.MeasureString(str.title, ft.title, 0, 0, 0, 0).Height) / 2);
+ var numLines = Math.min(2, txtRec.lines);
+ height = gr.CalcTextHeight(str.title, ft.title) * numLines + 3;
+
+ trackNumWidth = Math.ceil(trackNumWidth);
+ gr.DrawString(str.tracknum, ft.tracknum, col.info_text, textLeft, top - heightAdjustment, trackNumWidth, height);
+ // gr.DrawRect(textLeft, top, trackNumWidth, height, 1, rgb(255,0,0));
+ gr.SetTextRenderingHint(TextRenderingHint.ClearTypeGridFit); // thicker fonts can use anti-alias
+ gr.DrawString(str.title, ft.title, col.info_text, textLeft + trackNumWidth, top, text_width - trackNumWidth, height, g_string_format.trim_ellipsis_word);
+ // gr.DrawRect(textLeft, top, text_width - trackNumWidth, height, 1, rgb(255,0,0));
+
+ top += height + (is_4k ? 20 : 12);
+ gr.SetTextRenderingHint(TextRenderingHint.AntiAlias);
+ }
+
+ //Timeline playcount bars
+ if (fb.IsPlaying) {
+ var extraLeftSpace = is_4k ? 6 : 3; // add a little space to the left so songs that were played a long time ago show more in the "added" stage
+ gr.SetSmoothingMode(SmoothingMode.None); // disable smoothing
+ width = albumart_size.x - extraLeftSpace - 1; // albumart_size.x set even if no art. Subtract 1 because we want the timeline stop 1 pixel short of art
+
+ gr.FillSolidRect(0, top, width + extraLeftSpace, geo.timeline_h, col.tl_added);
+ if (tl_firstPlayedRatio >= 0 && tl_lastPlayedRatio >= 0) {
+ x1 = Math.floor(width * tl_firstPlayedRatio) + extraLeftSpace;
+ x2 = Math.floor(width * tl_lastPlayedRatio) + extraLeftSpace;
+ gr.FillSolidRect(x1, top, width - x1 + extraLeftSpace, geo.timeline_h, col.tl_played);
+ gr.FillSolidRect(x2, top, width - x2 + extraLeftSpace, geo.timeline_h, col.tl_unplayed);
+ }
+ for (i = 0; i < playedTimesRatios.length; i++) {
+ x = Math.floor(width * playedTimesRatios[i]) + extraLeftSpace;
+ if (!isNaN(x)) {
+ gr.DrawLine(x, top, x, top + geo.timeline_h, is_4k ? 3 : 2, col.tl_play);
+ } else {
+ // console.log('Played Times Error! ratio: ' + playedTimesRatios[i], 'x: ' + x);
+ }
+ }
+ gr.SetSmoothingMode(SmoothingMode.AntiAlias);
+ }
+
+ top += geo.timeline_h + (is_4k ? 20 : 12);
+
+ if (str.album) {
+ var drawSubtitle = !!str.album_subtitle.length;
+ ft_album = ft.album_lrg;
+ ft_subtitle = ft.album_substitle_lrg;
+ txtRec = gr.MeasureString(str.album, ft_album, 0, 0, text_width, wh);
+ subtitleRec = gr.MeasureString(str.album_subtitle, ft_subtitle, 0, 0, text_width, wh);
+ if (txtRec.lines > 2 || subtitleRec.lines > 2) {
+ ft_album = ft.album_med;
+ txtRec = gr.MeasureString(str.album, ft_album, 0, 0, text_width, wh);
+ if (txtRec.lines > 2) {
+ ft.album = ft.album_sml;
+ }
+ album_text = str.album + str.album_subtitle;
+ drawSubtitle = false;
+ } else if (txtRec.width + subtitleRec.width > text_width) {
+ album_text = str.album + str.album_subtitle;
+ drawSubtitle = false;
+ } else {
+ // draw subtitle separately
+ album_text = str.album;
+ }
+ var numLines = Math.min(2, txtRec.lines);
+ height = gr.CalcTextHeight(album_text, ft_album) * numLines;
+
+ gr.DrawString(album_text, ft_album, col.info_text, textLeft, top, text_width, height, g_string_format.trim_ellipsis_word);
+ // console.log(drawSubtitle, str.album_subtitle, txtRec.width, subtitleRec.width, text_width);
+ if (drawSubtitle) {
+ gr.DrawString(str.album_subtitle, ft_subtitle, col.info_text,
+ textLeft + Math.ceil(txtRec.width), top, text_width - Math.ceil(txtRec.width), height, g_string_format.trim_ellipsis_word);
+ }
+
+ top += height + (is_4k ? 20 : 10);
+ }
+
+ // Tag grid
+ grid_key_ft = ft.grd_key_lrg;
+ col1_width = calculateGridMaxTextWidth(gr, str.grid, grid_key_ft);
+ if (col1_width < text_width / 3) {
+ grid_val_ft = ft.grd_val_lrg;
+ } else {
+ grid_key_ft = ft.grd_key_med;
+ col1_width = calculateGridMaxTextWidth(gr, str.grid, grid_key_ft);
+ if (col1_width < text_width / 3) {
+ grid_val_ft = ft.grd_val_med;
+ } else {
+ grid_key_ft = ft.grd_key_sml;
+ grid_val_ft = ft.grd_val_sml;
+ col1_width = calculateGridMaxTextWidth(gr, str.grid, grid_key_ft);
+ if (col1_width > text_width / 3) {
+ col1_width = Math.floor(text_width / 3);
+ }
+ }
+ }
+ var column_margin = is_4k ? 20 : 10;
+ var col2_width = text_width - column_margin - col1_width;
+ var col2_left = textLeft + col1_width + column_margin;
+
+ for (k = 0, i = 0; k < str.grid.length; k++) {
+ var key = str.grid[k].label;
+ var value = str.grid[k].val;
+ var showLastFmImage = false;
+ var dropShadow = false;
+ var grid_val_col = col.info_text;
+
+ if (value.length) {
+ switch (key) {
+ case 'Rating':
+ grid_val_col = col.rating;
+ dropShadow = true;
+ break;
+ case 'Mood':
+ grid_val_col = col.mood;
+ dropShadow = true;
+ break;
+ case 'Hotness':
+ grid_val_col = col.hotness;
+ dropShadow = true;
+ break;
+ case 'Play Count':
+ showLastFmImage = true;
+ break;
+ default:
+ break;
+ }
+ txtRec = gr.MeasureString(value, grid_val_ft, 0, 0, col2_width, wh);
+ if (top + txtRec.Height < albumart_size.y + albumart_size.h) {
+ cell_height = txtRec.Height + 5;
+ if (dropShadow) {
+ var border_w = is_4k ? 1 : 0.5;
+ gr.DrawString(value, grid_val_ft, col.extraDarkAccent, col2_left + border_w, top + border_w, col2_width, cell_height, StringFormat(0, 0, 4));
+ gr.DrawString(value, grid_val_ft, col.extraDarkAccent, col2_left - border_w, top + border_w, col2_width, cell_height, StringFormat(0, 0, 4));
+ gr.DrawString(value, grid_val_ft, col.extraDarkAccent, col2_left + border_w, top - border_w, col2_width, cell_height, StringFormat(0, 0, 4));
+ gr.DrawString(value, grid_val_ft, col.extraDarkAccent, col2_left - border_w, top - border_w, col2_width, cell_height, StringFormat(0, 0, 4));
+ }
+ gr.DrawString(key, grid_key_ft, col.info_text, textLeft, top, col1_width, cell_height, g_string_format.trim_ellipsis_char); // key
+ gr.DrawString(value, grid_val_ft, grid_val_col, col2_left, top, col2_width, cell_height, StringFormat(0, 0, 4));
+
+ if (playCountVerifiedByLastFm && showLastFmImage) {
+ var lastFmLogo = lastFmImg;
+ if (colorDistance(col.primary, rgb(185, 0, 0), false) < 132) {
+ lastFmLogo = lastFmWhiteImg;
+ }
+ var heightRatio = (cell_height - 12) / lastFmImg.height;
+ gr.DrawImage(lastFmLogo, col2_left + txtRec.Width + 20, top + 3, Math.round(lastFmLogo.width * heightRatio), cell_height - 12,
+ 0, 0, lastFmLogo.width, lastFmLogo.height);
+ }
+ top += cell_height + 5;
+ }
+ }
+ }
+ }
+ if (showExtraDrawTiming) drawTextGrid.Print();
+
+ } /* if (!displayPlaylist && !displayLibrary) */
+
+ if ((fb.IsPlaying && !displayPlaylist && !displayLibrary) || (!albumart && !cdart && noArtwork)) {
+ // BAND LOGO drawing code
+ showExtraDrawTiming && (drawBandLogos = fb.CreateProfiler("on_paint -> band logos"));
+ availableSpace = albumart_size.y + albumart_size.h - top;
+ if (bandLogo && availableSpace > 75) {
+ // max width we'll draw is 1/2 the full size because the HQ images are just so big
+ logoWidth = Math.min(bandLogoHQ ? (is_4k ? bandLogo.width : bandLogo.width / 2) : bandLogo.width * 1.5, albumart_size.x - ww * 0.05);
+ heightScale = logoWidth / bandLogo.width; // width is fixed to logoWidth, so scale height accordingly
+ if (bandLogo.height * heightScale > availableSpace) {
+ // TODO: could probably do this calc just once, but the logic is complicated
+ heightScale = availableSpace / bandLogo.height;
+ logoWidth = bandLogo.width * heightScale;
+ }
+ logoTop = Math.round(albumart_size.y + albumart_size.h - (heightScale * bandLogo.height)) - 4;
+ if (!bandLogoHQ || is_4k) {
+ logoTop -= 20;
+ }
+ gr.DrawImage(bandLogo, Math.round(albumart_size.x / 2 - logoWidth / 2), logoTop, Math.round(logoWidth), Math.round(bandLogo.height * heightScale),
+ 0, 0, bandLogo.width, bandLogo.height, 0);
+ }
+ if (showExtraDrawTiming) drawBandLogos.Print();
+
+
+ // RECORD LABEL drawing code
+ // this section should draw in 3ms or less always
+ if (recordLabels.length > 0) {
+ var rightSideGap = 20, // how close last label is to right edge
+ labelSpacing = 0,
+ leftEdgeGap = art_off_center ? 20 : 40, // space between art and label
+ maxLabelWidth = is_4k ? 400 : 200;
+ leftEdgeWidth = is_4k ? 45 : 30; // how far label background extends on left
+ if (showExtraDrawTiming) drawLabelTime = fb.CreateProfiler("on_paint -> record labels");
+ totalLabelWidth = 0;
+ for (i = 0; i < recordLabels.length; i++) {
+ if (recordLabels[i].width > maxLabelWidth) {
+ totalLabelWidth += maxLabelWidth;
+ } else {
+ if (is_4k && recordLabels[i].width < 200) {
+ totalLabelWidth += recordLabels[i].width * 2;
+ } else {
+ totalLabelWidth += recordLabels[i].width;
+ }
+ }
+ }
+ if (!lastLeftEdge) { // we don't want to recalculate this every screen refresh
+ debugLog('recalculating lastLeftEdge');
+ labelShadowImg = disposeImg(labelShadowImg);
+ labelWidth = Math.round(totalLabelWidth / recordLabels.length);
+ labelHeight = Math.round(recordLabels[0].height * labelWidth / recordLabels[0].width); // might be recalc'd below
+ if (albumart) {
+ if (cdart && pref.display_cdart) {
+ leftEdge = Math.round(Math.max(albumart_size.x + albumart_scaled.Width + 5, ww * 0.975 - totalLabelWidth + 1));
+ var cdCenter = {};
+ cdCenter.x = Math.round(cdart_size.x + cdart_size.w / 2);
+ cdCenter.y = Math.round(cdart_size.y + cdart_size.h / 2);
+ var radius = cdCenter.y - cdart_size.y;
+
+ while (true) {
+ allLabelsWidth = Math.max(Math.min(Math.round((ww - leftEdge - rightSideGap) / recordLabels.length), maxLabelWidth), 50);
+ //console.log("leftEdge = " + leftEdge + ", ww-leftEdge-10 = " + (ww-leftEdge-10) + ", allLabelsWidth=" + allLabelsWidth);
+ var maxWidth = is_4k && recordLabels[0].width < 200 ? recordLabels[0].width * 2 : recordLabels[0].width;
+ labelWidth = (allLabelsWidth > maxWidth) ? maxWidth : allLabelsWidth;
+ labelHeight = Math.round(recordLabels[0].height * labelWidth / recordLabels[0].width); // width is based on height scale
+ topEdge = Math.round(albumart_size.y + albumart_size.h - labelHeight);
+
+ var a = topEdge - cdCenter.y + 1; // adding 1 to a and b so that the border just touches the edge of the cdart
+ var b = leftEdge - cdCenter.x + 1;
+
+ if ((a * a + b * b) > radius * radius) {
+ break;
+ }
+ leftEdge += 4;
+ }
+ } else {
+ leftEdge = Math.round(Math.max(albumart_size.x + albumart_size.w + leftEdgeWidth + leftEdgeGap, ww * 0.975 - totalLabelWidth + 1));
+ }
+ } else {
+ leftEdge = Math.round(ww * 0.975 - totalLabelWidth);
+ }
+ labelAreaWidth = ww - leftEdge - rightSideGap;
+ lastLeftEdge = leftEdge;
+ } else {
+ // already calculated
+ leftEdge = lastLeftEdge;
+ labelAreaWidth = ww - leftEdge - rightSideGap;
+ }
+ if (labelAreaWidth >= 50) {
+ if (recordLabels.length > 1) {
+ labelSpacing = Math.min(12, Math.max(3, Math.round((labelAreaWidth / (recordLabels.length - 1)) * 0.048))); // spacing should be proportional, and between 3 and 12 pixels
+ }
+ // console.log('labelAreaWidth = ' + labelAreaWidth + ", labelSpacing = " + labelSpacing);
+ allLabelsWidth = Math.max(Math.min(Math.round((labelAreaWidth - (labelSpacing * (recordLabels.length - 1))) / recordLabels.length), maxLabelWidth), 50); // allLabelsWidth must be between 50 and 200 pixels wide
+ var labelX = leftEdge;
+ topEdge = albumart_size.y + albumart_size.h - labelHeight - 20;
+ var origLabelHeight = labelHeight;
+
+ if (!labelShadowImg) {
+ labelShadowImg = createShadowRect(ww - labelX + leftEdgeWidth, labelHeight + 40);
+ }
+ gr.DrawImage(labelShadowImg, labelX - leftEdgeWidth - geo.aa_shadow, topEdge - 20 - geo.aa_shadow, ww - labelX + leftEdgeWidth + 2 * geo.aa_shadow, labelHeight + 40 + 2 * geo.aa_shadow,
+ 0, 0, labelShadowImg.width, labelShadowImg.height);
+ gr.SetSmoothingMode(SmoothingMode.None); // disable smoothing
+ gr.FillSolidRect(labelX - leftEdgeWidth, topEdge - 20, ww - labelX + leftEdgeWidth, labelHeight + 40, col.info_bg);
+ gr.DrawRect(labelX - leftEdgeWidth, topEdge - 20, ww - labelX + leftEdgeWidth, labelHeight + 40 - 1, 1, col.accent);
+ gr.SetSmoothingMode(SmoothingMode.AntiAlias);
+ for (i = 0; i < recordLabels.length; i++) {
+ // allLabelsWidth can never be greater than 200, so if a label image is 161 pixels wide, never draw it wider than 161
+ var maxWidth = is_4k && recordLabels[i].width < 200 ? recordLabels[i].width * 2 : recordLabels[i].width;
+ labelWidth = (allLabelsWidth > maxWidth) ? maxWidth : allLabelsWidth;
+ labelHeight = Math.round(recordLabels[i].height * labelWidth / recordLabels[i].width); // width is based on height scale
+
+ gr.DrawImage(recordLabels[i], labelX, Math.round(topEdge + origLabelHeight / 2 - labelHeight / 2), labelWidth, labelHeight, 0, 0, recordLabels[i].width, recordLabels[i].height);
+ // gr.DrawRect(labelX, topEdge, labelWidth, labelHeight, 1, RGB(255,0,0)); // shows bounding rect of record labels
+ labelX += labelWidth + labelSpacing;
+ }
+ labelHeight = origLabelHeight; // restore
+ }
+ if (showExtraDrawTiming) drawLabelTime.Print();
+ }
+ } /* if (!displayPlaylist && !displayLibrary) */
+
+ // MENUBAR
+ showExtraDrawTiming && (drawMenuBar = fb.CreateProfiler("on_paint -> menu bar"));
+ for (var i in btns) {
+ var x = btns[i].x,
+ y = btns[i].y,
+ w = btns[i].w,
+ h = btns[i].h,
+ img = btns[i].img;
+
+ if (img) { // TODO: fix
+ gr.DrawImage(img[0], x, y, w, h, 0, 0, w, h, 0, 255); // normal
+ gr.DrawImage(img[1], x, y, w, h, 0, 0, w, h, 0, btns[i].hoverAlpha);
+ gr.DrawImage(img[2], x, y, w, h, 0, 0, w, h, 0, btns[i].downAlpha);
+ }
+ }
+
+ showExtraDrawTiming && drawMenuBar.Print();
+
+ // LOWER BAR
+ var lowerBarTop = wh - geo.lower_bar_h;
+ var pbLeft = Math.round(0.025 * ww);
+
+ // Title & artist
+ //if (showExtraDrawTiming) drawLowerBar = fb.CreateProfiler("on_paint -> lowerBar");
+ if (ww > 600) {
+ if (str.disc != '')
+ width = gr.CalcTextWidth(str.disc + ' ' + str.time + ' ' + str.length, ft.lower_bar);
+ else
+ width = gr.CalcTextWidth(' ' + str.time + ' ' + str.length, ft.lower_bar);
+ } else {
+ width = 0;
+ }
+
+ var ft_lower_bold = ft.lower_bar_bold;
+ var ft_lower = ft.lower_bar;
+ var ft_lower_orig_artist = ft.lower_bar_artist;
+ var trackNumWidth = Math.ceil(gr.MeasureString(str.tracknum, ft_lower, 0, 0, 0, 0).Width);
+ var titleMeasurements = gr.MeasureString(str.title_lower, ft_lower, 0, 0, 0, 0);
+ var titleWidth = titleMeasurements.Width;
+ var origArtistWidth = gr.MeasureString(str.original_artist, ft_lower_orig_artist, 0, 0, 0, 0).Width;
+ if (width + trackNumWidth + titleWidth + origArtistWidth > 0.95 * ww) {
+ // we don't have room for all the text so use a smaller font and recalc size
+ ft_lower_bold = ft.lower_bar_sml_bold;
+ ft_lower = ft.lower_bar_sml;
+ ft_lower_orig_artist = ft.lower_bar_artist_sml;
+ titleMeasurements = gr.MeasureString(str.title_lower, ft_lower, 0, 0, 0, 0);
+ trackNumWidth = Math.ceil(gr.MeasureString(str.tracknum, ft.lower_bar_sml_bold, 0, 0, 0, 0).Width);
+ if (str.disc !== '') {
+ width = gr.CalcTextWidth(str.disc + ' ' + str.time + ' ' + str.length, ft_lower);
+ } else {
+ width = gr.CalcTextWidth(' ' + str.time + ' ' + str.length, ft_lower);
+ }
+ }
+ gr.DrawString(str.tracknum, ft_lower_bold, col.now_playing, pbLeft, lowerBarTop, 0.95 * ww - width, titleMeasurements.Height, StringFormat(0, 0, 4, 0x00001000));
+ width += trackNumWidth;
+ gr.DrawString(str.title_lower, ft_lower, col.now_playing, pbLeft + trackNumWidth, lowerBarTop, 0.95 * ww - width, titleMeasurements.Height, StringFormat(0, 0, 4, 0x00001000));
+ width += Math.ceil(titleMeasurements.Width);
+ if (str.original_artist && width < 0.95 * ww) {
+ var h_spacing = 0;
+ var v_spacing = 0;
+ if (useNeue) {
+ h_spacing = is_4k ? 8 : 4;
+ v_spacing = is_4k ? 2 : 1;
+ }
+ gr.DrawString(str.original_artist, ft_lower_orig_artist, col.now_playing, pbLeft + trackNumWidth + titleMeasurements.Width + h_spacing, lowerBarTop + v_spacing, 0.95 * ww - width, titleMeasurements.Height, StringFormat(0, 0, 4, 0x00001000));
+ }
+
+ // Progress bar/Seekbar
+ var pbTop = Math.round(lowerBarTop + titleMeasurements.Height) + (is_4k ? 16 : 8);
+ gr.SetSmoothingMode(SmoothingMode.None); // disable smoothing
+ if (pref.show_progress_bar) {
+ gr.FillSolidRect(pbLeft, pbTop, Math.round(0.95 * ww), geo.prog_bar_h, col.progress_bar);
+ }
+ if (fb.PlaybackLength > 0) {
+ if (ww > 600) {
+ gr.DrawString(str.length, ft_lower, col.now_playing, 0.725 * ww, lowerBarTop, 0.25 * ww, titleMeasurements.Height, StringFormat(2, 0));
+ width = gr.CalcTextWidth(' ' + str.length, ft_lower);
+ gr.DrawString(str.time, ft_lower_bold, col.now_playing, 0.725 * ww, lowerBarTop, 0.25 * ww - width, titleMeasurements.Height, StringFormat(2, 0));
+ width += gr.CalcTextWidth(' ' + str.time, ft_lower_bold);
+ gr.DrawString(str.disc, ft_lower, col.now_playing, 0.725 * ww, lowerBarTop, 0.25 * ww - width, titleMeasurements.Height, StringFormat(2, 0));
+ }
+
+ if (pref.show_progress_bar) {
+ var progressStationary = false;
+ /* in some cases the progress bar would move backwards at the end of a song while buffering/streaming was occurring.
+ This created strange looking jitter so now the progress bar can only increase unless the user seeked in the track. */
+ if (progressMoved || Math.floor(0.95 * ww * (fb.PlaybackTime / fb.PlaybackLength)) > progressLength) {
+ progressLength = Math.floor(0.95 * ww * (fb.PlaybackTime / fb.PlaybackLength));
+ } else {
+ progressStationary = true;
+ }
+ progressMoved = false;
+ gr.FillSolidRect(pbLeft, pbTop, progressLength, geo.prog_bar_h, col.progress_fill);
+ gr.DrawLine(progressLength + pbLeft, pbTop, progressLength + pbLeft, pbTop + geo.prog_bar_h - 1, 1, col.accent);
+ if (progressStationary && fb.IsPlaying && !fb.IsPaused) {
+ if (col.accent !== last_accent_col || progressAlphaCol === undefined) {
+ var c = new Color(col.accent);
+ progressAlphaCol = rgba(c.r, c.g, c.b, 100); // fake anti-aliased edge so things look a little smoother
+ last_accent_col = col.accent;
+ }
+ gr.DrawLine(progressLength + pbLeft + 1, pbTop, progressLength + pbLeft + 1, pbTop + geo.prog_bar_h - 1, 1, progressAlphaCol);
+ }
+ }
+ } else if (ww > 600) { // streaming, but still want to show time
+ gr.DrawString(str.time, ft.lower_bar, col.now_playing, Math.floor(0.725 * ww), lowerBarTop, 0.25 * ww, 0.5 * geo.lower_bar_h, StringFormat(2, 0));
+ }
+ gr.SetSmoothingMode(SmoothingMode.AntiAlias);
+
+ if (displayPlaylist) {
+ showExtraDrawTiming && (drawPlaylist = fb.CreateProfiler('on_paint -> playlist'));
+ if (!playlist_shadow) {
+ playlist_shadow = createShadowRect(playlist.w + 2 * geo.aa_shadow, playlist.h); // extend shadow past edge
+ }
+ gr.DrawImage(playlist_shadow, playlist.x - geo.aa_shadow, playlist.y - geo.aa_shadow, playlist.w + 2 * geo.aa_shadow, playlist.h + 2 * geo.aa_shadow,
+ 0, 0, playlist_shadow.width, playlist_shadow.height);
+ playlist.on_paint(gr);
+ showExtraDrawTiming && drawPlaylist.Print();
+ } else if (displayLibrary) {
+ if (typeof libraryPanel !== 'undefined') {
+ libraryPanel.on_paint(gr);
+ } else {
+ // TODO: take this if/else out once this part is done
+ displayLibrary = false;
+ }
+ }
+
+ if (showDrawTiming) {
+ drawStuff.Print();
+ }
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+function show_lyrics(gr, tab, posy) {
+ var i, k, text_colour;
+ divider_spacing = is_4k ? 80 : 40;
+ divider_height = is_4k ? 20 : 10;
+
+ if (showDebugTiming)
+ show_lyricsTime = fb.CreateProfiler("show_lyrics");
+ gr.SetTextRenderingHint(TextRenderingHint.AntiAlias);
+ var g_txt_align = cc_stringformat;
+
+ if (dividerImg && dividerImg.width < (albumart_size.w - 10) && posy - divider_spacing - dividerImg.height >= albumart_size.y + pref.lyrics_h_padding) {
+ gr.FillRoundRect(albumart_size.x + Math.floor(albumart_size.w * .2) - 1, posy - divider_spacing - divider_height + 1, Math.floor(albumart_size.w * 0.6), divider_height, divider_height / 2, divider_height / 2, col.darkAccent);
+ gr.FillRoundRect(albumart_size.x + Math.floor(albumart_size.w * .2), posy - divider_spacing - divider_height, Math.floor(albumart_size.w * 0.6), divider_height, divider_height / 2, divider_height / 2, col.info_bg);
+ }
+ for (i = 0; i < tab.length; i++) {
+ if (posy >= albumart_size.y + pref.lyrics_h_padding && posy < albumart_size.h - pref.lyrics_h_padding) {
+ if (i == focus && g_lyrics_status == 1) {
+ text_colour = g_txt_highlightcolour;
+ } else {
+ if (g_lyrics_status == 0) {
+ text_colour = g_txt_highlightcolour;
+ } else {
+ text_colour = g_txt_normalcolour;
+ }
+ }
+ lineHeight = tab[i].total_lines * pref.lyrics_line_height;
+ // maybe redo this to use albumart_size.x+(albumart_size.w-lyricsWidth)/2 and lyricsWidth
+ pref.lyrics_glow && gr.DrawString(tab[i].text, ft.lyrics, g_txt_shadowcolor, albumart_size.x + (albumart_size.w - lyricsWidth) / 2 - 1, posy, lyricsWidth, lineHeight, g_txt_align);
+ pref.lyrics_glow && gr.DrawString(tab[i].text, ft.lyrics, g_txt_shadowcolor, albumart_size.x + (albumart_size.w - lyricsWidth) / 2, posy - 1, lyricsWidth, lineHeight, g_txt_align);
+ pref.lyrics_text_shadow && gr.DrawString(tab[i].text, ft.lyrics, g_txt_shadowcolor, albumart_size.x + (albumart_size.w - lyricsWidth) / 2 + 2, posy + 2, lyricsWidth, lineHeight, g_txt_align);
+ gr.DrawString(tab[i].text, ft.lyrics, text_colour, albumart_size.x + (albumart_size.w - lyricsWidth) / 2, posy, lyricsWidth, lineHeight, g_txt_align);
+ }
+ posy = Math.floor(posy + pref.lyrics_line_height + ((tab[i].total_lines - 1) * pref.lyrics_line_height));
+ }
+ posy += divider_spacing;
+ if (dividerImg && dividerImg.width < (albumart_size.w - 10) && posy < albumart_size.h - pref.lyrics_h_padding) {
+ // gr.DrawImage(dividerImg, albumart_size.x+(albumart_size.w-dividerImg.width)/2, posy, dividerImg.width, dividerImg.height, 0,0,dividerImg.width,dividerImg.height);
+ gr.FillRoundRect(albumart_size.x + Math.floor(albumart_size.w * .2) - 1, posy + 1, Math.floor(albumart_size.w * 0.6), divider_height, divider_height / 2, divider_height / 2, col.darkAccent);
+ gr.FillRoundRect(albumart_size.x + Math.floor(albumart_size.w * .2), posy, Math.floor(albumart_size.w * 0.6), divider_height, divider_height / 2, divider_height / 2, col.info_bg);
+ }
+
+ if (showDebugTiming)
+ show_lyricsTime.Print();
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+function onRatingMenu(x, y) {
+ var MF_SEPARATOR = 0x00000800;
+ var MF_STRING = 0x00000000;
+ var idx;
+ var _menu = window.CreatePopupMenu();
+
+ menu_down = true;
+
+ var rating = fb.TitleFormat("%rating%").Eval();
+
+ _menu.AppendMenuItem(MF_STRING, 1, "No rating");
+ _menu.CheckMenuItem(1, rating == null ? 1 : 0);
+ _menu.AppendMenuItem(MF_STRING, 11, "1 Star");
+ _menu.CheckMenuItem(11, rating == 1 ? 1 : 0);
+ _menu.AppendMenuItem(MF_STRING, 12, "2 Stars");
+ _menu.CheckMenuItem(12, rating == 2 ? 1 : 0);
+ _menu.AppendMenuItem(MF_STRING, 13, "3 Stars");
+ _menu.CheckMenuItem(13, rating == 3 ? 1 : 0);
+ _menu.AppendMenuItem(MF_STRING, 14, "4 Stars");
+ _menu.CheckMenuItem(14, rating == 4 ? 1 : 0);
+ _menu.AppendMenuItem(MF_STRING, 15, "5 Stars");
+ _menu.CheckMenuItem(15, rating == 5 ? 1 : 0);
+
+ idx = _menu.TrackPopupMenu(x, y);
+ switch (idx) {
+ case 1:
+ fb.RunContextCommand("Playback Statistics/Rating/");
+ break;
+ case 11:
+ fb.RunContextCommand("Playback Statistics/Rating/1");
+ break;
+ case 12:
+ fb.RunContextCommand("Playback Statistics/Rating/2");
+ break;
+ case 13:
+ fb.RunContextCommand("Playback Statistics/Rating/3");
+ break;
+ case 14:
+ fb.RunContextCommand("Playback Statistics/Rating/4");
+ break;
+ case 15:
+ fb.RunContextCommand("Playback Statistics/Rating/5");
+ break;
+ }
+ _menu.Dispose();
+ menu_down = false;
+}
+
+function GetTimezoneMenuItem() {
+ var timezone = pref.time_zone.trim();
+ var isNegative = timezone[0] === '-' ? true : false;
+ timezone = timezone.replace('-', '').replace('+', '');
+ timezone = timezone.split(':');
+
+ var hours = parseInt(timezone[0]);
+ var mins = parseInt(timezone[1]);
+
+ if (mins > 0 || hours > 12) { // not in our timezone menu list
+ return 0;
+ }
+ return 140 + 12 + (isNegative ? -hours : hours);
+}
+
+function SetTimezoneFromMenuItem(menu_idx) {
+ var index = menu_idx - 140;
+ var timezone = '';
+
+ if (index > 12) {
+ timezone = '+';
+ timezone += leftPad(index - 12, 2, '0');
+ timezone += ':00';
+ } else {
+ timezone = '-';
+ timezone += leftPad(12 - index, 2, '0');
+ timezone += ':00';
+ }
+
+ console.log('Setting timezone to', timezone);
+ pref.time_zone = timezone;
+}
+
+function onSettingsMenu(x, y) {
+ var MF_SEPARATOR = 0x00000800;
+ var MF_STRING = 0x00000000;
+ var MF_GRAYED = 0x00000001;
+ var MF_DISABLED = 0x00000002;
+ var MF_POPUP = 0x00000010;
+ var idx;
+
+ menu_down = true;
+
+ // Settings
+ var _menu = window.CreatePopupMenu();
+ var _rotationMenu = window.CreatePopupMenu();
+ var _debugMenu = window.CreatePopupMenu();
+ var _libraryMenu = window.CreatePopupMenu();
+ var _timeZoneMenu = window.CreatePopupMenu();
+
+ //var pbo = fb.PlaybackOrder;
var _4kMenu = window.CreatePopupMenu();
_4kMenu.AppendMenuItem(MF_STRING, 120, 'Auto-detect');
_4kMenu.CheckMenuItem(120, pref.use_4k === 'auto');
@@ -1124,238 +1124,238 @@ function onSettingsMenu(x, y) {
_4kMenu.CheckMenuItem(122, pref.use_4k === 'always');
_4kMenu.AppendTo(_menu, MF_STRING, 'Use 4K mode');
- _menu.AppendMenuItem(MF_STRING, 1, 'Cycle Through All Artwork');
- _menu.CheckMenuItem(1, pref.aa_glob);
- _menu.AppendMenuItem(MF_STRING, 4, 'Display CD Art (cd.pngs)');
- _menu.CheckMenuItem(4, pref.display_cdart);
- _menu.AppendMenuItem(pref.display_cdart ? MF_STRING : MF_DISABLED, 5, 'Rotate CD Art on track change');
- _menu.CheckMenuItem(5, pref.rotate_cdart);
-
- _rotationMenu.AppendMenuItem(MF_STRING, 130, '2 degrees');
- _rotationMenu.AppendMenuItem(MF_STRING, 131, '3 degrees');
- _rotationMenu.AppendMenuItem(MF_STRING, 132, '4 degrees');
- _rotationMenu.AppendMenuItem(MF_STRING, 133, '5 degrees');
- _rotationMenu.CheckMenuRadioItem(130, 133, parseInt(pref.rotation_amt) + 128);
- _rotationMenu.AppendTo(_menu, MF_STRING, 'CD Art Rotation Amount');
-
- _menu.AppendMenuItem(pref.display_cdart ? MF_STRING : MF_DISABLED, 6, 'Display CD Art above cover');
- _menu.CheckMenuItem(6, pref.cdart_ontop);
- _menu.AppendMenuSeparator();
-
- _menu.AppendMenuItem(MF_STRING, 12, 'Display playlist on startup');
- _menu.CheckMenuItem(12, pref.start_Playlist);
- _menu.AppendMenuItem(MF_STRING, 13, 'Show Transport Controls');
- _menu.CheckMenuItem(13, pref.show_transport);
- _menu.AppendMenuItem(MF_STRING, 14, 'Show Progress Bar');
- _menu.CheckMenuItem(14, pref.show_progress_bar);
- _menu.AppendMenuItem(MF_STRING, 15, 'Update Progress Bar frequently (higher CPU)');
- _menu.CheckMenuItem(15, pref.freq_update);
- _menu.AppendMenuSeparator();
-
- _menu.AppendMenuItem(MF_STRING, 17, 'Use Vinyl Style Numbering if Available');
- _menu.CheckMenuItem(17, pref.use_vinyl_nums);
- _menu.AppendMenuSeparator();
- _menu.AppendMenuItem(MF_STRING, 18, 'Show Artist Country Flags');
- _menu.CheckMenuItem(18, pref.show_flags);
- _menu.AppendMenuSeparator();
-
- _timeZoneMenu.AppendMenuItem(MF_STRING, 140, 'GMT -12:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 141, 'GMT -11:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 142, 'GMT -10:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 143, 'GMT -9:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 144, 'GMT -8:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 145, 'GMT -7:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 146, 'GMT -6:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 147, 'GMT -5:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 148, 'GMT -4:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 149, 'GMT -3:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 150, 'GMT -2:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 151, 'GMT -1:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 152, 'GMT +0:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 153, 'GMT +1:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 154, 'GMT +2:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 155, 'GMT +3:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 156, 'GMT +4:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 157, 'GMT +5:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 158, 'GMT +6:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 159, 'GMT +7:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 160, 'GMT +8:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 161, 'GMT +9:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 162, 'GMT +10:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 163, 'GMT +11:00');
- _timeZoneMenu.AppendMenuItem(MF_STRING, 164, 'GMT +12:00');
- _timeZoneMenu.CheckMenuRadioItem(140, 164, GetTimezoneMenuItem());
- _timeZoneMenu.AppendTo(_menu, MF_STRING, 'Time-Zone');
-
- _menu.AppendMenuSeparator();
- _menu.AppendMenuItem(MF_STRING, 30, 'Follow Hyperlinks only if CTRL-key is down');
- _menu.CheckMenuItem(30, pref.hyperlinks_ctrl);
- _menu.AppendMenuSeparator();
-
-
- _libraryMenu.AppendMenuItem(MF_STRING, 50, 'Remember Library State');
- _libraryMenu.CheckMenuItem(50, libraryProps.rememberTree);
- _libraryMenu.AppendMenuItem(MF_STRING, 51, 'Full Line Clickable');
- _libraryMenu.CheckMenuItem(51, libraryProps.fullLine);
- _libraryMenu.AppendMenuItem(MF_STRING, 52, 'Show Tooltips');
- _libraryMenu.CheckMenuItem(52, libraryProps.tooltips);
-
- var _rootNodeMenu = window.CreatePopupMenu();
- _rootNodeMenu.AppendMenuItem(MF_STRING, 170, 'Hide');
- _rootNodeMenu.AppendMenuItem(MF_STRING, 171, '"All Music"');
- _rootNodeMenu.AppendMenuItem(MF_STRING, 172, 'View Name');
- _rootNodeMenu.CheckMenuRadioItem(170, 172, 170 + libraryProps.rootNode);
- _rootNodeMenu.AppendTo(_libraryMenu, MF_STRING, 'Root Node Type');
- var _nodeitemCountsMenu = window.CreatePopupMenu();
- _nodeitemCountsMenu.AppendMenuItem(MF_STRING, 180, 'Hidden');
- _nodeitemCountsMenu.AppendMenuItem(MF_STRING, 181, '# Tracks');
- _nodeitemCountsMenu.AppendMenuItem(MF_STRING, 182, '# Sub-Items');
- _nodeitemCountsMenu.CheckMenuRadioItem(180, 182, 180 + libraryProps.nodeItemCounts);
- _nodeitemCountsMenu.AppendTo(_libraryMenu, MF_STRING, 'Node Item Counts');
-
- _libraryMenu.AppendMenuItem(MF_STRING, 53, 'Show Library Scrollbar');
- _libraryMenu.CheckMenuItem(53, libraryProps.showScrollbar);
- _libraryMenu.AppendMenuItem(MF_STRING, 54, 'Send files to Current Playlist');
- _libraryMenu.CheckMenuItem(54, libraryProps.sendToCurrent);
- _libraryMenu.AppendMenuItem(MF_STRING, 55, 'Auto-Fill Playlist on Selection');
- _libraryMenu.CheckMenuItem(55, libraryProps.autoFill);
-
- var _doubleClickMenu = window.CreatePopupMenu();
- _doubleClickMenu.AppendMenuItem(MF_STRING, 190, 'Expand/Collapse Folders');
- _doubleClickMenu.AppendMenuItem(MF_STRING, 191, 'Send and Play');
- _doubleClickMenu.AppendMenuItem(MF_STRING, 192, 'Send to Playlist');
- _doubleClickMenu.CheckMenuRadioItem(190, 192, 190 + libraryProps.doubleClickAction);
- _doubleClickMenu.AppendTo(_libraryMenu, MF_STRING, 'Double Click Action');
- _libraryMenu.AppendMenuItem(MF_STRING, 57, 'Auto Collapse Nodes');
- _libraryMenu.CheckMenuItem(57, libraryProps.autoCollapse);
- _libraryMenu.AppendMenuItem(MF_STRING, 58, 'Reset Library Zoom');
- _libraryMenu.AppendTo(_menu, MF_STRING, 'Library Settings');
- _menu.AppendMenuSeparator();
-
- _debugMenu.AppendMenuItem(MF_STRING, 90, 'Enable debug output');
- _debugMenu.CheckMenuItem(90, pref.show_debug_log);
- _debugMenu.AppendMenuItem(MF_STRING, 95, 'Enable theme debug output');
- _debugMenu.CheckMenuItem(95, pref.show_theme_log);
- _debugMenu.AppendMenuItem(MF_STRING, 91, 'Show draw timing');
- _debugMenu.CheckMenuItem(91, showDrawTiming);
- _debugMenu.AppendMenuItem(MF_STRING, 92, 'Show extra draw timing');
- _debugMenu.CheckMenuItem(92, showExtraDrawTiming);
- _debugMenu.AppendMenuItem(MF_STRING, 93, 'Show debug timing');
- _debugMenu.CheckMenuItem(93, showDebugTiming);
- _debugMenu.AppendMenuItem(MF_STRING, 94, 'Show Reload button');
- _debugMenu.CheckMenuItem(94, pref.show_reload_button);
- _debugMenu.AppendTo(_menu, MF_STRING, 'Debug Settings');
- _menu.AppendMenuSeparator();
- _menu.AppendMenuItem(MF_STRING, 100, 'Lock Right Click...');
- _menu.CheckMenuItem(100, pref.locked);
- _menu.AppendMenuItem(MF_STRING, 101, 'Restart');
-
- idx = _menu.TrackPopupMenu(x, y);
- switch (idx) {
- case 1:
- pref.aa_glob = !pref.aa_glob;
- if (!pref.aa_glob) {
- window.ClearTimeout(globTimer);
- globTimer = 0;
- }
- break;
- case 3:
- break;
- case 4:
- pref.display_cdart = !pref.display_cdart;
- if (fb.IsPlaying) fetchNewArtwork(fb.GetNowPlaying());
- lastLeftEdge = 0; // resize labels
- ResizeArtwork(true);
- RepaintWindow();
- break;
- case 5:
- pref.rotate_cdart = !pref.rotate_cdart;
- RepaintWindow();
- break;
- case 6:
- pref.cdart_ontop = !pref.cdart_ontop;
- RepaintWindow();
- break;
- case 12:
- pref.start_Playlist = !pref.start_Playlist;
- break;
- case 13:
- pref.show_transport = !pref.show_transport;
- createButtonImages();
- createButtonObjects(ww, wh);
- ResizeArtwork(true);
- RepaintWindow();
- break;
- case 14:
- pref.show_progress_bar = !pref.show_progress_bar;
- setGeometry();
- ResizeArtwork(true);
- RepaintWindow();
- break;
- case 15:
- pref.freq_update = !pref.freq_update;
- SetProgressBarRefresh();
- break;
- case 17:
- pref.use_vinyl_nums = !pref.use_vinyl_nums;
- RepaintWindow();
- break;
- case 18:
- pref.show_flags = !pref.show_flags;
- LoadCountryFlags();
- RepaintWindow();
- break;
- case 30:
- pref.hyperlinks_ctrl = !pref.hyperlinks_ctrl;
- break;
- /* Library Menu Items */
- case 50:
- libraryProps.rememberTree = !libraryProps.rememberTree;
- break;
- case 51:
- libraryProps.fullLine = !libraryProps.fullLine;
- break;
- case 52:
- libraryProps.tooltips = !libraryProps.tooltips;
- setLibrarySize();
- break;
- case 53:
- libraryProps.showScrollbar = !libraryProps.showScrollbar;
- setLibrarySize();
- break;
- case 54:
- libraryProps.sendToCurrent = !libraryProps.sendToCurrent;
- break;
- case 55:
- libraryProps.autoFill = !libraryProps.autoFill;
- break;
- case 57:
- libraryProps.autoCollapse = !libraryProps.autoCollapse;
- break;
- case 58:
- libraryProps.filterZoom = 100;
- libraryProps.fontZoom = 100;
- libraryProps.nodeZoom = 100;
- setLibrarySize();
- break;
- case 170:
- case 171:
- case 172:
- libraryProps.rootNode = idx - 170;
- lib_manager.rootNodes(1);
- break;
- case 180:
- case 181:
- case 182:
- libraryProps.nodeItemCounts = idx - 180;
- lib_manager.rootNodes(1);
- break;
- case 190:
- case 191:
- case 192:
- libraryProps.doubleClickAction = idx - 190;
- break;
-
+ _menu.AppendMenuItem(MF_STRING, 1, 'Cycle Through All Artwork');
+ _menu.CheckMenuItem(1, pref.aa_glob);
+ _menu.AppendMenuItem(MF_STRING, 4, 'Display CD Art (cd.pngs)');
+ _menu.CheckMenuItem(4, pref.display_cdart);
+ _menu.AppendMenuItem(pref.display_cdart ? MF_STRING : MF_DISABLED, 5, 'Rotate CD Art on track change');
+ _menu.CheckMenuItem(5, pref.rotate_cdart);
+
+ _rotationMenu.AppendMenuItem(MF_STRING, 130, '2 degrees');
+ _rotationMenu.AppendMenuItem(MF_STRING, 131, '3 degrees');
+ _rotationMenu.AppendMenuItem(MF_STRING, 132, '4 degrees');
+ _rotationMenu.AppendMenuItem(MF_STRING, 133, '5 degrees');
+ _rotationMenu.CheckMenuRadioItem(130, 133, parseInt(pref.rotation_amt) + 128);
+ _rotationMenu.AppendTo(_menu, MF_STRING, 'CD Art Rotation Amount');
+
+ _menu.AppendMenuItem(pref.display_cdart ? MF_STRING : MF_DISABLED, 6, 'Display CD Art above cover');
+ _menu.CheckMenuItem(6, pref.cdart_ontop);
+ _menu.AppendMenuSeparator();
+
+ _menu.AppendMenuItem(MF_STRING, 12, 'Display playlist on startup');
+ _menu.CheckMenuItem(12, pref.start_Playlist);
+ _menu.AppendMenuItem(MF_STRING, 13, 'Show Transport Controls');
+ _menu.CheckMenuItem(13, pref.show_transport);
+ _menu.AppendMenuItem(MF_STRING, 14, 'Show Progress Bar');
+ _menu.CheckMenuItem(14, pref.show_progress_bar);
+ _menu.AppendMenuItem(MF_STRING, 15, 'Update Progress Bar frequently (higher CPU)');
+ _menu.CheckMenuItem(15, pref.freq_update);
+ _menu.AppendMenuSeparator();
+
+ _menu.AppendMenuItem(MF_STRING, 17, 'Use Vinyl Style Numbering if Available');
+ _menu.CheckMenuItem(17, pref.use_vinyl_nums);
+ _menu.AppendMenuSeparator();
+ _menu.AppendMenuItem(MF_STRING, 18, 'Show Artist Country Flags');
+ _menu.CheckMenuItem(18, pref.show_flags);
+ _menu.AppendMenuSeparator();
+
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 140, 'GMT -12:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 141, 'GMT -11:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 142, 'GMT -10:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 143, 'GMT -9:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 144, 'GMT -8:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 145, 'GMT -7:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 146, 'GMT -6:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 147, 'GMT -5:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 148, 'GMT -4:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 149, 'GMT -3:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 150, 'GMT -2:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 151, 'GMT -1:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 152, 'GMT +0:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 153, 'GMT +1:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 154, 'GMT +2:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 155, 'GMT +3:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 156, 'GMT +4:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 157, 'GMT +5:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 158, 'GMT +6:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 159, 'GMT +7:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 160, 'GMT +8:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 161, 'GMT +9:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 162, 'GMT +10:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 163, 'GMT +11:00');
+ _timeZoneMenu.AppendMenuItem(MF_STRING, 164, 'GMT +12:00');
+ _timeZoneMenu.CheckMenuRadioItem(140, 164, GetTimezoneMenuItem());
+ _timeZoneMenu.AppendTo(_menu, MF_STRING, 'Time-Zone');
+
+ _menu.AppendMenuSeparator();
+ _menu.AppendMenuItem(MF_STRING, 30, 'Follow Hyperlinks only if CTRL-key is down');
+ _menu.CheckMenuItem(30, pref.hyperlinks_ctrl);
+ _menu.AppendMenuSeparator();
+
+
+ _libraryMenu.AppendMenuItem(MF_STRING, 50, 'Remember Library State');
+ _libraryMenu.CheckMenuItem(50, libraryProps.rememberTree);
+ _libraryMenu.AppendMenuItem(MF_STRING, 51, 'Full Line Clickable');
+ _libraryMenu.CheckMenuItem(51, libraryProps.fullLine);
+ _libraryMenu.AppendMenuItem(MF_STRING, 52, 'Show Tooltips');
+ _libraryMenu.CheckMenuItem(52, libraryProps.tooltips);
+
+ var _rootNodeMenu = window.CreatePopupMenu();
+ _rootNodeMenu.AppendMenuItem(MF_STRING, 170, 'Hide');
+ _rootNodeMenu.AppendMenuItem(MF_STRING, 171, '"All Music"');
+ _rootNodeMenu.AppendMenuItem(MF_STRING, 172, 'View Name');
+ _rootNodeMenu.CheckMenuRadioItem(170, 172, 170 + libraryProps.rootNode);
+ _rootNodeMenu.AppendTo(_libraryMenu, MF_STRING, 'Root Node Type');
+ var _nodeitemCountsMenu = window.CreatePopupMenu();
+ _nodeitemCountsMenu.AppendMenuItem(MF_STRING, 180, 'Hidden');
+ _nodeitemCountsMenu.AppendMenuItem(MF_STRING, 181, '# Tracks');
+ _nodeitemCountsMenu.AppendMenuItem(MF_STRING, 182, '# Sub-Items');
+ _nodeitemCountsMenu.CheckMenuRadioItem(180, 182, 180 + libraryProps.nodeItemCounts);
+ _nodeitemCountsMenu.AppendTo(_libraryMenu, MF_STRING, 'Node Item Counts');
+
+ _libraryMenu.AppendMenuItem(MF_STRING, 53, 'Show Library Scrollbar');
+ _libraryMenu.CheckMenuItem(53, libraryProps.showScrollbar);
+ _libraryMenu.AppendMenuItem(MF_STRING, 54, 'Send files to Current Playlist');
+ _libraryMenu.CheckMenuItem(54, libraryProps.sendToCurrent);
+ _libraryMenu.AppendMenuItem(MF_STRING, 55, 'Auto-Fill Playlist on Selection');
+ _libraryMenu.CheckMenuItem(55, libraryProps.autoFill);
+
+ var _doubleClickMenu = window.CreatePopupMenu();
+ _doubleClickMenu.AppendMenuItem(MF_STRING, 190, 'Expand/Collapse Folders');
+ _doubleClickMenu.AppendMenuItem(MF_STRING, 191, 'Send and Play');
+ _doubleClickMenu.AppendMenuItem(MF_STRING, 192, 'Send to Playlist');
+ _doubleClickMenu.CheckMenuRadioItem(190, 192, 190 + libraryProps.doubleClickAction);
+ _doubleClickMenu.AppendTo(_libraryMenu, MF_STRING, 'Double Click Action');
+ _libraryMenu.AppendMenuItem(MF_STRING, 57, 'Auto Collapse Nodes');
+ _libraryMenu.CheckMenuItem(57, libraryProps.autoCollapse);
+ _libraryMenu.AppendMenuItem(MF_STRING, 58, 'Reset Library Zoom');
+ _libraryMenu.AppendTo(_menu, MF_STRING, 'Library Settings');
+ _menu.AppendMenuSeparator();
+
+ _debugMenu.AppendMenuItem(MF_STRING, 90, 'Enable debug output');
+ _debugMenu.CheckMenuItem(90, pref.show_debug_log);
+ _debugMenu.AppendMenuItem(MF_STRING, 95, 'Enable theme debug output');
+ _debugMenu.CheckMenuItem(95, pref.show_theme_log);
+ _debugMenu.AppendMenuItem(MF_STRING, 91, 'Show draw timing');
+ _debugMenu.CheckMenuItem(91, showDrawTiming);
+ _debugMenu.AppendMenuItem(MF_STRING, 92, 'Show extra draw timing');
+ _debugMenu.CheckMenuItem(92, showExtraDrawTiming);
+ _debugMenu.AppendMenuItem(MF_STRING, 93, 'Show debug timing');
+ _debugMenu.CheckMenuItem(93, showDebugTiming);
+ _debugMenu.AppendMenuItem(MF_STRING, 94, 'Show Reload button');
+ _debugMenu.CheckMenuItem(94, pref.show_reload_button);
+ _debugMenu.AppendTo(_menu, MF_STRING, 'Debug Settings');
+ _menu.AppendMenuSeparator();
+ _menu.AppendMenuItem(MF_STRING, 100, 'Lock Right Click...');
+ _menu.CheckMenuItem(100, pref.locked);
+ _menu.AppendMenuItem(MF_STRING, 101, 'Restart');
+
+ idx = _menu.TrackPopupMenu(x, y);
+ switch (idx) {
+ case 1:
+ pref.aa_glob = !pref.aa_glob;
+ if (!pref.aa_glob) {
+ window.ClearTimeout(globTimer);
+ globTimer = 0;
+ }
+ break;
+ case 3:
+ break;
+ case 4:
+ pref.display_cdart = !pref.display_cdart;
+ if (fb.IsPlaying) fetchNewArtwork(fb.GetNowPlaying());
+ lastLeftEdge = 0; // resize labels
+ ResizeArtwork(true);
+ RepaintWindow();
+ break;
+ case 5:
+ pref.rotate_cdart = !pref.rotate_cdart;
+ RepaintWindow();
+ break;
+ case 6:
+ pref.cdart_ontop = !pref.cdart_ontop;
+ RepaintWindow();
+ break;
+ case 12:
+ pref.start_Playlist = !pref.start_Playlist;
+ break;
+ case 13:
+ pref.show_transport = !pref.show_transport;
+ createButtonImages();
+ createButtonObjects(ww, wh);
+ ResizeArtwork(true);
+ RepaintWindow();
+ break;
+ case 14:
+ pref.show_progress_bar = !pref.show_progress_bar;
+ setGeometry();
+ ResizeArtwork(true);
+ RepaintWindow();
+ break;
+ case 15:
+ pref.freq_update = !pref.freq_update;
+ SetProgressBarRefresh();
+ break;
+ case 17:
+ pref.use_vinyl_nums = !pref.use_vinyl_nums;
+ RepaintWindow();
+ break;
+ case 18:
+ pref.show_flags = !pref.show_flags;
+ LoadCountryFlags();
+ RepaintWindow();
+ break;
+ case 30:
+ pref.hyperlinks_ctrl = !pref.hyperlinks_ctrl;
+ break;
+ /* Library Menu Items */
+ case 50:
+ libraryProps.rememberTree = !libraryProps.rememberTree;
+ break;
+ case 51:
+ libraryProps.fullLine = !libraryProps.fullLine;
+ break;
+ case 52:
+ libraryProps.tooltips = !libraryProps.tooltips;
+ setLibrarySize();
+ break;
+ case 53:
+ libraryProps.showScrollbar = !libraryProps.showScrollbar;
+ setLibrarySize();
+ break;
+ case 54:
+ libraryProps.sendToCurrent = !libraryProps.sendToCurrent;
+ break;
+ case 55:
+ libraryProps.autoFill = !libraryProps.autoFill;
+ break;
+ case 57:
+ libraryProps.autoCollapse = !libraryProps.autoCollapse;
+ break;
+ case 58:
+ libraryProps.filterZoom = 100;
+ libraryProps.fontZoom = 100;
+ libraryProps.nodeZoom = 100;
+ setLibrarySize();
+ break;
+ case 170:
+ case 171:
+ case 172:
+ libraryProps.rootNode = idx - 170;
+ lib_manager.rootNodes(1);
+ break;
+ case 180:
+ case 181:
+ case 182:
+ libraryProps.nodeItemCounts = idx - 180;
+ lib_manager.rootNodes(1);
+ break;
+ case 190:
+ case 191:
+ case 192:
+ libraryProps.doubleClickAction = idx - 190;
+ break;
+
case 120:
case 121:
case 122:
@@ -1370,1826 +1370,1825 @@ function onSettingsMenu(x, y) {
RepaintWindow();
break;
- case 130:
- case 131:
- case 132:
- case 133:
- pref.rotation_amt = (idx - 28) % 360;
- CreateRotatedCDImage();
- RepaintWindow();
- break;
- case 90:
- pref.show_debug_log = !pref.show_debug_log;
- break;
- case 91:
- showDrawTiming = !showDrawTiming;
- break;
- case 92:
- showExtraDrawTiming = !showExtraDrawTiming;
- break;
- case 93:
- showDebugTiming = !showDebugTiming;
- break;
- case 94:
- pref.show_reload_button = !pref.show_reload_button;
- window.Reload();
- break;
- case 95:
- pref.show_theme_log = !pref.show_theme_log;
- if (pref.show_theme_log) {
- // this is overkill, but it'll print the theme logging at least
- albumart = null;
- loadFromCache = false;
- on_playback_new_track(fb.GetNowPlaying());
- }
- break;
- case 100:
- pref.locked = !pref.locked;
- break;
- case 101:
- fb.RunMainMenuCommand("File/Restart");
- break;
- case 140:
- case 141:
- case 142:
- case 143:
- case 144:
- case 145:
- case 146:
- case 147:
- case 148:
- case 149:
- case 150:
- case 151:
- case 152:
- case 153:
- case 154:
- case 155:
- case 156:
- case 157:
- case 158:
- case 159:
- case 160:
- case 161:
- case 162:
- case 163:
- case 164:
- SetTimezoneFromMenuItem(idx);
- break;
- }
- _menu.Dispose();
-
- menu_down = false;
- window.RepaintRect(pad_x, pad_y, menu_width, 24);
-}
-
-function on_mouse_leave() {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_mouse_leave();
-}
-
-
-// -----------------------------------------------------------------------
-// CALLBACKS
-// -----------------------------------------------------------------------
-
-// custom initialisation function, called once after variable declarations
-function on_init() {
- var i;
- console.log("in on_init()");
-
- if (!fso.folderExists(fb.ProfilePath + themeBaseName)) {
- fso.createFolder(fb.ProfilePath + themeBaseName);
- }
-
- str = clearUIVariables();
-
- ww = window.Width;
- wh = window.Height;
-
- last_path = '';
-
- last_pb = fb.PlaybackOrder;
-
- if (fb.IsPlaying && fb.GetNowPlaying()) {
- on_size();
- on_playback_new_track(fb.GetNowPlaying());
- }
-
- g_playtimer && window.ClearInterval(g_playtimer);
- g_playtimer = null;
-
+ case 130:
+ case 131:
+ case 132:
+ case 133:
+ pref.rotation_amt = (idx - 28) % 360;
+ CreateRotatedCDImage();
+ RepaintWindow();
+ break;
+ case 90:
+ pref.show_debug_log = !pref.show_debug_log;
+ break;
+ case 91:
+ showDrawTiming = !showDrawTiming;
+ break;
+ case 92:
+ showExtraDrawTiming = !showExtraDrawTiming;
+ break;
+ case 93:
+ showDebugTiming = !showDebugTiming;
+ break;
+ case 94:
+ pref.show_reload_button = !pref.show_reload_button;
+ window.Reload();
+ break;
+ case 95:
+ pref.show_theme_log = !pref.show_theme_log;
+ if (pref.show_theme_log) {
+ // this is overkill, but it'll print the theme logging at least
+ albumart = null;
+ loadFromCache = false;
+ on_playback_new_track(fb.GetNowPlaying());
+ }
+ break;
+ case 100:
+ pref.locked = !pref.locked;
+ break;
+ case 101:
+ fb.RunMainMenuCommand("File/Restart");
+ break;
+ case 140:
+ case 141:
+ case 142:
+ case 143:
+ case 144:
+ case 145:
+ case 146:
+ case 147:
+ case 148:
+ case 149:
+ case 150:
+ case 151:
+ case 152:
+ case 153:
+ case 154:
+ case 155:
+ case 156:
+ case 157:
+ case 158:
+ case 159:
+ case 160:
+ case 161:
+ case 162:
+ case 163:
+ case 164:
+ SetTimezoneFromMenuItem(idx);
+ break;
+ }
+ _menu.Dispose();
+
+ menu_down = false;
+ window.RepaintRect(pad_x, pad_y, menu_width, 24);
+}
+
+function on_mouse_leave() {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_mouse_leave();
+}
+
+
+// -----------------------------------------------------------------------
+// CALLBACKS
+// -----------------------------------------------------------------------
+
+// custom initialisation function, called once after variable declarations
+function on_init() {
+ var i;
+ console.log("in on_init()");
+
+ if (!fso.folderExists(fb.ProfilePath + themeBaseName)) {
+ fso.createFolder(fb.ProfilePath + themeBaseName);
+ }
+
+ str = clearUIVariables();
+
+ ww = window.Width;
+ wh = window.Height;
+
+ last_path = '';
+
+ last_pb = fb.PlaybackOrder;
+
+ if (fb.IsPlaying && fb.GetNowPlaying()) {
+ on_size();
+ on_playback_new_track(fb.GetNowPlaying());
+ }
+
+ g_playtimer && window.ClearInterval(g_playtimer);
+ g_playtimer = null;
+
setTimeout(function () {
// defer initing of library panel until everything else has loaded
initLibraryPanel();
}, 10000);
-}
-
-// window size changed
-function on_size() {
- console.log("in on_size()");
- ww = window.Width;
- wh = window.Height;
- console.log('width: ' + ww + ', height: ' + wh);
- var count = 0;
-
- if (ww <= 0 || wh <= 0) return;
-
- checkFor4k(ww);
-
- if (!sizeInitialized) {
- createFonts();
- setGeometry();
- if (fb.IsPlaying) {
- LoadCountryFlags(); // wrong size flag gets loaded on 4k systems
- }
- sizeInitialized = true;
- }
-
- lastLeftEdge = 0;
-
- ResizeArtwork(true);
- createButtonImages();
- createButtonObjects(ww, wh);
-
- // we aren't creating these buttons anymore, but we still use these values for now. TODO: replace these
- settingsY = btns[30].y;
-
- if (albumart)
- midpoint = Math.ceil(albumart_size.y + pref.lyrics_line_height + albumart_size.h / 2);
- else
- midpoint = Math.ceil((wh - geo.lower_bar_h + pref.lyrics_line_height) / 2);
- if (displayLyrics) {
- refresh_lyrics();
- }
-
- playlist_shadow = disposeImg(playlist_shadow);
- if (displayPlaylist) {
- playlist.on_size(ww, wh);
- } else if (displayLibrary) {
- initLibraryPanel();
- setLibrarySize();
- }
-}
-
-function setLibrarySize() {
- if (typeof libraryPanel !== 'undefined') {
- var x = Math.round(ww * .5);
- var y = btns[30].y + btns[30].h + 10 + listTop;
- var library_w = ww - x;
- var library_h = Math.max(0, wh - geo.lower_bar_h - 10 - y - listBottom);
- ui.sizedNode = false;
- ui.node_sz = Math.round(16 * ui.scale);
+}
+
+// window size changed
+function on_size() {
+ console.log("in on_size()");
+ ww = window.Width;
+ wh = window.Height;
+ console.log('width: ' + ww + ', height: ' + wh);
+ var count = 0;
+
+ if (ww <= 0 || wh <= 0) return;
+
+ checkFor4k(ww);
+
+ if (!sizeInitialized) {
+ createFonts();
+ setGeometry();
+ if (fb.IsPlaying) {
+ LoadCountryFlags(); // wrong size flag gets loaded on 4k systems
+ }
+ sizeInitialized = true;
+ }
+
+ lastLeftEdge = 0;
+
+ ResizeArtwork(true);
+ createButtonImages();
+ createButtonObjects(ww, wh);
+
+ // we aren't creating these buttons anymore, but we still use these values for now. TODO: replace these
+ settingsY = btns[30].y;
+
+ if (albumart)
+ midpoint = Math.ceil(albumart_size.y + pref.lyrics_line_height + albumart_size.h / 2);
+ else
+ midpoint = Math.ceil((wh - geo.lower_bar_h + pref.lyrics_line_height) / 2);
+ if (displayLyrics) {
+ refresh_lyrics();
+ }
+
+ playlist_shadow = disposeImg(playlist_shadow);
+ if (displayPlaylist) {
+ playlist.on_size(ww, wh);
+ } else if (displayLibrary) {
+ initLibraryPanel();
+ setLibrarySize();
+ }
+}
+
+function setLibrarySize() {
+ if (typeof libraryPanel !== 'undefined') {
+ var x = Math.round(ww * .5);
+ var y = btns[30].y + btns[30].h + 10 + listTop;
+ var library_w = ww - x;
+ var library_h = Math.max(0, wh - geo.lower_bar_h - 10 - y - listBottom);
+ ui.sizedNode = false;
+ ui.node_sz = Math.round(16 * ui.scale);
p.setFilterFont(); // resets filter font in case the zoom was reset
- libraryPanel.on_size(x, y, library_w, library_h);
- } else {
- // TODO: take this if/else out once this part is done
- displayLibrary = false;
- }
-}
-
-// new track
-function on_playback_new_track(metadb) {
- console.log('in on_playback_new_track()');
- if (showDebugTiming) newTrackTime = fb.CreateProfiler('on_playback_new_track');
- start_timer = 0;
- lastLeftEdge = 0;
- newTrackFetchingArtwork = true;
- themeColorSet = false;
-
- isStreaming = metadb ? !metadb.RawPath.match(/^file\:\/\//) : false;
- if (!isStreaming) {
- current_path = $('%directoryname%');
- } else {
- current_path = '';
- }
-
- SetProgressBarRefresh();
-
- if (globTimer) {
- window.ClearTimeout(globTimer);
- globTimer = 0;
- }
-
- // Fetch new albumart
- if ((pref.aa_glob && aa_list.length != 1) || current_path != last_path || albumart == null ||
- $('$if2(%discnumber%,0)') != lastDiscNumber || $('$if2(' + tf.vinyl_side + ',ZZ)') != lastVinylSide) {
- fetchNewArtwork(metadb);
- }
- loadFromCache = true;
- CreateRotatedCDImage(); // we need to always setup the rotated image because it rotates on every track
-
- /* code to retrieve record label logos */
- var labelStrings = [];
- while (recordLabels.length > 0)
- disposeImg(recordLabels.pop());
- for (i = 0; i < tf.labels.length; i++) {
- for (j = 0; j < $('$meta_num(' + tf.labels[i] + ')'); j++) {
- labelStrings.push($('$meta(' + tf.labels[i] + ',' + j + ')'));
- }
- }
- labelStrings = _.uniq(labelStrings);
- for (i = 0; i < labelStrings.length; i++) {
- var addLabel = LoadLabelImage(labelStrings[i].replace(/'/, '\'\''));
- if (addLabel != null) {
- recordLabels.push(addLabel);
- }
- }
-
- function testBandLogo(imgDir, bandStr, isHQ) {
- var logoPath = imgDir + bandStr + '.png'
- if (utils.FileTest(logoPath, 'e')) {
- if (isHQ) {
- bandLogoHQ = true;
- console.log('Found band logo: ' + logoPath);
- }
- return logoPath;
- }
- return false;
- }
-
- /* code to retrieve band logo */
- bandStr = $('[%artist%]').replace(/"/g, '\'').replace(/:/g, '_').replace(/\//g, '-').replace(/\*/g, '').replace(/\?/g, '');
- bandLogo = disposeImg(bandLogo);
- if (bandStr) {
- bandLogoHQ = false;
-
- var path = testBandLogo(pref.logo_hq, bandStr, true) || // try 800x310 white
- testBandLogo(pref.logo_color, bandStr, true); // try 800x310 color
- if (path) {
- bandLogo = gdi.Image(path);
- }
- }
-
- last_path = current_path; // for art caching purposes
- lastDiscNumber = $('$if2(%discnumber%,0)'); // for art caching purposes
- lastVinylSide = $('$if2(" + tf.vinyl_side + ",ZZ)');
- currentLastPlayed = $(tf.last_played);
-
- // enable "watch for tag changes" on new track
- metadb_handle = fb.GetNowPlaying();
- if (metadb_handle) {
- on_metadb_changed(); // refresh panel
- }
-
- on_playback_time();
- progressLength = 0;
-
- if (displayPlaylist) {
- playlist.on_playback_new_track(metadb);
- } else if (displayLibrary) {
- library.on_playback_new_track(metadb);
- }
-
- // Lyrics stuff
- g_playtimer && window.ClearInterval(g_playtimer);
- g_playtimer = null;
- if (displayLyrics) { // no need to try retrieving them if we aren't going to display them now
- updateLyricsPositionOnScreen();
- }
- if (showDebugTiming) newTrackTime.Print();
-}
-
-// tag content changed
-function on_metadb_changed(handle_list, fromhook) {
- console.log('on_metadb_changed()');
- if (fb.IsPlaying) {
- var nowPlayingUpdated = !handle_list; // if we don't have a handle_list we called this manually from on_playback_new_track
- var metadb = fb.GetNowPlaying();
- if (metadb && handle_list) {
- for (i = 0; i < handle_list.Count; i++) {
- if (metadb.RawPath === handle_list.Item(i).RawPath) {
- nowPlayingUpdated = true;
- break;
- }
- }
- }
-
- if (nowPlayingUpdated) {
- // the handle_list contains the currently playing song so update
- var title = $(tf.title);
- var artist = $(tf.artist);
- var original_artist = $(tf.original_artist);
- if (pref.use_vinyl_nums)
- tracknum = $(tf.vinyl_track);
- else
- tracknum = $(tf.tracknum);
-
- str.tracknum = tracknum.trim();
- str.title = title + original_artist;
- str.title_lower = ' ' + title;
- str.original_artist = original_artist;
- str.artist = artist;
- str.year = $('$year($if2(%original release date%,%date%)))');
- str.album = $("[%album%][ '['" + tf.album_trans + "']']");
- str.album_subtitle = $("[ '['" + tf.album_subtitle + "']']");
- var codec = $("$lower($if2(%codec%,$ext(%path%)))");
- if (codec == "cue") {
- codec = $("$ext($info(referenced_file))");
- } else if (codec == "mpc") {
- codec = codec + "-" + $("$info(codec_profile)").replace("quality ", "q");
- } else if (codec == "dts" || codec == "ac3" || codec == "atsc a/52") {
- codec += $("[ $replace($replace($replace($info(channel_mode), + LFE,),' front, ','/'),' rear surround channels',$if($strstr($info(channel_mode),' + LFE'),.1,.0))] %bitrate%") + " kbps";
- codec = codec.replace("atsc a/52", "Dolby Digital");
- } else if ($("$info(encoding)") == "lossy") {
- if ($("$info(codec_profile)") == "CBR") codec = codec + "-" + $("%bitrate%") + " kbps";
- else codec = codec + "-" + $("$info(codec_profile)");
- }
- str.trackInfo = $(codec + '[ | %replaygain_album_gain%]');
-
- str.disc = fb.TitleFormat(tf.disc).Eval();
-
- h = Math.floor(fb.PlaybackLength / 3600);
- m = Math.floor(fb.PlaybackLength % 3600 / 60);
- s = Math.floor(fb.PlaybackLength % 60);
- str.length = (h > 0 ? h + ":" + (m < 10 ? "0" : '') + m : m) + ":" + (s < 10 ? "0" : '') + s;
-
- str.grid = [];
- for (k = 0; k < tf.grid.length; k++) {
- val = $(tf.grid[k].val);
- if (val) {
- if (tf.grid[k].age) {
- val = $('$date(' + val + ')'); // never show time
- var age = calcAgeDateString(val);
- if (age) {
- val += ' (' + age + ')';
- }
- }
- str.grid.push({
- age: tf.grid[k].age,
- label: tf.grid[k].label,
- val: val,
- });
- }
- }
-
- var lastfm_count = $('%lastfm_play_count%');
- if (lastfm_count !== '0' && lastfm_count !== '?') {
- playCountVerifiedByLastFm = true;
- } else {
- playCountVerifiedByLastFm = false;
- }
-
- lastPlayed = $(tf.last_played);
- calcDateRatios($date(currentLastPlayed) !== $date(lastPlayed), currentLastPlayed); // last_played has probably changed and we want to update the date bar
- if (lastPlayed.length) {
- today = dateToYMD(new Date());
- if (!currentLastPlayed.length || $date(lastPlayed) !== today) {
- currentLastPlayed = lastPlayed;
- console.log('currentLastPlayed:', currentLastPlayed);
- }
- }
-
- lp = str.grid.find(function (value) {
- return value.label === 'Last Played';
- });
- if (lp) {
- lp.val = $date(currentLastPlayed);
- if (calcAgeDateString(lp.val)) {
- lp.val += ' (' + calcAgeDateString(lp.val) + ')';
- }
- }
-
- if (pref.show_flags) {
- LoadCountryFlags();
- }
-
- tag_timer = 0;
- }
- }
- // createHyperlinks();
- if (displayPlaylist) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_metadb_changed(handle_list, fromhook);
- }
- RepaintWindow();
-}
-
-
-// User activity
-
-function on_playback_order_changed(this_pb) {
- // Repaint playback order
- if (this_pb != last_pb) {
- debugLog("Repainting on_playback_order_changed");
- window.RepaintRect(0.5 * ww, wh - geo.lower_bar_h, 0.5 * ww, geo.lower_bar_h);
- }
- last_pb = this_pb;
-}
-
-function on_playback_seek() {
- progressMoved = true;
- if (displayLyrics) {
- refresh_lyrics();
- }
- on_playback_time();
-}
-
-var onMouseLbtnDown = false;
-
-function on_mouse_lbtn_down(x, y, m) {
- var menu_yOffset = 19;
- if (y > wh - geo.lower_bar_h) {
- g_drag = 1;
- }
-
- // clicking on progress bar
- if (pref.show_progress_bar && y >= wh - 0.5 * geo.lower_bar_h && y <= wh - 0.5 * geo.lower_bar_h + geo.prog_bar_h && x >= 0.025 * ww && x < 0.975 * ww) {
- var v = (x - 0.025 * ww) / (0.95 * ww);
- v = (v < 0) ? 0 : (v < 1) ? v : 1;
- if (fb.PlaybackTime != v * fb.PlaybackLength) fb.PlaybackTime = v * fb.PlaybackLength;
- window.RepaintRect(0, wh - geo.lower_bar_h, ww, geo.lower_bar_h);
- }
-
- buttonEventHandler(x, y, m);
-
- if (displayPlaylist && playlist.mouse_in_this(x, y)) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_mouse_lbtn_down(x, y, m);
- } else if (displayLibrary && library.mouse_in_this(x, y)) {
- trace_call && console.log(qwr_utils.function_name());
- library.on_mouse_lbtn_down(x, y, m);
- }
-}
-
-function on_mouse_lbtn_up(x, y, m) {
- g_drag = 0;
-
- if (displayPlaylist && playlist.mouse_in_this(x, y)) {
- trace_call && console.log(qwr_utils.function_name());
-
- playlist.on_mouse_lbtn_up(x, y, m);
-
- qwr_utils.EnableSizing(m);
- } else if (displayLibrary && library.mouse_in_this(x, y)) {
- trace_call && console.log(qwr_utils.function_name());
- library.on_mouse_lbtn_up(x, y, m);
- } else {
-
- if (just_dblclicked) {
- // You just did a double-click, so do nothing
- just_dblclicked = false;
- } else {
- if ((albumart && albumart_size.x <= x && albumart_size.y <= y && albumart_size.x + albumart_size.w >= x && albumart_size.y + albumart_size.h >= y) ||
- (cdart && !albumart && cdart_size.x <= x && cdart_size.y <= y && cdart_size.x + cdart_size.w >= x && cdart_size.y + cdart_size.h >= y) ||
- pauseBtn.trace(x, y)) {
- fb.PlayOrPause();
- }
- }
- }
- on_mouse_move(x, y);
- buttonEventHandler(x, y, m);
-
- onMouseLbtnDown = false;
-}
-
-function on_mouse_lbtn_dblclk(x, y, m) {
- if (displayPlaylist && playlist.mouse_in_this(x, y)) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_mouse_lbtn_dblclk(x, y, m);
- } else if (displayLibrary && library.mouse_in_this(x, y)) {
- trace_call && console.log(qwr_utils.function_name());
- library.on_mouse_lbtn_dblclk(x, y, m);
- } else {
- // re-initialise the panel
- just_dblclicked = true;
- if (fb.IsPlaying) {
- albumart = null;
- loadFromCache = false;
- on_playback_new_track(fb.GetNowPlaying());
- }
- if (displayLyrics) {
- refresh_lyrics();
- }
- buttonEventHandler(x, y, m);
- }
-}
-
-function on_mouse_rbtn_down(x, y, m) {
- if (displayPlaylist && playlist.mouse_in_this(x, y)) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_mouse_rbtn_down(x, y, m);
- } else if (displayLibrary) {
- // trace_call && console.log(qwr_utils.function_name());
- // library.on_mouse_rbtn_down(x, y, m);
- }
-}
-
-function on_mouse_rbtn_up(x, y, m) {
- if (displayPlaylist && playlist.mouse_in_this(x, y)) {
- trace_call && console.log(qwr_utils.function_name());
- return playlist.on_mouse_rbtn_up(x, y, m);
- } else if (displayLibrary && library.mouse_in_this(x, y)) {
- trace_call && console.log(qwr_utils.function_name());
- return library.on_mouse_rbtn_up(x, y, m);
- } else
- return pref.locked;
-}
-
-function on_mouse_move(x, y, m) {
- if (x != state["mouse_x"] || y != state["mouse_y"]) {
- window.SetCursor(32512); // arrow
- if (g_drag) {
- var v = (x - 0.025 * ww) / (0.95 * ww);
- v = (v < 0) ? 0 : (v < 1) ? v : 1;
- if (fb.PlaybackTime != v * fb.PlaybackLength) fb.PlaybackTime = v * fb.PlaybackLength;
- }
- state["mouse_x"] = x;
- state["mouse_y"] = y;
- if (pref.hide_cursor) {
- window.ClearTimeout(hideCursor);
- //debugLog("on_mouse_move: creating window.SetCursor() timeout with timeout = " + 10000);
- hideCursor = window.SetTimeout(function () {
- // if there's a menu id (i.e. a menu is down) we don't want the cursor to ever disappear
- if (!menu_down) {
- window.SetCursor(-1); // hide cursor
- }
- }, 10000);
- }
-
- buttonEventHandler(x, y, m);
- // hyperlinkEventHandler(x, y, m);
-
- if (displayPlaylist && playlist.mouse_in_this(x, y)) {
- trace_call && trace_on_move && console.log(qwr_utils.function_name());
-
- if (mouse_move_suppress.is_supressed(x, y, m)) {
- return;
- }
-
- qwr_utils.DisableSizing(m);
- playlist.on_mouse_move(x, y, m);
- } else if (displayLibrary && library.mouse_in_this(x, y)) {
- library.on_mouse_move(x, y, m);
- }
- }
-}
-
-function on_mouse_wheel(delta) {
- if (state["mouse_y"] > wh - geo.lower_bar_h) {
- fb.PlaybackTime = fb.PlaybackTime - delta * pref.mouse_wheel_seek_speed;
- refresh_seekbar();
- return;
- }
- if (displayPlaylist) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_mouse_wheel(delta);
- } else if (displayLibrary) {
- // trace_call && console.log(qwr_utils.function_name());
- library.on_mouse_wheel(delta);
- }
-}
-// =================================================== //
-
-// trace_call = true;
-
-function on_mouse_leave() {
-
- if (displayPlaylist) {
- playlist.on_mouse_leave();
- } else if (displayLibrary) {
- library.on_mouse_leave();
- }
-}
-
-function on_playlists_changed() {
- if (displayPlaylist) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_playlists_changed();
- }
-}
-
-function on_playlist_switch() {
- if (displayPlaylist) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_playlist_switch();
- }
-}
-
-function on_playlist_item_ensure_visible(playlistIndex, playlistItemIndex) {
- if (displayPlaylist) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_playlist_item_ensure_visible(playlistIndex, playlistItemIndex);
- }
-}
-
-function on_playlist_items_added(playlistIndex) {
- if (displayPlaylist) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_playlist_items_added(playlistIndex);
- }
-}
-
-function on_playlist_items_reordered(playlistIndex) {
- if (displayPlaylist) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_playlist_items_reordered(playlistIndex);
- }
-}
-
-function on_playlist_items_removed(playlistIndex) {
- if (displayPlaylist) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_playlist_items_removed(playlistIndex);
- }
-}
-
-function on_playlist_items_selection_change() {
- if (displayPlaylist) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_playlist_items_selection_change();
- }
-}
-
-function on_library_items_added(handle_list) {
- if (displayLibrary) {
- trace_call && console.log(qwr_utils.function_name());
- library.on_library_items_added(handle_list);
- }
-}
-
-function on_library_items_removed(handle_list) {
- if (displayLibrary) {
- trace_call && console.log(qwr_utils.function_name());
- library.on_library_items_removed(handle_list);
- }
-}
-
-function on_library_items_changed(handle_list) {
- if (displayLibrary) {
- trace_call && console.log(qwr_utils.function_name());
- library.on_library_items_changed(handle_list);
- }
-}
-
-function on_item_focus_change(playlist_arg, from, to) {
- if (displayPlaylist) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_item_focus_change(playlist_arg, from, to);
- } else if (displayLibrary) {
- trace_call && console.log(qwr_utils.function_name());
- library.on_item_focus_change();
- }
-}
-
-function on_key_down(vkey) {
-
- var CtrlKeyPressed = utils.IsKeyPressed(VK_CONTROL);
- var ShiftKeyPressed = utils.IsKeyPressed(VK_SHIFT);
-
- if (displayPlaylist) {
- trace_call && console.log(qwr_utils.function_name());
-
- if (key_down_suppress.is_supressed(vkey)) {
- return;
- }
-
- playlist.on_key_down(vkey);
- } else if (displayLibrary) {
- trace_call && console.log(qwr_utils.function_name());
- library.on_key_down(vkey);
- }
-
- switch (vkey) {
- case 0x6B: // VK_ADD ??
- case 0x6D: // VK_SUBTRACT ??
- if (CtrlKeyPressed && ShiftKeyPressed) {
- var action = vkey === 0x6B ? '+' : '-';
- if (fb.IsPlaying) {
- var metadb = fb.GetNowPlaying();
- fb.RunContextCommandWithMetadb('Rating/' + action, metadb);
- } else if (!metadb && displayPlaylist) {
- var metadbList = plman.GetPlaylistSelectedItems(plman.ActivePlaylist);
- if (metadbList.Count === 1) {
- fb.RunContextCommandWithMetadb('Rating/' + action, metadbList.Item(0));
- } else {
- console.log('Won\'t change rating with more than one selected item');
- }
- }
- }
- break;
- }
-}
-// =================================================== //
-
-
-function on_char(code) {
- if (displayLibrary) {
- trace_call && console.log(qwr_utils.function_name());
- library.on_char(code);
- }
-}
-
-function on_key_up(vkey) {
- if (displayLibrary) {
- trace_call && console.log(qwr_utils.function_name());
- library.on_key_up(vkey);
- }
-}
-
-function on_playback_queue_changed(origin) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_playback_queue_changed(origin);
-}
-
-
-function on_playback_pause(state) {
- if (pref.show_transport) {
- createButtonObjects(ww, wh);
- window.RepaintRect(btns[2].x, btns[2].y, btns[2].w, btns[2].h); // redraw play/pause button
- }
- if (state) { // pausing
- if (progressTimer) window.ClearInterval(progressTimer);
- progressTimer = 0;
- window.RepaintRect(0.015 * ww, 0.12 * wh, Math.max(albumart_size.x - 0.015 * ww, 0.015 * ww), wh - geo.lower_bar_h - 0.12 * wh);
- } else { // unpausing
- if (progressTimer > 0) window.ClearInterval(progressTimer); // clear to avoid multiple progressTimers which can happen depending on the playback state when theme is loaded
- debugLog("on_playback_pause: creating refresh_seekbar() interval with delay = " + t_interval);
- progressTimer = window.SetInterval(function () {
- refresh_seekbar();
- }, t_interval);
- }
-
- pauseBtn.repaint();
- if (albumart && displayLyrics) { // if we are displaying lyrics we need to refresh all the lyrics to avoid tearing at the edges of the pause button
- window.RepaintRect(albumart_size.x + (albumart_size.w - lyricsWidth) / 2, albumart_size.y + pref.lyrics_h_padding, lyricsWidth, albumart_size.h - pref.lyrics_h_padding * 2);
- }
-
- if (displayPlaylist) {
- playlist.on_playback_pause(state);
- }
-}
-
-function on_playback_stop(reason) {
- if (reason !== 2) { // 2 = starting_another
- // clear all variables and repaint
- str = clearUIVariables()
- debugLog("Repainting on_playback_stop");
- RepaintWindow();
- last_path = '';
- lastDiscNumber = "0";
- while (recordLabels.length > 0) {
- disposeImg(recordLabels.pop());
- }
- if (metadb_handle) {
- metadb_handle = null;
- }
- createButtonObjects(ww, wh); // switch pause button to play
- loadFromCache = false;
- }
- progressTimer && window.ClearInterval(progressTimer);
- if (globTimer)
- window.ClearTimeout(globTimer);
- if (albumart && ((pref.aa_glob && aa_list.length != 1) || last_path == '')) {
- debugLog("disposing artwork");
- albumart = null;
- albumart_scaled = disposeImg(albumart_scaled);
- }
- bandLogo = disposeImg(bandLogo);
- while (flagImgs.length > 0)
- disposeImg(flagImgs.pop());
- rotatedCD = disposeImg(rotatedCD);
- globTimer = 0;
-
- g_playtimer && window.ClearInterval(g_playtimer);
- g_playtimer = null;
- if (reason === 0) {
- // Stop
- cdart = disposeCDImg(cdart);
- window.Repaint();
- }
- if (displayPlaylist) {
- playlist.on_playback_stop(reason);
- }
-}
-
-function on_playback_starting(cmd, is_paused) {
- if (pref.hide_cursor) {
- window.SetCursor(-1); // hide cursor
- }
- createButtonObjects(ww, wh); // play button to pause
-}
-
-function on_drag_enter(action, x, y, mask) {
- if (displayPlaylist) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_drag_enter(action, x, y, mask);
- }
-}
-
-function on_drag_leave() {
- if (displayPlaylist) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_drag_leave();
- }
-}
-
-function on_drag_drop(action, x, y, mask) {
- if (displayPlaylist) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_drag_drop(action, x, y, mask);
- }
-}
-
-function on_focus(is_focused) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_focus(is_focused);
-}
-
-function on_notify_data(name, info) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_notify_data(name, info);
-}
-
-var debounced_init_playlist = _.debounce(function (playlistIndex) {
- trace_call && console.log('debounced_init_playlist');
- playlist.on_playlist_items_added(playlistIndex);
-}, 0, {
- leading: false,
- trailing: true
-});
-
-// =================================================== //
-
-function clearUIVariables() {
- return {
- artist: '',
- tracknum: stoppedStr1,
- title_lower: ' ' + stoppedStr2,
- year: '',
- grid: [],
- time: ''
- }
-}
-
-// album art retrieved from GetAlbumArtAsync
-function on_get_album_art_done(metadb, art_id, image, image_path) {
- if (displayPlaylist) {
- trace_call && console.log(qwr_utils.function_name());
- playlist.on_get_album_art_done(metadb, art_id, image, image_path);
- } else if (displayLibrary) {
- // trace_call && console.log(qwr_utils.function_name());
- // library.on_get_album_art_done(metadb, art_id, image, image_path);
- }
-}
-
-// returned from LoadImageAsync
-function on_load_image_done(cookie, image) {
- console.log('on_load_image_done returned');
- if (cookie == disc_art_loading) {
- disposeCDImg(cdart); // delay disposal so we don't get flashing
- cdart = art_cache.encache(image, cdartPath);
- ResizeArtwork(true);
- CreateRotatedCDImage();
- lastLeftEdge = 0; // recalc label location
- } else if (cookie == album_art_loading) {
- albumart = art_cache.encache(image, album_art_path);
- if (retrieveThemeColorsWhenLoaded && newTrackFetchingArtwork) {
- getThemeColors(albumart);
- retrieveThemeColorsWhenLoaded = false;
- newTrackFetchingArtwork = false;
- }
- ResizeArtwork(true);
- cdart && CreateRotatedCDImage();
- lastLeftEdge = 0; // recalc label location
- displayLyrics && updateLyricsPositionOnScreen();
- }
- RepaintWindow();
-}
-
-function on_script_unload() {
- console.log('Unloading Script');
- // it appears we don't need to dispose the images which we loaded using gdi.Image in their declaration for some reason. Attempting to dispose them causes a script error.
-}
-
-// Timed events
-
-function on_playback_time() {
- // Refresh playback time
- str.time = $('%playback_time%');
-
- // at each new second, hundredth is reset to 0 (Increment on timer every 100ms)
- hundredth = 0;
- if (displayLyrics && g_lyrics_status == 0 && lyricsWidth > 0 && albumart_size.w > 0) {
- if (elap_seconds.Eval() == 3) {
- refresh_lyrics();
- }
- window.RepaintRect(albumart_size.x + (albumart_size.w - lyricsWidth) / 2, albumart_size.y + pref.lyrics_h_padding, lyricsWidth, albumart_size.h - pref.lyrics_h_padding * 2);
- }
-}
-
-function refresh_seekbar() {
- //debugLog("in refresh_seekbar()");
- window.RepaintRect(0.025 * ww, wh - geo.lower_bar_h, 0.95 * ww, geo.lower_bar_h, true);
-}
-
-
-// TIMER Callback functions
-function doRotateImage() {
- debugLog("Repainting in doRotateImate: " + albumArtIndex);
- albumArtIndex = (albumArtIndex + 1) % aa_list.length;
- glob_image(albumArtIndex, true);
- lastLeftEdge = 0;
- RepaintWindow();
- globTimer = window.SetTimeout(function () {
- doRotateImage();
- }, pref.art_rotate_delay * 1000);
-}
-
-function timerTick(id) {
- if (displayLyrics) {
- var t1 = elap_seconds.Eval() * 100 + hundredth;
- var t2 = len_seconds.Eval() * 100;
- var p1, p2;
-
- if (t1 > t2 - 200) {
- // stop scrolling in final 2 seconds to make sure we clear interval
- console.log('clearing g_playtimer because t1 > t2-200 - t1 = ' + t1 + ', t2 = ' + t2);
- g_playtimer && window.clearInterval(g_playtimer);
- g_playtimer = null;
- }
-
- if (g_playtimer) {
- if (!g_is_scrolling && t1 >= g_tab[focus_next].timer) {
- p1 = g_tab[focus].ante_lines * pref.lyrics_line_height;
- p2 = g_tab[focus_next].ante_lines * pref.lyrics_line_height;
- g_scroll = (p2 - p1);
- // console.log("about to scroll " + g_scroll + " pixels");
- change_focus();
- g_is_scrolling = true;
- }
- g_timer_abs--;
- if (g_scroll > 0) {
- lyrPos -= g_scroll < SCROLL_STEP ? g_scroll : SCROLL_STEP;
- g_scroll -= g_scroll < SCROLL_STEP ? g_scroll : SCROLL_STEP;
- if (g_timer_abs <= 1) {
- g_timer_abs = 4;
- window.RepaintRect(albumart_size.x + (albumart_size.w - lyricsWidth) / 2, albumart_size.y + pref.lyrics_h_padding, lyricsWidth, albumart_size.h - pref.lyrics_h_padding * 2);
- }
- } else {
- g_timer_abs = 4;
- g_is_scrolling = false;
- }
- }
- }
- hundredth = (hundredth + 1) % 100;
-}
-
-function createShadowRect(width, height) {
- var shadow = gdi.CreateImage(width + 2 * geo.aa_shadow, height + 2 * geo.aa_shadow);
- var shimg = shadow.GetGraphics();
- shimg.FillRoundRect(geo.aa_shadow, geo.aa_shadow, width, height, 0.5 * geo.aa_shadow, 0.5 * geo.aa_shadow, col.aa_shadow);
- shadow.ReleaseGraphics(shimg);
- shadow.StackBlur(geo.aa_shadow);
-
- return shadow;
-}
-
-// HELPER FUNCTIONS
-function createDropShadow() {
- if (showDebugTiming) shadow = fb.CreateProfiler("createDropShadow");
- if ((albumart && albumart_size.w > 0) || (cdart && pref.display_cdart && cdart_size.w > 0)) {
- disposeImg(shadow_image);
- if (cdart && !displayPlaylist && !displayLibrary && pref.display_cdart)
- shadow_image = gdi.CreateImage(cdart_size.x + cdart_size.w + 2 * geo.aa_shadow, cdart_size.h + 4 + 2 * geo.aa_shadow);
- else
- shadow_image = gdi.CreateImage(albumart_size.x + albumart_size.w + 2 * geo.aa_shadow, albumart_size.h + 2 * geo.aa_shadow);
- if (shadow_image) {
- shimg = shadow_image.GetGraphics();
- if (albumart) {
- shimg.FillRoundRect(geo.aa_shadow, geo.aa_shadow, albumart_size.x + albumart_size.w, albumart_size.h,
- 0.5 * geo.aa_shadow, 0.5 * geo.aa_shadow, col.aa_shadow);
- }
-
- if (cdart && pref.display_cdart && !displayPlaylist && !displayLibrary) {
- var offset = cdart_size.w * 0.40; // don't change this value
- var xVal = cdart_size.x;
- var shadowOffset = geo.aa_shadow * 2;
- shimg.DrawEllipse(xVal + shadowOffset, shadowOffset + 1, cdart_size.w - shadowOffset, cdart_size.w - shadowOffset, geo.aa_shadow, col.aa_shadow); // outer shadow
- shimg.DrawEllipse(xVal + geo.aa_shadow + offset - 2, offset + geo.aa_shadow + 1, cdart_size.w - offset * 2, cdart_size.h - offset * 2, 60, col.aa_shadow); // inner shadow
- }
- shadow_image.ReleaseGraphics(shimg);
- shadow_image.StackBlur(geo.aa_shadow);
- }
- }
-
- if (showDebugTiming) shadow.Print();
-}
-
-function SetProgressBarRefresh() {
- debugLog("SetProgressBarRefresh()");
- if (fb.PlaybackLength > 0) {
- if (pref.freq_update) {
- t_interval = Math.abs(Math.ceil(1000 / ((0.95 * ww) / fb.PlaybackLength))); // we want to update the progress bar for every pixel so divide total time by number of pixels in progress bar
- while (t_interval > 500) // we want even multiples of the base t_interval, so that the progress bar always updates as smoothly as possible
- t_interval = Math.floor(t_interval / 2);
- while (t_interval < 25)
- t_interval *= 2;
- } else {
- t_interval = 333; // for slow computers, only update 3x a second
- }
-
- if (showDebugTiming)
- console.log("Progress bar will update every " + t_interval + "ms or " + 1000 / t_interval + " times per second.");
-
- progressTimer && window.ClearInterval(progressTimer);
- progressTimer = null;
- if (!fb.IsPaused) { // only create progressTimer if actually playing
- progressTimer = window.SetInterval(function () {
- refresh_seekbar();
- }, t_interval);
- }
- }
-}
-
-function parseJson(json, label) {
- var parsed = [];
- try {
- console.log(label + json);
- parsed = JSON.parse(json);
- } catch (e) {
- console.log('<<< ERROR IN parseJson >>>');
- console.log(json);
- }
- return parsed;
-}
-
-function calcAgeRatio(num, divisor) {
- return toFixed(1.0 - (calcAge(num, false) / divisor), 3);
-}
-
-function calcDateRatios(dontUpdateLastPlayed, currentLastPlayed) {
- dontUpdateLastPlayed = dontUpdateLastPlayed || false;
-
- playedTimesRatios = [];
- lfmPlayedTimesRatios = [];
- var added = toTime($('$if2(%added_enhanced%,%added%)'));
- var first_played = toTime($('$if2(%first_played_enhanced%,%first_played%)'));
- var last_played = $('$if2(%last_played_enhanced%,%last_played%)');
- var today = dateToYMD(new Date());
- // console.log('today:', today);
- if (dontUpdateLastPlayed && $date(last_played) === today) {
- last_played = new Date(toDatetime(currentLastPlayed)).getTime();
- console.log('Setting last_played to:', currentLastPlayed, ' => ', last_played);
- } else {
- last_played = toTime(last_played);
- }
-
- var lfmPlayedTimes = [];
- var playedTimes = [];
- if (componentEnhancedPlaycount) {
- var raw = $('[%played_times_js%]', fb.GetNowPlaying());
- var lastfm = $('[%lastfm_played_times_js%]', fb.GetNowPlaying());
- lfmPlayedTimes = parseJson(lastfm, 'lastfm: ');
- playedTimes = parseJson(raw, 'foobar: ');
- } else {
- playedTimes.push(first_played);
- playedTimes.push(last_played);
- }
-
-
- if (added && first_played) { //(first_played || lfmPlayedTimes.length)) {
- age = calcAge(added, false);
-
- tl_firstPlayedRatio = calcAgeRatio(first_played, age);
- tl_lastPlayedRatio = calcAgeRatio(last_played, age);
- console.log('fp (' + first_played + ') ratio: ', tl_firstPlayedRatio, 'lp (' + last_played + ') ratio:', tl_lastPlayedRatio);
- if (tl_lastPlayedRatio < tl_firstPlayedRatio) {
- // due to daylight savings time, if there's a single play before the time changed lastPlayed could be < firstPlayed
- tl_lastPlayedRatio = tl_firstPlayedRatio;
- }
-
- if (playedTimes.length) {
- for (i = 0; i < playedTimes.length; i++) {
- var ratio = calcAgeRatio(playedTimes[i], age);
- playedTimesRatios.push(ratio);
- }
- } else {
- playedTimesRatios = [tl_firstPlayedRatio, tl_lastPlayedRatio];
- }
-
- var j = 0;
- var tempPlayedTimesRatios = playedTimesRatios.slice();
- tempPlayedTimesRatios.push(1.0001); // pick up every last.fm time after last_played fb knows about
- for (i = 0; i < tempPlayedTimesRatios.length; i++) {
- while (j < lfmPlayedTimes.length &&
- (ratio = calcAgeRatio(lfmPlayedTimes[j], age)) < tempPlayedTimesRatios[i]) {
- playedTimesRatios.push(ratio);
- j++;
- }
- if (ratio === tempPlayedTimesRatios[i]) { // skip one instance
- // console.log('skipped -->', ratio);
- j++;
- }
- }
-
- } else {
- tl_firstPlayedRatio = 0.33;
- tl_lastPlayedRatio = 0.66;
- }
-}
-
-function glob_image(index, loadFromCache) {
- var temp_albumart;
- if (loadFromCache) {
- temp_albumart = art_cache.getImage(aa_list[index]);
- }
- if (temp_albumart) {
- // albumart = disposeImg(albumart);
- albumart = temp_albumart;
- if (cdart) {
- ResizeArtwork(false);
- CreateRotatedCDImage();
- }
- if (index === 0 && newTrackFetchingArtwork) {
- newTrackFetchingArtwork = false;
- getThemeColors(albumart);
- }
- } else {
- album_art_loading = gdi.LoadImageAsync(window.ID, aa_list[index]);
- album_art_path = aa_list[index];
- if (index === 0) {
- retrieveThemeColorsWhenLoaded = true;
- }
- }
- ResizeArtwork(false); // recalculate image positions
- displayLyrics && updateLyricsPositionOnScreen();
-}
-
-function fisherYates(myArray) {
- var i = myArray.length;
- if (i == 0) return false;
- while (--i) {
- var j = Math.floor(Math.random() * (i + 1));
- var tempi = myArray[i];
- var tempj = myArray[j];
- myArray[i] = tempj;
- myArray[j] = tempi;
- }
-}
-
-/* I use the debugLog function instead of console.log so that I can easily hide messages that I don't want cluttering the console constantly */
-function debugLog(str) {
- if (pref.show_debug_log) console.log(str);
-}
-
-function disposeImg(oldImage) {
- if (oldImage)
- oldImage.Dispose();
- return null;
-}
-
-function disposeCDImg(cdImage) {
- cdart_size = new ImageSize(0, 0, 0, 0);
- // disposeImg(cdImage);
- return null;
-}
-
-function CreateRotatedCDImage() {
- rotatedCD = disposeImg(rotatedCD);
- if (pref.display_cdart) { // drawing cdArt rotated is slow, so first draw it rotated into the rotatedCD image, and then draw rotatedCD image unrotated in on_paint
- if (cdart && cdart_size.w > 0) { // cdart must be square so just use cdart_size.w (width)
- rotatedCD = gdi.CreateImage(cdart_size.w, cdart_size.w);
- rotCDimg = rotatedCD.GetGraphics();
- trackNum = parseInt(fb.TitleFormat('$num($if(' + tf.vinyl_tracknum + ',$sub($mul(' + tf.vinyl_tracknum + ',2),1),$if2(%tracknumber%,1)),1)').Eval()) - 1;
- if (!pref.rotate_cdart || trackNum != trackNum) trackNum = 0; // avoid NaN issues when changing tracks rapidly
- rotCDimg.DrawImage(cdart, 0, 0, cdart_size.w, cdart_size.w, 0, 0, 1000, 1000, trackNum * pref.rotation_amt, 255);
- rotatedCD.ReleaseGraphics(rotCDimg);
- }
- }
-}
-
-function ResizeArtwork(resetCDPosition) {
- debugLog('Resizing artwork');
- var hasArtwork = false;
- if (albumart && albumart.Width && albumart.Height) {
- // Size for big albumart
- var album_scale = Math.min(((displayPlaylist || displayLibrary) ? 0.47 * ww : 0.75 * ww) / albumart.Width, (wh - geo.top_art_spacing - geo.lower_bar_h - 32) / albumart.Height);
- if (displayPlaylist || displayLibrary) {
- xCenter = 0.25 * ww;
- } else if (ww / wh < 1.40) { // when using a roughly 4:3 display the album art crowds, so move it slightly off center
- xCenter = 0.56 * ww; // TODO: check if this is still needed?
- } else {
- xCenter = 0.5 * ww;
- art_off_center = false;
- if (album_scale == 0.75 * ww / albumart.Width) {
- xCenter += 0.1 * ww;
- art_off_center = true; // TODO: We should probably suppress labels in this case
- }
- }
- albumart_size.w = Math.floor(albumart.Width * album_scale); // width
- albumart_size.h = Math.floor(albumart.Height * album_scale); // height
- albumart_size.x = Math.floor(xCenter - 0.5 * albumart_size.w); // left
- if (album_scale !== (wh - geo.top_art_spacing - geo.lower_bar_h - 32) / albumart.Height) {
- // restricted by width
- var y = geo.top_art_spacing + Math.floor(((wh - geo.top_art_spacing - geo.lower_bar_h - 32) / 2) - albumart_size.h / 2);
- albumart_size.y = Math.min(y, 160);
- } else {
- albumart_size.y = geo.top_art_spacing; // height of menu bar + spacing + height of Artist text (32+32+32) // top
- }
+ libraryPanel.on_size(x, y, library_w, library_h);
+ } else {
+ // TODO: take this if/else out once this part is done
+ displayLibrary = false;
+ }
+}
+
+// new track
+function on_playback_new_track(metadb) {
+ console.log('in on_playback_new_track()');
+ if (showDebugTiming) newTrackTime = fb.CreateProfiler('on_playback_new_track');
+ start_timer = 0;
+ lastLeftEdge = 0;
+ newTrackFetchingArtwork = true;
+ themeColorSet = false;
+
+ isStreaming = metadb ? !metadb.RawPath.match(/^file\:\/\//) : false;
+ if (!isStreaming) {
+ current_path = $('%directoryname%');
+ } else {
+ current_path = '';
+ }
+
+ SetProgressBarRefresh();
+
+ if (globTimer) {
+ window.ClearTimeout(globTimer);
+ globTimer = 0;
+ }
+
+ // Fetch new albumart
+ if ((pref.aa_glob && aa_list.length != 1) || current_path != last_path || albumart == null ||
+ $('$if2(%discnumber%,0)') != lastDiscNumber || $('$if2(' + tf.vinyl_side + ',ZZ)') != lastVinylSide) {
+ fetchNewArtwork(metadb);
+ }
+ loadFromCache = true;
+ CreateRotatedCDImage(); // we need to always setup the rotated image because it rotates on every track
+
+ /* code to retrieve record label logos */
+ var labelStrings = [];
+ while (recordLabels.length > 0)
+ disposeImg(recordLabels.pop());
+ for (i = 0; i < tf.labels.length; i++) {
+ for (j = 0; j < $('$meta_num(' + tf.labels[i] + ')'); j++) {
+ labelStrings.push($('$meta(' + tf.labels[i] + ',' + j + ')'));
+ }
+ }
+ labelStrings = _.uniq(labelStrings);
+ for (i = 0; i < labelStrings.length; i++) {
+ var addLabel = LoadLabelImage(labelStrings[i].replace(/'/, '\'\''));
+ if (addLabel != null) {
+ recordLabels.push(addLabel);
+ }
+ }
+
+ function testBandLogo(imgDir, bandStr, isHQ) {
+ var logoPath = imgDir + bandStr + '.png'
+ if (utils.FileTest(logoPath, 'e')) {
+ if (isHQ) {
+ bandLogoHQ = true;
+ console.log('Found band logo: ' + logoPath);
+ }
+ return logoPath;
+ }
+ return false;
+ }
+
+ /* code to retrieve band logo */
+ bandStr = $('[%artist%]').replace(/"/g, '\'').replace(/:/g, '_').replace(/\//g, '-').replace(/\*/g, '').replace(/\?/g, '');
+ bandLogo = disposeImg(bandLogo);
+ if (bandStr) {
+ bandLogoHQ = false;
+
+ var path = testBandLogo(pref.logo_hq, bandStr, true) || // try 800x310 white
+ testBandLogo(pref.logo_color, bandStr, true); // try 800x310 color
+ if (path) {
+ bandLogo = gdi.Image(path);
+ }
+ }
+
+ last_path = current_path; // for art caching purposes
+ lastDiscNumber = $('$if2(%discnumber%,0)'); // for art caching purposes
+ lastVinylSide = $('$if2(" + tf.vinyl_side + ",ZZ)');
+ currentLastPlayed = $(tf.last_played);
+
+ // enable "watch for tag changes" on new track
+ metadb_handle = fb.GetNowPlaying();
+ if (metadb_handle) {
+ on_metadb_changed(); // refresh panel
+ }
+
+ on_playback_time();
+ progressLength = 0;
+
+ if (displayPlaylist) {
+ playlist.on_playback_new_track(metadb);
+ } else if (displayLibrary) {
+ library.on_playback_new_track(metadb);
+ }
+
+ // Lyrics stuff
+ g_playtimer && window.ClearInterval(g_playtimer);
+ g_playtimer = null;
+ if (displayLyrics) { // no need to try retrieving them if we aren't going to display them now
+ updateLyricsPositionOnScreen();
+ }
+ if (showDebugTiming) newTrackTime.Print();
+}
+
+// tag content changed
+function on_metadb_changed(handle_list, fromhook) {
+ console.log('on_metadb_changed()');
+ if (fb.IsPlaying) {
+ var nowPlayingUpdated = !handle_list; // if we don't have a handle_list we called this manually from on_playback_new_track
+ var metadb = fb.GetNowPlaying();
+ if (metadb && handle_list) {
+ for (i = 0; i < handle_list.Count; i++) {
+ if (metadb.RawPath === handle_list.Item(i).RawPath) {
+ nowPlayingUpdated = true;
+ break;
+ }
+ }
+ }
+
+ if (nowPlayingUpdated) {
+ // the handle_list contains the currently playing song so update
+ var title = $(tf.title);
+ var artist = $(tf.artist);
+ var original_artist = $(tf.original_artist);
+ if (pref.use_vinyl_nums)
+ tracknum = $(tf.vinyl_track);
+ else
+ tracknum = $(tf.tracknum);
+
+ str.tracknum = tracknum.trim();
+ str.title = title + original_artist;
+ str.title_lower = ' ' + title;
+ str.original_artist = original_artist;
+ str.artist = artist;
+ str.year = $('$year($if2(%original release date%,%date%)))');
+ str.album = $("[%album%][ '['" + tf.album_trans + "']']");
+ str.album_subtitle = $("[ '['" + tf.album_subtitle + "']']");
+ var codec = $("$lower($if2(%codec%,$ext(%path%)))");
+ if (codec == "cue") {
+ codec = $("$ext($info(referenced_file))");
+ } else if (codec == "mpc") {
+ codec = codec + "-" + $("$info(codec_profile)").replace("quality ", "q");
+ } else if (codec == "dts" || codec == "ac3" || codec == "atsc a/52") {
+ codec += $("[ $replace($replace($replace($info(channel_mode), + LFE,),' front, ','/'),' rear surround channels',$if($strstr($info(channel_mode),' + LFE'),.1,.0))] %bitrate%") + " kbps";
+ codec = codec.replace("atsc a/52", "Dolby Digital");
+ } else if ($("$info(encoding)") == "lossy") {
+ if ($("$info(codec_profile)") == "CBR") codec = codec + "-" + $("%bitrate%") + " kbps";
+ else codec = codec + "-" + $("$info(codec_profile)");
+ }
+ str.trackInfo = $(codec + '[ | %replaygain_album_gain%]');
+
+ str.disc = fb.TitleFormat(tf.disc).Eval();
+
+ h = Math.floor(fb.PlaybackLength / 3600);
+ m = Math.floor(fb.PlaybackLength % 3600 / 60);
+ s = Math.floor(fb.PlaybackLength % 60);
+ str.length = (h > 0 ? h + ":" + (m < 10 ? "0" : '') + m : m) + ":" + (s < 10 ? "0" : '') + s;
+
+ str.grid = [];
+ for (k = 0; k < tf.grid.length; k++) {
+ val = $(tf.grid[k].val);
+ if (val) {
+ if (tf.grid[k].age) {
+ val = $('$date(' + val + ')'); // never show time
+ var age = calcAgeDateString(val);
+ if (age) {
+ val += ' (' + age + ')';
+ }
+ }
+ str.grid.push({
+ age: tf.grid[k].age,
+ label: tf.grid[k].label,
+ val: val,
+ });
+ }
+ }
+
+ var lastfm_count = $('%lastfm_play_count%');
+ if (lastfm_count !== '0' && lastfm_count !== '?') {
+ playCountVerifiedByLastFm = true;
+ } else {
+ playCountVerifiedByLastFm = false;
+ }
+
+ lastPlayed = $(tf.last_played);
+ calcDateRatios($date(currentLastPlayed) !== $date(lastPlayed), currentLastPlayed); // last_played has probably changed and we want to update the date bar
+ if (lastPlayed.length) {
+ today = dateToYMD(new Date());
+ if (!currentLastPlayed.length || $date(lastPlayed) !== today) {
+ currentLastPlayed = lastPlayed;
+ console.log('currentLastPlayed:', currentLastPlayed);
+ }
+ }
+
+ lp = str.grid.find(function (value) {
+ return value.label === 'Last Played';
+ });
+ if (lp) {
+ lp.val = $date(currentLastPlayed);
+ if (calcAgeDateString(lp.val)) {
+ lp.val += ' (' + calcAgeDateString(lp.val) + ')';
+ }
+ }
+
+ if (pref.show_flags) {
+ LoadCountryFlags();
+ }
+
+ tag_timer = 0;
+ }
+ }
+ // createHyperlinks();
+ if (displayPlaylist) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_metadb_changed(handle_list, fromhook);
+ }
+ RepaintWindow();
+}
+
+
+// User activity
+
+function on_playback_order_changed(this_pb) {
+ // Repaint playback order
+ if (this_pb != last_pb) {
+ debugLog("Repainting on_playback_order_changed");
+ window.RepaintRect(0.5 * ww, wh - geo.lower_bar_h, 0.5 * ww, geo.lower_bar_h);
+ }
+ last_pb = this_pb;
+}
+
+function on_playback_seek() {
+ progressMoved = true;
+ if (displayLyrics) {
+ refresh_lyrics();
+ }
+ on_playback_time();
+}
+
+var onMouseLbtnDown = false;
+
+function on_mouse_lbtn_down(x, y, m) {
+ var menu_yOffset = 19;
+ if (y > wh - geo.lower_bar_h) {
+ g_drag = 1;
+ }
+
+ // clicking on progress bar
+ if (pref.show_progress_bar && y >= wh - 0.5 * geo.lower_bar_h && y <= wh - 0.5 * geo.lower_bar_h + geo.prog_bar_h && x >= 0.025 * ww && x < 0.975 * ww) {
+ var v = (x - 0.025 * ww) / (0.95 * ww);
+ v = (v < 0) ? 0 : (v < 1) ? v : 1;
+ if (fb.PlaybackTime != v * fb.PlaybackLength) fb.PlaybackTime = v * fb.PlaybackLength;
+ window.RepaintRect(0, wh - geo.lower_bar_h, ww, geo.lower_bar_h);
+ }
+
+ buttonEventHandler(x, y, m);
+
+ if (displayPlaylist && playlist.mouse_in_this(x, y)) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_mouse_lbtn_down(x, y, m);
+ } else if (displayLibrary && library.mouse_in_this(x, y)) {
+ trace_call && console.log(qwr_utils.function_name());
+ library.on_mouse_lbtn_down(x, y, m);
+ }
+}
+
+function on_mouse_lbtn_up(x, y, m) {
+ g_drag = 0;
+
+ if (displayPlaylist && playlist.mouse_in_this(x, y)) {
+ trace_call && console.log(qwr_utils.function_name());
+
+ playlist.on_mouse_lbtn_up(x, y, m);
+
+ qwr_utils.EnableSizing(m);
+ } else if (displayLibrary && library.mouse_in_this(x, y)) {
+ trace_call && console.log(qwr_utils.function_name());
+ library.on_mouse_lbtn_up(x, y, m);
+ } else {
+
+ if (just_dblclicked) {
+ // You just did a double-click, so do nothing
+ just_dblclicked = false;
+ } else {
+ if ((albumart && albumart_size.x <= x && albumart_size.y <= y && albumart_size.x + albumart_size.w >= x && albumart_size.y + albumart_size.h >= y) ||
+ (cdart && !albumart && cdart_size.x <= x && cdart_size.y <= y && cdart_size.x + cdart_size.w >= x && cdart_size.y + cdart_size.h >= y) ||
+ pauseBtn.trace(x, y)) {
+ fb.PlayOrPause();
+ }
+ }
+ }
+ on_mouse_move(x, y);
+ buttonEventHandler(x, y, m);
+
+ onMouseLbtnDown = false;
+}
+
+function on_mouse_lbtn_dblclk(x, y, m) {
+ if (displayPlaylist && playlist.mouse_in_this(x, y)) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_mouse_lbtn_dblclk(x, y, m);
+ } else if (displayLibrary && library.mouse_in_this(x, y)) {
+ trace_call && console.log(qwr_utils.function_name());
+ library.on_mouse_lbtn_dblclk(x, y, m);
+ } else {
+ // re-initialise the panel
+ just_dblclicked = true;
+ if (fb.IsPlaying) {
+ albumart = null;
+ loadFromCache = false;
+ on_playback_new_track(fb.GetNowPlaying());
+ }
+ if (displayLyrics) {
+ refresh_lyrics();
+ }
+ buttonEventHandler(x, y, m);
+ }
+}
+
+function on_mouse_rbtn_down(x, y, m) {
+ if (displayPlaylist && playlist.mouse_in_this(x, y)) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_mouse_rbtn_down(x, y, m);
+ } else if (displayLibrary) {
+ // trace_call && console.log(qwr_utils.function_name());
+ // library.on_mouse_rbtn_down(x, y, m);
+ }
+}
+
+function on_mouse_rbtn_up(x, y, m) {
+ if (displayPlaylist && playlist.mouse_in_this(x, y)) {
+ trace_call && console.log(qwr_utils.function_name());
+ return playlist.on_mouse_rbtn_up(x, y, m);
+ } else if (displayLibrary && library.mouse_in_this(x, y)) {
+ trace_call && console.log(qwr_utils.function_name());
+ return library.on_mouse_rbtn_up(x, y, m);
+ } else
+ return pref.locked;
+}
+
+function on_mouse_move(x, y, m) {
+ if (x != state["mouse_x"] || y != state["mouse_y"]) {
+ window.SetCursor(32512); // arrow
+ if (g_drag) {
+ var v = (x - 0.025 * ww) / (0.95 * ww);
+ v = (v < 0) ? 0 : (v < 1) ? v : 1;
+ if (fb.PlaybackTime != v * fb.PlaybackLength) fb.PlaybackTime = v * fb.PlaybackLength;
+ }
+ state["mouse_x"] = x;
+ state["mouse_y"] = y;
+ if (pref.hide_cursor) {
+ window.ClearTimeout(hideCursor);
+ //debugLog("on_mouse_move: creating window.SetCursor() timeout with timeout = " + 10000);
+ hideCursor = window.SetTimeout(function () {
+ // if there's a menu id (i.e. a menu is down) we don't want the cursor to ever disappear
+ if (!menu_down) {
+ window.SetCursor(-1); // hide cursor
+ }
+ }, 10000);
+ }
+
+ buttonEventHandler(x, y, m);
+ // hyperlinkEventHandler(x, y, m);
+
+ if (displayPlaylist && playlist.mouse_in_this(x, y)) {
+ trace_call && trace_on_move && console.log(qwr_utils.function_name());
+
+ if (mouse_move_suppress.is_supressed(x, y, m)) {
+ return;
+ }
+
+ qwr_utils.DisableSizing(m);
+ playlist.on_mouse_move(x, y, m);
+ } else if (displayLibrary && library.mouse_in_this(x, y)) {
+ library.on_mouse_move(x, y, m);
+ }
+ }
+}
+
+function on_mouse_wheel(delta) {
+ if (state["mouse_y"] > wh - geo.lower_bar_h) {
+ fb.PlaybackTime = fb.PlaybackTime - delta * pref.mouse_wheel_seek_speed;
+ refresh_seekbar();
+ return;
+ }
+ if (displayPlaylist) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_mouse_wheel(delta);
+ } else if (displayLibrary) {
+ // trace_call && console.log(qwr_utils.function_name());
+ library.on_mouse_wheel(delta);
+ }
+}
+// =================================================== //
+
+// trace_call = true;
+
+function on_mouse_leave() {
+
+ if (displayPlaylist) {
+ playlist.on_mouse_leave();
+ } else if (displayLibrary) {
+ library.on_mouse_leave();
+ }
+}
+
+function on_playlists_changed() {
+ if (displayPlaylist) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_playlists_changed();
+ }
+}
+
+function on_playlist_switch() {
+ if (displayPlaylist) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_playlist_switch();
+ }
+}
+
+function on_playlist_item_ensure_visible(playlistIndex, playlistItemIndex) {
+ if (displayPlaylist) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_playlist_item_ensure_visible(playlistIndex, playlistItemIndex);
+ }
+}
+
+function on_playlist_items_added(playlistIndex) {
+ if (displayPlaylist) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_playlist_items_added(playlistIndex);
+ }
+}
+
+function on_playlist_items_reordered(playlistIndex) {
+ if (displayPlaylist) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_playlist_items_reordered(playlistIndex);
+ }
+}
+
+function on_playlist_items_removed(playlistIndex) {
+ if (displayPlaylist) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_playlist_items_removed(playlistIndex);
+ }
+}
+
+function on_playlist_items_selection_change() {
+ if (displayPlaylist) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_playlist_items_selection_change();
+ }
+}
+
+function on_library_items_added(handle_list) {
+ if (displayLibrary) {
+ trace_call && console.log(qwr_utils.function_name());
+ library.on_library_items_added(handle_list);
+ }
+}
+
+function on_library_items_removed(handle_list) {
+ if (displayLibrary) {
+ trace_call && console.log(qwr_utils.function_name());
+ library.on_library_items_removed(handle_list);
+ }
+}
+
+function on_library_items_changed(handle_list) {
+ if (displayLibrary) {
+ trace_call && console.log(qwr_utils.function_name());
+ library.on_library_items_changed(handle_list);
+ }
+}
+
+function on_item_focus_change(playlist_arg, from, to) {
+ if (displayPlaylist) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_item_focus_change(playlist_arg, from, to);
+ } else if (displayLibrary) {
+ trace_call && console.log(qwr_utils.function_name());
+ library.on_item_focus_change();
+ }
+}
+
+function on_key_down(vkey) {
+
+ var CtrlKeyPressed = utils.IsKeyPressed(VK_CONTROL);
+ var ShiftKeyPressed = utils.IsKeyPressed(VK_SHIFT);
+
+ if (displayPlaylist) {
+ trace_call && console.log(qwr_utils.function_name());
+
+ if (key_down_suppress.is_supressed(vkey)) {
+ return;
+ }
+
+ playlist.on_key_down(vkey);
+ } else if (displayLibrary) {
+ trace_call && console.log(qwr_utils.function_name());
+ library.on_key_down(vkey);
+ }
+
+ switch (vkey) {
+ case 0x6B: // VK_ADD ??
+ case 0x6D: // VK_SUBTRACT ??
+ if (CtrlKeyPressed && ShiftKeyPressed) {
+ var action = vkey === 0x6B ? '+' : '-';
+ if (fb.IsPlaying) {
+ var metadb = fb.GetNowPlaying();
+ fb.RunContextCommandWithMetadb('Rating/' + action, metadb);
+ } else if (!metadb && displayPlaylist) {
+ var metadbList = plman.GetPlaylistSelectedItems(plman.ActivePlaylist);
+ if (metadbList.Count === 1) {
+ fb.RunContextCommandWithMetadb('Rating/' + action, metadbList.Item(0));
+ } else {
+ console.log('Won\'t change rating with more than one selected item');
+ }
+ }
+ }
+ break;
+ }
+}
+// =================================================== //
+
+
+function on_char(code) {
+ if (displayLibrary) {
+ trace_call && console.log(qwr_utils.function_name());
+ library.on_char(code);
+ }
+}
+
+function on_key_up(vkey) {
+ if (displayLibrary) {
+ trace_call && console.log(qwr_utils.function_name());
+ library.on_key_up(vkey);
+ }
+}
+
+function on_playback_queue_changed(origin) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_playback_queue_changed(origin);
+}
+
+
+function on_playback_pause(state) {
+ if (pref.show_transport) {
+ createButtonObjects(ww, wh);
+ window.RepaintRect(btns[2].x, btns[2].y, btns[2].w, btns[2].h); // redraw play/pause button
+ }
+ if (state) { // pausing
+ if (progressTimer) window.ClearInterval(progressTimer);
+ progressTimer = 0;
+ window.RepaintRect(0.015 * ww, 0.12 * wh, Math.max(albumart_size.x - 0.015 * ww, 0.015 * ww), wh - geo.lower_bar_h - 0.12 * wh);
+ } else { // unpausing
+ if (progressTimer > 0) window.ClearInterval(progressTimer); // clear to avoid multiple progressTimers which can happen depending on the playback state when theme is loaded
+ debugLog("on_playback_pause: creating refresh_seekbar() interval with delay = " + t_interval);
+ progressTimer = window.SetInterval(function () {
+ refresh_seekbar();
+ }, t_interval);
+ }
+
+ pauseBtn.repaint();
+ if (albumart && displayLyrics) { // if we are displaying lyrics we need to refresh all the lyrics to avoid tearing at the edges of the pause button
+ window.RepaintRect(albumart_size.x + (albumart_size.w - lyricsWidth) / 2, albumart_size.y + pref.lyrics_h_padding, lyricsWidth, albumart_size.h - pref.lyrics_h_padding * 2);
+ }
+
+ if (displayPlaylist) {
+ playlist.on_playback_pause(state);
+ }
+}
+
+function on_playback_stop(reason) {
+ if (reason !== 2) { // 2 = starting_another
+ // clear all variables and repaint
+ str = clearUIVariables()
+ debugLog("Repainting on_playback_stop");
+ RepaintWindow();
+ last_path = '';
+ lastDiscNumber = "0";
+ while (recordLabels.length > 0) {
+ disposeImg(recordLabels.pop());
+ }
+ if (metadb_handle) {
+ metadb_handle = null;
+ }
+ createButtonObjects(ww, wh); // switch pause button to play
+ loadFromCache = false;
+ }
+ progressTimer && window.ClearInterval(progressTimer);
+ if (globTimer)
+ window.ClearTimeout(globTimer);
+ if (albumart && ((pref.aa_glob && aa_list.length != 1) || last_path == '')) {
+ debugLog("disposing artwork");
+ albumart = null;
+ albumart_scaled = disposeImg(albumart_scaled);
+ }
+ bandLogo = disposeImg(bandLogo);
+ while (flagImgs.length > 0)
+ disposeImg(flagImgs.pop());
+ rotatedCD = disposeImg(rotatedCD);
+ globTimer = 0;
+
+ g_playtimer && window.ClearInterval(g_playtimer);
+ g_playtimer = null;
+ if (reason === 0) {
+ // Stop
+ cdart = disposeCDImg(cdart);
+ window.Repaint();
+ }
+ if (displayPlaylist) {
+ playlist.on_playback_stop(reason);
+ }
+}
+
+function on_playback_starting(cmd, is_paused) {
+ if (pref.hide_cursor) {
+ window.SetCursor(-1); // hide cursor
+ }
+ createButtonObjects(ww, wh); // play button to pause
+}
+
+function on_drag_enter(action, x, y, mask) {
+ if (displayPlaylist) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_drag_enter(action, x, y, mask);
+ }
+}
+
+function on_drag_leave() {
+ if (displayPlaylist) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_drag_leave();
+ }
+}
+
+function on_drag_drop(action, x, y, mask) {
+ if (displayPlaylist) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_drag_drop(action, x, y, mask);
+ }
+}
+
+function on_focus(is_focused) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_focus(is_focused);
+}
+
+function on_notify_data(name, info) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_notify_data(name, info);
+}
+
+var debounced_init_playlist = _.debounce(function (playlistIndex) {
+ trace_call && console.log('debounced_init_playlist');
+ playlist.on_playlist_items_added(playlistIndex);
+}, 0, {
+ leading: false,
+ trailing: true
+});
+
+// =================================================== //
+
+function clearUIVariables() {
+ return {
+ artist: '',
+ tracknum: stoppedStr1,
+ title_lower: ' ' + stoppedStr2,
+ year: '',
+ grid: [],
+ time: ''
+ }
+}
+
+// album art retrieved from GetAlbumArtAsync
+function on_get_album_art_done(metadb, art_id, image, image_path) {
+ if (displayPlaylist) {
+ trace_call && console.log(qwr_utils.function_name());
+ playlist.on_get_album_art_done(metadb, art_id, image, image_path);
+ } else if (displayLibrary) {
+ // trace_call && console.log(qwr_utils.function_name());
+ // library.on_get_album_art_done(metadb, art_id, image, image_path);
+ }
+}
+
+// returned from LoadImageAsync
+function on_load_image_done(cookie, image) {
+ console.log('on_load_image_done returned');
+ if (cookie == disc_art_loading) {
+ disposeCDImg(cdart); // delay disposal so we don't get flashing
+ cdart = art_cache.encache(image, cdartPath);
+ ResizeArtwork(true);
+ CreateRotatedCDImage();
+ lastLeftEdge = 0; // recalc label location
+ } else if (cookie == album_art_loading) {
+ albumart = art_cache.encache(image, album_art_path);
+ if (retrieveThemeColorsWhenLoaded && newTrackFetchingArtwork) {
+ getThemeColors(albumart);
+ retrieveThemeColorsWhenLoaded = false;
+ newTrackFetchingArtwork = false;
+ }
+ ResizeArtwork(true);
+ cdart && CreateRotatedCDImage();
+ lastLeftEdge = 0; // recalc label location
+ displayLyrics && updateLyricsPositionOnScreen();
+ }
+ RepaintWindow();
+}
+
+function on_script_unload() {
+ console.log('Unloading Script');
+ // it appears we don't need to dispose the images which we loaded using gdi.Image in their declaration for some reason. Attempting to dispose them causes a script error.
+}
+
+// Timed events
+
+function on_playback_time() {
+ // Refresh playback time
+ str.time = $('%playback_time%');
+
+ // at each new second, hundredth is reset to 0 (Increment on timer every 100ms)
+ hundredth = 0;
+ if (displayLyrics && g_lyrics_status == 0 && lyricsWidth > 0 && albumart_size.w > 0) {
+ if (elap_seconds.Eval() == 3) {
+ refresh_lyrics();
+ }
+ window.RepaintRect(albumart_size.x + (albumart_size.w - lyricsWidth) / 2, albumart_size.y + pref.lyrics_h_padding, lyricsWidth, albumart_size.h - pref.lyrics_h_padding * 2);
+ }
+}
+
+function refresh_seekbar() {
+ //debugLog("in refresh_seekbar()");
+ window.RepaintRect(0.025 * ww, wh - geo.lower_bar_h, 0.95 * ww, geo.lower_bar_h, true);
+}
+
+
+// TIMER Callback functions
+function doRotateImage() {
+ debugLog("Repainting in doRotateImate: " + albumArtIndex);
+ albumArtIndex = (albumArtIndex + 1) % aa_list.length;
+ glob_image(albumArtIndex, true);
+ lastLeftEdge = 0;
+ RepaintWindow();
+ globTimer = window.SetTimeout(function () {
+ doRotateImage();
+ }, pref.art_rotate_delay * 1000);
+}
+
+function timerTick(id) {
+ if (displayLyrics) {
+ var t1 = elap_seconds.Eval() * 100 + hundredth;
+ var t2 = len_seconds.Eval() * 100;
+ var p1, p2;
+
+ if (t1 > t2 - 200) {
+ // stop scrolling in final 2 seconds to make sure we clear interval
+ console.log('clearing g_playtimer because t1 > t2-200 - t1 = ' + t1 + ', t2 = ' + t2);
+ g_playtimer && window.clearInterval(g_playtimer);
+ g_playtimer = null;
+ }
+
+ if (g_playtimer) {
+ if (!g_is_scrolling && t1 >= g_tab[focus_next].timer) {
+ p1 = g_tab[focus].ante_lines * pref.lyrics_line_height;
+ p2 = g_tab[focus_next].ante_lines * pref.lyrics_line_height;
+ g_scroll = (p2 - p1);
+ // console.log("about to scroll " + g_scroll + " pixels");
+ change_focus();
+ g_is_scrolling = true;
+ }
+ g_timer_abs--;
+ if (g_scroll > 0) {
+ lyrPos -= g_scroll < SCROLL_STEP ? g_scroll : SCROLL_STEP;
+ g_scroll -= g_scroll < SCROLL_STEP ? g_scroll : SCROLL_STEP;
+ if (g_timer_abs <= 1) {
+ g_timer_abs = 4;
+ window.RepaintRect(albumart_size.x + (albumart_size.w - lyricsWidth) / 2, albumart_size.y + pref.lyrics_h_padding, lyricsWidth, albumart_size.h - pref.lyrics_h_padding * 2);
+ }
+ } else {
+ g_timer_abs = 4;
+ g_is_scrolling = false;
+ }
+ }
+ }
+ hundredth = (hundredth + 1) % 100;
+}
+
+function createShadowRect(width, height) {
+ var shadow = gdi.CreateImage(width + 2 * geo.aa_shadow, height + 2 * geo.aa_shadow);
+ var shimg = shadow.GetGraphics();
+ shimg.FillRoundRect(geo.aa_shadow, geo.aa_shadow, width, height, 0.5 * geo.aa_shadow, 0.5 * geo.aa_shadow, col.aa_shadow);
+ shadow.ReleaseGraphics(shimg);
+ shadow.StackBlur(geo.aa_shadow);
+
+ return shadow;
+}
+
+// HELPER FUNCTIONS
+function createDropShadow() {
+ if (showDebugTiming) shadow = fb.CreateProfiler("createDropShadow");
+ if ((albumart && albumart_size.w > 0) || (cdart && pref.display_cdart && cdart_size.w > 0)) {
+ disposeImg(shadow_image);
+ if (cdart && !displayPlaylist && !displayLibrary && pref.display_cdart)
+ shadow_image = gdi.CreateImage(cdart_size.x + cdart_size.w + 2 * geo.aa_shadow, cdart_size.h + 4 + 2 * geo.aa_shadow);
+ else
+ shadow_image = gdi.CreateImage(albumart_size.x + albumart_size.w + 2 * geo.aa_shadow, albumart_size.h + 2 * geo.aa_shadow);
+ if (shadow_image) {
+ shimg = shadow_image.GetGraphics();
+ if (albumart) {
+ shimg.FillRoundRect(geo.aa_shadow, geo.aa_shadow, albumart_size.x + albumart_size.w, albumart_size.h,
+ 0.5 * geo.aa_shadow, 0.5 * geo.aa_shadow, col.aa_shadow);
+ }
+
+ if (cdart && pref.display_cdart && !displayPlaylist && !displayLibrary) {
+ var offset = cdart_size.w * 0.40; // don't change this value
+ var xVal = cdart_size.x;
+ var shadowOffset = geo.aa_shadow * 2;
+ shimg.DrawEllipse(xVal + shadowOffset, shadowOffset + 1, cdart_size.w - shadowOffset, cdart_size.w - shadowOffset, geo.aa_shadow, col.aa_shadow); // outer shadow
+ shimg.DrawEllipse(xVal + geo.aa_shadow + offset - 2, offset + geo.aa_shadow + 1, cdart_size.w - offset * 2, cdart_size.h - offset * 2, 60, col.aa_shadow); // inner shadow
+ }
+ shadow_image.ReleaseGraphics(shimg);
+ shadow_image.StackBlur(geo.aa_shadow);
+ }
+ }
+
+ if (showDebugTiming) shadow.Print();
+}
+
+function SetProgressBarRefresh() {
+ debugLog("SetProgressBarRefresh()");
+ if (fb.PlaybackLength > 0) {
+ if (pref.freq_update) {
+ t_interval = Math.abs(Math.ceil(1000 / ((0.95 * ww) / fb.PlaybackLength))); // we want to update the progress bar for every pixel so divide total time by number of pixels in progress bar
+ while (t_interval > 500) // we want even multiples of the base t_interval, so that the progress bar always updates as smoothly as possible
+ t_interval = Math.floor(t_interval / 2);
+ while (t_interval < 25)
+ t_interval *= 2;
+ } else {
+ t_interval = 333; // for slow computers, only update 3x a second
+ }
+
+ if (showDebugTiming)
+ console.log("Progress bar will update every " + t_interval + "ms or " + 1000 / t_interval + " times per second.");
+
+ progressTimer && window.ClearInterval(progressTimer);
+ progressTimer = null;
+ if (!fb.IsPaused) { // only create progressTimer if actually playing
+ progressTimer = window.SetInterval(function () {
+ refresh_seekbar();
+ }, t_interval);
+ }
+ }
+}
+
+function parseJson(json, label) {
+ var parsed = [];
+ try {
+ console.log(label + json);
+ parsed = JSON.parse(json);
+ } catch (e) {
+ console.log('<<< ERROR IN parseJson >>>');
+ console.log(json);
+ }
+ return parsed;
+}
+
+function calcAgeRatio(num, divisor) {
+ return toFixed(1.0 - (calcAge(num, false) / divisor), 3);
+}
+
+function calcDateRatios(dontUpdateLastPlayed, currentLastPlayed) {
+ dontUpdateLastPlayed = dontUpdateLastPlayed || false;
+
+ playedTimesRatios = [];
+ lfmPlayedTimesRatios = [];
+ var added = toTime($('$if2(%added_enhanced%,%added%)'));
+ var first_played = toTime($('$if2(%first_played_enhanced%,%first_played%)'));
+ var last_played = $('$if2(%last_played_enhanced%,%last_played%)');
+ var today = dateToYMD(new Date());
+ // console.log('today:', today);
+ if (dontUpdateLastPlayed && $date(last_played) === today) {
+ last_played = new Date(toDatetime(currentLastPlayed)).getTime();
+ console.log('Setting last_played to:', currentLastPlayed, ' => ', last_played);
+ } else {
+ last_played = toTime(last_played);
+ }
+
+ var lfmPlayedTimes = [];
+ var playedTimes = [];
+ if (componentEnhancedPlaycount) {
+ var raw = $('[%played_times_js%]', fb.GetNowPlaying());
+ var lastfm = $('[%lastfm_played_times_js%]', fb.GetNowPlaying());
+ lfmPlayedTimes = parseJson(lastfm, 'lastfm: ');
+ playedTimes = parseJson(raw, 'foobar: ');
+ } else {
+ playedTimes.push(first_played);
+ playedTimes.push(last_played);
+ }
+
+
+ if (added && first_played) { //(first_played || lfmPlayedTimes.length)) {
+ age = calcAge(added, false);
+
+ tl_firstPlayedRatio = calcAgeRatio(first_played, age);
+ tl_lastPlayedRatio = calcAgeRatio(last_played, age);
+ console.log('fp (' + first_played + ') ratio: ', tl_firstPlayedRatio, 'lp (' + last_played + ') ratio:', tl_lastPlayedRatio);
+ if (tl_lastPlayedRatio < tl_firstPlayedRatio) {
+ // due to daylight savings time, if there's a single play before the time changed lastPlayed could be < firstPlayed
+ tl_lastPlayedRatio = tl_firstPlayedRatio;
+ }
+
+ if (playedTimes.length) {
+ for (i = 0; i < playedTimes.length; i++) {
+ var ratio = calcAgeRatio(playedTimes[i], age);
+ playedTimesRatios.push(ratio);
+ }
+ } else {
+ playedTimesRatios = [tl_firstPlayedRatio, tl_lastPlayedRatio];
+ }
+
+ var j = 0;
+ var tempPlayedTimesRatios = playedTimesRatios.slice();
+ tempPlayedTimesRatios.push(1.0001); // pick up every last.fm time after last_played fb knows about
+ for (i = 0; i < tempPlayedTimesRatios.length; i++) {
+ while (j < lfmPlayedTimes.length &&
+ (ratio = calcAgeRatio(lfmPlayedTimes[j], age)) < tempPlayedTimesRatios[i]) {
+ playedTimesRatios.push(ratio);
+ j++;
+ }
+ if (ratio === tempPlayedTimesRatios[i]) { // skip one instance
+ // console.log('skipped -->', ratio);
+ j++;
+ }
+ }
+
+ } else {
+ tl_firstPlayedRatio = 0.33;
+ tl_lastPlayedRatio = 0.66;
+ }
+}
+
+function glob_image(index, loadFromCache) {
+ var temp_albumart;
+ if (loadFromCache) {
+ temp_albumart = art_cache.getImage(aa_list[index]);
+ }
+ if (temp_albumart) {
+ // albumart = disposeImg(albumart);
+ albumart = temp_albumart;
+ if (cdart) {
+ ResizeArtwork(false);
+ CreateRotatedCDImage();
+ }
+ if (index === 0 && newTrackFetchingArtwork) {
+ newTrackFetchingArtwork = false;
+ getThemeColors(albumart);
+ }
+ } else {
+ album_art_loading = gdi.LoadImageAsync(window.ID, aa_list[index]);
+ album_art_path = aa_list[index];
+ if (index === 0) {
+ retrieveThemeColorsWhenLoaded = true;
+ }
+ }
+ ResizeArtwork(false); // recalculate image positions
+ displayLyrics && updateLyricsPositionOnScreen();
+}
+
+function fisherYates(myArray) {
+ var i = myArray.length;
+ if (i == 0) return false;
+ while (--i) {
+ var j = Math.floor(Math.random() * (i + 1));
+ var tempi = myArray[i];
+ var tempj = myArray[j];
+ myArray[i] = tempj;
+ myArray[j] = tempi;
+ }
+}
+
+/* I use the debugLog function instead of console.log so that I can easily hide messages that I don't want cluttering the console constantly */
+function debugLog(str) {
+ if (pref.show_debug_log) console.log(str);
+}
+
+function disposeImg(oldImage) {
+ if (oldImage)
+ oldImage.Dispose();
+ return null;
+}
+
+function disposeCDImg(cdImage) {
+ cdart_size = new ImageSize(0, 0, 0, 0);
+ // disposeImg(cdImage);
+ return null;
+}
+
+function CreateRotatedCDImage() {
+ rotatedCD = disposeImg(rotatedCD);
+ if (pref.display_cdart) { // drawing cdArt rotated is slow, so first draw it rotated into the rotatedCD image, and then draw rotatedCD image unrotated in on_paint
+ if (cdart && cdart_size.w > 0) { // cdart must be square so just use cdart_size.w (width)
+ rotatedCD = gdi.CreateImage(cdart_size.w, cdart_size.w);
+ rotCDimg = rotatedCD.GetGraphics();
+ trackNum = parseInt(fb.TitleFormat('$num($if(' + tf.vinyl_tracknum + ',$sub($mul(' + tf.vinyl_tracknum + ',2),1),$if2(%tracknumber%,1)),1)').Eval()) - 1;
+ if (!pref.rotate_cdart || trackNum != trackNum) trackNum = 0; // avoid NaN issues when changing tracks rapidly
+ rotCDimg.DrawImage(cdart, 0, 0, cdart_size.w, cdart_size.w, 0, 0, 1000, 1000, trackNum * pref.rotation_amt, 255);
+ rotatedCD.ReleaseGraphics(rotCDimg);
+ }
+ }
+}
+
+function ResizeArtwork(resetCDPosition) {
+ debugLog('Resizing artwork');
+ var hasArtwork = false;
+ if (albumart && albumart.Width && albumart.Height) {
+ // Size for big albumart
+ var album_scale = Math.min(((displayPlaylist || displayLibrary) ? 0.47 * ww : 0.75 * ww) / albumart.Width, (wh - geo.top_art_spacing - geo.lower_bar_h - 32) / albumart.Height);
+ if (displayPlaylist || displayLibrary) {
+ xCenter = 0.25 * ww;
+ } else if (ww / wh < 1.40) { // when using a roughly 4:3 display the album art crowds, so move it slightly off center
+ xCenter = 0.56 * ww; // TODO: check if this is still needed?
+ } else {
+ xCenter = 0.5 * ww;
+ art_off_center = false;
+ if (album_scale == 0.75 * ww / albumart.Width) {
+ xCenter += 0.1 * ww;
+ art_off_center = true; // TODO: We should probably suppress labels in this case
+ }
+ }
+ albumart_size.w = Math.floor(albumart.Width * album_scale); // width
+ albumart_size.h = Math.floor(albumart.Height * album_scale); // height
+ albumart_size.x = Math.floor(xCenter - 0.5 * albumart_size.w); // left
+ if (album_scale !== (wh - geo.top_art_spacing - geo.lower_bar_h - 32) / albumart.Height) {
+ // restricted by width
+ var y = geo.top_art_spacing + Math.floor(((wh - geo.top_art_spacing - geo.lower_bar_h - 32) / 2) - albumart_size.h / 2);
+ albumart_size.y = Math.min(y, 160);
+ } else {
+ albumart_size.y = geo.top_art_spacing; // height of menu bar + spacing + height of Artist text (32+32+32) // top
+ }
if (btns.playlist && albumart_size.x + albumart_size.w > btns.playlist.x - 50) {
- albumart_size.y += 16 - pref.show_transport * 6;
- }
-
- if (albumart_scaled) {
- albumart_scaled.Dispose();
- }
- albumart_scaled = albumart.Resize(albumart_size.w, albumart_size.h);
- pauseBtn.setCoords(albumart_size.x + albumart_size.w / 2, albumart_size.y + albumart_size.h / 2);
- hasArtwork = true;
- } else {
- albumart_size = new ImageSize(0, 0, 0, 0);
- }
- if (cdart) {
- if (!hasArtwork) {
- // no album art so we need to calc size of disc
- var album_scale = Math.min(((displayPlaylist || displayLibrary) ? 0.47 * ww : 0.75 * ww) / cdart.Width, (wh - geo.top_art_spacing - geo.lower_bar_h - 32) / cdart.Height);
- if (displayPlaylist || displayLibrary) {
- xCenter = 0.25 * ww;
- } else if (ww / wh < 1.40) { // when using a roughly 4:3 display the album art crowds, so move it slightly off center
- xCenter = 0.56 * ww; // TODO: check if this is still needed?
- } else {
- xCenter = 0.5 * ww;
- art_off_center = false;
- if (album_scale == 0.75 * ww / cdart.Width) {
- xCenter += 0.1 * ww;
- art_off_center = true; // TODO: We should probably suppress labels in this case
- }
- }
- cdart_size.w = Math.floor(cdart.Width * album_scale); // width
- cdart_size.h = Math.floor(cdart.Height * album_scale); // height
- cdart_size.x = Math.floor(xCenter - 0.5 * cdart_size.w); // left
- if (album_scale !== (wh - geo.top_art_spacing - geo.lower_bar_h - 32) / cdart.Height) {
- // restricted by width
- var y = geo.top_art_spacing + Math.floor(((wh - geo.top_art_spacing - geo.lower_bar_h - 32) / 2) - cdart_size.h / 2);
- cdart_size.y = Math.min(y, 160);
- } else {
- cdart_size.y = geo.top_art_spacing; // height of menu bar + spacing + height of Artist text (32+32+32) // top
- }
- pauseBtn.setCoords(cdart_size.x + cdart_size.w / 2, cdart_size.y + cdart_size.h / 2);
- } else {
- if (resetCDPosition) {
- if (ww - (albumart_size.x + albumart_size.w) < albumart_size.h * pref.cdart_amount + 5)
- cdart_size.x = Math.floor(0.99 * ww - albumart_size.h);
- else
- cdart_size.x = Math.floor(albumart_size.x + albumart_size.w - (albumart_size.h - 4) * (1 - pref.cdart_amount));
- cdart_size.y = albumart_size.y + 2;
- cdart_size.w = albumart_size.h - 4; // cdart must be square so use the height of album art for width of cdart
- cdart_size.h = cdart_size.w;
- } else { // when CDArt moves because folder images are different sizes we want to push it outwards, but not move it back in so it jumps around less
- cdart_size.x = Math.max(cdart_size.x, Math.floor(Math.min(0.99 * ww - albumart_size.h, albumart_size.x + albumart_size.w - (albumart_size.h - 4) * (1 - pref.cdart_amount))));
- cdart_size.y = cdart_size.y > 0 ? Math.min(cdart_size.y, albumart_size.y + 2) : albumart_size.y + 2;
- cdart_size.w = Math.max(cdart_size.w, albumart_size.h - 4);
- cdart_size.h = cdart_size.w;
- }
- }
- hasArtwork = true;
- } else {
- cdart_size = new ImageSize(0, 0, 0, 0);
- }
- if (hasArtwork) {
- createDropShadow();
- } else {
- if (displayLibrary || displayPlaylist) {
- pauseBtn.setCoords(ww * (0.33 + .167 / 2), wh / 2);
- } else {
- pauseBtn.setCoords(ww / 2, wh / 2);
- }
- }
-}
-
-function LoadCountryFlags() {
- while (flagImgs.length) {
- disposeImg(flagImgs.pop());
- }
- for (i = 0; i < $('$meta_num(' + tf.artist_country + ')'); i++) {
- path = $(pref.flags_base) + (is_4k ? '64\\' : '32\\') + $('$meta(' + tf.artist_country + ',' + i + ')').replace(/ /g, '-') + '.png';
- var fImg = gdi.Image(path);
- fImg && flagImgs.push(fImg);
- }
-}
-
-function LoadLabelImage(publisherString) {
- recordLabel = null;
- d = new Date();
- labelStr = $(publisherString.replace(']', '').replace('[', '').replace(':', ''));
- if (labelStr) {
- /* First check for record label folder */
- lastSrchYear = d.getFullYear();
- dir = pref.label_base; // also used below
- if (utils.FileTest(dir + labelStr, 'd') ||
- utils.FileTest(dir + (labelStr = labelStr.replace(/ Records$/, '')
- .replace(/ Recordings$/, '')
- .replace(/ Music$/, '')
- .replace(/\.$/, '')), 'd')) {
- year = parseInt($('$year(%date%)'));
- for (; year <= lastSrchYear; year++) {
- yearFolder = dir + labelStr + '\\' + year;
- if (utils.FileTest(yearFolder, 'd')) {
- console.log('Found folder for ' + labelStr + ' for year ' + year + '.');
- dir += labelStr + '\\' + year + '\\';
- break;
- }
- }
- if (year > lastSrchYear) {
- dir += labelStr + '\\'; /* we didn't find a year folder so use the "default" logo in the root */
- }
- }
- /* actually load the label from either the directory we found above, or the base record label folder */
- labelStr = $(publisherString.replace(']', '').replace('[', '').replace(':', '')); // we need to start over with the original string when searching for the file, just to be safe
- label = dir + labelStr + '.png';
- if (utils.FileTest(label, 'e')) {
- recordLabel = gdi.Image(label);
- console.log('Found Record label:', label, !recordLabel ? '' : '');
- } else {
- labelStr = labelStr.replace(/ Records$/, '').replace(/ Recordings$/, '').replace(/ Music$/, '');
- label = dir + labelStr + '.png';
- if (utils.FileTest(label, 'e')) {
- recordLabel = gdi.Image(label);
- } else {
- label = dir + labelStr + ' Records.png';
- if (utils.FileTest(label, 'e')) {
- recordLabel = gdi.Image(label);
- }
- }
- }
- }
- return recordLabel;
-}
-
-function fetchNewArtwork(metadb) {
- if (showDebugTiming) artworkTime = fb.CreateProfiler('fetchNewArtwork');
- console.log('Fetching new art'); // can remove this soon
- aa_list = [];
- var disc_art_exists = true;
-
- if (pref.display_cdart && !isStreaming) { // we must attempt to load CD/vinyl art first so that the shadow is drawn correctly
- cdartPath = $(pref.vinylside_path); // try vinyl%vinyl disc%.png first
- if (!utils.FileTest(cdartPath, 'e')) {
- cdartPath = $(pref.vinyl_path); // try vinyl.png
- if (!utils.FileTest(cdartPath, 'e')) {
- cdartPath = $(pref.cdartdisc_path); // try cd%discnumber%.png
- if (!utils.FileTest(cdartPath, 'e')) {
- cdartPath = $(pref.cdart_path); // cd%discnumber%.png didn't exist so try cd.png.
- if (!utils.FileTest(cdartPath, 'e')) {
- disc_art_exists = false; // didn't find anything
- }
- }
- }
- }
- if (disc_art_exists) {
- var temp_cdart;
- if (loadFromCache)
- temp_cdart = art_cache.getImage(cdartPath);
- if (temp_cdart) {
- disposeCDImg(cdart);
- cdart = temp_cdart;
- ResizeArtwork(true);
- CreateRotatedCDImage();
- } else {
- disc_art_loading = gdi.LoadImageAsync(window.ID, cdartPath);
- }
- } else {
- cdart = disposeCDImg(cdart);
- }
- }
- if (showDebugTiming) artworkTime.Print();
-
- if (isStreaming) {
- cdart = disposeCDImg(cdart);
- albumart = utils.GetAlbumArtV2(metadb);
- getThemeColors(albumart);
- ResizeArtwork(true);
- } else {
- for (k = 0; k < tf.glob_paths.length; k++) {
- aa_list = aa_list.concat(utils.Glob($(tf.glob_paths[k])).toArray());
- }
- pattern = /(cd|vinyl)([0-9]*|[a-h])\.png/i;
- aa_list = _.remove(_.uniq(aa_list), function (path) {
- return !pattern.test(path);
- });
- // remove duplicates
-
- if (aa_list.length) {
- noArtwork = false;
- if (aa_list.length > 1 && pref.aa_glob) {
- globTimer = window.SetTimeout(function () {
- doRotateImage();
- }, pref.art_rotate_delay * 1000);
- }
- albumArtIndex = 0;
- glob_image(albumArtIndex, loadFromCache); // display first image
- } else if (albumart = utils.GetAlbumArtV2(metadb)) {
- getThemeColors(albumart);
- ResizeArtwork(true);
- } else {
- noArtwork = true;
- albumart = null;
- ResizeArtwork(true);
- debugLog("Repainting on_playback_new_track due to no cover image");
- RepaintWindow();
- }
- }
- if (showDebugTiming) artworkTime.Print();
-}
-
-
-function RepaintWindow() {
- debugLog("Repainting from RepaintWindow()");
- window.Repaint();
-}
-
-function createHyperlinks() {
- hyperlinks = [];
-}
-
-function createButtonObjects(ww, wh) {
-
- btns = [];
-
- if (typeof btnImg === 'undefined')
- createButtonImages();
- else if (ww <= 0 || wh <= 0)
- return;
-
- //---> Transport buttons
- if (pref.show_transport) {
- var add = 0;
- var count = 4 + (pref.show_random_button ? 1 : 0) + (pref.show_reload_button ? 1 : 0);
-
- var y = is_4k ? 20 : 10;
- var w = is_4k ? 64 : 32;
- var h = w;
- var p = is_4k ? 10 : 5; // space between buttons
- var x = (ww - w * count - p * (count - 1)) / 2;
-
- count = 0;
-
- btns[count] = new Button(x, y, w, h, "Stop", btnImg.Stop, "Stop");
- btns[++count] = new Button(x + (w + p) * count, y, w, h, "Previous", btnImg.Previous, '');
- btns[++count] = new Button(x + (w + p) * count, y, w, h, "Play/Pause", (fb.IsPlaying ? (fb.IsPaused ? btnImg.Play : btnImg.Pause) : btnImg.Play));
- btns[++count] = new Button(x + (w + p) * count, y, w, h, "Next", btnImg.Next);
- if (pref.show_random_button) {
- btns[++count] = new Button(x + (w + p) * count, y, w, h, "Playback/Random", btnImg.PlaybackRandom, "Play Random Song");
- }
- if (pref.show_reload_button) {
- btns[++count] = new Button(x + (w + p) * count, y, w, h, "Reload", btnImg.Reload);
- }
- }
-
- //---> Caption buttons
- // if (uiHacks && UIHacks.FrameStyle) {
-
- // (UIHacks.FrameStyle == FrameStyle.SmallCaption && UIHacks.FullScreen != true) ? hideClose = true : hideClose = false;
-
- // var y = 5;
- // var w = 22;
- // var h = w;
- // var p = 3;
- // var x = ww - w * (hideClose ? 2 : 3) - p * (hideClose ? 1 : 2) - 8;
-
- // btns[10] = new Button(x, y, w, h, "Minimize", btnImg.Minimize);
- // btns[11] = new Button(x + w + p, y, w, h, "Maximize", btnImg.Maximize);
- // if (!hideClose)
- // btns[12] = new Button(x + (w + p) * 2, y, w, h, "Close", btnImg.Close);
-
- // }
- //---> Menu buttons
-
- var img = btnImg.File;
- var x = 5;
- var y = 5;
- var h = img[0].Height;
- var w = img[0].Width;
- //var p = 0;
-
- btns[20] = new Button(x, y, w, h, 'File', img);
- var img = btnImg.Edit;
- var x = x + w;
- var w = img[0].Width;
- btns[21] = new Button(x, y, w, h, 'Edit', img);
- var img = btnImg.View;
- var x = x + w;
- var w = img[0].Width;
- btns[22] = new Button(x, y, w, h, 'View', img);
- var img = btnImg.Playback;
- var x = x + w;
- var w = img[0].Width;
- btns[23] = new Button(x, y, w, h, 'Playback', img);
- var img = btnImg.Library;
- var x = x + w;
- var w = img[0].Width;
- btns[24] = new Button(x, y, w, h, 'Library', img);
- var img = btnImg.Help;
- var x = x + w;
- var w = img[0].Width;
- btns[25] = new Button(x, y, w, h, 'Help', img);
- var img = btnImg.Playlists;
- var x = x + w;
- var w = img[0].Width;
- btns[26] = new Button(x, y, w, h, 'Playlists', img);
- var img = btnImg.Options;
- var x = x + w;
- var w = img[0].Width;
- btns[27] = new Button(x, y, w, h, 'Options', img);
-
- var img = btnImg.Settings;
- var x = ww - settingsImg.width * 2;
- var y = 15;
- var h = img[0].height;
- var w = img[0].width;
- btns[30] = new Button(x, y, w, h, 'Settings', img, 'Foobar Settings');
- var img = btnImg.Properties;
- var w = img[0].width;
- x -= (w + 10);
- btns[31] = new Button(x, y, w, h, 'Properties', img, 'Properties');
- var img = btnImg.Rating;
- var w = img[0].width;
- x -= (w + 10);
- btns[32] = new Button(x, y, w, h, 'Rating', img, 'Rate Song');
- var img = btnImg.Lyrics;
- var w = img[0].width;
- x -= (w + 10);
- btns[33] = new Button(x, y, w, h, 'Lyrics', img, 'Display Lyrics');
- if (showLibraryButton) {
- var img = btnImg.ShowLibrary;
- var w = img[0].width;
- x -= (w + 10);
+ albumart_size.y += 16 - pref.show_transport * 6;
+ }
+
+ if (albumart_scaled) {
+ albumart_scaled.Dispose();
+ }
+ albumart_scaled = albumart.Resize(albumart_size.w, albumart_size.h);
+ pauseBtn.setCoords(albumart_size.x + albumart_size.w / 2, albumart_size.y + albumart_size.h / 2);
+ hasArtwork = true;
+ } else {
+ albumart_size = new ImageSize(0, 0, 0, 0);
+ }
+ if (cdart) {
+ if (!hasArtwork) {
+ // no album art so we need to calc size of disc
+ var album_scale = Math.min(((displayPlaylist || displayLibrary) ? 0.47 * ww : 0.75 * ww) / cdart.Width, (wh - geo.top_art_spacing - geo.lower_bar_h - 32) / cdart.Height);
+ if (displayPlaylist || displayLibrary) {
+ xCenter = 0.25 * ww;
+ } else if (ww / wh < 1.40) { // when using a roughly 4:3 display the album art crowds, so move it slightly off center
+ xCenter = 0.56 * ww; // TODO: check if this is still needed?
+ } else {
+ xCenter = 0.5 * ww;
+ art_off_center = false;
+ if (album_scale == 0.75 * ww / cdart.Width) {
+ xCenter += 0.1 * ww;
+ art_off_center = true; // TODO: We should probably suppress labels in this case
+ }
+ }
+ cdart_size.w = Math.floor(cdart.Width * album_scale); // width
+ cdart_size.h = Math.floor(cdart.Height * album_scale); // height
+ cdart_size.x = Math.floor(xCenter - 0.5 * cdart_size.w); // left
+ if (album_scale !== (wh - geo.top_art_spacing - geo.lower_bar_h - 32) / cdart.Height) {
+ // restricted by width
+ var y = geo.top_art_spacing + Math.floor(((wh - geo.top_art_spacing - geo.lower_bar_h - 32) / 2) - cdart_size.h / 2);
+ cdart_size.y = Math.min(y, 160);
+ } else {
+ cdart_size.y = geo.top_art_spacing; // height of menu bar + spacing + height of Artist text (32+32+32) // top
+ }
+ pauseBtn.setCoords(cdart_size.x + cdart_size.w / 2, cdart_size.y + cdart_size.h / 2);
+ } else {
+ if (resetCDPosition) {
+ if (ww - (albumart_size.x + albumart_size.w) < albumart_size.h * pref.cdart_amount + 5)
+ cdart_size.x = Math.floor(0.99 * ww - albumart_size.h);
+ else
+ cdart_size.x = Math.floor(albumart_size.x + albumart_size.w - (albumart_size.h - 4) * (1 - pref.cdart_amount));
+ cdart_size.y = albumart_size.y + 2;
+ cdart_size.w = albumart_size.h - 4; // cdart must be square so use the height of album art for width of cdart
+ cdart_size.h = cdart_size.w;
+ } else { // when CDArt moves because folder images are different sizes we want to push it outwards, but not move it back in so it jumps around less
+ cdart_size.x = Math.max(cdart_size.x, Math.floor(Math.min(0.99 * ww - albumart_size.h, albumart_size.x + albumart_size.w - (albumart_size.h - 4) * (1 - pref.cdart_amount))));
+ cdart_size.y = cdart_size.y > 0 ? Math.min(cdart_size.y, albumart_size.y + 2) : albumart_size.y + 2;
+ cdart_size.w = Math.max(cdart_size.w, albumart_size.h - 4);
+ cdart_size.h = cdart_size.w;
+ }
+ }
+ hasArtwork = true;
+ } else {
+ cdart_size = new ImageSize(0, 0, 0, 0);
+ }
+ if (hasArtwork) {
+ createDropShadow();
+ } else {
+ if (displayLibrary || displayPlaylist) {
+ pauseBtn.setCoords(ww * (0.33 + .167 / 2), wh / 2);
+ } else {
+ pauseBtn.setCoords(ww / 2, wh / 2);
+ }
+ }
+}
+
+function LoadCountryFlags() {
+ while (flagImgs.length) {
+ disposeImg(flagImgs.pop());
+ }
+ for (i = 0; i < $('$meta_num(' + tf.artist_country + ')'); i++) {
+ path = $(pref.flags_base) + (is_4k ? '64\\' : '32\\') + $('$meta(' + tf.artist_country + ',' + i + ')').replace(/ /g, '-') + '.png';
+ var fImg = gdi.Image(path);
+ fImg && flagImgs.push(fImg);
+ }
+}
+
+function LoadLabelImage(publisherString) {
+ recordLabel = null;
+ d = new Date();
+ labelStr = $(publisherString.replace(']', '').replace('[', '').replace(':', ''));
+ if (labelStr) {
+ /* First check for record label folder */
+ lastSrchYear = d.getFullYear();
+ dir = pref.label_base; // also used below
+ if (utils.FileTest(dir + labelStr, 'd') ||
+ utils.FileTest(dir + (labelStr = labelStr.replace(/ Records$/, '')
+ .replace(/ Recordings$/, '')
+ .replace(/ Music$/, '')
+ .replace(/\.$/, '')), 'd')) {
+ year = parseInt($('$year(%date%)'));
+ for (; year <= lastSrchYear; year++) {
+ yearFolder = dir + labelStr + '\\' + year;
+ if (utils.FileTest(yearFolder, 'd')) {
+ console.log('Found folder for ' + labelStr + ' for year ' + year + '.');
+ dir += labelStr + '\\' + year + '\\';
+ break;
+ }
+ }
+ if (year > lastSrchYear) {
+ dir += labelStr + '\\'; /* we didn't find a year folder so use the "default" logo in the root */
+ }
+ }
+ /* actually load the label from either the directory we found above, or the base record label folder */
+ labelStr = $(publisherString.replace(']', '').replace('[', '').replace(':', '')); // we need to start over with the original string when searching for the file, just to be safe
+ label = dir + labelStr + '.png';
+ if (utils.FileTest(label, 'e')) {
+ recordLabel = gdi.Image(label);
+ console.log('Found Record label:', label, !recordLabel ? '' : '');
+ } else {
+ labelStr = labelStr.replace(/ Records$/, '').replace(/ Recordings$/, '').replace(/ Music$/, '');
+ label = dir + labelStr + '.png';
+ if (utils.FileTest(label, 'e')) {
+ recordLabel = gdi.Image(label);
+ } else {
+ label = dir + labelStr + ' Records.png';
+ if (utils.FileTest(label, 'e')) {
+ recordLabel = gdi.Image(label);
+ }
+ }
+ }
+ }
+ return recordLabel;
+}
+
+function fetchNewArtwork(metadb) {
+ if (showDebugTiming) artworkTime = fb.CreateProfiler('fetchNewArtwork');
+ console.log('Fetching new art'); // can remove this soon
+ aa_list = [];
+ var disc_art_exists = true;
+
+ if (pref.display_cdart && !isStreaming) { // we must attempt to load CD/vinyl art first so that the shadow is drawn correctly
+ cdartPath = $(pref.vinylside_path); // try vinyl%vinyl disc%.png first
+ if (!utils.FileTest(cdartPath, 'e')) {
+ cdartPath = $(pref.vinyl_path); // try vinyl.png
+ if (!utils.FileTest(cdartPath, 'e')) {
+ cdartPath = $(pref.cdartdisc_path); // try cd%discnumber%.png
+ if (!utils.FileTest(cdartPath, 'e')) {
+ cdartPath = $(pref.cdart_path); // cd%discnumber%.png didn't exist so try cd.png.
+ if (!utils.FileTest(cdartPath, 'e')) {
+ disc_art_exists = false; // didn't find anything
+ }
+ }
+ }
+ }
+ if (disc_art_exists) {
+ var temp_cdart;
+ if (loadFromCache)
+ temp_cdart = art_cache.getImage(cdartPath);
+ if (temp_cdart) {
+ disposeCDImg(cdart);
+ cdart = temp_cdart;
+ ResizeArtwork(true);
+ CreateRotatedCDImage();
+ } else {
+ disc_art_loading = gdi.LoadImageAsync(window.ID, cdartPath);
+ }
+ } else {
+ cdart = disposeCDImg(cdart);
+ }
+ }
+ if (showDebugTiming) artworkTime.Print();
+
+ if (isStreaming) {
+ cdart = disposeCDImg(cdart);
+ albumart = utils.GetAlbumArtV2(metadb);
+ getThemeColors(albumart);
+ ResizeArtwork(true);
+ } else {
+ for (k = 0; k < tf.glob_paths.length; k++) {
+ aa_list = aa_list.concat(utils.Glob($(tf.glob_paths[k])).toArray());
+ }
+ pattern = /(cd|vinyl)([0-9]*|[a-h])\.png/i;
+ aa_list = _.remove(_.uniq(aa_list), function (path) {
+ return !pattern.test(path);
+ });
+ // remove duplicates
+
+ if (aa_list.length) {
+ noArtwork = false;
+ if (aa_list.length > 1 && pref.aa_glob) {
+ globTimer = window.SetTimeout(function () {
+ doRotateImage();
+ }, pref.art_rotate_delay * 1000);
+ }
+ albumArtIndex = 0;
+ glob_image(albumArtIndex, loadFromCache); // display first image
+ } else if (albumart = utils.GetAlbumArtV2(metadb)) {
+ getThemeColors(albumart);
+ ResizeArtwork(true);
+ } else {
+ noArtwork = true;
+ albumart = null;
+ ResizeArtwork(true);
+ debugLog("Repainting on_playback_new_track due to no cover image");
+ RepaintWindow();
+ }
+ }
+ if (showDebugTiming) artworkTime.Print();
+}
+
+
+function RepaintWindow() {
+ debugLog("Repainting from RepaintWindow()");
+ window.Repaint();
+}
+
+function createHyperlinks() {
+ hyperlinks = [];
+}
+
+function createButtonObjects(ww, wh) {
+
+ btns = [];
+
+ if (typeof btnImg === 'undefined')
+ createButtonImages();
+ else if (ww <= 0 || wh <= 0)
+ return;
+
+ //---> Transport buttons
+ if (pref.show_transport) {
+ var add = 0;
+ var count = 4 + (pref.show_random_button ? 1 : 0) + (pref.show_reload_button ? 1 : 0);
+
+ var y = is_4k ? 20 : 10;
+ var w = is_4k ? 64 : 32;
+ var h = w;
+ var p = is_4k ? 10 : 5; // space between buttons
+ var x = (ww - w * count - p * (count - 1)) / 2;
+
+ count = 0;
+
+ btns[count] = new Button(x, y, w, h, "Stop", btnImg.Stop, "Stop");
+ btns[++count] = new Button(x + (w + p) * count, y, w, h, "Previous", btnImg.Previous, '');
+ btns[++count] = new Button(x + (w + p) * count, y, w, h, "Play/Pause", (fb.IsPlaying ? (fb.IsPaused ? btnImg.Play : btnImg.Pause) : btnImg.Play));
+ btns[++count] = new Button(x + (w + p) * count, y, w, h, "Next", btnImg.Next);
+ if (pref.show_random_button) {
+ btns[++count] = new Button(x + (w + p) * count, y, w, h, "Playback/Random", btnImg.PlaybackRandom, "Play Random Song");
+ }
+ if (pref.show_reload_button) {
+ btns[++count] = new Button(x + (w + p) * count, y, w, h, "Reload", btnImg.Reload);
+ }
+ }
+
+ //---> Caption buttons
+ // if (uiHacks && UIHacks.FrameStyle) {
+
+ // (UIHacks.FrameStyle == FrameStyle.SmallCaption && UIHacks.FullScreen != true) ? hideClose = true : hideClose = false;
+
+ // var y = 5;
+ // var w = 22;
+ // var h = w;
+ // var p = 3;
+ // var x = ww - w * (hideClose ? 2 : 3) - p * (hideClose ? 1 : 2) - 8;
+
+ // btns[10] = new Button(x, y, w, h, "Minimize", btnImg.Minimize);
+ // btns[11] = new Button(x + w + p, y, w, h, "Maximize", btnImg.Maximize);
+ // if (!hideClose)
+ // btns[12] = new Button(x + (w + p) * 2, y, w, h, "Close", btnImg.Close);
+
+ // }
+ //---> Menu buttons
+
+ var img = btnImg.File;
+ var x = 5;
+ var y = 5;
+ var h = img[0].Height;
+ var w = img[0].Width;
+ //var p = 0;
+
+ btns[20] = new Button(x, y, w, h, 'File', img);
+ var img = btnImg.Edit;
+ var x = x + w;
+ var w = img[0].Width;
+ btns[21] = new Button(x, y, w, h, 'Edit', img);
+ var img = btnImg.View;
+ var x = x + w;
+ var w = img[0].Width;
+ btns[22] = new Button(x, y, w, h, 'View', img);
+ var img = btnImg.Playback;
+ var x = x + w;
+ var w = img[0].Width;
+ btns[23] = new Button(x, y, w, h, 'Playback', img);
+ var img = btnImg.Library;
+ var x = x + w;
+ var w = img[0].Width;
+ btns[24] = new Button(x, y, w, h, 'Library', img);
+ var img = btnImg.Help;
+ var x = x + w;
+ var w = img[0].Width;
+ btns[25] = new Button(x, y, w, h, 'Help', img);
+ var img = btnImg.Playlists;
+ var x = x + w;
+ var w = img[0].Width;
+ btns[26] = new Button(x, y, w, h, 'Playlists', img);
+ var img = btnImg.Options;
+ var x = x + w;
+ var w = img[0].Width;
+ btns[27] = new Button(x, y, w, h, 'Options', img);
+
+ var img = btnImg.Settings;
+ var x = ww - settingsImg.width * 2;
+ var y = 15;
+ var h = img[0].height;
+ var w = img[0].width;
+ btns[30] = new Button(x, y, w, h, 'Settings', img, 'Foobar Settings');
+ var img = btnImg.Properties;
+ var w = img[0].width;
+ x -= (w + 10);
+ btns[31] = new Button(x, y, w, h, 'Properties', img, 'Properties');
+ var img = btnImg.Rating;
+ var w = img[0].width;
+ x -= (w + 10);
+ btns[32] = new Button(x, y, w, h, 'Rating', img, 'Rate Song');
+ var img = btnImg.Lyrics;
+ var w = img[0].width;
+ x -= (w + 10);
+ btns[33] = new Button(x, y, w, h, 'Lyrics', img, 'Display Lyrics');
+ if (showLibraryButton) {
+ var img = btnImg.ShowLibrary;
+ var w = img[0].width;
+ x -= (w + 10);
btns.library = new Button(x, y, w, h, 'ShowLibrary', img, 'Show Library');
- }
- var img = btnImg.Playlist;
- var w = img[0].width;
- x -= (w + 10);
+ }
+ var img = btnImg.Playlist;
+ var w = img[0].width;
+ x -= (w + 10);
btns.playlist = new Button(x, y, w, h, 'Playlist', img, 'Show Playlist');
- /* if a new image button is added to the left of playlist we need to update the ResizeArtwork code */
-}
-
-// =================================================== //
-
-function createButtonImages() {
- if (showExtraDrawTiming) createButtonTime = fb.CreateProfiler('createButtonImages');
-
- try {
- var btn = {
-
- Stop: {
- ico: g_guifx.stop,
- font: ft.guifx,
- type: 'transport',
- w: 30,
- h: 30
- },
- Previous: {
- ico: g_guifx.previous,
- font: ft.guifx,
- type: 'transport',
- w: 30,
- h: 30
- },
- Play: {
- ico: g_guifx.play,
- font: ft.guifx,
- type: 'transport',
- w: 30,
- h: 30
- },
- Pause: {
- ico: g_guifx.pause,
- font: ft.guifx,
- type: 'transport',
- w: 30,
- h: 30
- },
- Next: {
- ico: g_guifx.next,
- font: ft.guifx,
- type: 'transport',
- w: 30,
- h: 30
- },
- PlaybackRandom: {
- ico: g_guifx.shuffle,
- font: ft.guifx,
- type: 'transport',
- w: 30,
- h: 30
- },
- Reload: {
- ico: g_guifx.power,
- font: ft.guifx,
- type: 'transport',
- w: 30,
- h: 30
- },
- Minimize: {
- ico: "0",
- font: ft.Marlett,
- type: "caption",
- w: 22,
- h: 22
- },
- Maximize: {
- ico: "2",
- font: ft.Marlett,
- type: "caption",
- w: 22,
- h: 22
- },
- Close: {
- ico: "r",
- font: ft.Marlett,
- type: "caption",
- w: 22,
- h: 22
- },
- File: {
- ico: "File",
- font: ft.SegoeUi,
- type: "menu"
- },
- Edit: {
- ico: "Edit",
- font: ft.SegoeUi,
- type: "menu"
- },
- View: {
- ico: "View",
- font: ft.SegoeUi,
- type: "menu"
- },
- Playback: {
- ico: "Playback",
- font: ft.SegoeUi,
- type: "menu"
- },
- Library: {
- ico: "Library",
- font: ft.SegoeUi,
- type: "menu"
- },
- Help: {
- ico: "Help",
- font: ft.SegoeUi,
- type: "menu"
- },
- Playlists: {
- ico: "Playlists",
- font: ft.SegoeUi,
- type: "menu"
- },
- Options: {
- ico: "Options",
- font: ft.SegoeUi,
- type: "menu"
- },
-
-
- Playlist: {
- ico: playlistImg,
- type: 'image',
- w: playlistImg.width,
- h: playlistImg.height
- },
- ShowLibrary: {
- ico: libraryImg,
- type: 'image',
- w: libraryImg.width,
- h: libraryImg.height
- },
- Lyrics: {
- ico: lyricsImg,
- type: 'image',
- w: lyricsImg.width,
- h: lyricsImg.height
- },
- Rating: {
- ico: ratingsImg,
- type: 'image',
- w: ratingsImg.width,
- h: ratingsImg.height
- },
- Properties: {
- ico: propertiesImg,
- type: 'image',
- w: propertiesImg.width,
- h: propertiesImg.height
- },
- Settings: {
- ico: settingsImg,
- type: 'image',
- w: settingsImg.width,
- h: settingsImg.height
- },
- };
- } catch (e) {
- var str = pref.lyrics_img;
- console.log("**********************************");
- console.log("ATTENTION: Buttons could not be created, most likely because the images were not found in \"" + str.substring(0, str.lastIndexOf("/")) + '\"'); //.Eval().substring(0, str.lastIndexOf("/")));
- console.log("Make sure you installed the theme correctly to your configuration folder.")
- console.log("**********************************");
- }
-
-
- btnImg = [];
-
- for (var i in btn) {
-
- if (btn[i].type === 'menu') {
- var img = gdi.CreateImage(100, 100);
- g = img.GetGraphics();
-
- var measurements = g.MeasureString(btn[i].ico, btn[i].font, 0, 0, 0, 0);
- btn[i].w = Math.ceil(measurements.Width + 20);
- img.ReleaseGraphics(g);
- img.Dispose();
- btn[i].h = Math.ceil(measurements.Height + 5);
- }
-
- var w = btn[i].w
- h = btn[i].h,
- lw = 2;
-
- if (is_4k && btn[i].type === 'transport') {
- w *= 2;
- h *= 2;
- } else if (is_4k && btn[i].type !== 'menu') {
- w = Math.round(btn[i].w * 1.5);
- h = Math.round(btn[i].h * 1.6);
- } else if (is_4k) {
- w += 20;
- h += 10;
- }
-
- var stateImages = []; //0=normal, 1=hover, 2=down;
-
- for (var s = 0; s <= 2; s++) {
-
- var img = gdi.CreateImage(w, h);
- g = img.GetGraphics();
- g.SetSmoothingMode(SmoothingMode.AntiAlias);
- if (btn[i].type !== 'transport') {
- g.SetTextRenderingHint(TextRenderingHint.AntiAlias); // positions playback icons weirdly
- }
-
- var menuTextColor = RGB(140, 142, 144);
- var menuRectColor = RGB(120, 122, 124);
- var captionIcoColor = RGB(140, 142, 144);
- var playbackIcoColor = RGB(150, 152, 154);
- var playbackEllypseColor = RGB(80, 80, 80);
- var iconAlpha = 140;
-
- if (s == 1) {
- menuTextColor = RGB(180, 182, 184);
- menuRectColor = RGB(160, 162, 164);
- captionIcoColor = RGB(190, 192, 194);
- playbackIcoColor = RGB(190, 192, 194);
- playbackEllypseColor = RGB(190, 195, 200);
- iconAlpha = 215;
- } else if (s == 2) {
- menuTextColor = RGB(120, 122, 124);
- menuRectColor = RGB(110, 112, 114);
- captionIcoColor = RGB(100, 102, 104);
- playbackIcoColor = RGB(90, 90, 90);
- playbackEllypseColor = RGB(80, 80, 80);
- iconAlpha = 190;
- }
-
- //--->
- if (btn[i].type == 'menu') {
- s && g.DrawRoundRect(Math.floor(lw / 2), Math.floor(lw / 2), w - lw, h - lw, 3, 3, 1, menuRectColor);
- g.DrawString(btn[i].ico, btn[i].font, menuTextColor, 0, 0, w, h - 1, StringFormat(1, 1));
- } else if (btn[i].type == 'caption') {
- g.DrawString(btn[i].ico, btn[i].font, captionIcoColor, 0, 0, w, h, StringFormat(1, 1));
- } else if (btn[i].type == 'transport') {
- g.DrawEllipse(Math.floor(lw / 2) + 1, Math.floor(lw / 2) + 1, w - lw - 2, h - lw - 2, lw, playbackEllypseColor);
- g.DrawString(btn[i].ico, btn[i].font, playbackIcoColor, (i == 'Stop' || i == 'OpenExplorer') ? 0 : 1, 0, w, h, StringFormat(1, 1));
- } else if (btn[i].type == 'image') {
- g.DrawImage(btn[i].ico, Math.round((w - btn[i].ico.width) / 2), Math.round((h - btn[i].ico.height) / 2), btn[i].ico.width, btn[i].ico.height, 0, 0, btn[i].ico.width, btn[i].ico.height, 0, iconAlpha);
- }
- //--->
-
- img.ReleaseGraphics(g);
- stateImages[s] = img;
-
- }
-
- btnImg[i] = stateImages;
-
- }
- if (showExtraDrawTiming) createButtonTime.Print();
-}
-
-// =================================================== //
-
-function resizeDone() {
- console.log("resizeDone()");
- // to speed up draw times, we scale the bg image once, and then draw it without scaling in on_paint which is up to 3-4x faster
-
- progressMoved = true;
- SetProgressBarRefresh();
- window.Repaint();
- if (displayPlaylist && listLength) {
- getAlbumArt();
- }
-}
+ /* if a new image button is added to the left of playlist we need to update the ResizeArtwork code */
+}
+
+// =================================================== //
+
+function createButtonImages() {
+ if (showExtraDrawTiming) createButtonTime = fb.CreateProfiler('createButtonImages');
+
+ try {
+ var btn = {
+
+ Stop: {
+ ico: g_guifx.stop,
+ font: ft.guifx,
+ type: 'transport',
+ w: 30,
+ h: 30
+ },
+ Previous: {
+ ico: g_guifx.previous,
+ font: ft.guifx,
+ type: 'transport',
+ w: 30,
+ h: 30
+ },
+ Play: {
+ ico: g_guifx.play,
+ font: ft.guifx,
+ type: 'transport',
+ w: 30,
+ h: 30
+ },
+ Pause: {
+ ico: g_guifx.pause,
+ font: ft.guifx,
+ type: 'transport',
+ w: 30,
+ h: 30
+ },
+ Next: {
+ ico: g_guifx.next,
+ font: ft.guifx,
+ type: 'transport',
+ w: 30,
+ h: 30
+ },
+ PlaybackRandom: {
+ ico: g_guifx.shuffle,
+ font: ft.guifx,
+ type: 'transport',
+ w: 30,
+ h: 30
+ },
+ Reload: {
+ ico: g_guifx.power,
+ font: ft.guifx,
+ type: 'transport',
+ w: 30,
+ h: 30
+ },
+ Minimize: {
+ ico: "0",
+ font: ft.Marlett,
+ type: "caption",
+ w: 22,
+ h: 22
+ },
+ Maximize: {
+ ico: "2",
+ font: ft.Marlett,
+ type: "caption",
+ w: 22,
+ h: 22
+ },
+ Close: {
+ ico: "r",
+ font: ft.Marlett,
+ type: "caption",
+ w: 22,
+ h: 22
+ },
+ File: {
+ ico: "File",
+ font: ft.SegoeUi,
+ type: "menu"
+ },
+ Edit: {
+ ico: "Edit",
+ font: ft.SegoeUi,
+ type: "menu"
+ },
+ View: {
+ ico: "View",
+ font: ft.SegoeUi,
+ type: "menu"
+ },
+ Playback: {
+ ico: "Playback",
+ font: ft.SegoeUi,
+ type: "menu"
+ },
+ Library: {
+ ico: "Library",
+ font: ft.SegoeUi,
+ type: "menu"
+ },
+ Help: {
+ ico: "Help",
+ font: ft.SegoeUi,
+ type: "menu"
+ },
+ Playlists: {
+ ico: "Playlists",
+ font: ft.SegoeUi,
+ type: "menu"
+ },
+ Options: {
+ ico: "Options",
+ font: ft.SegoeUi,
+ type: "menu"
+ },
+
+
+ Playlist: {
+ ico: playlistImg,
+ type: 'image',
+ w: playlistImg.width,
+ h: playlistImg.height
+ },
+ ShowLibrary: {
+ ico: libraryImg,
+ type: 'image',
+ w: libraryImg.width,
+ h: libraryImg.height
+ },
+ Lyrics: {
+ ico: lyricsImg,
+ type: 'image',
+ w: lyricsImg.width,
+ h: lyricsImg.height
+ },
+ Rating: {
+ ico: ratingsImg,
+ type: 'image',
+ w: ratingsImg.width,
+ h: ratingsImg.height
+ },
+ Properties: {
+ ico: propertiesImg,
+ type: 'image',
+ w: propertiesImg.width,
+ h: propertiesImg.height
+ },
+ Settings: {
+ ico: settingsImg,
+ type: 'image',
+ w: settingsImg.width,
+ h: settingsImg.height
+ },
+ };
+ } catch (e) {
+ var str = pref.lyrics_img;
+ console.log("**********************************");
+ console.log("ATTENTION: Buttons could not be created, most likely because the images were not found in \"" + str.substring(0, str.lastIndexOf("/")) + '\"'); //.Eval().substring(0, str.lastIndexOf("/")));
+ console.log("Make sure you installed the theme correctly to your configuration folder.")
+ console.log("**********************************");
+ }
+
+
+ btnImg = [];
+
+ for (var i in btn) {
+
+ if (btn[i].type === 'menu') {
+ var img = gdi.CreateImage(100, 100);
+ g = img.GetGraphics();
+
+ var measurements = g.MeasureString(btn[i].ico, btn[i].font, 0, 0, 0, 0);
+ btn[i].w = Math.ceil(measurements.Width + 20);
+ img.ReleaseGraphics(g);
+ img.Dispose();
+ btn[i].h = Math.ceil(measurements.Height + 5);
+ }
+
+ var w = btn[i].w
+ h = btn[i].h,
+ lw = 2;
+
+ if (is_4k && btn[i].type === 'transport') {
+ w *= 2;
+ h *= 2;
+ } else if (is_4k && btn[i].type !== 'menu') {
+ w = Math.round(btn[i].w * 1.5);
+ h = Math.round(btn[i].h * 1.6);
+ } else if (is_4k) {
+ w += 20;
+ h += 10;
+ }
+
+ var stateImages = []; //0=normal, 1=hover, 2=down;
+
+ for (var s = 0; s <= 2; s++) {
+
+ var img = gdi.CreateImage(w, h);
+ g = img.GetGraphics();
+ g.SetSmoothingMode(SmoothingMode.AntiAlias);
+ if (btn[i].type !== 'transport') {
+ g.SetTextRenderingHint(TextRenderingHint.AntiAlias); // positions playback icons weirdly
+ }
+
+ var menuTextColor = RGB(140, 142, 144);
+ var menuRectColor = RGB(120, 122, 124);
+ var captionIcoColor = RGB(140, 142, 144);
+ var playbackIcoColor = RGB(150, 152, 154);
+ var playbackEllypseColor = RGB(80, 80, 80);
+ var iconAlpha = 140;
+
+ if (s == 1) {
+ menuTextColor = RGB(180, 182, 184);
+ menuRectColor = RGB(160, 162, 164);
+ captionIcoColor = RGB(190, 192, 194);
+ playbackIcoColor = RGB(190, 192, 194);
+ playbackEllypseColor = RGB(190, 195, 200);
+ iconAlpha = 215;
+ } else if (s == 2) {
+ menuTextColor = RGB(120, 122, 124);
+ menuRectColor = RGB(110, 112, 114);
+ captionIcoColor = RGB(100, 102, 104);
+ playbackIcoColor = RGB(90, 90, 90);
+ playbackEllypseColor = RGB(80, 80, 80);
+ iconAlpha = 190;
+ }
+
+ //--->
+ if (btn[i].type == 'menu') {
+ s && g.DrawRoundRect(Math.floor(lw / 2), Math.floor(lw / 2), w - lw, h - lw, 3, 3, 1, menuRectColor);
+ g.DrawString(btn[i].ico, btn[i].font, menuTextColor, 0, 0, w, h - 1, StringFormat(1, 1));
+ } else if (btn[i].type == 'caption') {
+ g.DrawString(btn[i].ico, btn[i].font, captionIcoColor, 0, 0, w, h, StringFormat(1, 1));
+ } else if (btn[i].type == 'transport') {
+ g.DrawEllipse(Math.floor(lw / 2) + 1, Math.floor(lw / 2) + 1, w - lw - 2, h - lw - 2, lw, playbackEllypseColor);
+ g.DrawString(btn[i].ico, btn[i].font, playbackIcoColor, (i == 'Stop' || i == 'OpenExplorer') ? 0 : 1, 0, w, h, StringFormat(1, 1));
+ } else if (btn[i].type == 'image') {
+ g.DrawImage(btn[i].ico, Math.round((w - btn[i].ico.width) / 2), Math.round((h - btn[i].ico.height) / 2), btn[i].ico.width, btn[i].ico.height, 0, 0, btn[i].ico.width, btn[i].ico.height, 0, iconAlpha);
+ }
+ //--->
+
+ img.ReleaseGraphics(g);
+ stateImages[s] = img;
+
+ }
+
+ btnImg[i] = stateImages;
+
+ }
+ if (showExtraDrawTiming) createButtonTime.Print();
+}
+
+// =================================================== //
+
+function resizeDone() {
+ console.log("resizeDone()");
+ // to speed up draw times, we scale the bg image once, and then draw it without scaling in on_paint which is up to 3-4x faster
+ progressMoved = true;
+ SetProgressBarRefresh();
+ window.Repaint();
+ if (displayPlaylist && listLength) {
+ getAlbumArt();
+ }
+}
diff --git a/js/globals.js b/js/globals.js
index 229f8847..e86ee24c 100644
--- a/js/globals.js
+++ b/js/globals.js
@@ -2,7 +2,7 @@ var globals = PanelProperties.get_instance();
var pref = PanelProperties.get_instance(); // preferences
var tf = PanelProperties.get_instance(); // titleformating strings
-var currentVersion = '1.0.0';
+var currentVersion = '1.0.1';
globals.add_properties({
version: ['_theme_version (do not hand edit!)', 'NONE']