View difference between Paste ID: LwdynFk8 and ZMZgDU0v
SHOW: | | - or go back to the newest paste.
1
// ==PREPROCESSOR==
2
// @name "Youtube Radio"
3
// @author "Mire777"
4
// @feature "v1.4"
5
// @feature "watch-metadb"
6
// ==/PREPROCESSOR==
7
8
// Paths
9
var fbfolder = (fb.ProfilePath + "Artist_info");
10
var lfm_folder = fbfolder;
11
12
//image download size
13
size = "high";
14
15
//Download server
16
auto_yt = window.GetProperty("YT Radio", "0");
17
18
//Search terms(google,yahoo)
19
terms = "";
20
21
//Cycle
22
cycle2 = 15;
23
24
var VERSION = "7.2013-10-19.01";
25
var DT_LEFT = 0x00000000;
26
var DT_CENTER = 0x00000001;
27
var DT_RIGHT = 0x00000002;
28
var DT_VCENTER = 0x00000004;
29
var DT_WORDBREAK = 0x00000010;
30
var DT_CALCRECT = 0x00000400;
31
var DT_NOPREFIX = 0x00000800;
32
var DT_END_ELLIPSIS = 0x00008000;
33
34
var MF_GRAYED = 0x00000001;
35
var MF_STRING = 0x00000000;
36
37
var IDC_ARROW = 32512;
38
var IDC_HAND = 32649;
39
40
var ONE_DAY = 86400000;
41
var ONE_WEEK = 604800000;
42
43
String.prototype.addCommas = function() {
44
	return this.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
45
}
46
47
String.prototype.trim = function() {
48
	return this.replace(/^\s+|\s+$/g, "");
49
}
50
51
String.prototype.ucfirst = function() {
52
	return this.charAt(0).toUpperCase() + this.substr(1);
53
}
54
55
function RGB(r, g, b) {
56
	return (0xff000000 | (r << 16) | (g << 8) | (b));
57
}
58
59
function RGBA(r, g, b, a) {
60
	return ((a << 24) | (r << 16) | (g << 8) | (b));
61
}
62
63
function on_colors_changed() {
64
	p.colors_changed();
65
}
66
67
function on_font_changed() {
68
	p.font_changed();
69
}
70
71
function on_selection_changed() {
72
	p.item_focus_change();
73
}
74
75
function on_playlist_switch() {
76
	p.item_focus_change();
77
}
78
79
function on_playback_new_track() {
80
	p.item_focus_change();
81
    im.download();
82
}
83
84
function on_playback_dynamic_info_track() {
85
	p.item_focus_change();
86
}
87
88
function on_playback_stop() {
89
	p.item_focus_change();
90
}
91
92
function on_item_focus_change() {
93
	p.item_focus_change();
94
}
95
96
function on_mouse_leave() {
97
	if (typeof b == "object") b.leave();
98
	if (typeof r == "object") r.leave();
99
	if (typeof li == "object") li.leave();
100
	if (typeof s == "object") s.leave();
101
}
102
103
function on_mouse_rbtn_up(x, y) {
104
	p.rbtn_up(x, y);
105
	return true;
106
}
107
108
function on_notify_data(name, data) {
109
	if (name == "lastfm" && data == "update" && typeof l == "object") l.notify_data(name, data);
110
	if (name == "autoplaylists" && data == "update" && typeof li == "object" && li.mode == "autoplaylists") li.update();
111
	if (name == "images" && data == "update" && typeof im == "object") im.update();
112
	if (name == "love" && typeof ps == "object") l.post(fb.TitleFormat("%LASTFM_LOVED_DB%").EvalWithMetadb(data) == 1 ? "track.unlove" : "track.love", data);
113
}
114
115
function panel(name, features) {
116
	this.item_focus_change = function() {
117
		if (!this.metadb_func) return;
118
		switch(this.selection_mode) {
119
			case 0:
120
				this.metadb = fb.GetSelection();
121
				break;
122
			case 1:
123
				this.metadb = fb.IsPlaying ? fb.GetNowPlaying() : fb.GetFocusItem();
124
				break;
125
			case 2:
126
				this.metadb = fb.GetFocusItem();
127
				break;
128
		}
129
		if (this.metadb) on_metadb_changed();
130
	}
131
	
132
this.colors_changed = function() {
133
		if (this.dui) {
134
            this.background_mode=(1);
135
			this.textcolour = window.GetColorDUI(0);
136
			this.textcolour_hl = window.GetColorDUI(2);
137
			this.backcolour = window.GetColorDUI(1);
138
		} else {
139
            this.background_mode=(0);
140
			this.textcolour = window.GetColorCUI(0);
141
			this.textcolour_hl = window.GetColorCUI(0);
142
			this.backcolour = window.GetColorCUI(3);
143
		}
144
		window.Repaint();
145
	}
146
	
147
	this.font_changed = function() {
148
		this.font = this.dui ? window.GetFontDUI(0) : window.GetFontCUI(0);
149
		try {
150
			this.font_name = this.font.Name;
151
		} catch(e) {
152
			this.console("Unable to use your default font. Using Segoe UI instead.");
153
			this.font_name = "Segoe ui";
154
		}
155
		this.title_font = gdi.Font(this.font_name, 16, 1);
156
		this.normal_font = gdi.Font("segoe ui", 12, 1);
157
		this.fixed_font = gdi.Font("Lucida Console", this.normal_font_size);
158
		this.list_font = gdi.Font(this.font_name, this.list_font_size);
159
		this.row_height = this.normal_font.Height + 2;
160
		if (typeof t == "object") t.size();
161
		window.Repaint();
162
	}
163
	
164
	this.size = function() {
165
		this.w = window.Width;
166
		this.h = window.Height;
167
	}
168
	
169
	this.move = function(x, y) {
170
		this.mx = x;
171
		this.my = y;
172
	}
173
	
174
	this.rbtn_up = function(x, y) {
175
		var _menu = window.CreatePopupMenu();
176
		var _custom_background = window.CreatePopupMenu();
177
		var _metadb = window.CreatePopupMenu();
178
		var _cover = window.CreatePopupMenu();
179
		var _font = window.CreatePopupMenu();
180
		var _sub1 = window.CreatePopupMenu();
181
		var _sub2 = window.CreatePopupMenu();
182
		var _sub3 = window.CreatePopupMenu();
183
		var _sub4 = window.CreatePopupMenu();
184
		var _sub5 = window.CreatePopupMenu();
185
		var idx;
186
		switch(true) {
187
			case typeof a == "object" && a.trace(x, y):
188
				/*_menu.AppendMenuItem(MF_STRING, 1, "Refresh");
189
				_menu.AppendMenuSeparator();
190
				_menu.AppendMenuItem(MF_STRING, 2, "Front");
191
				_menu.AppendMenuItem(MF_STRING, 3, "Back");
192
				_menu.AppendMenuItem(MF_STRING, 4, "Disc");
193
				_menu.AppendMenuItem(MF_STRING, 5, "Icon");
194
				_menu.AppendMenuItem(MF_STRING, 6, "Artist");
195
				_menu.CheckMenuRadioItem(2, 6, a.id + 2);
196
				_menu.AppendMenuSeparator();*/
197
				_menu.AppendMenuItem(MF_STRING, 15, "Crop (focus on centre)");
198
				_menu.AppendMenuItem(MF_STRING, 16, "Crop (focus on top)");
199
				_menu.AppendMenuItem(MF_STRING, 17, "adjust");
200
				_menu.AppendMenuItem(MF_STRING, 18, "Stretch");
201
				_menu.CheckMenuRadioItem(15, 18, a.type == "centre" ? 15 : a.type == "top" ? 16 : a.type == "adjust" ? 17 : 18);
202
				_menu.AppendMenuSeparator();
203
				_cover.AppendMenuItem(this.metadb ? MF_STRING : MF_GRAYED, 21, "Google images (launches browser)");
204
				_cover.AppendMenuItem(this.metadb ? MF_STRING : MF_GRAYED, 22, "Album Art Downloader");
205
				_cover.AppendMenuSeparator();
206
				//_cover.AppendMenuItem(MF_STRING, 23, "Help");
207
				//_cover.AppendTo(_menu, MF_STRING, "Cover search");
208
				//_menu.AppendMenuSeparator();
209
				break;
210
			case typeof c == "object" && c.trace(x, y):
211
				if (this.check_feature("now_playing") && !np_cd) break;
212
				/*_menu.AppendMenuItem(MF_STRING, 1, "Refresh");
213
				_menu.AppendMenuSeparator();
214
				_menu.AppendMenuItem(MF_STRING, 11, "Gloss effect");
215
				_menu.CheckMenuItem(11, c.gloss);
216
				_menu.AppendMenuItem(MF_STRING, 12, "Shadow effect");
217
				_menu.CheckMenuItem(12, c.shadow);
218
				_menu.AppendMenuSeparator();
219
				_cover.AppendMenuItem(this.metadb ? MF_STRING : MF_GRAYED, 21, "Google images (launches browser)");
220
				_cover.AppendMenuItem(this.metadb ? MF_STRING : MF_GRAYED, 22, "Album Art Downloader");
221
				_cover.AppendMenuSeparator();
222
				_cover.AppendMenuItem(MF_STRING, 23, "Help");
223
				_cover.AppendTo(_menu, MF_STRING, "Cover search");
224
				_menu.AppendMenuSeparator();*/
225
				break;
226
			case typeof li == "object" && li.trace(x, y):
227
				switch(li.mode) {
228
					case "autoplaylists":
229
						_menu.AppendMenuItem(MF_STRING, 600, "Change title...");
230
						_menu.AppendMenuSeparator();
231
						for (i = 1; i < 9; i++) {
232
							_sub1.AppendMenuItem(MF_STRING, i + 600, i);
233
						}
234
						_sub1.AppendTo(_menu, MF_STRING, "Save slot");
235
						_sub1.CheckMenuRadioItem(601, 608, li.autoplaylists_slot + 600);
236
						_menu.AppendMenuSeparator();
237
						_sub2.AppendMenuItem(MF_STRING, 610, "run query");
238
						_sub2.AppendMenuItem(MF_STRING, 611, "do nothing");
239
						_sub2.CheckMenuRadioItem(610, 611, li.autoplaylists_success ? 610 : 611);
240
						_sub2.AppendTo(_menu, MF_STRING, "On successful creation/edit");
241
						for (i = 0; i < li.autoplaylists_deleted_items.length; i++) {
242
							var temp = li.autoplaylists_deleted_items[i].split("¬");
243
							_sub3.AppendMenuItem(MF_STRING, i + 620, temp[0]);
244
						}
245
						if (li.autoplaylists_deleted_items.length > 0) _sub3.AppendTo(_menu, MF_STRING, "Restore");
246
						_menu.AppendMenuSeparator();
247
						_menu.AppendMenuItem(MF_STRING, 650, "Replace exisiting playlists with the same name");
248
						_menu.CheckMenuItem(650, li.autoplaylists_remove_duplicates);
249
						_menu.AppendMenuSeparator();
250
						break;
251
					case "discogs":
252
						_menu.AppendMenuItem(MF_STRING, 29, "Show exact artist matches only");
253
						_menu.CheckMenuItem(29, li.discogs_match);
254
						_menu.AppendMenuSeparator();
255
						_menu.AppendMenuItem(MF_STRING, 28, "Show timestamp");
256
						_menu.CheckMenuItem(28, li.show_timestamp);
257
						_menu.AppendMenuSeparator();
258
						break;
259
					case "echonest":
260
						for (i = 0; i < li.echonest_modes.length; i++) {
261
							_menu.AppendMenuItem(MF_STRING, i + 500, li.echonest_modes[i].ucfirst());
262
						}
263
						_menu.CheckMenuRadioItem(500, 502, li.echonest_mode + 500);
264
						_menu.AppendMenuSeparator();
265
						_menu.AppendMenuItem(MF_STRING, 28, "Show timestamp");
266
						_menu.CheckMenuItem(28, li.show_timestamp);
267
						_menu.AppendMenuSeparator();
268
						break;
269
					case "lastfm":
270
						for (i = 0; i < li.lastfm_modes.length; i++) {
271
							_menu.AppendMenuItem(MF_STRING, 801 + i, li.lastfm_modes[i].ucfirst());
272
						}
273
						_menu.CheckMenuRadioItem(801, 805, li.lastfm_mode + 801);
274
						_menu.AppendMenuSeparator();
275
						if (li.lastfm_mode == 0) {
276
							if (li.lastfm_button == "spotify") {
277
								_menu.AppendMenuItem(MF_STRING, 810, "Pause playback when launching Spotify");
278
								_menu.CheckMenuItem(810, li.lastfm_pause);
279
								_menu.AppendMenuSeparator();
280
							}
281
							/*_sub1.AppendMenuItem(MF_STRING, 811, "Spotify");
282
							_sub1.AppendMenuItem(MF_STRING, 812, "Autoplaylist");
283
							_sub1.CheckMenuRadioItem(811, 812, li.lastfm_button == "spotify" ? 811 : 812);
284
							_sub1.AppendTo(_menu, MF_STRING, "Buttons");
285
							_menu.AppendMenuSeparator();*/
286
						}
287
						/*_menu.AppendMenuItem(MF_STRING, 28, "Show timestamp");
288
						_menu.CheckMenuItem(28, li.show_timestamp);
289
						_menu.AppendMenuSeparator();
290
						_menu.AppendMenuItem(MF_STRING, 51, "Last.fm auto-correct");
291
						_menu.CheckMenuItem(51, l.auto_correct);
292
						_menu.AppendMenuSeparator();*/
293
						break;
294
					case "lastfm_charts":
295
						_menu.AppendMenuItem(l.username.length > 0 ? MF_STRING : MF_GRAYED, 1000, "Refresh");
296
						_menu.AppendMenuSeparator();
297
						for (i = 0; i < li.lastfm_charts_modes.length; i++) {
298
							_menu.AppendMenuItem(MF_STRING, i + 1001, li.lastfm_charts_modes[i].ucfirst());
299
						}
300
						_menu.CheckMenuRadioItem(1001, 1003, li.lastfm_charts_mode + 1001);
301
						_menu.AppendMenuSeparator();
302
						for (i = 0; i < li.lastfm_charts_periods_display.length; i++) {
303
							_menu.AppendMenuItem(MF_STRING, i + 1004, li.lastfm_charts_periods_display[i].ucfirst());
304
						}
305
						/*_menu.CheckMenuRadioItem(1004, 1009, li.lastfm_charts_period + 1004);
306
						_menu.AppendMenuSeparator();
307
						_menu.AppendMenuItem(MF_STRING, 1010, "Bar colour...");
308
						_menu.AppendMenuSeparator();
309
						_menu.AppendMenuItem(MF_STRING, 28, "Show timestamp");
310
						_menu.CheckMenuItem(28, li.show_timestamp);
311
						_menu.AppendMenuSeparator();*/
312
						break;
313
					case "musicbrainz":
314
						_menu.AppendMenuItem(MF_STRING, 700, "Releases");
315
						_menu.AppendMenuItem(MF_STRING, 701, "Links");
316
						_menu.CheckMenuRadioItem(700, 701, li.musicbrainz_mode == "releases" ? 700 : 701);
317
						_menu.AppendMenuSeparator();
318
						if (li.musicbrainz_mode == "releases") {
319
							/*_menu.AppendMenuItem(MF_STRING, 702, "Include albums");
320
							_menu.CheckMenuItem(702, li.musicbrainz_album);
321
							_menu.AppendMenuItem(MF_STRING, 703, "Include EPs");
322
							_menu.CheckMenuItem(703, li.musicbrainz_ep);
323
							_menu.AppendMenuItem(MF_STRING, 704, "Include singles");
324
							_menu.CheckMenuItem(704, li.musicbrainz_single);
325
							_menu.AppendMenuSeparator();
326
							_menu.AppendMenuItem(MF_STRING, 705, "Include 'Live' releases");
327
							_menu.CheckMenuItem(705, li.musicbrainz_live);
328
							_menu.AppendMenuItem(MF_STRING, 706, "Include 'Remix' releases");
329
							_menu.CheckMenuItem(706, li.musicbrainz_remix);
330
							_menu.AppendMenuItem(MF_STRING, 707, "Include 'Compilation' releases");
331
							_menu.CheckMenuItem(707, li.musicbrainz_compilation);
332
							_menu.AppendMenuSeparator();
333
							_menu.AppendMenuItem(MF_STRING, 708, "Show release type");
334
							_menu.CheckMenuItem(708, li.musicbrainz_show_release_type);
335
							_menu.AppendMenuSeparator();*/
336
						}
337
						/*_menu.AppendMenuItem(MF_STRING, 28, "Show timestamp");
338
						_menu.CheckMenuItem(28, li.show_timestamp);
339
						_menu.AppendMenuSeparator();*/
340
						break;
341
				}
342
				break;
343
			case typeof ps == "object" && b.buttons.ps.trace(x, y):
344
				/*_sub1.AppendMenuItem(utils.CheckComponent("foo_customdb", true) && !ps.loved_working && !ps.playcount_working && l.username.length > 0 ? MF_STRING : MF_GRAYED, 1100, "loved tracks and playcount");
345
				_sub1.AppendMenuItem(utils.CheckComponent("foo_customdb", true) && !ps.loved_working && !ps.playcount_working && l.username.length > 0 ? MF_STRING : MF_GRAYED, 1109, "loved tracks only");
346
				_sub1.AppendMenuSeparator();
347
				_sub1.AppendMenuItem(utils.CheckComponent("foo_customdb", true) && this.fso.FileExists(ps.sql_file) ? MF_STRING : MF_GRAYED, 1101, "from file");
348
				_sub1.AppendMenuSeparator();
349
				_sub1.AppendMenuItem(MF_STRING, 1102, "Show console");
350
				_sub1.CheckMenuItem(1102, ps.show_console);
351
				_sub1.AppendTo(_menu, MF_STRING, "Library import");
352
				_menu.AppendMenuSeparator();
353
				_sub2.AppendMenuItem(MF_STRING, 1103, "Only update tracks in library");
354
				_sub2.CheckMenuItem(1103, ps.library);
355
				_sub2.AppendMenuItem(MF_STRING, 52, "Last.fm auto-correct");
356
				_sub2.CheckMenuItem(52, l.auto_correct);
357
				_sub2.AppendTo(_menu, MF_STRING, "Auto-updates");
358
				_menu.AppendMenuSeparator();
359
				_sub3.AppendMenuItem(MF_STRING, 1104, "Off");
360
				_sub3.AppendMenuItem(MF_STRING, 1105, "On");
361
				_sub3.CheckMenuRadioItem(1104, 1105, ps.auto_love ? 1105 : 1104);
362
				_sub3.AppendMenuSeparator();
363
				_sub3.AppendMenuItem(ps.auto_love ? MF_STRING : MF_GRAYED, 1106, "Condition");
364
				_sub3.AppendTo(_menu, MF_STRING, "Automatically love tracks");
365
				_menu.AppendMenuSeparator();
366
				_sub4.AppendMenuItem(MF_STRING, 1107, "tango");
367
				_sub4.AppendMenuItem(MF_STRING, 1108, "silk");
368
				_sub4.CheckMenuRadioItem(1107, 1108, ps.icon == "tango" ? 1107 : 1108);
369
				_sub4.AppendTo(_menu, MF_STRING, "Icon");
370
				_menu.AppendMenuSeparator();*/
371
				break;
372
			case typeof s == "object" && s.mode == "spectrogram" && s.trace(x, y) :
373
				/*_menu.AppendMenuItem(MF_STRING, 1804, "SoX options...");
374
				_menu.AppendMenuSeparator();
375
				_menu.AppendMenuItem(MF_STRING, 1805, "Marker colour...");
376
				_menu.AppendMenuSeparator();
377
				_menu.AppendMenuItem(MF_STRING, 1803, "Only analyse tracks in library");
378
				_menu.CheckMenuItem(1803, s.library);
379
				_menu.AppendMenuSeparator();
380
				_sub1.AppendMenuItem(MF_STRING, 1800, "Clear all");
381
				_sub1.AppendMenuItem(MF_STRING, 1801, "Clear older than 1 day");
382
				_sub1.AppendMenuItem(MF_STRING, 1802, "Clear older than 1 week");
383
				_sub1.AppendMenuSeparator();
384
				_sub1.AppendMenuItem(MF_GRAYED, 1803, "In use: " + (this.fso.GetFolder(spectrogram_cache).size / 1048576).toFixed(2) + "MB");
385
				_sub1.AppendTo(_menu, MF_STRING, "Cached images");
386
				_menu.AppendMenuSeparator();*/
387
				break;
388
			case typeof t == "object" && t.trace(x, y):
389
				if (this.check_feature("now_playing") && !np_bio) break;
390
				/*_font.AppendMenuItem(MF_STRING, 30, 12);
391
				_font.AppendMenuItem(MF_STRING, 31, 14);
392
				_font.AppendMenuItem(MF_STRING, 32, 16);
393
				_font.AppendTo(_menu, MF_STRING, "Font size");
394
				_font.CheckMenuRadioItem(30, 33, this.normal_font_size == 12 ? 30 : this.normal_font_size == 14 ? 31 : 32);
395
				_menu.AppendMenuSeparator();*/
396
				switch(t.mode) {
397
					case "lastfm_album":
398
						/*_menu.AppendMenuItem(MF_STRING, 53, "Last.fm auto-correct");
399
						_menu.CheckMenuItem(53, l.auto_correct);
400
						_menu.AppendMenuSeparator();*/
401
						break;
402
					case "lastfm_wiki":
403
						/*_menu.AppendMenuItem(MF_STRING, 25, "Last.fm");
404
						_menu.AppendMenuItem(MF_STRING, 26, "Wikipedia");
405
						_menu.CheckMenuRadioItem(25, 26, t.source == "last.fm" ? 25 : 26);
406
						_menu.AppendMenuSeparator();*/
407
						break;
408
					case "simple_tag":
409
						/*_menu.AppendMenuItem(MF_STRING, 1700, "Custom title...");
410
						_menu.AppendMenuItem(MF_STRING, 1701, "Custom tag...");
411
						_menu.AppendMenuSeparator();
412
						_menu.AppendMenuItem(MF_STRING, 1702, "Centre text");
413
						_menu.CheckMenuItem(1702, t.centre);
414
						_menu.AppendMenuSeparator();*/
415
						break;
416
					case "simple_text":
417
						/*_menu.AppendMenuItem(MF_STRING, 1700, "Custom title...");
418
						_menu.AppendMenuItem(MF_STRING, 200, "Custom path...");
419
						_menu.AppendMenuSeparator();
420
						_menu.AppendMenuItem(MF_STRING, 201, "Fixed width font");
421
						_menu.CheckMenuItem(201, t.fixed);
422
						_menu.AppendMenuSeparator();*/
423
						break;
424
				}
425
				break;
426
			case typeof th == "object":
427
			case typeof im == "object" && im.trace(x, y):
428
				if (im.mode == "last.fm") {
429
					/*_menu.AppendMenuItem(this.metadb ? MF_STRING : MF_GRAYED, 450, "Download artist art from Last.fm");
430
					_menu.AppendMenuSeparator();
431
					_sub1.AppendMenuItem(MF_STRING, 451, "Off");
432
					_sub1.AppendMenuItem(MF_STRING, 452, "Library tracks only");
433
					_sub1.AppendMenuItem(MF_STRING, 453, "All tracks");
434
					_sub1.CheckMenuRadioItem(451, 453, im.auto_download == "off" ? 451 : im.auto_download == "library" ? 452 : 453);
435
					//_sub1.AppendTo(_menu, MF_STRING, "Automatic download");
436
					_sub2.AppendMenuItem(MF_STRING, 461, "1");
437
					_sub2.AppendMenuItem(MF_STRING, 463, "3");
438
					_sub2.AppendMenuItem(MF_STRING, 465, "5");
439
					//_sub2.AppendMenuItem(MF_STRING, 470, "10");
440
					//_sub2.AppendMenuItem(MF_STRING, 480, "20");
441
					_sub2.CheckMenuRadioItem(461, 480, im.limit + 460);
442
					//_sub2.AppendTo(_menu, MF_STRING, "Limit");*/
443
                    
444
				} else {
445
					//_menu.AppendMenuItem(MF_STRING, 442, "Set custom folder...");
446
				}
447
var _settings = window.CreatePopupMenu();
448
var _auto_cycle = window.CreatePopupMenu();
449
var _download_source = window.CreatePopupMenu();
450
var _download_limit = window.CreatePopupMenu();
451
var _download_quality = window.CreatePopupMenu();
452
var _thumbs = window.CreatePopupMenu();                
453
var MF_POPUP = 0x00000010;              
454
var MF_GRAYED = 0x00000001;                
455
				//_menu.AppendMenuSeparator();
456
//_menu.AppendMenuItem(MF_STRING, 403, "Auto YT");
457
				//_menu.AppendMenuSeparator();
458
459
460
//Settings Menu
461
//_menu.AppendMenuItem(MF_STRING | MF_POPUP, _settings.ID, "Auto YT");
462
463
//_menu.AppendMenuSeparator();
464
465
//_settings.AppendMenuItem(MF_STRING | MF_POPUP, _auto_cycle.ID, "Auto Cycle");
466
                
467
				//_auto_cycle.AppendMenuItem(MF_STRING, 415, "05 sec");
468
				//_auto_cycle.AppendMenuItem(MF_STRING, 420, "10 sec");
469
				//_auto_cycle.AppendMenuItem(MF_STRING, 425, "15 sec");
470
                //_auto_cycle.AppendMenuItem(MF_STRING, 430, "20 sec");
471
                //_auto_cycle.AppendMenuItem(MF_STRING, 410, "Off");
472
                //_auto_cycle.CheckMenuRadioItem(410, 430, cycle2 + 410);
473
				
474
475
//_settings.AppendMenuItem(MF_STRING | MF_POPUP, _download_source.ID, "Download Source");
476
                  
477
478
                  if(auto_yt==1) _menu.AppendMenuItem(MF_STRING, 1902, "Youtube Radio");
479
                  if(auto_yt==0) _menu.AppendMenuItem(MF_STRING, 1903, "Youtube Radio");
480
                  _menu.CheckMenuItem(1902, auto_yt?1:0);
481
                  _menu.AppendMenuSeparator();
482
483
484
//_settings.AppendMenuItem(MF_STRING | MF_POPUP, _download_limit.ID, "Download Limit");
485
                   
486
                   //_download_limit.AppendMenuItem(MF_STRING, 1905, "1x");
487
                   //_download_limit.AppendMenuItem(MF_STRING, 1906, "2x");
488
                   //_download_limit.AppendMenuItem(MF_STRING, 1907, "3x");
489
                   //_download_limit.AppendMenuItem(MF_STRING, 1908, "4x");
490
                   //_download_limit.AppendMenuItem(MF_STRING, 1909, "5x");
491
                   //_download_limit.AppendMenuItem(MF_STRING, 1910, "6x");
492
                   //_download_limit.CheckMenuRadioItem(1905, 1910, im.limit + 1904);
493
494
495
//if (server=="last.fm") _settings.AppendMenuItem(MF_STRING | MF_POPUP, _download_quality.ID, "Download Quality");
496
                       /*_download_quality.AppendMenuItem(MF_STRING, 1911, "Low");
497
                       _download_quality.AppendMenuItem(MF_STRING, 1912, "Medium");
498
                       _download_quality.AppendMenuItem(MF_STRING, 1913, "High");
499
                       _download_quality.CheckMenuRadioItem(1911, 1913, size == "low" ? 1911 : size == "medium" ? 1912 : size == "high" ? 1913 : 1913);
500
501
502
503
_settings.AppendMenuItem(MF_STRING | MF_POPUP, _thumbs.ID, "Thumbs");
504
                    
505
                    _thumbs.AppendMenuItem(MF_STRING, 1201, "Left");
506
					_thumbs.AppendMenuItem(MF_STRING, 1202, "Right");
507
					_thumbs.AppendMenuItem(MF_STRING, 1203, "Top");
508
					_thumbs.AppendMenuItem(MF_STRING, 1204, "Bottom");
509
					_thumbs.AppendMenuItem(MF_STRING, 1205, "Off");
510
					_thumbs.CheckMenuRadioItem(1200, 1205, th.mode == "grid" ? 1200 : th.mode == "left" ? 1201 : th.mode == "right" ? 1202 : th.mode == "top" ? 1203 : th.mode == "bottom" ? 1204 : 1205);
511
512
513
514
if (th.mode == "left" | th.mode == "right" | th.mode == "top" | th.mode == "bottom")
515
                    {
516
                  _thumbs.AppendMenuSeparator();
517
                  _thumbs.AppendMenuItem(MF_STRING, 1240, "40px");
518
                  _thumbs.AppendMenuItem(MF_STRING, 1250, "50px");
519
                  _thumbs.AppendMenuItem(MF_STRING, 1260, "60px");
520
                  _thumbs.AppendMenuItem(MF_STRING, 1270, "70px");
521
                  _thumbs.AppendMenuItem(MF_STRING, 1280, "80px");
522
                  _thumbs.AppendMenuItem(MF_STRING, 1290, "90px");
523
                  _thumbs.AppendMenuItem(MF_STRING, 1300, "100px");
524
                  _thumbs.AppendMenuItem(MF_STRING, 1350, "150px");
525
                  _thumbs.AppendMenuItem(MF_STRING, 1400, "200px");
526
                  _thumbs.AppendMenuItem(MF_STRING, 1450, "250px");
527
                  _thumbs.AppendMenuItem(MF_STRING, 1500, "300px");
528
                  _thumbs.CheckMenuRadioItem(1240, 1500, th.px + 1200);
529
              }*/
530
531
			/*	_sub3.AppendMenuItem(MF_STRING, 440, "Last.fm artist art");
532
				_sub3.AppendMenuItem(MF_STRING, 441, "Custom folder");
533
				_sub3.CheckMenuRadioItem(440, 441, im.mode == "last.fm" ? 440 : 441);
534
				//_sub3.AppendTo(_menu, MF_STRING, "Image source");
535
               
536
				_menu.AppendMenuSeparator();
537
				/*_sub4.AppendMenuItem(MF_STRING, 410, "Off");
538
				_sub4.AppendMenuItem(MF_STRING, 415, "5 seconds");
539
				_sub4.AppendMenuItem(MF_STRING, 420, "10 seconds");
540
				_sub4.AppendMenuItem(MF_STRING, 430, "20 seconds");
541
				_sub4.CheckMenuRadioItem(410, 430, im.cycle + 410);
542
				_sub4.CheckMenuRadioItem(410, 430, im.cycle + 410);
543
				_menu.AppendMenuSeparator();*/
544
				if (typeof th == "object") {
545
					if (!this.check_feature("now_playing")) _sub5.AppendMenuItem(MF_STRING, 1200, "Grid");
546
					/*_sub5.AppendMenuItem(MF_STRING, 1201, "Left");
547
					_sub5.AppendMenuItem(MF_STRING, 1202, "Right");
548
					_sub5.AppendMenuItem(MF_STRING, 1203, "Top");
549
					_sub5.AppendMenuItem(MF_STRING, 1204, "Bottom");
550
					_sub5.AppendMenuItem(MF_STRING, 1205, "Off");
551
					_sub5.CheckMenuRadioItem(1200, 1205, th.mode == "grid" ? 1200 : th.mode == "left" ? 1201 : th.mode == "right" ? 1202 : th.mode == "top" ? 1203 : th.mode == "bottom" ? 1204 : 1205);*/
552
					if (th.mode != "off") {
553
						/*_sub5.AppendMenuSeparator();
554
						_sub5.AppendMenuItem(MF_STRING, 1275, "75px");
555
						_sub5.AppendMenuItem(MF_STRING, 1300, "100px");
556
						_sub5.AppendMenuItem(MF_STRING, 1350, "150px");
557
						_sub5.AppendMenuItem(MF_STRING, 1400, "200px");
558
						_sub5.AppendMenuItem(MF_STRING, 1450, "250px");
559
						_sub5.AppendMenuItem(MF_STRING, 1500, "300px");
560
						_sub5.CheckMenuRadioItem(1275, 1500, th.px + 1200);*/
561
					}
562
					//_sub5.AppendTo(_menu, MF_STRING, "Thumbs");
563
					//_menu.AppendMenuSeparator();
564
				}
565
				//if (im.trace(x, y) && im.images.length > 0 && (!this.check_feature("thumbs") || th.mode != "grid")) 
566
                {
567
_menu.AppendMenuItem(MF_STRING, 21, "Get Next Video");
568
_menu.AppendMenuItem(MF_STRING, 400, "Get All Videos")
569
_menu.AppendMenuItem(MF_STRING, 401, "Search Videos");
570
_menu.AppendMenuSeparator();
571
//_menu.AppendMenuItem(MF_STRING, 402, "Search For Artist");
572
_menu.AppendMenuItem(MF_STRING, 403, "Open Artist+Title");
573
_menu.AppendMenuSeparator();
574
_menu.AppendMenuItem(MF_STRING, 404, "Open In Browser");
575
					//_menu.AppendMenuItem(MF_STRING, 402, "Delete image");
576
					//_menu.AppendMenuSeparator();
577
					//_menu.AppendMenuItem(MF_STRING, 405, "Top");
578
                    //_menu.AppendMenuItem(MF_STRING, 404, "Centre");
579
					//_menu.AppendMenuItem(MF_STRING, 406, "Adjust");
580
					//_menu.AppendMenuItem(MF_STRING, 407, "Stretch");
581
					_menu.CheckMenuRadioItem(404, 407, im.type == "centre" ? 404 : im.type == "top" ? 405 : im.type == "adjust" ? 406 : 407);
582
					_menu.AppendMenuSeparator();
583
				}
584
				break;
585
		}
586
		if (this.check_feature("now_playing")) {
587
			/*_menu.AppendMenuItem(MF_STRING, 44, "Top style");
588
			_menu.AppendMenuItem(MF_STRING, 45, "Bottom style");
589
			_menu.CheckMenuRadioItem(44, 45, np_track_top ? 44 : 45);
590
			_menu.AppendMenuSeparator();
591
			_menu.AppendMenuItem(MF_STRING, 41, "Show CD cover");
592
			_menu.CheckMenuItem(41, np_cd);
593
			_menu.AppendMenuItem(MF_STRING, 42, "Show track info");
594
			_menu.CheckMenuItem(42, np_track);
595
			_menu.AppendMenuItem(MF_STRING, 46, "Show rating");
596
			_menu.CheckMenuItem(46, np_rating);
597
			_menu.AppendMenuItem(MF_STRING, 40, "Show web links");
598
			_menu.CheckMenuItem(40, np_buttons);
599
			_menu.AppendMenuItem(MF_STRING, 43, "Show biography");
600
			_menu.CheckMenuItem(43, np_bio);
601
			_menu.AppendMenuSeparator();*/
602
		}
603
		if (this.check_feature("custom_background")) {
604
			if (!this.dui) _custom_background.AppendMenuItem(MF_STRING, 100, "None");
605
			/*_custom_background.AppendMenuItem(MF_STRING, 101, this.dui ? "Use default UI setting" : "Use columns UI setting");
606
			_custom_background.AppendMenuItem(MF_STRING, 102, "Splitter");
607
			_custom_background.AppendMenuItem(MF_STRING, 104, "Pattern");
608
			_custom_background.AppendMenuItem(MF_STRING, 103, "Custom");
609
			_custom_background.AppendMenuSeparator();
610
			_custom_background.AppendMenuItem(this.background_mode == 3 ? MF_STRING : MF_GRAYED, 105, "Set custom colour...");
611
			_custom_background.CheckMenuRadioItem(101, 104, this.background_mode + 100);
612
			_custom_background.AppendTo(_menu, MF_STRING, "Background");
613
			_menu.AppendMenuSeparator();*/
614
		}
615
		if (typeof l == "object") {
616
			//_menu.AppendMenuItem(MF_STRING, 1900, "Last.fm username...");
617
			if (typeof ps == "object") _menu.AppendMenuItem(l.username.length > 0 ? MF_STRING : MF_GRAYED, 1901, "Last.fm password...");
618
			//_menu.AppendMenuSeparator();
619
		}
620
		if (this.check_feature("metadb")) {
621
			/*_metadb.AppendMenuItem(MF_STRING, 900, "Use display preferences");
622
			_metadb.AppendMenuItem(MF_STRING, 901, "Prefer now playing");
623
			_metadb.AppendMenuItem(MF_STRING, 902, "Follow selected track");
624
			_metadb.CheckMenuRadioItem(900, 903, this.selection_mode + 900);*/
625
			//_metadb.AppendTo(_menu, MF_STRING, "Selection mode");
626
			//_menu.AppendMenuSeparator();
627
		}
628
		if (this.check_feature("remap")) {
629
			//_menu.AppendMenuItem(MF_STRING, 7, "Artist field remapping...");
630
			//_menu.AppendMenuSeparator();
631
		}
632
		//_menu.AppendMenuItem(MF_STRING, 20, "Update script");
633
		//_menu.AppendMenuSeparator();
634
		//if (utils.IsKeyPressed(0x10)) _menu.AppendMenuItem(MF_STRING, 9, "Properties");
635
        _menu.AppendMenuItem(MF_STRING, 9, "Properties...");
636
        if (utils.IsKeyPressed(0x10)) _menu.AppendMenuItem(MF_STRING, 10, "Configure...");
637
		idx = _menu.TrackPopupMenu(x, y);
638
		switch(idx) {
639
			case 1:
640
				on_item_focus_change();
641
				break;
642
			case 2:
643
			case 3:
644
			case 4:
645
			case 5:
646
			case 6:
647
				a.id = idx - 2;
648
				window.SetProperty("artreader_id", a.id);
649
				on_item_focus_change();
650
				break;
651
			case 7:
652
				this.artist_tf = this.InputBox("The default is %artist%\n\nYou can use the full foobar2000 title formatting syntax here.", "Artist field remapping", this.artist_tf);
653
				if (this.artist_tf == "") this.artist_tf = "%path%";
654
				window.SetProperty("YT Search", this.artist_tf);
655
				on_item_focus_change();
656
				break;
657
			case 9:
658
				window.ShowProperties();
659
				break;
660
			case 10:
661
				window.ShowConfigure();
662
				break;
663
			case 11:
664
				c.gloss = !c.gloss;
665
				window.SetProperty("cd_gloss", c.gloss);
666
				window.Repaint();
667
				break;
668
			case 12:
669
				c.shadow = !c.shadow;
670
				window.SetProperty("cd_shadow", c.shadow);
671
				window.Repaint();
672
				break;
673
			case 15:
674
			case 16:
675
			case 17:
676
			case 18:
677
				a.type = idx == 15 ? "centre" : idx == 16 ? "top" : idx == 17 ? "adjust" : "stretch";
678
				window.SetProperty("artreader_image_type", a.type);
679
				window.RepaintRect(a.x, a.y, a.w, a.h);
680
				break;
681
			case 20:
682
				this.update_script();
683
				break;
684
			case 21:
685
				im.downloadONE();
686
                break;
687
			case 22:
688
				this.aad();
689
				break;
690
			case 23:
691
				fb.ShowPopupMessage("You can get Album Art Downloader here:\n\nhttp://www.hydrogenaudio.org/forums/index.php?showtopic=57392", this.name);
692
				break;
693
			case 25:
694
			case 26:
695
				t.source = idx == 25 ? "last.fm" : "wikipedia";
696
				window.SetProperty("biography_source", t.source);
697
				t.artist = "";
698
				on_item_focus_change();
699
				break;
700
			case 28:
701
				li.show_timestamp = !li.show_timestamp;
702
				window.SetProperty("show_timestamp", li.show_timestamp);
703
				window.RepaintRect(li.x, li.y, li.w, li.h);
704
				break;
705
			case 29:
706
				li.discogs_match = !li.discogs_match;
707
				window.SetProperty("discogs_match", li.discogs_match);
708
				li.artist = "";
709
				on_item_focus_change();
710
				break;
711
			case 30:
712
			case 31:
713
			case 32:
714
				this.normal_font_size = idx == 30 ? 12 : idx == 31 ? 14 : 16;
715
				window.SetProperty("normal_font_size", this.normal_font_size);
716
				this.font_changed();
717
				break;
718
			case 40:
719
				np_buttons = !np_buttons;
720
				window.SetProperty("np_buttons", np_buttons);
721
				on_size();
722
				window.Repaint();
723
				break;
724
			case 41:
725
				np_cd = !np_cd;
726
				window.SetProperty("np_cd", np_cd);
727
				window.Repaint();
728
				break;
729
			case 42:
730
				np_track = !np_track;
731
				window.SetProperty("np_track", np_track);
732
				on_size();
733
				window.Repaint();
734
				break;
735
			case 43:
736
				np_bio = !np_bio;
737
				window.SetProperty("np_bio", np_bio);
738
				window.Repaint();
739
				break;
740
			case 44:
741
			case 45:
742
				np_track_top = idx == 44 ? true : false;
743
				window.SetProperty("np_track_top", np_track_top);
744
				on_size();
745
				window.Repaint();
746
				break;
747
			case 46:
748
				np_rating = !np_rating;
749
				window.SetProperty("np_rating", np_rating);
750
				on_size();
751
				window.Repaint();
752
				break;
753
			case 51:
754
			case 52:
755
			case 53:
756
				l.auto_correct = !l.auto_correct;
757
				window.SetProperty("lastfm_auto_correct", l.auto_correct);
758
				if (this.metadb) {
759
					if (idx == 51) li.get();
760
					if (idx == 53) t.get();
761
				}
762
				break;
763
			case 100:
764
			case 101:
765
			case 102:
766
			case 103:
767
			case 104:
768
				this.background_mode = idx - 100;
769
				window.SetProperty("background_mode", this.background_mode);
770
				window.Repaint();
771
				break;
772
			case 105:
773
				this.background_custom_colour = this.InputBox("Enter a custom colour for the background. Uses RGB. Example usage:\n\n234-211-74", this.name, this.background_custom_colour);
774
				window.SetProperty("background_custom_colour", this.background_custom_colour);
775
				window.Repaint();
776
				break;
777
			case 200:
778
				t.filename_tf = this.InputBox("Use title formatting to specify a path to your text file. eg: $directory_path(%path%)\\info.txt\n\nIf you prefer, you can specify just the path to a folder and the first txt or log file will be used.", this.name, t.filename_tf);
779
				window.SetProperty("text_filename_tf", t.filename_tf);
780
				on_item_focus_change();
781
				break;
782
			case 201:
783
				t.fixed = !t.fixed;
784
				window.SetProperty("text_fixed_font", t.fixed);
785
				t.calc();
786
				window.RepaintRect(t.x, t.y, t.w, t.h);
787
				break;
788
			case 400:
789
				im.downloadALL();
790
				break;
791-
				im.delete_image();
791+
792
				fb.RunMainMenuCommand("View/Youtube Source");
793
				break;
794-
				if (im.images.length < im.limit)
794+
795
				im.downloadART();
796-
                p.run("RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 8");    
796+
797-
                im.download();
797+
798-
                im.update();
798+
				im.downloadART_TITLE();
799-
                }
799+
800-
                else
800+
801-
                p.run("RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 8");
801+
            p.artist = p.eval("%artist% %title%");
802-
                im.update();
802+
            p.browser("http://www.youtube.com/results?search_query=" + encodeURIComponent(p.artist));
803
            break;
804
			case 405:
805
			case 406:
806
			case 407:
807
				im.type = idx == 404 ? "centre" : idx == 405 ? "top" : idx == 406 ? "adjust" : "stretch";
808
				//window.SetProperty("Image type", im.type);
809
				window.Repaint();
810
				break;
811
			case 410:
812
			case 415:
813
			case 420:
814
			case 425:
815
            case 430:
816
				cycle2 = idx - 410;
817
				window.SetProperty("Image cycle", cycle2);
818
                cicleTimer = undefined;
819
                cicleTimerStarted = false;
820
                stopTimer();
821
                startTimer();
822
                cicleTimerStarted = true;
823
                break;
824
			case 440:
825
			case 441:
826
				im.mode = idx == 440 ? "last.fm" : "custom";
827
				window.SetProperty("image_mode", im.mode);
828
				im.artist = "";
829
				im.folder = "";
830
				on_item_focus_change();
831
				break;
832
			case 442:
833
				im.custom_folder_tf = this.InputBox("Enter title formatting or an absolute path to a folder. You can specify multiple folders using | as a separator.", this.name, im.custom_folder_tf);
834
				if (im.custom_folder_tf == "") im.custom_folder_tf = "$directory_path(%path%)";
835
				window.SetProperty("image_custom_folder_tf", im.custom_folder_tf);
836
				im.folder = "";
837
				on_item_focus_change();
838
				break;
839
			case 450:
840
				im.download();
841
				break;
842
			case 451:
843
			case 452:
844
			case 453:
845
				im.auto_download = idx == 451 ? "on" : idx == 452 ? "library" : "off";
846
				window.SetProperty("image_auto_download", im.auto_download);
847
				break;
848
			case 461:
849
			case 463:
850
			case 465:
851
				im.limit = idx - 460;
852
				window.SetProperty("image_limit", 50);
853
				break;
854
			case 490:
855
			case 491:
856
			case 492:
857
			case 493:
858
				im.type = idx == 490 ? "centre" : idx == 491 ? "top" : idx == 492 ? "adjust" : "stretch";
859
				window.SetProperty("image_type", im.type);
860
				window.RepaintRect(im.x, im.y, im.w, im.h);
861
				break;
862
			case 500:
863
			case 501:
864
			case 502:
865
				li.echonest_mode = idx - 500;
866
				window.SetProperty("echonest_mode", li.echonest_mode);
867
				li.artist = "";
868
				on_item_focus_change();
869
				break;
870
			case 600:
871
				li.autoplaylists_title = this.InputBox("Enter a new title", this.name, li.autoplaylists_title);
872
				if (li.autoplaylists_title == "") li.autoplaylists_title = "Autoplaylists";
873
				window.SetProperty("autoplaylists_title", li.autoplaylists_title);
874
				window.Repaint();
875
				break;
876
			case 601:
877
			case 602:
878
			case 603:
879
			case 604:
880
			case 605:
881
			case 606:
882
			case 607:
883
			case 608:
884
				li.autoplaylists_slot = idx - 600;
885
				window.SetProperty("autoplaylists_slot", li.autoplaylists_slot);
886
				li.filename = this.settings_folder + "autoplaylists" + li.autoplaylists_slot;
887
				li.offset = 0;
888
				li.update();
889
				break;
890
			case 610:
891
			case 611:
892
				li.autoplaylists_success = idx == 610 ? true : false;
893
				window.SetProperty("autoplaylists_success", li.autoplaylists_success);
894
				break;
895
			case 620:
896
			case 621:
897
			case 622:
898
			case 623:
899
			case 624:
900
			case 625:
901
			case 626:
902
			case 627:
903
				li.data.push(li.autoplaylists_deleted_items[idx - 620]);
904
				if (li.data.length > li.rows) li.offset = li.data.length - li.rows;
905
				li.autoplaylists_deleted_items.splice(idx - 620, 1);
906
				this.save(li.data.join("\n"), li.filename);
907
				window.NotifyOthers("autoplaylists", "update");
908
				li.update();
909
				break;
910
			case 650:
911
				li.autoplaylists_remove_duplicates = !li.autoplaylists_remove_duplicates
912
				window.SetProperty("autoplaylists_remove_duplicates", li.autoplaylists_remove_duplicates);
913
				break;
914
			case 700:
915
			case 701:
916
				li.musicbrainz_mode = idx == 700 ? "releases" : "URLs";
917
				window.SetProperty("musicbrainz_mode", li.musicbrainz_mode);
918
				li.artist = "";
919
				on_item_focus_change();
920
				break;
921
			case 702:
922
				li.musicbrainz_album = !li.musicbrainz_album;
923
				window.SetProperty("musicbrainz_album", li.musicbrainz_album);
924
				li.artist = "";
925
				on_item_focus_change();
926
				break;
927
			case 703:
928
				li.musicbrainz_ep = !li.musicbrainz_ep;
929
				window.SetProperty("musicbrainz_ep", li.musicbrainz_ep);
930
				li.artist = "";
931
				on_item_focus_change();
932
				break;
933
			case 704:
934
				li.musicbrainz_single = !li.musicbrainz_single;
935
				window.SetProperty("musicbrainz_single", li.musicbrainz_single);
936
				li.artist = "";
937
				on_item_focus_change();
938
				break;
939
			case 705:
940
				li.musicbrainz_live = !li.musicbrainz_live;
941
				window.SetProperty("musicbrainz_live", li.musicbrainz_live);
942
				li.artist = "";
943
				on_item_focus_change();
944
				break;
945
			case 706:
946
				li.musicbrainz_remix = !li.musicbrainz_remix;
947
				window.SetProperty("musicbrainz_remix", li.musicbrainz_remix);
948
				li.artist = "";
949
				on_item_focus_change();
950
				break;
951
			case 707:
952
				li.musicbrainz_compilation = !li.musicbrainz_compilation;
953
				window.SetProperty("musicbrainz_compilation", li.musicbrainz_compilation);
954
				li.artist = "";
955
				on_item_focus_change();
956
				break;
957
			case 708:
958
				li.musicbrainz_show_release_type = !li.musicbrainz_show_release_type;
959
				window.SetProperty("musicbrainz_show_release_type", li.musicbrainz_show_release_type);
960
				window.RepaintRect(li.x, li.y, li.w, li.h);
961
				break;
962
			case 801:
963
			case 802:
964
			case 803:
965
			case 804:
966
			case 805:
967
				li.lastfm_mode = idx - 801;
968
				window.SetProperty("lastfm_mode", li.lastfm_mode);
969
				li.artist = "";
970
				on_item_focus_change();
971
				break;
972
			case 810:
973
				li.lastfm_pause = !li.lastfm_pause;
974
				window.SetProperty("lastfm_pause", li.lastfm_pause);
975
				break;
976
			case 811:
977
			case 812:
978
				li.lastfm_button = idx == 811 ? "spotify" : "auto";
979
				window.SetProperty("lastfm_button", li.lastfm_button);
980
				window.RepaintRect(li.x, li.y, li.w, li.h);
981
				break;
982
			case 900:
983
			case 901:
984
			case 902:
985
				this.selection_mode = idx - 900;
986
				window.SetProperty("selection_mode", this.selection_mode);
987
				on_item_focus_change();
988
				break;
989
			case 1000:
990
				li.get();
991
				break;
992
			case 1001:
993
			case 1002:
994
			case 1003:
995
				li.lastfm_charts_mode = idx - 1001;
996
				window.SetProperty("lastfm_charts_mode", li.lastfm_charts_mode);
997
				li.update();
998
				break;
999
			case 1004:
1000
			case 1005:
1001
			case 1006:
1002
			case 1007:
1003
			case 1008:
1004
			case 1009:
1005
				li.lastfm_charts_period = idx - 1004;
1006
				window.SetProperty("lastfm_charts_period", li.lastfm_charts_period);
1007
				li.update();
1008
				break;
1009
			case 1010:
1010
				li.lastfm_charts_bar_colour = this.InputBox("Enter a custom colour for the bars. Uses RGB. Example usage:\n\n234-211-74", this.name, li.lastfm_charts_bar_colour);
1011
				window.SetProperty("lastfm_charts_bar_colour", li.lastfm_charts_bar_colour);
1012
				window.Repaint();
1013
				break;
1014
			case 1100:
1015
			case 1109:
1016
				ps.full_import = idx == 1100 ? true : false;
1017
				ps.start_import();
1018
				break;
1019
			case 1101:
1020
				ps.finish_import();
1021
				break;
1022
			case 1102:
1023
				ps.show_console = !ps.show_console;
1024
				window.SetProperty("playcount_sync_show_console", ps.show_console);
1025
				break;
1026
			case 1103:
1027
				ps.library = !ps.library;
1028
				window.SetProperty("playcount_sync_library", ps.library);
1029
				break;
1030
			case 1104:
1031
			case 1105:
1032
				ps.auto_love = idx == 1104 ? false : true;
1033
				window.SetProperty("playcount_sync_auto_love", ps.auto_love);
1034
				break;
1035
			case 1106:
1036
				ps.auto_love_tf = this.InputBox("The result of the title formatting set here must equal 1 for a track to be automatically loved.\n\nExample:\n\n$ifequal(%rating%,5,1,0)", this.name, ps.auto_love_tf);
1037
				window.SetProperty("playcount_sync_auto_love_tf", ps.auto_love_tf);
1038
				break;
1039
			case 1107:
1040
			case 1108:
1041
				ps.icon = idx == 1107 ? "tango" : "silk";
1042
				window.SetProperty("playcount_sync_icon", ps.icon);
1043
				b.update();
1044
				break;
1045
			case 1200:
1046
			case 1201:
1047
			case 1202:
1048
			case 1203:
1049
			case 1204:
1050
			case 1205:
1051
				th.mode = idx == 1200 ? "grid" : idx == 1201 ? "left" : idx == 1202 ? "right" : idx == 1203 ? "top" : idx == 1204 ? "bottom" : "off";
1052
				//window.SetProperty("Thumbs mode", th.mode);
1053
				th.nc = true;
1054
				on_size();
1055
				window.Repaint();
1056
				break;
1057
			case 1240:
1058
			case 1250:
1059
			case 1260:
1060
			case 1270:
1061
			case 1280:
1062
			case 1290:
1063
            case 1300:
1064
			case 1350:
1065
			case 1400:
1066
			case 1450:
1067
			case 1500:
1068
				th.px = idx - 1200;
1069
				
1070
				th.nc = true;
1071
				on_size();
1072
				window.Repaint();
1073
				break;
1074
			case 1700:
1075
				t.title = this.InputBox("You can use full title formatting here.", this.name, t.title);
1076
				window.SetProperty("text_title", t.title);
1077
				window.Repaint();
1078
				break;
1079
			case 1701:
1080
				t.tag = this.InputBox("Enter a custom tag.", this.name, t.tag);
1081
				window.SetProperty("text_tag", t.tag);
1082
				t.filename = "";
1083
				on_item_focus_change();
1084
				break;
1085
			case 1702:
1086
				t.centre = !t.centre;
1087
				window.SetProperty("text_centre", t.centre);
1088
				window.RepaintRect(t.x, t.y, t.w, t.h);
1089
				break;
1090
			case 1800:
1091
			case 1801:
1092
			case 1802:
1093
				var period = idx == 1800 ? 0 : idx == 1801 ? ONE_DAY : ONE_WEEK;
1094
				s.clear_images(period);
1095
				break;
1096
			case 1803:
1097
				s.library = !s.library;
1098
				window.SetProperty("seekbar_library", s.library);
1099
				break;
1100
			case 1804:
1101
				s.sox_params = this.InputBox("All SoX spectrogram options should work here.\n\n-r, -d and -o are already configured so do not use those. Check sox.pdf for everything else.", this.name, s.sox_params);
1102
				window.SetProperty("sox_params", s.sox_params);
1103
				if (fb.IsPlaying) s.playback_new_track();
1104
				break;
1105
			case 1805:
1106
				s.marker = this.InputBox("Enter a custom colour for the marker. Uses RGB. Example usage:\n\n234-211-74", this.name, s.marker);
1107
				window.SetProperty("seekbar_marker", s.marker);
1108
				break;
1109
			case 1900:
1110
				l.update_username();
1111
				break;
1112
			case 1901:
1113
				l.update_password();
1114
				break;
1115
            
1116
                
1117
           case 1902:
1118
                auto_yt = 0;
1119
                window.SetProperty("YT Radio", "0");
1120
                break;
1121
       
1122
           case 1903:
1123
                auto_yt = 1;
1124
                window.SetProperty("YT Radio", "1");
1125
                break; 
1126
  
1127
1128
            case 1904:
1129
            if (server=="on")server = window.SetProperty("YT Radio", "off");
1130
            if (server=="off")server = window.SetProperty("YT Radio", "on");
1131
            break;
1132
1133
            case 1905:    
1134
            case 1906:    
1135
            case 1907: 
1136
            case 1908:    
1137
            case 1909:    
1138
            case 1910: 
1139
            im.limit = idx - 1904;
1140
            //window.SetProperty("Download limit", im.limit);
1141
            break;
1142
            
1143
            case 1911:    
1144
            case 1912:    
1145
            case 1913: 
1146
            size = idx == 1911 ? "low" : idx == 1912 ? "medium" : idx == 1913 ? "high" : "high";
1147
		    window.SetProperty("Download quality", size);
1148
            break;
1149
        }
1150
		_menu.Dispose();
1151
		_custom_background.Dispose();
1152
		_metadb.Dispose();
1153
		_cover.Dispose();
1154
		_font.Dispose();
1155
		_sub1.Dispose();
1156
		_sub2.Dispose();
1157
		_sub3.Dispose();
1158
		_sub4.Dispose();
1159
		_sub5.Dispose();
1160
	}
1161
	
1162
	this.features_init = function() {
1163
		for (i = 0; i < this.features.length; i++) {
1164
			switch(this.features[i]) {
1165
				case "custom_background":
1166
					//this.background_mode = (0);
1167
                    //window.GetProperty("background_mode", 0);
1168
					//this.background_custom_colour = ("0-0-0");
1169
                    //window.GetProperty("background_custom_colour", "0-0-0");
1170
					break;
1171
				case "metadb":
1172
					this.selection_mode = 1;
1173
					break;
1174
				case "themes":
1175
					this.themed_seekbar = window.CreateThemeManager("Progress");
1176
					this.themed_header = window.CreateThemeManager("Header");
1177
					this.themed_header.SetPartAndStateId(1, 1);
1178
					this.themed_button = window.CreateThemeManager("Button");
1179
					break;
1180
				case "remap":
1181
					this.artist_tf = window.GetProperty("YT Search", "%path%");
1182
					break;
1183
			}
1184
		}
1185
	}
1186
	
1187
	this.check_feature = function(f) {
1188
		for (i = 0; i < this.features.length; i++) {
1189
			if (this.features[i] == f) return true;
1190
		}
1191
		return false;
1192
	}
1193
	
1194
	this.eval = function(tf) {
1195
		if (!this.metadb || tf == "") return "";
1196
		if (fb.IsPlaying && this.metadb.RawPath.indexOf("file://") != 0) {
1197
			return fb.TitleFormat(tf).Eval();
1198
		} else {
1199
			return fb.TitleFormat(tf).EvalWithMetadb(this.metadb);
1200
		}
1201
	}
1202
	
1203
	this.open = function(filename) {
1204
		return utils.ReadTextFile(filename);
1205
	}
1206
	
1207
	this.save = function(t, f) {
1208
		try {
1209
			var ts = this.fso.OpenTextFile(f, 2, true, -1);
1210
			ts.WriteLine(t);
1211
			ts.Close();
1212
			return true;
1213
		} catch(e) {
1214
			return false;
1215
		}
1216
	}
1217
	
1218
	this.console = function(message) {
1219
		fb.trace(this.name + ": " + message);
1220
	}
1221
	
1222
	this.strip_tags = function(value) {
1223
		if (!this.doc) this.doc = new ActiveXObject("htmlfile");
1224
		try {
1225
			this.doc.open();
1226
			var div = this.doc.createElement("div");
1227
			div.innerHTML = value.replace(/\n/g, "<br>");
1228
			return div.innerText.trim();
1229
		} catch(e) {
1230
			return "Error reading content.";
1231
		}
1232
	}
1233
	
1234
	this.InputBox = function(prompt, title, value) {
1235
		prompt = prompt.replace(/"/g, '" + Chr(34) + "').replace(/\n/g, '" + Chr(13) + "');
1236
		title = title.replace(/"/g, '" + Chr(34) + "');
1237
		value = value.replace(/"/g, '" + Chr(34) + "');
1238
		var temp_value = this.vb.eval('InputBox' + '("' + prompt + '", "' + title + '", "' + value + '")');
1239
		if (typeof temp_value == "undefined") return value;
1240
		if (temp_value.length == 254) this.MsgBox("Your entry was too long and will be truncated.\n\nSee the WSH panel mod script discussion thread on hydrogenaudio forums for help.", 0, this.name);
1241
		return temp_value.trim();
1242
	}
1243
	
1244
	this.MsgBox = function(prompt, buttons, title) {
1245
		prompt = prompt.replace(/"/g, '" + Chr(34) + "').replace(/\n/g, '" + Chr(13) + "');
1246
		title = title.replace(/"/g, '" + Chr(34) + "');
1247
		return this.vb.eval('MsgBox' + '("' + prompt + '", "' + buttons + '", "' + title + '")');
1248
	}
1249
	
1250
	this.browser = function(command) {
1251
		if (!this.run(command)) this.MsgBox("Unable to launch your default browser.", 0, this.name);
1252
	}
1253
	
1254
	this.run = function(command) {
1255
		try {
1256
			this.WshShell.Run(command);
1257
			return true;
1258
		} catch(e) {
1259
			return false;
1260
		}
1261
	}
1262
	
1263
	this.aad = function() {
1264
		if (!this.app) this.app = new ActiveXObject("Shell.Application");
1265
		var aad_path = window.GetProperty("aad_path", "");
1266
		if (!this.fso.FileExists(aad_path)) {
1267
			var folder = this.app.BrowseForFolder(0, "Locate Album Art Downloader", 0x00000200);
1268
			var file = folder ? folder.items().item().path + "\\AlbumArt.exe" : "";
1269
			if (this.fso.FileExists(file)) {
1270
				aad_path = file;
1271
				window.SetProperty("aad_path", file);
1272
			}
1273
		}
1274
		if (this.fso.FileExists(aad_path)) {
1275
			var album_artist = "/ar \"" + this.eval("[%album artist%]") + "\"";
1276
			var album = " /al \"" + this.eval("[%album%]") + "\"";
1277
			this.run("\"" + aad_path + "\"" + album_artist + album);
1278
		}
1279
	}
1280
	
1281
	this.tt = function(t) {
1282
		if (this.tooltip.Text == t) return;
1283
		this.tooltip.Text = t;
1284
		this.tooltip.Activate();
1285
	}
1286
	
1287
	this.ttd = function() {
1288
		this.tooltip.Text = "";
1289
		this.tooltip.Deactivate();
1290
	}
1291
	
1292
	this.splitRGB = function(value) {
1293
		var temp_col = value.split("-");
1294
		return RGB(temp_col[0], temp_col[1], temp_col[2]);
1295
	}
1296
	
1297
	this.draw_background = function(gr) {
1298
		if (this.check_feature("custom_background")) {
1299
			var col;
1300
			switch(this.background_mode) {
1301
				case 0:
1302
					col = null;
1303
					break;
1304
				case 1:
1305
					col = this.backcolour;
1306
					break;
1307
				case 2:
1308
					col = utils.GetSysColor(15);
1309
					break;
1310
				case 3:
1311
					col = this.splitRGB(this.background_custom_colour);
1312
					break;
1313
				case 4:
1314
					col = null;
1315
					var spacing = 3;
1316
					var line_thickness = 1;
1317
					var bg = RGB(65, 65, 65);
1318
					var colour = RGB(92, 92, 92);
1319
					gr.FillSolidRect(0, 0, this.w, this.h, bg);
1320
					for (i = 0; i < Math.ceil(this.w / spacing); i++) {
1321
						gr.DrawLine(i * spacing, 0, i * spacing, this.h, line_thickness, colour);
1322
					}
1323
					for (i = 0; i < Math.ceil(this.h / spacing); i++) {
1324
						gr.DrawLine(0, i * spacing, this.w, i * spacing, line_thickness, colour);
1325
					}
1326
					break;
1327
			}
1328
			if (col) gr.FillSolidRect(0, 0, this.w, this.h, col);
1329
		} else {
1330
			gr.FillSolidRect(0, 0, this.w, this.h, this.backcolour);
1331
		}
1332
	}
1333
	
1334
	this.draw_image = function(gr, img, pos_x, pos_y, width, height, type, border, alpha) {
1335
		if (!img) return;
1336
		gr.SetInterpolationMode(7);
1337
		switch(type) {
1338
			case "centre":
1339
			  case "top":
1340
               {
1341
                var sr = img.Width / img.Height;
1342
				var dr = width / height;
1343
				if (sr < dr) {
1344
					var r = img.Width / width;
1345
					var ch = height * r;
1346
					var sy = Math.round((img.Height - ch) / (type == "top" ? 1000 : 2));
1347
					var cw = img.Width;
1348
					var sx = 0;
1349
				} else {
1350
                    var r = img.Height / height;
1351
					var cw = width * r;
1352
					var sx = Math.round((img.Width - cw) / 2);
1353
					var ch = img.Height;
1354
					var sy = 0;
1355
				}
1356
                  { 
1357
                   gr.DrawImage(img, pos_x, pos_y, width, height, sx + 5, sy + 5, cw - 10, ch - 10, 0, alpha || 255);
1358
				   if (border) gr.DrawRect(pos_x, pos_y, width - 1, height - 1, 1, border);    
1359
                  }
1360
             }
1361
                break;
1362
			case "stretch":
1363
                //strech
1364
                
1365
                 gr.DrawImage(img, pos_x, pos_y, width, height, 5, 5, img.Width-10, img.Height-10, 0, alpha || 255);
1366
				 if (border) gr.DrawRect(pos_x, pos_y, width - 1, height - 1, 1, border);
1367
                 
1368
                break;
1369
			case "adjust":
1370
			default:
1371
                //adjust
1372
                var s = Math.min(width / img.Width, height / img.Height);
1373
				var nw = Math.round(img.Width * s);
1374
				var nh = Math.round(img.Height * s);
1375
				pos_x += Math.round((width - nw) / 2);
1376
				pos_y += Math.round((height - nh) / 2);
1377
                
1378
                
1379
                gr.DrawImage(img, pos_x, pos_y, nw, nh, 5, 5, img.Width-10, img.Height-10, 0, alpha || 255);
1380
                if (border) gr.DrawRect(pos_x, pos_y, nw - 1, nh - 1, 1, border);
1381
				break;
1382
		
1383
	}
1384
}
1385
	this.header = function(gr, text) {
1386
		this.left_text(gr, text, this.title_font, this.textcolour_hl, 6, 6, this.w - 77, 24);
1387
		gr.DrawLine(6, 29, this.w - 6, 29, 1, this.textcolour_hl);
1388
	}
1389
	
1390
	this.centre_text = function(gr, text, font, colour, x, y, w, h) {
1391
		gr.GdiDrawText(text, font, colour, x, y, w, h, DT_VCENTER | DT_CENTER | DT_WORDBREAK | DT_CALCRECT | DT_NOPREFIX);
1392
	}
1393
	
1394
	this.left_text = function(gr, text, font, colour, x, y, w, h) {
1395
		gr.GdiDrawText(text, font, colour, x, y, w, h, DT_VCENTER | DT_END_ELLIPSIS | DT_CALCRECT | DT_NOPREFIX);
1396
	}
1397
	
1398
	this.right_text = function(gr, text, font, colour, x, y, w, h) {
1399
		gr.GdiDrawText(text, font, colour, x, y, w, h, DT_VCENTER | DT_RIGHT | DT_END_ELLIPSIS | DT_CALCRECT | DT_NOPREFIX);
1400
	}
1401
	
1402
	this.format_time = function(t) {
1403
		var h = Math.floor(t / 3600);
1404
		var m = Math.floor((t -= h * 3600) / 60);
1405
		var s = Math.floor(t -= m * 60);
1406
		return((h > 0 ? h + ":" + (m < 10 ? "0" + m : m) : m) + ":" + (s < 10 ? "0" + s : s));
1407
	}
1408
	
1409
	this.check_version = function() {
1410
		//not used any more but will leave intact so old scripts don't crash.
1411
		return;
1412
	}
1413
	
1414
	this.update_script = function() {
1415
		if (!this.xmlhttp) this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
1416
		this.xmlhttp.open("GET", this.common_url, true);
1417
		this.xmlhttp.send();
1418
		this.xmlhttp.onreadystatechange = function() {
1419
			if (p.xmlhttp.readyState == 4) {
1420
				switch(p.xmlhttp.status) {
1421
					case 200:
1422
						var text = p.xmlhttp.responsetext;
1423
						switch (true) {
1424
							case text.indexOf("function panel") == -1:
1425
								p.MsgBox("Unexpected server error. Not updating.", 0, p.name);
1426
								break;
1427
							case text.indexOf('var VERSION = "' + VERSION) == 0:
1428
								p.MsgBox("Already using latest version.", 0, p.name);
1429
								break;
1430
							default:
1431
								if (p.save(text, p.common_filename)) {
1432
									if (p.MsgBox("Download successful. Restart foobar2000 now?", 4, p.name) == 6) fb.RunMainMenuCommand("File/Restart");
1433
								} else {
1434
									p.MsgBox("Unexpected error. Not updating.", 0, p.name);
1435
								}
1436
								break;
1437
						}
1438
						break;
1439
					case 404:
1440
						fb.ShowPopupMessage("The script reports that the update file has not been found. It could be a temporary problem with dropbox but if this error persists then it is most likely due to support stopping for this version. Check the hydrogenaudio thread or the full zip for updates.\n\nhttp://www.hydrogenaudio.org/forums/index.php?showtopic=77883\n" + p.root_url + "samples.zip", p.name);
1441
						break;
1442
					default:
1443
						p.console(p.xmlhttp.responsetext || "HTTP error: " + p.xmlhttp.status);
1444
						break;
1445
				}
1446
			}
1447
		}
1448
	}
1449
//remove false string from file names	
1450
    this.clean_filename = function(filename) {
1451
		return filename.replace(/[\/\\|:]/g, '-').replace(/\*/g, 'x').replace(/"/g, "''").replace(/[?<>]/g, '_');
1452
	}
1453
    
1454
    
1455
    
1456
	this.json_parse = function(text) {
1457
		try {
1458
			var data = JSON.parse(text);
1459
			return data;
1460
		} catch(e) {
1461
			this.console("JSON.parse error.");
1462
			return false;
1463
		}
1464
	}
1465
	
1466
	this.name = name;
1467
	this.features = features;
1468
	this.dui = window.InstanceType;
1469
	this.script_path = fb.ProfilePath;
1470
	this.images_path = this.script_path + "images\\";
1471
	this.root_url = "https://dl.dropboxusercontent.com/u/22801321/wsh/"
1472
	this.common_url = this.root_url + "marc2003/common7.js";
1473
	this.common_filename = this.script_path + "common7.js";
1474
	this.tooltip = window.CreateTooltip();
1475
	this.w = 0;
1476
	this.h = 0;
1477
	this.mx = 0;
1478
	this.my = 0;
1479
	this.metadb = fb.GetFocusItem();
1480
	this.WshShell = new ActiveXObject("WScript.Shell");
1481
	this.fso = new ActiveXObject("Scripting.FileSystemObject");
1482
	this.vb = new ActiveXObject("ScriptControl");
1483
	this.vb.Language = "VBScript";
1484
	//this.settings_folder = fb.ProfilePath + "last_fm\\";
1485
	//if (!this.fso.FolderExists(this.settings_folder)) this.fso.CreateFolder(this.settings_folder);
1486
	
1487
    //this.data_folder = lfm_folder + "\\";
1488
    //if (lfm_folder==fb.ProfilePath + "Artist_info") if (!this.fso.FolderExists(this.data_folder)) this.fso.CreateFolder(this.data_folder), this.data_folder=this.data_folder;
1489
    //if (!this.fso.FolderExists(this.data_folder)) return;   
1490
    this.artist = "";
1491
	this.artist_tf = "%path%";
1492
	this.normal_font_size = (12);
1493
    //window.GetProperty("normal_font_size", 12);
1494
	this.list_font_size = 11;
1495
	this.up_img = gdi.Image(this.images_path + "down.png");
1496
	this.down_img = gdi.Image(this.images_path + "down.png");
1497
	this.metadb_func = typeof on_metadb_changed == "function";
1498
	this.features_init();
1499
	this.colors_changed();
1500
	this.font_changed();
1501
}
1502
1503
function artreader(x, y, w, h) {
1504
	this.draw = function(gr) {
1505
		if (!this.img) return;
1506
		p.draw_image(gr, this.img, this.x, this.y, this.w, this.h, this.type);
1507
	}
1508
	
1509
	this.metadb_changed = function() {
1510
		if (!p.metadb) return;
1511
		this.img && this.img.Dispose();
1512
		this.path = "";
1513
		this.img = utils.GetAlbumArtV2(p.metadb, this.id);
1514
		window.RepaintRect(this.x, this.y, this.w, this.h);
1515
		utils.GetAlbumArtAsync(window.ID, p.metadb, this.id);
1516
	}
1517
	
1518
	this.get_album_art_done = function(ip) {
1519
		this.path = ip;
1520
	}
1521
	
1522
	this.trace = function(x, y) {
1523
		return (x > this.x && x < this.x + this.w && y > this.y && y < this.y + this.h);
1524
	}
1525
	
1526
	this.wheel = function(step) {
1527
		if (!this.trace(p.mx, p.my)) return false;
1528
		this.id -= step;
1529
		if (this.id < 0) this.id = 4;
1530
		if (this.id > 4) this.id = 0;
1531
		window.SetProperty("artreader_id", this.id);
1532
		this.metadb_changed();
1533
		return true;
1534
	}
1535
	
1536
	this.move = function(x, y) {
1537
		if (this.trace(x, y)) {
1538
			if (this.img) p.tt("Original size: " + this.img.Width + "x" + this.img.Height + "px");
1539
			return true;
1540
		} else {
1541
			p.ttd();
1542
			return false;
1543
		}
1544
	}
1545
	
1546
	this.lbtn_dblclk = function(x, y) {
1547
		if (!this.trace(x, y)) return false;
1548
		if (this.img) p.run("explorer /select,\"" + this.path + "\"");
1549
		return true;
1550
	}
1551
	
1552
	this.x = x;
1553
	this.y = y;
1554
	this.w = w;
1555
	this.h = h;
1556
	this.id = window.GetProperty("artreader_id", 0);
1557
	this.img = null;
1558
	this.path = null;
1559
	this.type = window.GetProperty("artreader_image_type", "top");
1560
}
1561
1562
function buttons() {
1563
	this.draw = function(gr) {
1564
		for (i in this.buttons) {
1565
			this.buttons[i].draw(gr);
1566
		}
1567
	}
1568
	
1569
	this.move = function(x, y) {
1570
		this.tmp_btn = null;
1571
		for (i in this.buttons) {
1572
			if (this.buttons[i].trace(x, y)) this.tmp_btn = i;
1573
		}
1574
		if (this.btn == this.tmp_btn) return this.btn;
1575
		if (this.tmp_btn) this.buttons[this.tmp_btn].state("hover");
1576
		if (this.btn) this.buttons[this.btn].state("normal");
1577
		this.btn = this.tmp_btn;
1578
		return this.btn;
1579
	}
1580
	
1581
	this.lbtn_up = function(x, y) {
1582
		if (!this.btn) return false;
1583
		this.buttons[this.btn].lbtn_up(x, y);
1584
		return true;
1585
	}
1586
	
1587
	this.leave = function() {
1588
		if (this.btn) this.buttons[this.btn].state("normal");
1589
		this.btn = null;
1590
	}
1591
	
1592
	this.buttons = [];
1593
	this.btn = null;
1594
}
1595
1596
function button(x, y, w, h, img_src, func, tiptext, themed) {
1597
	this.draw = function (gr) {
1598
		if (this.themed) {
1599
			p.themed_button.SetPartAndStateId(1, this.id);
1600
			p.themed_button.DrawThemeBackground(gr, this.x, this.y, this.w, this.h);
1601
			this.img && p.draw_image(gr, this.img, this.x + Math.round((this.w - this.img.Width) / 2), this.y + Math.round((this.h - this.img.Height) / 2), this.img.Width, this.img.Height, "adjust");
1602
		} else {
1603
			this.img && p.draw_image(gr, this.img, this.x, this.y, this.w, this.h, "adjust");
1604
		}
1605
	}
1606
	
1607
	this.trace = function(x, y) {
1608
		return (x > this.x && x < this.x + this.w && y > this.y && y < this.y + this.h);
1609
	}
1610
	
1611
	this.lbtn_up = function () {
1612
		this.func && this.func(x, y);
1613
	}
1614
	
1615
	this.state = function(s) {
1616
		if (s == "hover") {
1617
			this.img = this.img_hover;
1618
			this.id = 2;
1619
			p.tt(this.tiptext);
1620
		} else {
1621
			this.img = this.img_normal;
1622
			this.id = 0;
1623
			p.ttd();
1624
		}
1625
		window.RepaintRect(this.x, this.y, this.w, this.h);
1626
	}
1627
	
1628
	this.x = x;
1629
	this.y = y;
1630
	this.w = w;
1631
	this.h = h;
1632
	this.func = func;
1633
	this.tiptext = tiptext;
1634
	this.themed = themed;
1635
	this.id = 0;
1636
	this.img_normal = gdi.Image(p.images_path + img_src.normal);
1637
	this.img_hover = img_src.hover ? gdi.Image(p.images_path + img_src.hover) : this.img_normal;
1638
	this.img = this.img_normal;
1639
}
1640
1641
function cd(x, y, w, h) {
1642
	this.draw = function(gr) {
1643
		if (this.shadow) p.draw_image(gr, this.shadow_img, this.x, this.y, this.w, this.h, "adjust");
1644
		p.draw_image(gr, this.case_img, this.x, this.y, this.w, this.h, "adjust");
1645
		if (this.img) {
1646
			this.ratio = Math.min(this.w / this.case_img.Width, this.h / this.case_img.Height);
1647
			this.nw = 488 * this.ratio;
1648
			this.nh = 476 * this.ratio;
1649
			this.nx = Math.round((this.w - (452 * this.ratio)) / 2);
1650
			this.ny = Math.round((this.h - this.nh) / 2);
1651
			p.draw_image(gr, this.img, this.nx + this.x, this.ny + this.y, this.nw, this.nh, "top");
1652
		}
1653
		p.draw_image(gr, this.semi_img, this.x, this.y, this.w, this.h, "adjust");
1654
		if (this.gloss) p.draw_image(gr, this.gloss_img, this.x, this.y, this.w, this.h, "adjust");
1655
	}
1656
	
1657
	this.metadb_changed = function() {
1658
		if (!p.metadb) return;
1659
		this.img && this.img.Dispose();
1660
		this.path = "";
1661
		this.img = utils.GetAlbumArtV2(p.metadb, 0);
1662
		window.Repaint();
1663
		utils.GetAlbumArtAsync(window.ID, p.metadb, 0);
1664
	}
1665
	
1666
	this.get_album_art_done = function(ip) {;
1667
		this.path = ip;
1668
	}
1669
	
1670
	this.trace = function(x, y) {
1671
		return (x > this.x && x < this.x + this.w && y > this.y && y < this.y + this.h);
1672
	}
1673
	
1674
	this.move = function(x, y) {
1675
		if (this.trace(x, y)) {
1676
			if (this.img) p.tt("Original size: " + this.img.Width + "x" + this.img.Height + "px");
1677
			return true;
1678
		} else {
1679
			p.ttd();
1680
			return false;
1681
		}
1682
	}
1683
	
1684
	this.lbtn_dblclk = function(x, y) {
1685
		if (!this.trace(x, y)) return false;
1686
		if (this.img) p.run("explorer /select,\"" + this.path + "\"");
1687
		return true;
1688
	}
1689
	
1690
	this.x = x;
1691
	this.y = y;
1692
	this.w = w;
1693
	this.h = h;
1694
	this.shadow_img = gdi.Image(p.images_path + "shadow.png");
1695
	this.case_img = gdi.Image(p.images_path + "case.png");
1696
	this.semi_img = gdi.Image(p.images_path + "semi.png");
1697
	this.gloss_img = gdi.Image(p.images_path + "gloss.png");
1698
	this.gloss = window.GetProperty("cd_gloss", false);
1699
	this.shadow = window.GetProperty("cd_shadow", false);
1700
	this.img = null;
1701
	this.path = null;
1702
}
1703
1704
function images(x, y, w, h) {
1705
	this.playback_time = function(time) {
1706
		if (this.mode == "last.fm" && time == 1 && this.files.length == 0 && p.metadb.RawPath == fb.GetNowPlaying().RawPath && ((this.auto_download == "library" && fb.IsMetadbInMediaLibrary(p.metadb)) || this.auto_download == "on")) this.download();
1707
		if (this.cycle > 0 && this.images.length > 1 && time % this.cycle == 0) {
1708
			this.index++;
1709
			if (this.index == this.images.length) this.index = 0;
1710
			window.RepaintRect(this.x, this.y, this.w, this.h);
1711
		}
1712
	}
1713
	
1714
	this.draw = function (gr) {
1715
		if (this.images.length == 0) return;
1716
		p.draw_image(gr, this.images[this.index], this.x, this.y, this.w, this.h, this.type);
1717
	}
1718
	
1719
	this.metadb_changed = function() {
1720
		if (!p.metadb) return false;
1721
		switch(this.mode) {
1722
			case "last.fm":
1723
				p.artist = p.eval(p.artist_tf);
1724
				if (this.artist == p.artist) return false;
1725
				this.artist = p.artist;
1726
				//this.folder = p.data_folder + p.clean_filename(p.artist);
1727
				//if (!p.fso.FolderExists(this.folder)) p.fso.CreateFolder(this.folder);
1728
				break;
1729
			case "custom":
1730
				this.temp_folder = p.eval(this.custom_folder_tf);
1731
				if (this.temp_folder == this.folder) return false;
1732
				this.folder = this.temp_folder;
1733
				break;
1734
		}
1735
		this.update();
1736
		return true;
1737
	}
1738
	
1739
	this.trace = function(x, y) {
1740
		return (x > this.x && x < this.x + this.w && y > this.y && y < this.y + this.h);
1741
	}
1742
	
1743
	this.wheel = function(step) {
1744
		if (!p.metadb || this.images.length < 2 || !this.trace(p.mx, p.my) || (typeof th == "object" && th.mode == "grid" && !th.overlay)) return false;
1745
		this.index -= step;
1746
		if (this.index < 0) this.index = this.images.length - 1;
1747
		if (this.index >= this.images.length) this.index = 0;
1748
		window.RepaintRect(this.x, this.y, this.w, this.h);
1749
		return true;
1750
	}
1751
	
1752
	this.lbtn_dblclk = function(x, y) {
1753
		if (!this.trace(x, y)) return false;
1754
		p.run("\"" + this.files[this.index] + "\"");
1755
		return true;
1756
	}
1757
	
1758
this.download = function()
1759
     {
1760
     //if (!p.fso.FolderExists(this.folder))  return;
1761
        {
1762
        
1763
       if (auto_yt=="1")
1764
        {
1765
        
1766
   if (p.artist.indexOf("3dydfy://")== 0 | p.artist.indexOf("www.youtube.com/")== 0 | p.artist.indexOf("youtube.com/")== 0 | p.artist.indexOf("http://www.youtube.com/")== 0 | p.artist.indexOf("3dydfy://www.youtube.com:80/")== 0 | p.artist.indexOf("www.youtube.com:80/")== 0 | p.artist.indexOf("youtube.com:80/")== 0 | p.artist.indexOf("http://www.youtube.com:80/")== 0)
1767-
   if (p.artist.indexOf("3dydfy://")== 0 | p.artist.indexOf("www.youtube.com/")== 0 | p.artist.indexOf("youtube.com/")== 0 | p.artist.indexOf("http://www.youtube.com/")== 0)
1767+
1768
    {
1769
        this.working=true;
1770
        if (p.artist == "" || p.artist == "?") return;
1771
        var folder = this.folder + "\\";
1772
		if (!this.xmlhttp) this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
1773
		this.xmlhttp.open("GET", "http://www.youtube.com/" + p.artist.replace("3dydfy://www.youtube.com/","").replace("3dydfy://youtube.com/","").replace("3dydfy://www.youtube.com:80/","").replace("www.youtube.com:80/","").replace("youtube.com:80/","").replace("http://www.youtube.com:80/","").replace("www.youtube.com/","").replace("youtube.com/","").replace("http://www.youtube.com/",""), true);
1774
		this.xmlhttp.send();
1775
		this.xmlhttp.onreadystatechange = function() {
1776
			if (im.xmlhttp.readyState == 4) {
1777
				if (im.xmlhttp.status == 200) {
1778
					var text = im.xmlhttp.responsetext;
1779
					if (!im.doc) im.doc = new ActiveXObject("htmlfile");
1780
					im.doc.open();
1781
					var div = im.doc.createElement("div");
1782
					div.innerHTML = text;
1783
					var data = div.getElementsByTagName("a");
1784
					var urls = [];
1785
    
1786
			
1787
1788
for (i = 0; i < data.length; i++) {
1789
    if (data[i].href.indexOf("about:/watch?v=") == 0) urls.push("http://www.youtube.com/" + data[i].href.replace(/about:\//,""));
1790
}
1791
1792
//select random URL
1793
var randomnumber = Math.floor(Math.random()*Math.max(urls.length-1))+1;
1794
i=randomnumber;
1795
1796
{
1797
1798
//do something with urls[i]
1799
p.console("" + urls[i]);
1800
1801
var tmppath = p.fso.GetFolder(fb.FoobarPath).ShortPath;
1802
p.run(tmppath+"\\foobar2000.exe /add "+"\ " + urls[i] + "\"");                   
1803
                    
1804
1805
}
1806
                im.doc.close();
1807
                im.working=false;
1808
				im.update();
1809
				window.NotifyOthers("images", "update");
1810
				} else {
1811
					p.console("HTTP error: " + im.xmlhttp.status);
1812
				}
1813
			}
1814
		}
1815
	}
1816
}
1817
}   
1818
}
1819
1820
1821
this.downloadALL = function()
1822
     {
1823
     //if (!p.fso.FolderExists(this.folder))  return;
1824
        {
1825
        
1826
       
1827
        {
1828
        
1829
   if (p.artist.indexOf("3dydfy://")== 0 | p.artist.indexOf("www.youtube.com/")== 0 | p.artist.indexOf("youtube.com/")== 0 | p.artist.indexOf("http://www.youtube.com/")== 0 | p.artist.indexOf("3dydfy://www.youtube.com:80/")== 0 | p.artist.indexOf("www.youtube.com:80/")== 0 | p.artist.indexOf("youtube.com:80/")== 0 | p.artist.indexOf("http://www.youtube.com:80/")== 0)
1830-
   if (p.artist.indexOf("3dydfy://")== 0 | p.artist.indexOf("www.youtube.com/")== 0 | p.artist.indexOf("youtube.com/")== 0 | p.artist.indexOf("http://www.youtube.com/")== 0)
1830+
1831
    {
1832
        this.working=true;
1833
        if (p.artist == "" || p.artist == "?") return;
1834
        var folder = this.folder + "\\";
1835
		if (!this.xmlhttp) this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
1836
		this.xmlhttp.open("GET", "http://www.youtube.com/" + p.artist.replace("3dydfy://www.youtube.com/","").replace("3dydfy://youtube.com/","").replace("3dydfy://www.youtube.com:80/","").replace("www.youtube.com:80/","").replace("youtube.com:80/","").replace("http://www.youtube.com:80/","").replace("www.youtube.com/","").replace("youtube.com/","").replace("http://www.youtube.com/",""), true);
1837
		this.xmlhttp.send();
1838
		this.xmlhttp.onreadystatechange = function() {
1839
			if (im.xmlhttp.readyState == 4) {
1840
				if (im.xmlhttp.status == 200) {
1841
					var text = im.xmlhttp.responsetext;
1842
					if (!im.doc) im.doc = new ActiveXObject("htmlfile");
1843
					im.doc.open();
1844
					var div = im.doc.createElement("div");
1845
					div.innerHTML = text;
1846
					var data = div.getElementsByTagName("a");
1847
					var urls = [];
1848
    
1849
			
1850
1851
for (i = 0; i < data.length; i++) {
1852
    if (data[i].href.indexOf("about:/watch?v=") == 0) urls.push("http://www.youtube.com/" + data[i].href.replace(/about:\//,""));
1853
}
1854
1855
for (i = 0; i < urls.length; i++) {
1856
1857
//do something with urls[i]
1858
p.console("" + urls[i]);
1859
1860
var tmppath = p.fso.GetFolder(fb.FoobarPath).ShortPath;
1861
p.run(tmppath+"\\foobar2000.exe /add "+"\ " + urls[i] + "\"");                   
1862
                    
1863
1864
}
1865
                im.doc.close();
1866
                im.working=false;
1867
				im.update();
1868
				window.NotifyOthers("images", "update");
1869
				} else {
1870
					p.console("HTTP error: " + im.xmlhttp.status);
1871
				}
1872
			}
1873
		}
1874
	}
1875
}
1876
}   
1877
}
1878
1879
1880
this.downloadONE = function()
1881
     {
1882
     //if (!p.fso.FolderExists(this.folder))  return;
1883
        {
1884
        
1885
       
1886
        {
1887
        
1888
   if (p.artist.indexOf("3dydfy://")== 0 | p.artist.indexOf("www.youtube.com/")== 0 | p.artist.indexOf("youtube.com/")== 0 | p.artist.indexOf("http://www.youtube.com/")== 0 | p.artist.indexOf("3dydfy://www.youtube.com:80/")== 0 | p.artist.indexOf("www.youtube.com:80/")== 0 | p.artist.indexOf("youtube.com:80/")== 0 | p.artist.indexOf("http://www.youtube.com:80/")== 0)
1889-
   if (p.artist.indexOf("3dydfy://")== 0 | p.artist.indexOf("www.youtube.com/")== 0 | p.artist.indexOf("youtube.com/")== 0 | p.artist.indexOf("http://www.youtube.com/")== 0)
1889+
1890
    {
1891
        this.working=true;
1892
        if (p.artist == "" || p.artist == "?") return;
1893
        var folder = this.folder + "\\";
1894
		if (!this.xmlhttp) this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
1895
		this.xmlhttp.open("GET", "http://www.youtube.com/" + p.artist.replace("3dydfy://www.youtube.com/","").replace("3dydfy://youtube.com/","").replace("3dydfy://www.youtube.com:80/","").replace("www.youtube.com:80/","").replace("youtube.com:80/","").replace("http://www.youtube.com:80/","").replace("www.youtube.com/","").replace("youtube.com/","").replace("http://www.youtube.com/",""), true);
1896
		this.xmlhttp.send();
1897
		this.xmlhttp.onreadystatechange = function() {
1898
			if (im.xmlhttp.readyState == 4) {
1899
				if (im.xmlhttp.status == 200) {
1900
					var text = im.xmlhttp.responsetext;
1901
					if (!im.doc) im.doc = new ActiveXObject("htmlfile");
1902
					im.doc.open();
1903
					var div = im.doc.createElement("div");
1904
					div.innerHTML = text;
1905
					var data = div.getElementsByTagName("a");
1906
					var urls = [];
1907
    
1908
			
1909
1910
for (i = 0; i < data.length; i++) {
1911
    if (data[i].href.indexOf("about:/watch?v=") == 0) urls.push("http://www.youtube.com/" + data[i].href.replace(/about:\//,""));
1912
}
1913
1914
//select random URL
1915
var randomnumber = Math.floor(Math.random()*Math.max(urls.length-1))+1;
1916
i=randomnumber;
1917
1918
{
1919
1920
//do something with urls[i]
1921
p.console("" + urls[i]);
1922
1923
var tmppath = p.fso.GetFolder(fb.FoobarPath).ShortPath;
1924
p.run(tmppath+"\\foobar2000.exe /add "+"\ " + urls[i] + "\"");                   
1925
                    
1926
1927
}
1928
                im.doc.close();
1929
                im.working=false;
1930
				im.update();
1931
				window.NotifyOthers("images", "update");
1932
				} else {
1933
					p.console("HTTP error: " + im.xmlhttp.status);
1934
				}
1935
			}
1936
		}
1937
	}
1938
}
1939
}   
1940
}
1941
1942
1943
this.downloadART_TITLE = function()
1944
     {
1945
   
1946
        {
1947
        
1948
        
1949
        {
1950
        
1951
  
1952
    
1953
    {
1954
        this.working=true;
1955
        p.artist = p.eval("%artist% %title%");
1956
        if (p.artist == "" || p.artist == "?") return;
1957
        var folder = this.folder + "\\";
1958
		if (!this.xmlhttp) this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
1959
		this.xmlhttp.open("GET", "http://www.youtube.com/results?search_query=" + encodeURIComponent(p.artist), true);
1960
		this.xmlhttp.send();
1961
		this.xmlhttp.onreadystatechange = function() {
1962
			if (im.xmlhttp.readyState == 4) {
1963
				if (im.xmlhttp.status == 200) {
1964
					var text = im.xmlhttp.responsetext;
1965
					if (!im.doc) im.doc = new ActiveXObject("htmlfile");
1966
					im.doc.open();
1967
					var div = im.doc.createElement("li");
1968
					div.innerHTML = text;
1969
					var data = div.getElementsByTagName("a");
1970
					var urls = [];
1971
    
1972
			
1973
1974
for (i = 0; i < data.length; i++) {
1975
    if (data[i].href.indexOf("about:/watch?v=") == 0) urls.push("http://www.youtube.com/" + data[i].href.replace(/about:\//,""));
1976
}
1977
1978
//select random URL
1979
//var randomnumber = Math.floor(Math.random()*Math.max(urls.length-1))+1;
1980
//i=randomnumber;
1981
//i = Math.min(urls.length-38);
1982
i=1;
1983
{
1984
1985
//do something with urls[i]
1986
p.console("" + urls[i]);
1987
1988
var tmppath = p.fso.GetFolder(fb.FoobarPath).ShortPath;
1989
p.run(tmppath+"\\foobar2000.exe /add "+"\ " + urls[i] + "\"");                   
1990
                    
1991
1992
}
1993
        
1994
                 
1995
             
1996
            
1997
             
1998
//open YT in playlist
1999
//var tmppath = p.fso.GetFolder(fb.FoobarPath).ShortPath;
2000
//p.run(tmppath+"\\foobar2000.exe /immediate /add "+"\""+urls[i] + "\"");
2001
//fb.RunMainMenuCommand("File/Add Youtube URL(s)...") + ("/immediate /add "+"\""+ urls[i]);                       
2002
2003
2004
                im.doc.close();
2005
                im.working=false;
2006
				im.update();
2007
				window.NotifyOthers("images", "update");
2008
				} else {
2009
					p.console("HTTP error: " + im.xmlhttp.status);
2010
				}
2011
			}
2012
		}
2013
	}
2014
}}}
2015
2016
    
2017
    
2018
    
2019
this.downloadART = function()
2020
     {
2021
   
2022
        {
2023
        
2024
        
2025
        {
2026
        
2027
  
2028
    
2029
    {
2030
        this.working=true;
2031
        p.artist = p.eval("%artist%");
2032
        if (p.artist == "" || p.artist == "?") return;
2033
        var folder = this.folder + "\\";
2034
		if (!this.xmlhttp) this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
2035
		this.xmlhttp.open("GET", "http://www.youtube.com/results?search_query=" + encodeURIComponent(p.artist), true);
2036
		this.xmlhttp.send();
2037
		this.xmlhttp.onreadystatechange = function() {
2038
			if (im.xmlhttp.readyState == 4) {
2039
				if (im.xmlhttp.status == 200) {
2040
					var text = im.xmlhttp.responsetext;
2041
					if (!im.doc) im.doc = new ActiveXObject("htmlfile");
2042
					im.doc.open();
2043
					var div = im.doc.createElement("li");
2044
					div.innerHTML = text;
2045
					var data = div.getElementsByTagName("a");
2046
					var urls = [];
2047
    
2048
			
2049
2050
for (i = 0; i < data.length; i++) {
2051
    if (data[i].href.indexOf("about:/watch?v=") == 0) urls.push("http://www.youtube.com/" + data[i].href.replace(/about:\//,""));
2052
}
2053
2054
//select random URL
2055
var randomnumber = Math.floor(Math.random()*Math.max(urls.length-1))+1;
2056
i=randomnumber;
2057
//i = Math.min(urls.length-38);
2058
2059
{
2060
2061
//do something with urls[i]
2062
p.console("HTTP: " + urls[i]);
2063
2064
var tmppath = p.fso.GetFolder(fb.FoobarPath).ShortPath;
2065
p.run(tmppath+"\\foobar2000.exe /add "+"\ " + urls[i] + "\"");                   
2066
                    
2067
2068
}
2069
        
2070
                 
2071
             
2072
            
2073
             
2074
//open YT in playlist
2075
//var tmppath = p.fso.GetFolder(fb.FoobarPath).ShortPath;
2076
//p.run(tmppath+"\\foobar2000.exe /immediate /add "+"\""+urls[i] + "\"");
2077
//fb.RunMainMenuCommand("File/Add Youtube URL(s)...") + ("/immediate /add "+"\""+ urls[i]);                       
2078
2079
2080
                im.doc.close();
2081
                im.working=false;
2082
				im.update();
2083
				window.NotifyOthers("images", "update");
2084
				} else {
2085
					p.console("HTTP error: " + im.xmlhttp.status);
2086
				}
2087
			}
2088
		}
2089
	}
2090
}
2091
}}  
2092
2093
2094
2095
2096
2097
this.update0 = function() {
2098
		this.index = 0;
2099
		for (i = 0; i < this.images.length; i++) {
2100
			try { this.images[i].Dispose(); } catch(e) {}
2101
		}
2102
		this.folders = this.folder.split("|");
2103
		this.files = [];
2104
		for (i = 0; i < this.folders.length; i++) {
2105
			if (p.fso.FolderExists(this.folders[i])) this.files = this.files.concat(utils.Glob(this.folders[i] + "\\" + p.clean_filename(p.artist) + "_0" + "*.jpg").toArray(), utils.Glob(this.folders[i] + "\\" + p.clean_filename(p.artist) + "_0" + "*.jpeg").toArray(), utils.Glob(this.folders[i] + "\\" + p.clean_filename(p.artist) + "_0" + "*.png").toArray(), utils.Glob(this.folders[i] + "\\" + p.clean_filename(p.artist) + "_0" + "*.gif").toArray());
2106
		}
2107
		this.images = [];
2108
		for (i = 0; i < this.files.length; i++) {
2109
			this.images[i] = gdi.Image(this.files[i]);
2110
		}
2111
		if (typeof th == "object") {
2112
			th.nc = true;
2113
			th.calc();
2114
		}
2115
		window.Repaint();
2116
	}  
2117
    
2118
    
2119
    
2120
	this.update = function() {
2121
		this.index = 0;
2122
		for (i = 0; i < this.images.length; i++) {
2123
			try { this.images[i].Dispose(); } catch(e) {}
2124
		}
2125
		this.folders = this.folder.split("|");
2126
		this.files = [];
2127
		for (i = 0; i < this.folders.length; i++) {
2128
			if (p.fso.FolderExists(this.folders[i])) this.files = this.files.concat(utils.Glob(this.folders[i] + "\\*.jpg").toArray(), utils.Glob(this.folders[i] + "\\*.jpeg").toArray(), utils.Glob(this.folders[i] + "\\*.png").toArray(), utils.Glob(this.folders[i] + "\\*.gif").toArray());
2129
		}
2130
2131
		this.images = [];
2132
		for (i = 0; i < this.files.length; i++) {
2133
			this.images[i] = gdi.Image(this.files[i]);
2134
		}
2135
		if (typeof th == "object") {
2136
			th.nc = true;
2137
			th.calc();
2138
		}
2139
		window.Repaint();
2140
	}
2141
	
2142
	this.delete_image = function() {
2143
		if (!this.app) this.app = new ActiveXObject("Shell.Application");
2144
		this.app.Namespace(10).MoveHere(this.files[this.index]);
2145
        window.SetTimeout(function() {
2146
			im.update();
2147
			window.NotifyOthers("images", "update");
2148
		}, 100);
2149
	}
2150
	
2151
	this.x = x;
2152
	this.y = y;
2153
	this.w = w;
2154
	this.h = h;
2155
	this.files = [];
2156
	this.images = [];
2157
	this.index = 0;
2158
	this.artist = "";
2159
	this.folder = "";
2160
	this.limit = 0;
2161
	//this.cycle = window.GetProperty("image_cycle", 0);
2162
	this.mode = ("last.fm");
2163
    //window.GetProperty("image_mode", "last.fm");
2164
	this.type = "adjust";
2165
	this.auto_download = "off";
2166
	this.custom_folder_tf = "$directory_path(%path%)";
2167
}
2168
2169
function lastfm() {
2170
	this.notify_data = function(name, data) {
2171
		if (name == "lastfm" && data == "update") {
2172
			this.username = p.open(this.username_file).trim();
2173
			this.sk = p.open(this.sk_file).trim();
2174
			if (p.check_feature("lastfm_charts")) li.update();
2175
			if (typeof ps == "object") {
2176
				ps.loved_working = false;
2177
				ps.playcount_working = false;
2178
				b.update();
2179
				on_item_focus_change();
2180
			}
2181
			if (p.check_feature("lastfm")) {
2182
				li.artist = "";
2183
				on_item_focus_change();
2184
			}
2185
			if (p.check_feature("lastfm_album")) {
2186
				t.artist = "";
2187
				t.album = "";
2188
				on_item_focus_change();
2189
			}
2190
			window.Repaint();
2191
		}
2192
	}
2193
	
2194
	this.post = function(method, metadb) {
2195
		if (!this.xmlhttp) this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
2196
		switch(method) {
2197
			case "auth.getMobileSession":
2198
				var func = function() {
2199
					var json_data = p.json_parse(l.xmlhttp.responsetext);
2200
					if (!json_data) return;
2201
					if (json_data.error) {
2202
						p.MsgBox(json_data.message, 0, p.name);
2203
					} else if (json_data.session) {
2204
						p.save(json_data.session.key, l.sk_file);
2205
						window.NotifyOthers("lastfm", "update");
2206
						l.notify_data("lastfm", "update");
2207
					}
2208
				}
2209
				
2210
				this.authToken = hex_md5(this.username + hex_md5(this.password));
2211
				this.api_sig = hex_md5("api_key" + this.api_key + "authToken" + this.authToken + "method" + method + "username" + this.username + this.secret);
2212
				this.data = "method=" + method + "&api_key=" + this.api_key + "&api_sig=" + this.api_sig + "&format=json&authToken=" + this.authToken + "&username=" + this.username;
2213
				break;
2214
			case "track.love":
2215
			case "track.unlove":
2216
				var func = function() {
2217
					var json_data = p.json_parse(l.xmlhttp.responsetext);
2218
					if (!json_data) return;
2219
					if (json_data.error) {
2220
						p.console(json_data.message);
2221
					} else if (json_data.status && json_data.status == "ok") {
2222
						p.console("Track " + (method == "track.love" ? "loved successfully." : "unloved successfully."));
2223
						fb.RunContextCommandWithMetadb("Customdb Love " + (method == "track.love" ? 1 : 0), metadb, 8);
2224
					}
2225
				}
2226
				
2227
				if (!metadb || this.username.length == 0 || this.sk.length != 32) return;
2228
				this.artist = fb.TitleFormat(p.artist_tf).EvalWithMetadb(metadb);
2229
				this.track = fb.TitleFormat("%title%").EvalWithMetadb(metadb);
2230
				if (this.artist == "" || this.artist == "?" || this.track == "?") return;
2231
				p.console("Attempting to " + (method == "track.love" ? "love \"" : "unlove \"") + this.track + "\" by \"" + this.artist + "\"");
2232
				p.console("Contacting Last.fm....");
2233
				this.api_sig = hex_md5("api_key" + this.api_key + "artist" + this.artist + "method" + method + "sk" + this.sk + "track" + this.track + this.secret);
2234
				this.data = "method=" + method + "&api_key=" + this.api_key + "&api_sig=" + this.api_sig + "&format=json&sk=" + this.sk + "&artist=" + encodeURIComponent(this.artist) + "&track=" + encodeURIComponent(this.track);
2235
				break;
2236
			default:
2237
				return;
2238
		}
2239
		
2240
		this.xmlhttp.open("POST", "https://ws.audioscrobbler.com/2.0/", true);
2241
		this.xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
2242
		this.xmlhttp.setRequestHeader("User-Agent", this.user_agent);
2243
		this.xmlhttp.send(this.data);
2244
		this.xmlhttp.onreadystatechange = function() {
2245
			if (l.xmlhttp.readyState == 4) {
2246
				if (l.xmlhttp.status == 200) {
2247
					func();
2248
				} else {
2249
					p.console(l.xmlhttp.responsetext || "HTTP error: " + l.xmlhttp.status);
2250
				}
2251
			}
2252
		}
2253
	}
2254
	
2255
	this.update_username = function() {
2256
		var old_username = this.username;
2257
		this.username = p.InputBox("Enter your Last.fm username.", p.name, this.username);
2258
		if (this.username.length > 0 && this.username != old_username) p.save("", this.sk_file);
2259
		p.save(this.username, this.username_file);
2260
		window.NotifyOthers("lastfm", "update");
2261
		this.notify_data("lastfm", "update");
2262
	}
2263
	
2264
	this.update_password = function() {
2265
		this.password = p.InputBox("Enter your Last.fm password\n\nThis is only required to love/unlove tracks.", p.name, "");
2266
		if (this.password.length > 0) {
2267
			this.sk = "";
2268
			p.save(this.sk, this.sk_file);
2269
			window.NotifyOthers("lastfm", "update");
2270
			this.notify_data("lastfm", "update");
2271
			this.post("auth.getMobileSession");
2272
		}
2273
	}
2274
	
2275
	this.get_url = function() {
2276
		return "http://ws.audioscrobbler.com/2.0/?format=json&api_key=" + this.api_key + "&user=" + this.username + "&username=" + this.username + "&s=" + Math.random();
2277
	}
2278
	
2279
	this.username_error = "Use the right click menu to set your Last.fm username.";
2280
	this.password_error = "Use the right click menu to set your Last.fm password.";
2281
	this.url = "http://www.last.fm/";
2282
	this.api_key = "56d9e050cc2d6b36102c8b4a5fe6152d";
2283
	this.secret = "9f1f4346ce3ba206390074ff8cb4c6ce";
2284
	this.user_agent = "foobar2000_wsh_panel_mod_scripts";
2285
	this.username_file = p.settings_folder + "username";
2286
	this.username = p.open(this.username_file).trim();
2287
	this.sk_file = p.settings_folder + "sk";
2288
	this.sk = p.open(this.sk_file).trim();
2289
	this.auto_correct = window.GetProperty("lastfm_auto_correct", true);
2290
}
2291
2292
function list(x, y, w, h) {
2293
	this.size = function() {
2294
		this.row_height = this.mode == "echonest" ? 90 : 20;
2295
		this.rows = Math.floor((this.h - (this.mode == "echonest" ? 50 : 30)) / this.row_height);
2296
		this.index = 0;
2297
		this.offset = 0;
2298
		switch(true) {
2299
			case this.mode == "lastfm_charts":
2300
				this.text_width = Math.round(this.w / 3);
2301
				this.lastfm_charts_bar_x = this.text_width + 30;
2302
				break;
2303
			case this.mode == "musicbrainz" && this.musicbrainz_mode == "releases":
2304
				this.text_width = this.w - 120;
2305
				break;
2306
			default:
2307
				this.text_width = this.w - 50;
2308
				break;
2309
		}
2310
		this.but_x = this.x + Math.round((this.w - 15) / 2);
2311
		this.up_btn = new sb(this.but_x, this.y, 15, 15, p.up_img, "li.offset > 0", function() { li.wheel(1); });
2312
		this.down_btn = new sb(this.but_x, this.y + this.h - 15, 15, 15, p.down_img, "li.offset < li.items - li.rows", function() { li.wheel(-1); });
2313
	}
2314
	
2315
	this.draw = function(gr) {
2316
		switch(this.mode) {
2317
			case "discogs":
2318
				for (i = 0; i < Math.min(this.items, this.rows); i++) {
2319
					p.left_text(gr, this.names[i + this.offset], p.list_font, p.textcolour, this.x + this.text_x, this.y + 15 + (i * this.row_height), this.text_width, 20);
2320
					p.right_text(gr, this.dates[i + this.offset], p.list_font, p.textcolour_hl, this.x, this.y + 15 + (i * this.row_height), this.w, 20);
2321
				}
2322
				break;
2323
			case "lastfm_charts":
2324
				var max_bar_width = (this.w - this.lastfm_charts_bar_x - 40) / this.playcounts[0];
2325
				for (i = 0; i < Math.min(this.items, this.rows); i++) {
2326
					p.right_text(gr, this.ranks[i + this.offset] + ".", p.list_font, p.textcolour_hl, this.x, this.y + 15 + (i * this.row_height), 17, 20);
2327
					var bar_width = max_bar_width * this.playcounts[i + this.offset];
2328
					var bar_colour = p.splitRGB(this.lastfm_charts_bar_colour);
2329
					gr.FillSolidRect(this.lastfm_charts_bar_x + this.x, this.y + 16 + (i * this.row_height), bar_width, 18, bar_colour);
2330
					p.left_text(gr, this.playcounts[i + this.offset].addCommas(), p.list_font, p.textcolour, this.x + 5 + this.lastfm_charts_bar_x + bar_width, this.y + 15 + (i * this.row_height), 50, 20);
2331
					p.left_text(gr, this.names[i + this.offset], p.list_font, p.textcolour, this.x + this.text_x, this.y + 15 + (i * this.row_height), this.text_width, 20);
2332
				}
2333
				break;
2334
			case "lastfm":
2335
				for (i = 0; i < Math.min(this.items, this.rows); i++) {
2336
					if (this.lastfm_mode == 0) p.draw_image(gr, this.lastfm_button == "spotify" ? this.lastfm_spotify_img : this.autoplaylist_img, this.x, this.y + 16 + (i * this.row_height), 16, 16, "adjust");
2337
					if (this.lastfm_mode == 1 || this.lastfm_mode == 3 || this.lastfm_mode == 4) p.draw_image(gr, this.autoplaylist_img, this.x, this.y + 16 + (i * this.row_height), 16, 16, "adjust");
2338
					p.left_text(gr, this.names[i + this.offset], p.list_font, p.textcolour, this.x + this.text_x, this.y + 15 + (i * this.row_height), this.text_width, 20);
2339
				}
2340
				break;
2341
			case "musicbrainz":
2342
				for (i = 0; i < Math.min(this.items, this.rows); i++) {
2343
					if (this.musicbrainz_mode == "URLs") p.draw_image(gr, this.musicbrainz_images[this.images[i + this.offset]], this.x, this.y + 16 + (i * this.row_height), 16, 16, "adjust");
2344
					if (this.musicbrainz_mode == "releases") {
2345
						p.draw_image(gr, this.autoplaylist_img, this.x, this.y + 16 + (i * this.row_height), 16, 16, "adjust");
2346
						if (this.musicbrainz_show_release_type) p.right_text(gr, this.release_types[i + this.offset], p.list_font, p.textcolour, this.x, this.y + 15 + (i * this.row_height), this.w - 30, 20);
2347
						p.right_text(gr, this.dates[i + this.offset], p.list_font, p.textcolour_hl, this.x, this.y + 15 + (i * this.row_height), this.w, 20);
2348
					}
2349
					p.left_text(gr, this.names[i + this.offset], p.list_font, p.textcolour, this.x + this.text_x, this.y + 15 + (i * this.row_height), this.text_width, 20);
2350
				}
2351
				break;
2352
			case "autoplaylists":
2353
				for (i = 0; i < Math.min(this.items, this.rows); i++) {
2354
					p.left_text(gr, this.names[i + this.offset], p.list_font, p.textcolour, this.x, this.y + 15 + (i * this.row_height), this.text_width, 20);
2355
					if (!this.autoplaylists_editing && this.autoplaylists_hover && this.index == i + this.offset) {
2356
						p.draw_image(gr, this.autoplaylists_edit_img, this.x + this.w - 40, this.y + 16 + (i * this.row_height), 16, 16, "adjust");
2357
						p.draw_image(gr, this.autoplaylists_del_img, this.x + this.w - 20, this.y + 16 + (i * this.row_height), 16, 16, "adjust");
2358
					}
2359
				}
2360
				break;
2361
			case "echonest":
2362
				for (i = 0; i < Math.min(this.items, this.rows); i++) {
2363
					p.left_text(gr, this.names[i + this.offset], p.title_font, p.textcolour_hl, this.x, this.y + 15 + (i * this.row_height), this.w - 110, 24);
2364
					p.right_text(gr, this.dates[i + this.offset], p.title_font, p.textcolour_hl, this.x, this.y + 15 + (i * this.row_height), this.w, 24);
2365
					gr.GdiDrawText(this.summaries[i + this.offset], p.normal_font, p.textcolour, this.x, this.y + 37 + (i * this.row_height), this.w, p.normal_font.Height * Math.floor(64 / p.normal_font.Height), DT_WORDBREAK | DT_CALCRECT | DT_NOPREFIX);
2366
				}
2367
				break;
2368
		}
2369
		this.up_btn.draw(gr);
2370
		this.down_btn.draw(gr);
2371
		if (this.show_timestamp) p.left_text(gr, this.date, p.list_font, p.textcolour_hl, this.x, this.y + this.h - 15, this.w, 15);
2372
	}
2373
	
2374
	this.metadb_changed = function() {
2375
		p.artist = p.eval(p.artist_tf);
2376
		if (this.artist == p.artist) return false;
2377
		this.artist = p.artist;
2378
		this.folder = p.data_folder + p.artist_tf;
2379
		//if (!p.fso.FolderExists(this.folder)) p.fso.CreateFolder(this.folder);
2380
		this.update();
2381
		return true;
2382
	}
2383
	
2384
	this.trace = function(x, y) {
2385
		return (x > this.x && x < this.x + this.w && y > this.y && y < this.y + this.h);
2386
	}
2387
	
2388
	this.wheel = function(step) {
2389
		if (!this.trace(p.mx, p.my)) return false;
2390
		if (this.items > this.rows) {
2391
			this.offset -= step * (this.mode == "echonest" ? 1 : 3);
2392
			if (this.offset < 0) this.offset = 0;
2393
			if (this.rows + this.offset > this.items) this.offset = this.items - this.rows;
2394
			window.RepaintRect(this.x, this.y, this.w, this.h);
2395
		}
2396
		return true;
2397
	}
2398
	
2399
	this.move = function(x, y) {
2400
		this.index = Math.floor((y - this.y - 15) / this.row_height) + this.offset;
2401
		this.in_range = this.index >= this.offset && this.index < this.offset + Math.min(this.rows, this.items);
2402
		switch(true) {
2403
			case !this.trace(x, y):
2404
			case this.mode == "autoplaylists" && this.autoplaylists_editing:
2405
			case this.mode == "lastfm" && l.username.length == 0:
2406
				window.SetCursor(IDC_ARROW);
2407
				this.leave();
2408
				return false;
2409
			case this.up_btn.trace(x, y):
2410
			case this.down_btn.trace(x, y):
2411
				window.SetCursor(IDC_HAND);
2412
				break;
2413
			case !this.in_range:
2414
				window.SetCursor(IDC_ARROW);
2415
				this.leave();
2416
				break;
2417
			case this.mode == "musicbrainz" && this.musicbrainz_mode == "releases" && x > this.x && x < this.x + 20:
2418
			case this.mode == "lastfm" && this.text_x == 20 && x > this.x && x < this.x + 20:
2419
				window.SetCursor(IDC_HAND);
2420
				switch(true) {
2421
					case this.lastfm_mode == 0 && this.lastfm_button == "spotify":
2422
						p.tt('spotify:search:"' + this.names[this.index].replace(/\s+/g, "+") + '"');
2423
						break;
2424
					default:
2425
						p.tt("Autoplaylist: " + this.queries[this.index]);
2426
						break;
2427
				}
2428
				break;
2429
			case this.mode == "autoplaylists":
2430
				switch(true) {
2431
					case x > this.x && x < this.x + Math.min(this.names_widths[this.index], this.text_width):
2432
						window.SetCursor(IDC_HAND);
2433
						p.tt('Run "' + this.names[this.index] + '"');
2434
						break;
2435
					case x > this.x + this.w - 40 && x < this.x + this.w - 20:
2436
						window.SetCursor(IDC_HAND);
2437
						p.tt('Edit "' + this.names[this.index] + '"');
2438
						break;
2439
					case x > this.x + this.w - 20 && x < this.x + this.w:
2440
						window.SetCursor(IDC_HAND);
2441
						p.tt('Delete "' + this.names[this.index] + '"');
2442
						break;
2443
					default:
2444
						window.SetCursor(IDC_ARROW);
2445
						this.leave();
2446
						break;
2447
				}
2448
				this.autoplaylists_hover = true;
2449
				window.RepaintRect(this.x + this.w - 40, this.y + 15, 40, Math.min(this.rows, this.items) * this.row_height);
2450
				break;
2451
			case this.mode == "echonest":
2452
			case x > this.x + this.text_x && x < this.x + this.text_x + Math.min(this.names_widths[this.index], this.text_width):
2453
				window.SetCursor(IDC_HAND);
2454
				p.tt(this.urls[this.index]);
2455
				break;
2456
			default:
2457
				window.SetCursor(IDC_ARROW);
2458
				p.ttd();
2459
				break;
2460
		}
2461
		return true;
2462
	}
2463
	
2464
	this.lbtn_up = function(x, y) {
2465
		switch(true) {
2466
			case !this.trace(x, y):
2467
				return false;
2468
			case this.mode == "autoplaylists" && this.autoplaylists_editing:
2469
			case this.mode == "lastfm" && l.username.length == 0:
2470
			case this.up_btn.lbtn_up(x, y):
2471
			case this.down_btn.lbtn_up(x, y):
2472
			case !this.in_range:
2473
				break;
2474
			case this.mode == "musicbrainz" && this.musicbrainz_mode == "releases" && x > this.x && x < this.x + 20:
2475
			case this.mode == "lastfm" && this.text_x == 20 && x > this.x && x < this.x + 20:
2476
				switch(true) {
2477
					case this.lastfm_mode == 0 && this.lastfm_button == "spotify":
2478
						if (p.run('spotify:search:"' + this.names[this.index].replace(/\s+/g, "+") + '"')) {
2479
							if (fb.IsPlaying && !fb.IsPaused && this.lastfm_pause) fb.Pause();
2480
						} else {
2481
							p.MsgBox("Unable to launch Spotify.", 0, p.name);
2482
						}
2483
						break;
2484
					default:
2485
						fb.CreateAutoPlaylist(fb.PlaylistCount, this.names[this.index], this.queries[this.index]);
2486
						fb.ActivePlaylist = fb.PlaylistCount - 1;
2487
						break;
2488
				}
2489
				break;
2490
			case this.mode == "autoplaylists":
2491
				switch(true) {
2492
					case x > this.x && x < this.x + Math.min(this.names_widths[this.index], this.text_width):
2493
						this.autoplaylists_run(this.names[this.index], this.queries[this.index], this.sorts[this.index], this.forced[this.index]);
2494
						break;
2495
					case x > this.x + this.w - 40 && x < this.x + this.w - 20:
2496
						this.autoplaylists_edit(x, y);
2497
						break;
2498
					case x > this.x + this.w - 20 && x < this.x + this.w:
2499
						this.autoplaylists_delete();
2500
						break
2501
				}
2502
				break;
2503
			case this.mode == "echonest":
2504
			case x > this.x + this.text_x && x < this.x + this.text_x + Math.min(this.names_widths[this.index], this.text_width):
2505
				p.browser(this.urls[this.index]);
2506
				break;
2507
		}
2508
		return true;
2509
	}
2510
	
2511
	this.leave = function() {
2512
		p.ttd();
2513
		if (this.mode != "autoplaylists") return;
2514
		this.autoplaylists_hover = false;
2515
		window.RepaintRect(this.x, this.y, this.w, this.h);
2516
	}
2517
	
2518
	this.update = function() {
2519
		this.items = 0;
2520
		this.offset = 0;
2521
		this.index = 0;
2522
		this.names = [];
2523
		this.names_widths = [];
2524
		this.urls = [];
2525
		this.dates = [];
2526
		this.queries = [];
2527
		this.ranks = [];
2528
		this.playcounts = [];
2529
		this.sorts = [];
2530
		this.summaries = [];
2531
		this.release_types = [];
2532
		this.images = [];
2533
		this.forced = [];
2534
		this.data = [];
2535
		this.file = null;
2536
		this.date = "";
2537
		var temp_bmp = gdi.CreateImage(1, 1);
2538
		var temp_gr = temp_bmp.GetGraphics();
2539
		switch(this.mode) {
2540
			case "autoplaylists":
2541
				this.text = p.open(this.filename);
2542
				this.data = this.text.split(/\r?\n/g);
2543
				this.items = this.data.length;
2544
				for (i = 0; i < this.items; i++) {
2545
					var temp = this.data[i].split("¬");
2546
					this.names[i] = temp[0];
2547
					this.queries[i] = temp[1];
2548
					this.sorts[i] = temp[2];
2549
					this.forced[i] = temp[3];
2550
					this.names_widths[i] = temp_gr.CalcTextWidth(this.names[i], p.list_font);
2551
				}
2552
				break;
2553
			case "lastfm":
2554
				this.text_x = 20;
2555
				this.filename = this.folder + "\\" + this.lastfm_methods[this.lastfm_mode] + ".json";
2556
				if (p.fso.fileExists(this.filename)) {
2557
					this.file = p.fso.Getfile(this.filename);
2558
					this.json_text = p.open(this.filename);
2559
					this.json_data = p.json_parse(this.json_text);
2560
					if (this.json_data) {
2561
						switch(true) {
2562
							case this.json_data.error > 0:
2563
								p.console(this.json_data.message);
2564
								break;
2565
							case this.lastfm_mode == 0 && this.json_data.similarartists && typeof this.json_data.similarartists.artist == "object":
2566
								this.data = this.json_data.similarartists.artist;
2567
								break;
2568
							case this.lastfm_mode == 1 && this.json_data.toptags && typeof this.json_data.toptags.tag == "object":
2569
								this.data = this.json_data.toptags.tag;
2570
								break;
2571
							case this.lastfm_mode == 2 && this.json_data.topfans && typeof this.json_data.topfans.user == "object":
2572
								this.text_x = 0;
2573
								this.data = this.json_data.topfans.user;
2574
								break;
2575
							case this.lastfm_mode == 3 && this.json_data.topalbums && typeof this.json_data.topalbums.album == "object":
2576
								this.data = this.json_data.topalbums.album;
2577
								break;
2578
							case this.lastfm_mode == 4 && this.json_data.toptracks && typeof this.json_data.toptracks.track == "object":
2579
								this.data = this.json_data.toptracks.track;
2580
								break;
2581
						}
2582
						this.items = this.data.length;
2583
						for (i = 0; i < this.items; i++) {
2584
							this.names[i] = this.data[i].name;
2585
							this.urls[i] = this.data[i].url;
2586
							this.names_widths[i] = temp_gr.CalcTextWidth(this.names[i], p.list_font);
2587
							if (this.lastfm_mode == 0) this.queries[i] = "artist HAS " + this.names[i];
2588
							if (this.lastfm_mode == 1) this.queries[i] = "genre HAS " + this.names[i];
2589
							if (this.lastfm_mode == 3) this.queries[i] = "album HAS " + this.names[i] + " OR title HAS " + this.names[i];
2590
							if (this.lastfm_mode == 4) this.queries[i] = "title HAS " + this.names[i];
2591
						}
2592
					}
2593
					if (Date.parse(Date()) - Date.parse(this.file.DateLastModified) > ONE_DAY) this.get();
2594
				} else {
2595
					this.get();
2596
				}
2597
				break;
2598
			case "lastfm_charts":
2599
				this.filename = this.folder + "\\" + l.username + "_" + this.lastfm_charts_modes[this.lastfm_charts_mode] + "_" + this.lastfm_charts_periods[this.lastfm_charts_period] + ".json";
2600
				if (p.fso.fileExists(this.filename)) {
2601
					this.file = p.fso.Getfile(this.filename);
2602
					this.json_text = p.open(this.filename);
2603
					this.json_data = p.json_parse(this.json_text);
2604
					if (this.json_data) {
2605
						switch(true) {
2606
							case this.json_data.error > 0:
2607
								p.console(this.json_data.message);
2608
								break;
2609
							case this.lastfm_charts_mode == 0 && this.json_data.topartists && typeof this.json_data.topartists.artist == "object":
2610
								this.data = this.json_data.topartists.artist;
2611
								break;
2612
							case this.lastfm_charts_mode == 1 && this.json_data.topalbums && typeof this.json_data.topalbums.album == "object":
2613
								this.data = this.json_data.topalbums.album;
2614
								break;
2615
							case this.lastfm_charts_mode == 2 && this.json_data.toptracks && typeof this.json_data.toptracks.track == "object":
2616
								this.data = this.json_data.toptracks.track;
2617
								break;
2618
						}
2619
						this.items = this.data.length;
2620
						for (i = 0; i < this.items; i++) {
2621
							this.names[i] = this.lastfm_charts_mode != 0 ? this.data[i].artist.name + " - " + this.data[i].name : this.data[i].name;
2622
							this.ranks[i] = (i > 0 && this.data[i].playcount == this.data[i - 1].playcount) ? this.ranks[i - 1] : this.data[i]["@attr"].rank;
2623
							this.urls[i] = this.data[i].url;
2624
							this.names_widths[i] = temp_gr.CalcTextWidth(this.names[i], p.list_font);
2625
							this.playcounts[i] = this.data[i].playcount;
2626
						}
2627
					}
2628
					if (Date.parse(Date()) - Date.parse(this.file.DateLastModified) > ONE_DAY) this.get();
2629
				} else {
2630
					this.get();
2631
				}
2632
				break;
2633
			case "discogs":
2634
				this.filename = this.folder + "\\discogs.json";
2635
				if (p.fso.fileExists(this.filename)) {
2636
					this.file = p.fso.Getfile(this.filename);
2637
					this.json_text = p.open(this.filename);
2638
					this.json_data = p.json_parse(this.json_text);
2639
					if (this.json_data && this.json_data.results) {
2640
						this.data = this.json_reverse_sort(this.json_data.results, "year");
2641
						var swap_artist = fb.TitleFormat("$swapprefix($lower(" + p.artist + ")) - ").Eval(true);
2642
						for (i = 0; i < this.data.length; i++) {
2643
							var temp_artist = this.data[i].title.replace(/\s{2,}/g,' ');
2644
							if (this.discogs_match && temp_artist.toLowerCase().indexOf(swap_artist) != 0) continue;
2645
							this.dates.push(this.data[i].year || "");
2646
							this.urls.push("http://www.discogs.com" + this.data[i].uri);
2647
							this.names.push(temp_artist);
2648
							this.names_widths.push(temp_gr.CalcTextWidth(temp_artist, p.list_font));
2649
						}
2650
						this.items = this.names.length;
2651
					}
2652
					if (Date.parse(Date()) - Date.parse(this.file.DateLastModified) > ONE_DAY) this.get();
2653
				} else {
2654
					this.get();
2655
				}
2656
				break;
2657
			case "musicbrainz":
2658
				this.filename = this.folder + "\\musicbrainz_" + this.musicbrainz_mode + ".json";
2659
				if (p.fso.fileExists(this.filename)) {
2660
					this.file = p.fso.Getfile(this.filename);
2661
					this.json_text = p.open(this.filename);
2662
					this.json_data = p.json_parse(this.json_text);
2663
					if (this.json_data) {
2664
						switch(this.musicbrainz_mode) {
2665
							case "releases":
2666
								this.data = this.json_data["release-groups"] || [];
2667
								this.data = this.json_reverse_sort(this.data, "first-release-date");
2668
								var primary, secondary, name;
2669
								for (i = 0; i < this.data.length; i++) {
2670
									primary = this.data[i]["primary-type"];
2671
									secondary = this.data[i]["secondary-types"].join("").toLowerCase();
2672
									switch(true) {
2673
										case !this.musicbrainz_remix && secondary.indexOf("remix") > -1:
2674
										case !this.musicbrainz_compilation && secondary.indexOf("compilation") > -1:
2675
										case !this.musicbrainz_live && secondary.indexOf("live") > -1:
2676
											break;
2677
										case this.musicbrainz_single && primary == "Single":
2678
										case this.musicbrainz_ep && primary == "EP":
2679
										case this.musicbrainz_album && primary == "Album":
2680
											name = this.data[i].title;
2681
											this.dates.push(this.data[i]["first-release-date"].substring(0,4));
2682
											this.names.push(name);
2683
											this.urls.push("http://musicbrainz.org/release-group/" + this.data[i].id);
2684
											this.names_widths.push(temp_gr.CalcTextWidth(name, p.list_font));
2685
											this.queries.push("album HAS " + name + " OR title HAS " + name);
2686
											switch(true) {
2687
												case secondary.indexOf("remix") > -1:
2688
													this.release_types.push("Remix");
2689
													break;
2690
												case secondary.indexOf("compilation") > -1:
2691
													this.release_types.push("Compilation");
2692
													break;
2693
												case secondary.indexOf("live") > -1:
2694
													this.release_types.push("Live");
2695
													break;
2696
												default:
2697
													this.release_types.push(primary);
2698
													break;
2699
											}
2700
									}
2701
								}
2702
								this.items = this.names.length;
2703
								break;
2704
							case "URLs":
2705
								this.data = this.json_data.relations || [];
2706
								this.items = this.data.length;
2707
								for (i = 0; i < this.items; i++) {
2708
									this.urls[i] = this.data[i].url.resource;
2709
									this.images[i] = "";
2710
									if (this.data[i].type == "official homepage") {
2711
										this.images[i] = "home";
2712
									} else {
2713
										for (name in this.musicbrainz_images) {
2714
											if (this.urls[i].indexOf(name) > -1) {
2715
												this.images[i] = name;
2716
												break;
2717
											}
2718
										}
2719
										if (this.images[i].length == 0) this.images[i] = "external";
2720
									}
2721
									this.names[i] = decodeURIComponent(this.urls[i]);
2722
									this.names_widths[i] = temp_gr.CalcTextWidth(this.names[i], p.list_font);
2723
								}
2724
								break;
2725
						}
2726
					}
2727
					if (Date.parse(Date()) - Date.parse(this.file.DateLastModified) > ONE_DAY) this.get();
2728
				} else {
2729
					this.get();
2730
				}
2731
				break;
2732
			case "echonest":
2733
				this.filename = this.folder + "\\echonest_" + this.echonest_modes[this.echonest_mode] + ".json";
2734
				if (p.fso.fileExists(this.filename)) {
2735
					this.file = p.fso.Getfile(this.filename);
2736
					this.json_text = p.open(this.filename);
2737
					this.json_data = p.json_parse(this.json_text);
2738
					if (this.json_data && this.json_data.response && this.json_data.response.status && this.json_data.response.status.code == 0) {
2739
						this.data = this.json_data.response[this.echonest_modes[this.echonest_mode]] || [];
2740
						this.items = this.data.length;
2741
						for (i = 0; i < this.items; i++) {
2742
							this.names[i] = p.strip_tags(this.data[i].name);
2743
							this.urls[i] = (this.data[i].url || "").replace(/\\/g, "");
2744
							this.temp_date = (this.data[i].date_posted || this.data[i].date_reviewed || this.data[i].date_found || "").substring(0, 10);
2745
							this.dates[i] = this.temp_date.substring(8,10) + "-" + this.temp_date.substring(5,7) + "-" + this.temp_date.substring(0,4);
2746
							this.summaries[i] = p.strip_tags(this.data[i].summary);
2747
						}
2748
					}
2749
					if (Date.parse(Date()) - Date.parse(this.file.DateLastModified) > ONE_DAY) this.get();
2750
				} else {
2751
					this.get();
2752
				}
2753
				break;
2754
		}
2755
		temp_bmp.ReleaseGraphics(temp_gr);
2756
		temp_bmp.Dispose();
2757
		temp_gr = null;
2758
		temp_bmp = null;
2759
		if (this.file) {
2760
			var temp_date = new Date(this.file.DateLastModified);
2761
			this.date = "Updated: " + temp_date.toLocaleTimeString() + ", " + temp_date.toLocaleDateString();
2762
		}
2763
		window.Repaint();
2764
	}
2765
	
2766
	this.get = function() {
2767
		var fn = this.filename;
2768
		var func = function() {
2769
			if (!p.save(li.xmlhttp.responsetext, fn)) return;
2770
			li.update();
2771
		}
2772
		var url = "";
2773
		var user_agent = "";
2774
		switch(this.mode) {
2775
			case "discogs":
2776
				if (this.artist == "" || this.artist == "?") return;
2777
				url = "http://api.discogs.com/database/search?per_page=100&type=master&artist=" + encodeURIComponent(this.artist);
2778
				user_agent = "foobar2000_wsh_panel_mod_discogs +http://www.hydrogenaudio.org/forums/index.php?showuser=19379";
2779
				break;
2780
			case "lastfm_charts":
2781
				if (l.username.length == 0) return(p.console(l.username_error));
2782
				url = l.get_url() + "&method=user." + this.lastfm_charts_methods[this.lastfm_charts_mode] + "&period=" + this.lastfm_charts_periods[this.lastfm_charts_period];
2783
				user_agent = l.user_agent;
2784
				break;
2785
			case "lastfm":
2786
				if (this.artist == "" || this.artist == "?") return;
2787
				if (l.username.length == 0) return(p.console(l.username_error));
2788
				url = l.get_url() + "&method=" + this.lastfm_methods[this.lastfm_mode] + "&artist=" + encodeURIComponent(this.artist) + "&autocorrect=" + (l.auto_correct ? 1 : 0);
2789
				user_agent = l.user_agent;
2790
				break;
2791
			case "musicbrainz":
2792
				user_agent = "foobar2000_wsh_panel_mod_musicbrainz +http://www.hydrogenaudio.org/forums/index.php?showuser=19379";
2793
				var fn1 = this.folder + "\\MUSICBRAINZ_ARTISTID.txt";
2794
				this.musicbrainz_id = p.eval("$if3(%musicbrainz_artistid%,%musicbrainz artist id%,)");
2795
				this.musicbrainz_id = this.musicbrainz_id.substring(0, 36);
2796
				if (this.musicbrainz_id.length == 0) this.musicbrainz_id = p.open(fn1);
2797
				if (this.musicbrainz_id.length == 0) {
2798
					if (this.artist == "" || this.artist == "?") return;
2799
					url = "https://musicbrainz.org/ws/2/artist/?query=artist:" + encodeURIComponent(this.artist.toLowerCase()) + "&fmt=json";
2800
					var func = function() {
2801
						var json_data = p.json_parse(li.xmlhttp.responsetext);
2802
						if (!json_data) return;
2803
						var artist = li.artist.toLowerCase();
2804
						var artists = json_data.artist || [];
2805
						for (i = 0; i < artists.length; i++) {
2806
							if (artist == artists[i].name.toLowerCase()) {
2807
								if (!p.save(artists[i].id, fn1)) return;
2808
								li.get();
2809
								break;
2810
							}
2811
						}
2812
					}
2813
				} else {
2814
					if (this.musicbrainz_mode == "releases") url = "https://musicbrainz.org/ws/2/release-group?artist=" + this.musicbrainz_id + "&limit=100&offset=0&fmt=json";
2815
					else url = "https://musicbrainz.org/ws/2/artist/" + this.musicbrainz_id + "?inc=url-rels&fmt=json";
2816
				}
2817
				break;
2818
			case "echonest":
2819
				if (this.artist == "" || this.artist == "?") return;
2820
				url = "http://developer.echonest.com/api/v4/artist/" + this.echonest_modes[this.echonest_mode] + "/?name=" + encodeURIComponent(this.artist) + "&api_key=EKWS4ESQLKN3G2ZWV";
2821
				break;
2822
		}
2823
		if (url.length == 0) return;
2824
		this.xmlhttp.open("GET", url, true);
2825
		if (user_agent.length > 0) this.xmlhttp.setRequestHeader('User-Agent', user_agent);
2826
		this.xmlhttp.send();
2827
		this.xmlhttp.onreadystatechange = function() {
2828
			if (li.xmlhttp.readyState == 4) {
2829
				if (li.xmlhttp.status == 200) {
2830
					func();
2831
				} else {
2832
					p.console(li.xmlhttp.responsetext || "HTTP error: " + li.xmlhttp.status);
2833
				}
2834
			}
2835
		}
2836
	}
2837
	
2838
	this.json_reverse_sort = function(data, prop) {
2839
		data = data.sort(function(a, b) {
2840
			if (!a[prop] || b[prop] > a[prop]) return 1;
2841
			if (!b[prop] || b[prop] < a[prop]) return -1;
2842
			return 0;
2843
		});
2844
		return data;
2845
	}
2846
	
2847
	this.init = function() {
2848
		switch(true) {
2849
			case p.check_feature("discogs"):
2850
				this.mode = "discogs";
2851
				this.discogs_match = window.GetProperty("discogs_match", false);
2852
				break;
2853
			case p.check_feature("lastfm_charts"):
2854
				this.mode = "lastfm_charts";
2855
				this.text_x = 20;
2856
				this.lastfm_charts_modes = ["artist", "album", "track"];
2857
				this.lastfm_charts_mode = window.GetProperty("lastfm_charts_mode", 0);
2858
				this.lastfm_charts_methods = ["getTopArtists", "getTopAlbums", "getTopTracks"];
2859
				this.lastfm_charts_periods_display = ["overall", "last 7 days", "1 month", "3 month", "6 month", "12 month"];
2860
				this.lastfm_charts_periods = ["overall", "7day", "1month", "3month", "6month", "12month"];
2861
				this.lastfm_charts_period = window.GetProperty("lastfm_charts_period", 0);
2862
				this.lastfm_charts_bar_colour = window.GetProperty("lastfm_charts_bar_colour", "72-127-221");
2863
				this.folder = p.data_folder + "charts";
2864
				//if (!p.fso.FolderExists(this.folder)) p.fso.CreateFolder(this.folder);
2865
				break;
2866
			case p.check_feature("lastfm"):
2867
				this.mode = "lastfm";
2868
				this.lastfm_methods = ["artist.getSimilar", "artist.getTopTags", "artist.getTopFans", "artist.getTopAlbums", "artist.getTopTracks"];
2869
				this.lastfm_modes = ["similar artists", "top tags", "top fans", "top albums", "top tracks"];
2870
				this.lastfm_mode = window.GetProperty("lastfm_mode", 0);
2871
				this.lastfm_button = window.GetProperty("lastfm_button", "spotify");
2872
				this.lastfm_pause = window.GetProperty("lastfm_pause", true);
2873
				this.lastfm_spotify_img = gdi.Image(p.images_path + "spotify.png");
2874
				break;
2875
			case p.check_feature("musicbrainz"):
2876
				this.mode = "musicbrainz";
2877
				this.text_x = 20;
2878
				this.musicbrainz_images = {
2879
					"viaf.org": gdi.Image(p.images_path + "viaf_small.png"),
2880
					"allmusic.com": gdi.Image(p.images_path + "allmusic_small.png"),
2881
					"external": gdi.Image(p.images_path + "external_small.png"),
2882
					"bbc.co.uk": gdi.Image(p.images_path + "bbc_small.png"),
2883
					"facebook.com": gdi.Image(p.images_path + "facebook_small.png"),
2884
					"home": gdi.Image(p.images_path + "home_small.png"),
2885
					"last.fm": gdi.Image(p.images_path + "lastfm_small.png"),
2886
					"twitter.com": gdi.Image(p.images_path + "twitter_small.png"),
2887
					"soundcloud.com": gdi.Image(p.images_path + "soundcloud_small.png"),
2888
					"wikipedia.org": gdi.Image(p.images_path + "wikipedia_small.png"),
2889
					"discogs.com": gdi.Image(p.images_path + "discogs_small.png"),
2890
					"myspace.com": gdi.Image(p.images_path + "myspace_small.png"),
2891
					"youtube.com": gdi.Image(p.images_path + "youtube_small.png"),
2892
					"imdb.com": gdi.Image(p.images_path + "imdb_small.png"),
2893
					"plus.google.com": gdi.Image(p.images_path + "google_plus_small.png"),
2894
					"lyrics.wikia.com": gdi.Image(p.images_path + "lyrics_wikia_small.png"),
2895
					"flickr.com": gdi.Image(p.images_path + "flickr_small.png"),
2896
					"secondhandsongs.com": gdi.Image(p.images_path + "secondhandsongs_small.png"),
2897
					"vimeo.com": gdi.Image(p.images_path + "vimeo_small.png"),
2898
					"rateyourmusic.com": gdi.Image(p.images_path + "rateyourmusic_small.png"),
2899
					"instagram.com": gdi.Image(p.images_path + "instagram_small.png"),
2900
					"tumblr.com": gdi.Image(p.images_path + "tumblr_small.png"),
2901
					"decoda.com": gdi.Image(p.images_path + "decoda_small.png"),
2902
					"wikidata.org": gdi.Image(p.images_path + "wikidata_small.png")
2903
				}
2904
				this.musicbrainz_mode = window.GetProperty("musicbrainz_mode", "releases");
2905
				this.musicbrainz_show_release_type = window.GetProperty("musicbrainz_show_release_type", true);
2906
				this.musicbrainz_live = window.GetProperty("musicbrainz_live", false);
2907
				this.musicbrainz_ep = window.GetProperty("musicbrainz_ep", true);
2908
				this.musicbrainz_single = window.GetProperty("musicbrainz_single", true);
2909
				this.musicbrainz_album = window.GetProperty("musicbrainz_album", true);
2910
				this.musicbrainz_remix = window.GetProperty("musicbrainz_remix", true);
2911
				this.musicbrainz_compilation = window.GetProperty("musicbrainz_compilation", true);
2912
				break;
2913
			case p.check_feature("echonest"):
2914
				this.mode = "echonest";
2915
				this.echonest_modes = ["news", "reviews", "blogs"];
2916
				this.echonest_mode = window.GetProperty("echonest_mode", 0);
2917
				break;
2918
			case p.check_feature("autoplaylists"):
2919
				this.autoplaylists_add = function() {
2920
					if (this.autoplaylists_editing) return;
2921
					this.autoplaylists_editing = true;
2922
					var new_name = p.InputBox("Enter a name for your autoplaylist", p.name, "");
2923
					if (new_name == "") { this.autoplaylists_editing = false; return; }
2924
					var new_query = p.InputBox("Enter your autoplaylist query", p.name, "");
2925
					if (new_query == "") { this.autoplaylists_editing = false; return; }
2926
					var new_sort = p.InputBox("Enter a sort pattern\n\n(optional)", p.name, "");
2927
					var new_force = new_sort.length > 0 ? p.MsgBox("Force sort?", 4, p.name) : 7;
2928
					this.data.push(new_name + "¬" + new_query + "¬" + new_sort + "¬" + new_force);
2929
					if (this.data.length > this.rows) this.offset = this.data.length - this.rows;
2930
					p.save(this.data.join("\n"), this.filename);
2931
					if (this.autoplaylists_success) this.autoplaylists_run(new_name, new_query, new_sort, new_force);
2932
					window.NotifyOthers("autoplaylists", "update");
2933
					this.update();
2934
					this.autoplaylists_editing = false;
2935
				}
2936
				
2937
				this.autoplaylists_run = function(n, q, s, f) {
2938
					if (this.autoplaylists_remove_duplicates) {
2939
						i = 0;
2940
						while(i < fb.PlaylistCount) {
2941
							if (fb.GetPlaylistName(i) == n) fb.RemovePlaylist(i);
2942
							else i++;
2943
						}
2944
					}
2945
					fb.CreateAutoPlaylist(fb.PlaylistCount, n, q, s, f == 6 ? true : false);
2946
					fb.ActivePlaylist = fb.PlaylistCount - 1;
2947
				}
2948
				
2949
				this.autoplaylists_edit = function(x, y) {
2950
					var _menu = window.CreatePopupMenu();
2951
					var i = this.index;
2952
					_menu.AppendMenuItem(MF_STRING, 1, "Rename...");
2953
					_menu.AppendMenuItem(MF_STRING, 2, "Edit query...");
2954
					_menu.AppendMenuItem(MF_STRING, 3, "Edit sort pattern...");
2955
					_menu.AppendMenuItem(MF_STRING, 4, "Force Sort");
2956
					_menu.CheckMenuItem(4, this.forced[i] == 6 ? true : false);
2957
					this.autoplaylists_editing = true;
2958
					this.autoplaylists_hover = false;
2959
					window.RepaintRect(this.x + this.w - 40, this.y + 15, 40, Math.min(this.rows, this.items) * this.row_height);
2960
					idx = _menu.TrackPopupMenu(x, y);
2961
					switch(idx) {
2962
						case 0:
2963
							this.autoplaylists_editing = false;
2964
							_menu.Dispose();
2965
							return;
2966
						case 1:
2967
							var new_name = p.InputBox("Rename your autoplaylist", p.name, this.names[i]);
2968
							if (new_name != "") this.names[i] = new_name;
2969
							break;
2970
						case 2:
2971
							var new_query = p.InputBox("Enter your autoplaylist query", p.name, this.queries[i]);
2972
							if (new_query != "") this.queries[i] = new_query;
2973
							break;
2974
						case 3:
2975
							var new_sort = p.InputBox("Enter a sort pattern\n\n(optional)", p.name, this.sorts[i]);
2976
							this.sorts[i] = new_sort;
2977
							this.forced[i] = new_sort.length > 0 ? p.MsgBox("Force sort?", 4, p.name) : 7;
2978
							break;
2979
						case 4:
2980
							this.forced[i] = this.forced[i] == 6 ? 7 : 6;
2981
							break;
2982
					}
2983
					_menu.Dispose();
2984
					var temp = this.names[i] + "¬" + this.queries[i] + "¬" + this.sorts[i] + "¬" + this.forced[i];
2985
					if (this.data[i] != temp) {
2986
						this.data[i] = temp;
2987
						p.save(this.data.join("\n"), this.filename);
2988
						if (this.autoplaylists_success) this.autoplaylists_run(this.names[i], this.queries[i], this.sorts[i], this.forced[i]);
2989
						window.NotifyOthers("autoplaylists", "update");
2990
						this.update();
2991
					}
2992
					this.autoplaylists_editing = false;
2993
				}
2994
				
2995
				this.autoplaylists_delete = function() {
2996
					if (this.offset > 1) this.offset--;
2997
					this.autoplaylists_deleted_items.unshift(this.data[this.index]);
2998
					this.data.splice(this.index, 1);
2999
					p.save(this.data.join("\n"), this.filename);
3000
					window.NotifyOthers("autoplaylists", "update");
3001
					this.update();
3002
				}
3003
				
3004
				this.mode = "autoplaylists";
3005
				this.autoplaylists_del_img = gdi.Image(p.images_path + "cross.png");
3006
				this.autoplaylists_edit_img = gdi.Image(p.images_path + "edit.png");
3007
				this.autoplaylists_hover = false;
3008
				this.autoplaylists_editing = false;
3009
				this.autoplaylists_remove_duplicates = window.GetProperty("autoplaylists_remove_duplicates", true);
3010
				this.autoplaylists_success = window.GetProperty("autoplaylists_success", true);
3011
				this.autoplaylists_title = window.GetProperty("autoplaylists_title", "Autoplaylists");
3012
				this.autoplaylists_slot = window.GetProperty("autoplaylists_slot", 1);
3013
				this.filename = p.settings_folder + "autoplaylists" + this.autoplaylists_slot;
3014
				this.autoplaylists_deleted_items = [];
3015
				break;
3016
		}
3017
	}
3018
	
3019
	this.x = x;
3020
	this.y = y;
3021
	this.w = w;
3022
	this.h = h;
3023
	this.index = 0;
3024
	this.offset = 0;
3025
	this.items = 0;
3026
	this.text = "";
3027
	this.artist = "";
3028
	this.url = "";
3029
	this.text_x = 0;
3030
	this.show_timestamp = window.GetProperty("show_timestamp", true);
3031
	this.autoplaylist_img = gdi.Image(p.images_path + "search_small.png");
3032
	this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
3033
	this.init();
3034
}
3035
3036
function playcount_sync(x, y) {
3037
	this.playback_time = function() {
3038
		this.time_elapsed++;
3039
		if (this.time_elapsed == 3 && this.auto_love && fb.TitleFormat(this.auto_love_tf).Eval() == 1 && this.old_userloved == 0) {
3040
			p.console("Automatically loving this track....");
3041
			this.love_track();
3042
		}
3043
		if (this.time_elapsed == this.target_time) {
3044
			if (!this.library || fb.IsMetadbInMediaLibrary(p.metadb)) this.sync_track();
3045
			else p.console("Skipping... Track not in library.");
3046
		}
3047
	}
3048
	
3049
	this.metadb_changed = function() {
3050
		if (!p.metadb) return false;
3051
		this.artist = fb.TitleFormat(p.artist_tf).EvalWithMetadb(p.metadb);
3052
		this.track = fb.TitleFormat("%title%").EvalWithMetadb(p.metadb);
3053
		this.old_userloved = fb.TitleFormat("%LASTFM_LOVED_DB%").EvalWithMetadb(p.metadb) == 1 ? 1 : 0;
3054
		this.old_userplaycount = fb.TitleFormat("%LASTFM_PLAYCOUNT_DB%").EvalWithMetadb(p.metadb);
3055
		this.method = this.old_userloved == 1 ? "track.unlove" : "track.love";
3056
		this.tooltip = (this.old_userloved == 1 ? "Unlove" : "Love") + " \"" + this.track + "\" by \"" + this.artist + "\".";
3057
		this.crc32 = fb.TitleFormat("$crc32($lower(%artist%%title%))").EvalWithMetadb(p.metadb);
3058
		b.update();
3059
		return true;
3060
	}
3061
	
3062
	this.playback_new_track = function() {
3063
		this.auto_love_count = 0;
3064
		this.time_elapsed = 0;
3065
		switch(true) {
3066
			case fb.PlaybackLength == 0:
3067
				this.target_time = 240;
3068
				break;
3069
			case fb.PlaybackLength >= 30:
3070
				this.target_time = Math.min(Math.floor(fb.PlaybackLength / 2), 240);
3071
				break;
3072
			default:
3073
				this.target_time = 5;
3074
				break;
3075
		}
3076
		on_item_focus_change();
3077
	}
3078
	
3079
	this.playback_edited = function() {
3080
		if (this.auto_love && fb.TitleFormat(this.auto_love_tf).Eval() == 1 && this.old_userloved == 0 && this.auto_love_count == 0) {
3081
			this.auto_love_count = 1;
3082
			p.console("Automatically loving this track....");
3083
			this.love_track();
3084
		}
3085
	}
3086
	
3087
	this.tf = function(value) {
3088
		return(value.replace(/'/g, "''").replace(/,/g, "','").replace(/\//g, "'/'").replace(/\(/g, "'('").replace(/\)/g, "')'").replace(/\[/g, "'['").replace(/\]/g, "']'"));
3089
	}
3090
	
3091
	this.love_track = function() {
3092
		l.post(this.method, p.metadb);
3093
	}
3094
	
3095
	this.sync_track = function() {
3096
		switch(true) {
3097
			case this.loved_working || this.playcount_working:
3098
				return;
3099
			case !utils.CheckComponent("foo_customdb", true):
3100
				p.console("Not contacting Last.fm. foo_customdb is missing.");
3101
				return;
3102
			default:
3103
				p.console("Contacting Last.fm....");
3104
				this.get(l.get_url() + "&method=track.getinfo&artist=" + encodeURIComponent(this.artist) + "&track=" + encodeURIComponent(this.track) + "&autocorrect=" + (l.auto_correct ? 1 : 0), function() {
3105
					ps.update_track();
3106
				});
3107
		}
3108
	}
3109
	
3110
	this.get = function(url, func) {
3111
		if (l.username.length == 0) {
3112
			this.loved_working = false;
3113
			this.playcount_working = false;
3114
			p.console(l.username_error);
3115
			return;
3116
		}
3117
		this.xmlhttp.open("GET", url, true);
3118
		this.xmlhttp.setRequestHeader('User-Agent', l.user_agent);
3119
		this.xmlhttp.send();
3120
		this.xmlhttp.onreadystatechange = function() {
3121
			if (ps.xmlhttp.readyState == 4) {
3122
				if (ps.xmlhttp.status == 200) {
3123
					func();
3124
				} else {
3125
					p.console(ps.xmlhttp.responsetext || "HTTP error: " + ps.xmlhttp.status);
3126
				}
3127
			}
3128
		}
3129
	}
3130
	
3131
	this.update_track = function() {
3132
		this.json_data = p.json_parse(ps.xmlhttp.responsetext);
3133
		if (!this.json_data || this.json_data.error > 0 || !this.json_data.track) {
3134
			p.console(ps.xmlhttp.responsetext);
3135
			return;
3136
		}
3137
		this.userplaycount = this.json_data.track.userplaycount > 0 ? ++this.json_data.track.userplaycount : 1;
3138
		this.userloved = this.json_data.track.userloved == 1 ? 1 : 0;
3139
		if (fb.IsPlaying && this.time_elapsed >= this.target_time && fb.PlaybackLength > 29 && fb.PlaybackLength < 10800) {
3140
			switch(true) {
3141
				case this.userplaycount < this.old_userplaycount:
3142
					p.console("Playcount returned from Last.fm is lower than current value. Not updating.");
3143
					break;
3144
				case this.old_userplaycount == this.userplaycount:
3145
					p.console("No changes found. Not updating.");
3146
					break;
3147
				default:
3148
					p.console("Last.fm responded ok. Attempting to update playcount...");
3149
					fb.RunContextCommandWithMetadb("Customdb Delete Playcount", p.metadb, 8);
3150
					if (this.old_userloved == 1) fb.RunContextCommandWithMetadb("Customdb Love 0", p.metadb, 8);
3151
					var attempt = 0;
3152
					while(fb.TitleFormat("%LASTFM_PLAYCOUNT_DB%").EvalWithMetadb(p.metadb) != this.userplaycount && attempt <= 3) {
3153
						var query1 = '\"INSERT INTO quicktag(url,subsong,fieldname,value) VALUES(\\"' + this.crc32 + '\\",\\"-1\\",\\"LASTFM_PLAYCOUNT_DB\\",\\"' + this.userplaycount + '\\")\";';
3154
						p.WshShell.Run(p.fso.GetFile(p.script_path + "sqlite3.exe").ShortPath + " " + p.fso.GetFile(fb.ProfilePath + "customdb_sqlite.db").ShortPath + " " + query1, 0, true);
3155
						attempt++;
3156
					}
3157
					fb.RunContextCommandWithMetadb("Customdb Refresh", p.metadb, 8);
3158
					if (fb.TitleFormat("%LASTFM_PLAYCOUNT_DB%").EvalWithMetadb(p.metadb) == this.userplaycount) p.console("Playcount updated successfully.");
3159
					else p.console("Database error. Playcount not updated.");
3160
					break;
3161
			}
3162
		}
3163
		if (this.old_userloved != this.userloved) fb.RunContextCommandWithMetadb("Customdb Love " + this.userloved, p.metadb, 8);
3164
	}
3165
	
3166
	this.start_import = function() {
3167
		if (this.show_console) fb.ShowConsole();
3168
		this.loved_page_errors = 0;
3169
		this.playcount_page_errors = 0;
3170
		ps.pages = 0;
3171
		this.r = 1;
3172
		this.sql = "BEGIN TRANSACTION;\n";
3173
		this.loved_working = true;
3174
		this.sync_loved(1);
3175
	}
3176
	
3177
	this.sync_loved = function(page) {
3178
		if (!this.loved_working) return(p.console("Import aborted."));
3179
		this.page = page;
3180
		this.get(l.get_url() + "&method=user.getlovedtracks&limit=200&page=" + this.page, function() {
3181
			ps.update_loved();
3182
		});
3183
	}
3184
	
3185
	this.update_loved = function() {
3186
		this.json_data = p.json_parse(ps.xmlhttp.responsetext);
3187
		if (this.json_data && this.json_data.error > 0) {
3188
			this.loved_working = false;
3189
			p.MsgBox("There is a problem with the Last.fm web services. Please try again later.\n\n" + ps.xmlhttp.responsetext, 0, p.name);
3190
			return;
3191
		}
3192
		if (this.json_data && this.json_data.lovedtracks && this.json_data.lovedtracks.track) {
3193
			if (this.page == 1) this.pages = this.json_data.lovedtracks["@attr"].totalPages;
3194
			for (i = 0; i < this.json_data.lovedtracks.track.length; i++) {
3195
				var data = [];
3196
				data[0] = this.json_data.lovedtracks.track[i].artist.name;
3197
				data[1] = this.json_data.lovedtracks.track[i].name;
3198
				data[2] = 1;
3199
				if (data.length == 3) {
3200
					p.console(this.r + ": " + data[0] + " - " + data[1]);
3201
					var url = fb.TitleFormat("$crc32($lower(" + this.tf(data[0]) + this.tf(data[1]) + "))").Eval(true);
3202
					this.sql += 'INSERT OR REPLACE INTO quicktag(url,subsong,fieldname,value) VALUES("' + url + '","-1","LASTFM_LOVED_DB","' + data[2] + '");' + "\n";
3203
					this.r++;
3204
				}
3205
			}
3206
			p.console("Loved tracks: completed page " + this.page + " of " + this.pages);
3207
		} else if (this.pages > 0) {
3208
			this.loved_page_errors++;
3209
		}
3210
		if (this.page < this.pages) {
3211
			this.page++;
3212
			this.sync_loved(this.page);
3213
		} else {
3214
			this.loved_working = false;
3215
			if (this.full_import) {
3216
				this.playcount_working = true;
3217
				this.pages = 0;
3218
				this.r = 1;
3219
				this.sync_playcount(1);
3220
			} else {
3221
				try {
3222
					this.sql += "COMMIT;"
3223
					var ts = p.fso.OpenTextFile(this.sql_file, 2, true, 0);
3224
					ts.WriteLine(this.sql);
3225
					ts.Close();
3226
					this.finish_import();
3227
				} catch(e) {
3228
				}
3229
				if (this.loved_page_errors > 0) {
3230
					p.console("Loved track page errors: " + this.loved_page_errors + " (200 records are lost for every page that fails.)");
3231
				} else {
3232
					p.console("There were no errors reported.");
3233
				}
3234
			}
3235
		}
3236
	}
3237
	
3238
	this.sync_playcount = function(page) {
3239
		if (this.playcount_working == false) return(p.console("Import aborted."));
3240
		this.page = page;
3241
		this.get(l.get_url() + "&method=library.gettracks&limit=100&page=" + this.page, function() {
3242
			ps.update_playcount();
3243
		});
3244
	}
3245
	
3246
	this.update_playcount = function() {
3247
		this.json_data = p.json_parse(ps.xmlhttp.responsetext);
3248
		if (this.json_data && this.json_data.error > 0) {
3249
			this.playcount_working = false;
3250
			p.MsgBox("There is a problem with the Last.fm web services. Please try again later.\n\n" + ps.xmlhttp.responsetext, 0, p.name);
3251
			return;
3252
		}
3253
		if (this.json_data && this.json_data.tracks && this.json_data.tracks.track) {
3254
			if (this.page == 1) this.pages = this.json_data.tracks["@attr"].totalPages
3255
			for (i = 0; i < this.json_data.tracks.track.length; i++) {
3256
				var data = [];
3257
				data[0] = this.json_data.tracks.track[i].artist.name;
3258
				data[1] = this.json_data.tracks.track[i].name;
3259
				data[2] = this.json_data.tracks.track[i].playcount;
3260
				if (data[2] == 0) {
3261
					this.page = this.pages;
3262
					break;
3263
				}
3264
				if (data.length == 3) {
3265
					p.console(this.r + ": " + data[0] + " - " + data[1] + " " + data[2]);
3266
					var url = fb.TitleFormat("$crc32($lower(" + this.tf(data[0]) + this.tf(data[1]) + "))").Eval(true);
3267
					this.sql += 'INSERT OR REPLACE INTO quicktag(url,subsong,fieldname,value) VALUES("' + url + '","-1","LASTFM_PLAYCOUNT_DB","' + data[2] + '");' + "\n";
3268
					this.r++;
3269
				}
3270
			}
3271
			p.console("Playcount: completed page " + this.page + " of " + this.pages);
3272
		} else if (this.pages > 0) {
3273
			this.playcount_page_errors++;
3274
		}
3275
		if (this.page < this.pages) {
3276
			this.page++;
3277
			this.sync_playcount(this.page);
3278
		} else {
3279
			try {
3280
				this.sql += "COMMIT;"
3281
				var ts = p.fso.OpenTextFile(this.sql_file, 2, true, 0);
3282
				ts.WriteLine(this.sql);
3283
				ts.Close();
3284
				this.finish_import();
3285
			} catch(e) {
3286
			}
3287
			this.playcount_working = false;
3288
			if (this.loved_page_errors + this.playcount_page_errors > 0) {
3289
				p.console("Loved track page errors: " + this.loved_page_errors + " (200 records are lost for every page that fails.)");
3290
				p.console("Playcount page errors: " + this.playcount_page_errors + " (100 records are lost for every page that fails.)");
3291
			} else {
3292
				p.console("There were no errors reported.");
3293
			}
3294
		}
3295
	}
3296
	
3297
	this.finish_import = function() {
3298
		try {
3299
			var cmd_file = p.fso.GetFile(p.script_path + "lastfm_sql.cmd").ShortPath;
3300
			var db_file = p.fso.GetFile(fb.ProfilePath + "customdb_sqlite.db").ShortPath;
3301
			p.run(cmd_file + " " + p.fso.GetFile(p.script_path + "sqlite3.exe").ShortPath + " " + db_file + " " + p.fso.GetFile(this.sql_file).ShortPath);
3302
		} catch(e) {
3303
		}
3304
	}
3305
	
3306
	this.update_button = function() {
3307
		var exclamation = this.icon == "tango" ? "exclamation.png" : "exclamation_small.png";
3308
		var love = this.icon == "tango" ? "love.png" : "love_small.png";
3309
		var love_h = this.icon == "tango" ? "love_h.png" : "love_h_small.png";
3310
		this.size = this.icon == "tango" ? 32 : 20;
3311
		switch(true) {
3312
			case l.username.length == 0:
3313
				this.n = exclamation;
3314
				this.h = exclamation;
3315
				this.tooltip = l.username_error;
3316
				this.func = null;
3317
				break;
3318
			case l.sk.length != 32:
3319
				this.n = exclamation;
3320
				this.h = exclamation;
3321
				this.tooltip = l.password_error;
3322
				this.func = null;
3323
				break;
3324
			case !p.metadb:
3325
				this.n = exclamation;
3326
				this.h = exclamation;
3327
				this.tooltip = "No selection";
3328
				this.func = null;
3329
				break;
3330
			case !utils.CheckComponent("foo_customdb", true):
3331
				this.n = exclamation;
3332
				this.h = exclamation;
3333
				this.tooltip = "The foo_customdb component is not installed. Please refer to the readme.";
3334
				this.func = null;
3335
				break;
3336
			default:
3337
				this.n = this.old_userloved == 1 ? love_h : love;
3338
				this.h = this.old_userloved == 1 ? love : love_h;
3339
				this.func = function() { ps.love_track(); }
3340
				break;
3341
		}
3342
	}
3343
	
3344
	this.x = x;
3345
	this.y = y;
3346
	this.loved_working = false;
3347
	this.playcount_working = false;
3348
	this.sql_file = p.data_folder + "lastfm.sql";
3349
	this.page = 0;
3350
	this.last_page = 0;
3351
	this.auto_love = window.GetProperty("playcount_sync_auto_love", false);
3352
	this.auto_love_tf = window.GetProperty("playcount_sync_auto_love_tf", "");
3353
	this.icon = window.GetProperty("playcount_sync_icon", "tango");
3354
	this.show_console = window.GetProperty("playcount_sync_show_console", true);
3355
	this.library = window.GetProperty("playcount_sync_library", false);
3356
	this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
3357
	window.SetInterval(function() {
3358
		var temp = ps.page > 1 ? ps.page - 1 : 1;
3359
		if (ps.loved_working && ps.page == ps.last_page) {
3360
			ps.xmlhttp.abort();
3361
			ps.sync_loved(temp);
3362
		} else if (ps.playcount_working && ps.page == ps.last_page) {
3363
			ps.xmlhttp.abort();
3364
			ps.sync_playcount(temp);
3365
		} else {
3366
			ps.last_page = ps.page;
3367
		}
3368
	}, 15000);
3369
}
3370
3371
function rating(x, y, bs) {
3372
	this.draw = function(gr) {
3373
		if (!p.metadb) return;
3374
		for (i = 1; i < 6; i++) {
3375
			this.img = i > (this.hover ? this.lrating : this.rating) ? this.off_img : this.on_img;
3376
			p.draw_image(gr, this.img, this.x + this.bs * (i - 1), this.y, this.bs, this.bs, "adjust");
3377
		}
3378
	}
3379
	
3380
	this.metadb_changed = function() {
3381
		if (!p.metadb) return false;
3382
		this.hover = false;
3383
		this.rating = p.eval("$if2(%rating%,0)");
3384
		this.tiptext = p.eval(this.tiptext_tf);
3385
		this.lrating = this.rating;
3386
		window.RepaintRect(this.x, this.y, this.w, this.bs);
3387
		return true;
3388
	}
3389
	
3390
	this.trace = function(x, y) {
3391
		return x > this.x - this.bs && x < this.x + (this.bs * 5) && y > this.y && y < this.y + this.bs;
3392
	}
3393
	
3394
	this.move = function(x, y) {
3395
		if (!this.trace(x, y)) {
3396
			if (this.hover) this.leave();
3397
			return false;
3398
		}
3399
		if (p.metadb) {
3400
			if (x > this.x) p.tt(this.tiptext);
3401
			this.hover = true;
3402
			this.lrating = Math.ceil((x - this.x) / this.bs);
3403
			window.RepaintRect(this.x, this.y, this.w, this.bs);
3404
		}
3405
		return true;
3406
	}
3407
	
3408
	this.lbtn_up = function(x, y) {
3409
		if (!this.trace(x, y)) return false;
3410
		if (this.check) {
3411
			if (this.lrating != this.rating && this.hover == 1) fb.RunContextCommandWithMetadb("Rating/" + (this.lrating == 0 ? "<not set>" : this.lrating), p.metadb, 8);
3412
		} else {
3413
			p.MsgBox(this.error_text, 0, p.name);
3414
			p.browser("http://www.foobar2000.org/components/view/foo_playcount");
3415
		}
3416
		return true;
3417
	}
3418
	
3419
	this.leave = function() {
3420
		p.ttd();
3421
		this.hover = false;
3422
		window.RepaintRect(this.x, this.y, this.w, this.bs);
3423
	}
3424
	
3425
	this.x = x;
3426
	this.y = y;
3427
	this.bs = bs;
3428
	this.w = this.bs * 5;
3429
	this.hover = false;
3430
	this.rating = null;
3431
	this.lrating = null;
3432
	this.img = null;
3433
	this.off_img = gdi.Image(p.images_path + "off.png");
3434
	this.on_img = gdi.Image(p.images_path + "on.png");
3435
	this.check = utils.CheckComponent("foo_playcount", true);
3436
	this.error_text = "This script requires foo_playcount.";
3437
	this.tiptext_tf = this.check ? 'Rate "%title%" by "%artist%"' : this.error_text;
3438
}
3439
3440
function sb(x, y, w, h, img, isVisible, func) {
3441
	this.x = x;
3442
	this.y = y;
3443
	this.w = w;
3444
	this.h = h;
3445
	this.img = img;
3446
	this.isVisible = new Function("return (" + isVisible + ");");
3447
	this.func = func;
3448
	
3449
	this.draw = function(gr) {
3450
		if (this.isVisible()) p.draw_image(gr, this.img, this.x, this.y, this.w, this.h, "adjust");
3451
	}
3452
	
3453
	this.trace = function(x, y) {
3454
		return(x > this.x && x < this.x + this.w && y > this.y && y < this.y + this.h && this.isVisible());
3455
	}
3456
	
3457
	this.lbtn_up = function(x, y) {
3458
		if (!this.trace(x, y)) return false;
3459
		this.func && this.func(x, y);
3460
		return true;
3461
	}
3462
}
3463
3464
function seekbar(x, y, w, h) {
3465
	this.trace = function(x, y) {
3466
		return (x > this.x && x < this.x + this.w && y > this.y - (this.drag ? 200 : 0) && y < this.y + this.h + (this.drag ? 200 : 0));
3467
	}
3468
	
3469
	this.draw = function(gr) {
3470
		p.draw_background(gr);
3471
		switch(this.mode) {
3472
			case "spectrogram":
3473
				if (this.working) {
3474
					p.draw_image(gr, this.hourglass_img, this.x, this.y + Math.round((this.h - 32) / 2), this.w, 32, "adjust");
3475
				} else {
3476
					p.draw_image(gr, this.img, this.x, this.y, this.w, this.h, "stretch");
3477
				}
3478
				if (fb.IsPlaying && fb.PlaybackLength > 0) {
3479
					this.calc_pos();
3480
					gr.FillSolidRect(this.x + this.pos - 2, this.y, 2, this.h, p.splitRGB(this.marker));
3481
				}
3482
				break;
3483
			case "nyan_cat":
3484
				if (fb.IsPlaying && fb.PlaybackLength > 0) {
3485
					this.calc_pos();
3486
					for (i = 0; i < this.offsets.length; i++) {
3487
						gr.FillSolidRect(this.x - 48, this.y + this.offsets[i], this.pos + 2, this.heights[i], this.colours[i]);
3488
					}
3489
					p.draw_image(gr, this.cat_img[this.z], this.pos, this.y, 48, 30);
3490
				} else {
3491
					p.draw_image(gr, this.cat_img[0], 0, this.y, 48, 30);
3492
				}
3493
				break;
3494
		}
3495
	}
3496
	
3497
	this.playback_new_track = function() {
3498
		if (this.mode != "spectrogram") return;
3499
		var metadb = fb.GetNowPlaying();
3500
		this.img && this.img.Dispose();
3501
		this.img = null;
3502
		try {
3503
			this.png_filename = spectrogram_cache + "\\" + fb.TitleFormat("$crc32(%path%)").EvalWithMetadb(metadb) + this.sox_params + ".png";
3504
			switch(true) {
3505
				case !metadb:
3506
				case metadb.RawPath.indexOf("file") != 0:
3507
					p.console("Skipping... Not a valid file type.");
3508
					break;
3509
				case fb.PlaybackLength == 0:
3510
					p.console("Skipping... Unknown length.");
3511
					break;
3512
				case fb.TitleFormat("$if($or($strcmp(%__cue_embedded%,yes),$strcmp($right(%path%,3),cue)),cue,)").EvalWithMetadb(metadb) == "cue":
3513
					p.console("Skipping... Cannot support cuesheets.");
3514
					break;
3515
				case fb.TitleFormat("%subsong%").EvalWithMetadb(metadb) > 0:
3516
					p.console("Skipping... Cannot support tracks with chapters.");
3517
					break;
3518
				case this.library && !fb.IsMetadbInMediaLibrary(metadb):
3519
					p.console("Skipping... Track not in library.");
3520
					break;
3521
				case p.fso.FileExists(this.png_filename):
3522
					this.img = gdi.Image(this.png_filename);
3523
					break;
3524
				default:
3525
					this.working = true
3526
					window.Repaint();
3527
					var filename = metadb.Path;
3528
					var length = fb.TitleFormat("%length%").EvalWithMetadb(metadb);
3529
					var cmd = "cmd /c \"\"" + ffmpeg_exe + "\" -i \"" + filename + "\" -t " + length + " -f sox - | \"" + sox_exe + "\" -p -n " + this.sox_params + " -d " + length + " -r -o \"" + this.png_filename + "\"\"";
3530
					//p.console(cmd);
3531
					try { p.WshShell.Run(cmd, 0, true); } catch(e) {}
3532
					this.working = false;
3533
					this.img = gdi.Image(this.png_filename);
3534
					break;
3535
			}
3536
		} catch(e) {
3537
			//p.console(e);
3538
		}
3539
		window.Repaint();
3540
	}
3541
	
3542
	this.playback_stop = function() {
3543
		window.Repaint();
3544
	}
3545
	
3546
	this.playback_seek = function() {
3547
		this.update();
3548
	}
3549
	
3550
	this.move = function(x, y) {
3551
		if (this.drag) this.update();
3552
		if (this.trace(x, y)) {
3553
			if (fb.IsPlaying && fb.PlaybackLength > 0) {
3554
				x -= this.x;
3555
				this.drag_seek = x < 0 ? 0 : x > this.w ? 1 : x / this.w;
3556
				if (x != this.old_x || y != this.old_y) {
3557
					p.tt(p.format_time(fb.PlaybackLength * this.drag_seek));
3558
					this.old_x = x;
3559
					this.old_y = y;
3560
				}
3561
			}
3562
			return true;
3563
		} else {
3564
			this.leave();
3565
			return false;
3566
		}
3567
	}
3568
	
3569
	this.lbtn_down = function(x, y) {
3570
		if (!this.trace(x, y)) return false;
3571
		if (fb.IsPlaying && fb.PlaybackLength > 0) this.drag = true;
3572
		return true;
3573
	}
3574
	
3575
	this.lbtn_up = function(x, y) {
3576
		if (!this.trace(x, y)) return false;
3577
		if (this.drag) {
3578
			this.drag = false;
3579
			fb.PlaybackTime = fb.PlaybackLength * this.drag_seek;
3580
		}
3581
		return true;
3582
	}
3583
	
3584
	this.leave = function() {
3585
		this.drag = false;
3586
		p.ttd();
3587
	}
3588
	
3589
	this.update = function() {
3590
		window.RepaintRect(0, this.y, p.w, this.h);
3591
	}
3592
	
3593
	this.calc_pos = function() {
3594
		this.pos = this.drag ? this.w * this.drag_seek : this.w * (fb.PlaybackTime / fb.PlaybackLength);
3595
	}
3596
	
3597
	this.init = function() {
3598
		switch(true) {
3599
			case p.check_feature("spectrogram"):
3600
				this.clear_images = function(period) {
3601
					var now = Date.parse(Date());
3602
					images = utils.Glob(spectrogram_cache + "\\*.*").toArray();
3603
					for (i = 0; i < images.length; i++) {
3604
						if (this.png_filename == images[i]) continue;
3605
						var file = p.fso.Getfile(images[i]);
3606
						var file_date = Date.parse(file.DateLastModified);
3607
						if (now - file_date > period) {
3608
							try {
3609
								p.fso.DeleteFile(images[i]);
3610
							} catch(e) {
3611
								p.console("Could not delete " + images[i]);
3612
							}
3613
						}
3614
					}
3615
				}
3616
				
3617
				this.mode = "spectrogram";
3618
				this.library = window.GetProperty("seekbar_library", false);
3619
				this.marker = window.GetProperty("seekbar_marker", "240-240-240");
3620
				this.sox_params = window.GetProperty("sox_params", "channels 1 spectrogram -Y 130").trim();
3621
				this.working = false;
3622
				this.img = false;
3623
				this.hourglass_img = gdi.Image(p.images_path + "hourglass.png");
3624
				//if (!p.fso.FolderExists(spectrogram_cache)) p.fso.CreateFolder(spectrogram_cache);
3625
				if (fb.IsPlaying) {
3626
					window.SetTimeout(function() {
3627
						s.playback_new_track();
3628
					}, 100);
3629
				}
3630
				break;
3631
			case p.check_feature("nyan_cat"):
3632
				this.mode = "nyan_cat";
3633
				this.cat_img = [gdi.Image(p.images_path + "\\seekbar cat.png"), gdi.Image(p.images_path + "\\seekbar cat 2.png")];
3634
				this.offsets = [2, 6, 10, 15, 20, 24];
3635
				this.heights = [4, 4, 5, 5, 4, 4];
3636
				this.colours = [RGB(255, 0, 0), RGB(255, 153, 0), RGB(255, 255, 0), RGB(51, 255, 0), RGB(0, 153, 255), RGB(102, 51, 255)];
3637
				break;
3638
		}
3639
	}
3640
	
3641
	this.x = x;
3642
	this.y = y;
3643
	this.w = w;
3644
	this.h = h;
3645
	this.z = 0;
3646
	this.pos = 0;
3647
	this.drag = false;
3648
	this.drag_seek = 0;
3649
	this.old_x = 0;
3650
	this.old_y = 0;
3651
	this.init();
3652
	this.seekbar_timer = window.SetInterval(function() {
3653
		s.z = s.z == 0 ? 1 : 0;
3654
		if (!fb.IsPlaying || fb.IsPaused || fb.PlaybackLength == 0) return;
3655
		s.update();
3656
	}, 150);
3657
}
3658
3659
function text(x, y, w, h) {
3660
	this.size = function() {
3661
		this.rows = Math.floor((this.h - 36) / p.row_height);
3662
		this.but_x = this.x + Math.round((this.w - 15) / 2);
3663
		this.up_btn = new sb(this.but_x, this.y, 15, 15, p.up_img, "t.offset > 0", function() { t.wheel(1); });
3664
		this.down_btn = new sb(this.but_x, this.y + this.h - 15, 15, 15, p.down_img, "t.offset < t.text_rows - t.rows", function() { t.wheel(-1); });
3665
		this.calc();
3666
	}
3667
	
3668
	this.draw = function(gr, colour) {
3669
		for (i = 0; i < Math.min(this.rows, this.text_rows); i++) {
3670
			if (this.centre) p.centre_text(gr, this.text_array[i + this.offset], this.fixed ? p.fixed_font : p.normal_font, colour || p.textcolour, this.x, 18 + this.y + (i * p.row_height), this.w, p.row_height);
3671
			else p.left_text(gr, this.text_array[i + this.offset], this.fixed ? p.fixed_font : p.normal_font, colour || p.textcolour, this.x, 18 + this.y + (i * p.row_height), this.w, p.row_height);
3672
		}
3673
		this.up_btn.draw(gr);
3674
		this.down_btn.draw(gr);
3675
	}
3676
	
3677
	this.metadb_changed = function() {
3678
		if (!p.metadb) return false;
3679
		switch(this.mode) {
3680
			case "simple_tag":
3681
				this.temp_filename = p.metadb.Path;
3682
				if (this.filename == this.temp_filename) return false;
3683
				this.filename = this.temp_filename;
3684
				this.text = p.eval(this.tag);
3685
				break;
3686
			case "simple_text":
3687
				this.temp_filename = p.eval(this.filename_tf);
3688
				if (this.filename == this.temp_filename) return false;
3689
				this.text = "";
3690
				this.filename = this.temp_filename;
3691
				if (p.fso.FolderExists(this.filename)) {
3692
					this.files = [];
3693
					this.files = this.files.concat(utils.Glob(this.filename + "\\*.txt").toArray(), utils.Glob(this.filename + "\\*.log").toArray());
3694
					this.files.sort();
3695
					this.text = p.open(this.files[0]);
3696
				} else {
3697
					this.filenames = this.filename.split("|");
3698
					for (i = 0; i < this.filenames.length; i++) {
3699
						if (p.fso.fileExists(this.filenames[i])) {
3700
							this.text = p.open(this.filenames[i]);
3701
							break;
3702
						}
3703
					}
3704
				}
3705
				this.text = this.text.replace(/\t/g, "    ");
3706
				break;
3707
			case "lastfm_wiki":
3708
				p.artist = p.eval(p.artist_tf);
3709
				if (this.artist == p.artist) return false;
3710
				this.artist = p.artist;
3711
				this.folder = p.data_folder + p.artist;
3712
				if (!p.fso.FolderExists(this.folder)) p.fso.CreateFolder(this.folder);
3713
				this.filename = this.folder + "\\artist.getInfo_mod.json";
3714
				this.text = "Nothing found.";
3715
				this.url = "http://www.last.fm/";
3716
				if (p.fso.fileExists(this.filename)) {
3717
					this.json_text = p.open(this.filename);
3718
					this.json_data = p.json_parse(this.json_text);
3719
					if (this.json_data && this.json_data.response && this.json_data.response.biographies) {
3720
						this.items = this.json_data.response.biographies.length;
3721
						for (i = 0; i < this.items; i++) {
3722
							if (this.json_data.response.biographies[i].site == this.source) {
3723
								this.text = this.json_data.response.biographies[i].text;
3724
								this.url = this.json_data.response.biographies[i].license["attribution-url"];
3725
								break;
3726
							}
3727
						}
3728
						if (this.source == "last.fm") this.text = this.text.replace(/\.  /g, ".\n\n");
3729
						if (this.source == "wikipedia") this.text = this.text.replace(/\. \n/g, ".\n\n").replace(/\n\n\n/g, "\n\n").replace(/ edit:\n/g , ":\n").replace(/edit:\n/g , ":\n");
3730
					}
3731
				} else {
3732
					this.get();
3733
				}
3734
				break;
3735
			case "lastfm_album":
3736
				var temp_album = p.eval("[%album%]");
3737
				var temp_artist = p.eval("[%album artist%]");
3738
				if (this.album == temp_album && this.artist == temp_artist) return false;
3739
				this.artist = temp_artist;
3740
				this.album = temp_album;
3741
				this.folder = p.data_folder + p.eval("$crc32(%album artist%)");
3742
				if (!p.fso.FolderExists(this.folder)) p.fso.CreateFolder(this.folder);
3743
				this.filename = this.folder + "\\album.getInfo_" + p.eval("$crc32(%album%)") + ".json";
3744
				this.text = "Nothing found.";
3745
				this.url = l.url;
3746
				if (p.fso.fileExists(this.filename)) {
3747
					this.file = p.fso.GetFile(this.filename);
3748
					this.json_text = p.open(this.filename);
3749
					this.json_data = p.json_parse(this.json_text);
3750
					if (this.json_data && this.json_data.album) {
3751
						if (this.json_data.album.url) this.url = this.json_data.album.url;
3752
						if (this.json_data.album.wiki && this.json_data.album.wiki.content) {
3753
							this.text = p.strip_tags(this.json_data.album.wiki.content);
3754
							this.text = this.text.replace("User-contributed text is available under the Creative Commons By-SA License and may also be available under the GNU FDL.", "").trim();
3755
						}
3756
					}
3757
					if (Date.parse(Date()) - Date.parse(this.file.DateLastModified) > ONE_DAY) this.get();
3758
				} else {
3759
					this.get();
3760
				}
3761
				break;
3762
		}
3763
		this.calc();
3764
		window.Repaint();
3765
		return true;
3766
	}
3767
	
3768
	this.trace = function(x, y) {
3769
		return (x > this.x && x < this.x + this.w && y > this.y && y < this.y + this.h);
3770
	}
3771
	
3772
	this.wheel = function(step) {
3773
		if (!this.trace(p.mx, p.my)) return false;
3774
		if (this.text_rows > this.rows) {
3775
			this.offset -= step * 3;
3776
			if (this.offset < 0) this.offset = 0;
3777
			if (this.offset + this.rows > this.text_rows) this.offset = this.text_rows - this.rows;
3778
			window.RepaintRect(this.x, this.y, this.w, this.h);
3779
		}
3780
		return true;
3781
	}
3782
	
3783
	this.move = function(x, y) {
3784
		switch(true) {
3785
			case !this.trace(x, y):
3786
				window.SetCursor(IDC_ARROW);
3787
				return false;
3788
			case this.up_btn.trace(x, y):
3789
			case this.down_btn.trace(x, y):
3790
				window.SetCursor(IDC_HAND);
3791
				return true;
3792
			default:
3793
				window.SetCursor(IDC_ARROW);
3794
				return false;
3795
		}
3796
	}
3797
	
3798
	this.lbtn_up = function(x, y) {
3799
		if (!this.trace(x, y)) return false;
3800
		this.up_btn.lbtn_up(x, y);
3801
		this.down_btn.lbtn_up(x, y);
3802
		return true;
3803
	}
3804
	
3805
	this.get = function() {
3806
		var fn = this.filename;
3807
		var func = function() {
3808
			if (!p.save(t.xmlhttp.responsetext, fn)) return;
3809
			t.artist = "";
3810
			t.album = "";
3811
			on_item_focus_change();
3812
		}
3813
		var url = "";
3814
		var user_agent = "";
3815
		switch(this.mode) {
3816
			case "lastfm_album":
3817
				if (this.artist == "" || this.album == "") return;
3818
				url = l.get_url() + "&method=album.getInfo&artist=" + encodeURIComponent(this.artist) + "&album=" + encodeURIComponent(this.album);
3819
				user_agent = l.user_agent;
3820
				break;
3821
			case "lastfm_wiki":
3822
				if (this.artist == "" || this.artist == "?") return;
3823
				url = "http://developer.echonest.com/api/v4/artist/biographies?api_key=EKWS4ESQLKN3G2ZWV&format=json&name=" + encodeURIComponent(this.artist);
3824
				break;
3825
		}
3826
		if (url.length == 0) return;
3827
		this.xmlhttp.open("GET", url, true);
3828
		if (user_agent.length > 0) this.xmlhttp.setRequestHeader('User-Agent', user_agent);
3829
		this.xmlhttp.send();
3830
		this.xmlhttp.onreadystatechange = function() {
3831
			if (t.xmlhttp.readyState == 4) {
3832
				if (t.xmlhttp.status == 200) {
3833
					func();
3834
				} else {
3835
					p.console(t.xmlhttp.responsetext || "HTTP error: " + t.xmlhttp.status);
3836
				}
3837
			}
3838
		}
3839
	}
3840
	
3841
	this.calc = function() {
3842
		this.offset = 0;
3843
		this.text_rows = 0;
3844
		if (this.w < 100 || this.text.length == 0) return;
3845
		var temp_bmp = gdi.CreateImage(1, 1);
3846
		var temp_gr = temp_bmp.GetGraphics();
3847
		var paragraphs = this.text.split("\n");
3848
		this.text_array = [];
3849
		for (i = 0; i < paragraphs.length; i++) {
3850
			if (this.fixed) {
3851
				this.text_array.push(paragraphs[i]);
3852
			} else {
3853
				var lines = temp_gr.EstimateLineWrap(paragraphs[i], p.normal_font, this.w).toArray();
3854
				for (j = 0; j < lines.length; j += 2) {
3855
					this.text_array.push(lines[j].trim());
3856
				}
3857
			}
3858
		}
3859
		this.text_rows = this.text_array.length;
3860
		temp_bmp.ReleaseGraphics(temp_gr);
3861
		temp_bmp.Dispose();
3862
		temp_gr = null;
3863
		temp_bmp = null;
3864
	}
3865
	
3866
	this.init = function() {
3867
		switch(true) {
3868
			case p.check_feature("lastfm_album"):
3869
				this.mode = "lastfm_album";
3870
				break;
3871
			case p.check_feature("lastfm_wiki"):
3872
				this.mode = "lastfm_wiki";
3873
				this.source = window.GetProperty("biography_source", "last.fm");
3874
				break;
3875
			case p.check_feature("simple_text"):
3876
				this.mode = "simple_text";
3877
				this.title = window.GetProperty("text_title", "$directory_path(%path%)");
3878
				this.filename_tf = window.GetProperty("text_filename_tf", "$directory_path(%path%)");
3879
				this.filename = "";
3880
				this.fixed = window.GetProperty("text_fixed_font", true);
3881
				break;
3882
			case p.check_feature("simple_tag"):
3883
				this.mode = "simple_tag";
3884
				this.title = window.GetProperty("text_title", "%title%");
3885
				this.filename = "";
3886
				this.centre = window.GetProperty("text_centre", false);
3887
				this.tag = window.GetProperty("text_tag", "[%lyrics%]");
3888
				break;
3889
		}
3890
	}
3891
	
3892
	this.x = x;
3893
	this.y = y;
3894
	this.w = w;
3895
	this.h = h;
3896
	this.text = "";
3897
	this.artist = "";
3898
	this.album = "";
3899
	this.url = "";
3900
	this.fixed = false;
3901
	this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
3902
	this.init();
3903
	this.size();
3904
}
3905
3906
function thumbs() {
3907
	this.trace = function(x, y) {
3908
		return (x > this.x && x < this.x + this.w && y > this.y && y < this.y + this.h);
3909
	}
3910
	
3911
	this.draw = function(gr) {
3912
		switch(true) {
3913
			case im.images.length == 0:
3914
				break;
3915
			case this.mode == "off":
3916
				p.draw_image(gr, im.images[im.index], im.x, im.y, im.w, im.h, im.type);
3917
				break;
3918
			case !this.img:
3919
				break;
3920
			case this.mode == "grid":
3921
				gr.DrawImage(this.img, this.x, this.y, this.w, this.h, 0, this.offset * this.px, this.w, this.h);
3922
				if (this.overlay) {
3923
					gr.FillSolidRect(this.x, this.y, this.w, this.h, RGBA(0, 0, 0, 126));
3924
					p.draw_image(gr, im.images[im.index], im.x, im.y, im.w, im.h, "adjust");
3925
				}
3926
				break;
3927
			case this.mode == "left":
3928
			case this.mode == "right":
3929
				gr.DrawImage(this.img, this.x, this.y, this.w, this.h, 0, this.offset * this.px, this.w, this.h);
3930
				p.draw_image(gr, im.images[im.index], im.x, im.y, im.w, im.h, im.type);
3931
				break;
3932
			case this.mode == "bottom":
3933
			case this.mode == "top":
3934
				gr.DrawImage(this.img, this.x, this.y, this.w, this.h, this.offset * this.px, 0, this.w, this.h);
3935
				p.draw_image(gr, im.images[im.index], im.x, im.y, im.w, im.h, im.type);
3936
				break;
3937
		}
3938
	}
3939
	
3940
	this.calc = function() {
3941
		this.offset = 0;
3942
		switch(true) {
3943
			case p.w < this.px || p.h < this.px || this.mode == "off":
3944
				this.nc = true;
3945
				this.img && this.img.Dispose();
3946
				this.img = null;
3947
				im.x = 0;
3948
				im.y = 0;
3949
				im.w = p.w;
3950
				im.h = p.h;
3951
				break;
3952
			case this.mode == "grid":
3953
				this.x = 0;
3954
				this.y = 0;
3955
				this.w = p.w;
3956
				this.h = p.h;
3957
				im.x = 40;
3958
				im.y = 40;
3959
				im.w = this.w - 80;
3960
				im.h = this.h - 80;
3961
				if (!this.nc && this.columns != Math.floor(this.w / this.px)) this.nc = true;
3962
				this.overlay = false;
3963
				this.rows = Math.ceil(this.h / this.px);
3964
				this.columns = Math.floor(this.w / this.px);
3965
				this.img_rows = Math.ceil(im.images.length / this.columns);
3966
				if (this.nc && im.images.length > 0) {
3967
					this.nc = false;
3968
					this.img && this.img.Dispose();
3969
					this.img = null;
3970
					this.img = gdi.CreateImage(Math.min(this.columns, im.images.length) * this.px, this.img_rows * this.px);
3971
					var temp_gr = this.img.GetGraphics();
3972
					temp_gr.SetInterpolationMode(7);
3973
					var ci = 0;
3974
					var row, col;
3975
					for (row = 0; row < this.img_rows; row++) {
3976
						for (col = 0; col < this.columns; col++) {
3977
							if (ci == im.images.length) continue;
3978
							p.draw_image(temp_gr, im.images[ci], col * this.px, row * this.px, this.px, this.px, "top");
3979
							ci++;
3980
						}
3981
					}
3982
					this.img.ReleaseGraphics(temp_gr);
3983
					temp_gr = null;
3984
				}
3985
				break;
3986
			case this.mode == "left":
3987
			case this.mode == "right":
3988
				this.x = this.mode == "left" ? 0 : p.w - this.px;
3989
				this.y = 0;
3990
				this.w = this.px;
3991
				this.h = p.h;
3992
				im.x = this.mode == "right" ? 0 : this.px;
3993
				im.y = 0;
3994
				im.w = p.w - this.px;
3995
				im.h = p.h;
3996
				this.rows = Math.ceil(this.h / this.px);
3997
				if (this.nc && im.images.length > 0) {
3998
					this.nc = false;
3999
					this.img && this.img.Dispose();
4000
					this.img = null;
4001
					this.img = gdi.CreateImage(this.px, this.px * im.images.length);
4002
					var temp_gr = this.img.GetGraphics();
4003
					temp_gr.SetInterpolationMode(7);
4004
					for (i = 0; i < im.images.length; i++) {
4005
						p.draw_image(temp_gr, im.images[i], 0, i * this.px, this.px, this.px, "top");
4006
					}
4007
					this.img.ReleaseGraphics(temp_gr);
4008
					temp_gr = null;
4009
				}
4010
				break;
4011
			case this.mode == "bottom":
4012
			case this.mode == "top":
4013
				this.x = 0;
4014
				this.y = this.mode == "top" ? 0 : p.h - this.px;
4015
				this.w = p.w;
4016
				this.h = this.px;
4017
				im.x = 0;
4018
				im.y = this.mode == "bottom" ? 0 : this.px;
4019
				im.w = p.w;
4020
				im.h = p.h - this.px;
4021
				this.columns = Math.ceil(this.w / this.px);
4022
				if (this.nc && im.images.length > 0) {
4023
					this.nc = false;
4024
					this.img && this.img.Dispose();
4025
					this.img = null;
4026
					this.img = gdi.CreateImage(this.px * im.images.length, this.px);
4027
					var temp_gr = this.img.GetGraphics();
4028
					temp_gr.SetInterpolationMode(7);
4029
					for (i = 0; i < im.images.length; i++) {
4030
						p.draw_image(temp_gr, im.images[i], i * this.px, 0, this.px, this.px, "top");
4031
					}
4032
					this.img.ReleaseGraphics(temp_gr);
4033
					temp_gr = null;
4034
				}
4035
				break;
4036
		}
4037
	}
4038
	
4039
	this.wheel = function(step) {
4040
		switch(true) {
4041
			case !this.trace(p.mx, p.my):
4042
			case this.overlay:
4043
				return false;
4044
			case this.mode == "grid":
4045
				if (this.img_rows < this.rows) return true;
4046
				this.offset -= step;
4047
				if (this.offset < 0) this.offset = 0;
4048
				if (this.offset > this.img_rows - this.rows) this.offset = this.img_rows - this.rows + 1;
4049
				break;
4050
			case this.mode == "left":
4051
			case this.mode == "right":
4052
				if (im.images.length < this.rows) return true;
4053
				this.offset -= step;
4054
				if (this.offset < 0) this.offset = 0;
4055
				if (this.rows + this.offset > im.images.length) this.offset = im.images.length - this.rows + 1;
4056
				break;
4057
			case this.mode == "bottom":
4058
			case this.mode == "top":
4059
				if (im.images.length < this.columns) return true;
4060
				this.offset -= step;
4061
				if (this.offset < 0) this.offset = 0;
4062
				if (this.columns + this.offset > im.images.length) this.offset = im.images.length - this.columns + 1;
4063
				break;
4064
		}
4065
		window.RepaintRect(this.x, this.y, this.w, this.h);
4066
		return true;
4067
	}
4068
	
4069
	this.move = function(x, y) {
4070
		switch(true) {
4071
			case !this.trace(x, y):
4072
				window.SetCursor(IDC_ARROW);
4073
				return false;
4074
			case this.overlay:
4075
				window.SetCursor(IDC_ARROW);
4076
				return true;
4077
			case this.mode == "grid":
4078
				this.index = Math.floor((x - this.x) / this.px) + (Math.floor((y - this.y) / this.px) * this.columns) + (this.offset * this.columns);
4079
				break;
4080
			case this.mode == "left":
4081
			case this.mode == "right":
4082
				this.index = Math.floor((y - this.y) / this.px) + this.offset;
4083
				break;
4084
			case this.mode == "bottom":
4085
			case this.mode == "top":
4086
				this.index = Math.floor((x - this.x) / this.px) + this.offset;
4087
				break;
4088
		}
4089
		window.SetCursor(this.index < im.images.length ? IDC_HAND : IDC_ARROW);
4090
		return true;
4091
	}
4092
	
4093
	this.lbtn_up = function(x, y) {
4094
		switch(true) {
4095
			case !this.trace(x, y):
4096
				return false;
4097
			case this.mode == "grid" && this.overlay && im.trace(x, y):
4098
				this.overlay = false;
4099
				window.Repaint();
4100
				break;
4101
			case this.mode == "grid" && this.index < im.images.length && !this.overlay:
4102
				this.overlay = true;
4103
				im.index = this.index;
4104
				window.Repaint();
4105
				break;
4106
			case this.overlay:
4107
				break;
4108
			case this.index < im.images.length:
4109
				im.index = this.index;
4110
				window.Repaint();
4111
		}
4112
		return true;
4113
	}
4114
	
4115
	this.lbtn_dblclk = function(x, y) {
4116
		if (!im.trace(x, y) || th.mode == "grid") return false;
4117
		p.run("\"" + im.files[im.index] + "\"");
4118
		return true;
4119
	}
4120
	
4121
	this.nc = false;
4122
	this.mode = "off";
4123
	this.px = 40;
4124
	this.img = null;
4125
}
4126
4127
//json2.js
4128
if(typeof JSON!=='object'){JSON={};}
4129
(function(){'use strict';function f(n){return n<10?'0'+n:n;}
4130
if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+
4131
f(this.getUTCMonth()+1)+'-'+
4132
f(this.getUTCDate())+'T'+
4133
f(this.getUTCHours())+':'+
4134
f(this.getUTCMinutes())+':'+
4135
f(this.getUTCSeconds())+'Z':null;};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf();};}
4136
var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';}
4137
function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key);}
4138
if(typeof rep==='function'){value=rep.call(holder,key,value);}
4139
switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';}
4140
gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||'null';}
4141
v=partial.length===0?'[]':gap?'[\n'+gap+partial.join(',\n'+gap)+'\n'+mind+']':'['+partial.join(',')+']';gap=mind;return v;}
4142
if(rep&&typeof rep==='object'){length=rep.length;for(i=0;i<length;i+=1){if(typeof rep[i]==='string'){k=rep[i];v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}else{for(k in value){if(Object.prototype.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}
4143
v=partial.length===0?'{}':gap?'{\n'+gap+partial.join(',\n'+gap)+'\n'+mind+'}':'{'+partial.join(',')+'}';gap=mind;return v;}}
4144
if(typeof JSON.stringify!=='function'){JSON.stringify=function(value,replacer,space){var i;gap='';indent='';if(typeof space==='number'){for(i=0;i<space;i+=1){indent+=' ';}}else if(typeof space==='string'){indent=space;}
4145
rep=replacer;if(replacer&&typeof replacer!=='function'&&(typeof replacer!=='object'||typeof replacer.length!=='number')){throw new Error('JSON.stringify');}
4146
return str('',{'':value});};}
4147
if(typeof JSON.parse!=='function'){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==='object'){for(k in value){if(Object.prototype.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v;}else{delete value[k];}}}}
4148
return reviver.call(holder,key,value);}
4149
text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return'\\u'+
4150
('0000'+a.charCodeAt(0).toString(16)).slice(-4);});}
4151
if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){j=eval('('+text+')');return typeof reviver==='function'?walk({'':j},''):j;}
4152
throw new SyntaxError('JSON.parse');};}}());
4153
4154
/*
4155
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
4156
 * Digest Algorithm, as defined in RFC 1321.
4157
 * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
4158
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
4159
 * Distributed under the BSD License
4160
 * See http://pajhome.org.uk/crypt/md5 for more info.
4161
 */
4162
var hexcase=0;function hex_md5(a){return rstr2hex(rstr_md5(str2rstr_utf8(a)))}
4163
function hex_hmac_md5(a,b){return rstr2hex(rstr_hmac_md5(str2rstr_utf8(a),str2rstr_utf8(b)))}
4164
function md5_vm_test(){return hex_md5("abc").toLowerCase()=="900150983cd24fb0d6963f7d28e17f72"}
4165
function rstr_md5(a){return binl2rstr(binl_md5(rstr2binl(a),a.length*8))}
4166
function rstr_hmac_md5(c,f){var e=rstr2binl(c);if(e.length>16){e=binl_md5(e,c.length*8)}
4167
var a=Array(16),d=Array(16);for(var b=0;b<16;b++){a[b]=e[b]^909522486;d[b]=e[b]^1549556828}
4168
var g=binl_md5(a.concat(rstr2binl(f)),512+f.length*8);return binl2rstr(binl_md5(d.concat(g),512+128))}
4169
function rstr2hex(c){try{hexcase}catch(g){hexcase=0}
4170
var f=hexcase?"0123456789ABCDEF":"0123456789abcdef";var b="";var a;for(var d=0;d<c.length;d++){a=c.charCodeAt(d);b+=f.charAt((a>>>4)&15)+f.charAt(a&15)}
4171
return b}
4172
function str2rstr_utf8(c){var b="";var d=-1;var a,e;while(++d<c.length){a=c.charCodeAt(d);e=d+1<c.length?c.charCodeAt(d+1):0;if(55296<=a&&a<=56319&&56320<=e&&e<=57343){a=65536+((a&1023)<<10)+(e&1023);d++}
4173
if(a<=127){b+=String.fromCharCode(a)}else{if(a<=2047){b+=String.fromCharCode(192|((a>>>6)&31),128|(a&63))}else{if(a<=65535){b+=String.fromCharCode(224|((a>>>12)&15),128|((a>>>6)&63),128|(a&63))}else{if(a<=2097151){b+=String.fromCharCode(240|((a>>>18)&7),128|((a>>>12)&63),128|((a>>>6)&63),128|(a&63))}}}}}
4174
return b}
4175
function rstr2binl(b){var a=Array(b.length>>2);for(var c=0;c<a.length;c++){a[c]=0}
4176
for(var c=0;c<b.length*8;c+=8){a[c>>5]|=(b.charCodeAt(c/8)&255)<<(c%32)}
4177
return a}
4178
function binl2rstr(b){var a="";for(var c=0;c<b.length*32;c+=8){a+=String.fromCharCode((b[c>>5]>>>(c%32))&255)}
4179
return a}
4180
function binl_md5(p,k){p[k>>5]|=128<<((k)%32);p[(((k+64)>>>9)<<4)+14]=k;var o=1732584193;var n=-271733879;var m=-1732584194;var l=271733878;for(var g=0;g<p.length;g+=16){var j=o;var h=n;var f=m;var e=l;o=md5_ff(o,n,m,l,p[g+0],7,-680876936);l=md5_ff(l,o,n,m,p[g+1],12,-389564586);m=md5_ff(m,l,o,n,p[g+2],17,606105819);n=md5_ff(n,m,l,o,p[g+3],22,-1044525330);o=md5_ff(o,n,m,l,p[g+4],7,-176418897);l=md5_ff(l,o,n,m,p[g+5],12,1200080426);m=md5_ff(m,l,o,n,p[g+6],17,-1473231341);n=md5_ff(n,m,l,o,p[g+7],22,-45705983);o=md5_ff(o,n,m,l,p[g+8],7,1770035416);l=md5_ff(l,o,n,m,p[g+9],12,-1958414417);m=md5_ff(m,l,o,n,p[g+10],17,-42063);n=md5_ff(n,m,l,o,p[g+11],22,-1990404162);o=md5_ff(o,n,m,l,p[g+12],7,1804603682);l=md5_ff(l,o,n,m,p[g+13],12,-40341101);m=md5_ff(m,l,o,n,p[g+14],17,-1502002290);n=md5_ff(n,m,l,o,p[g+15],22,1236535329);o=md5_gg(o,n,m,l,p[g+1],5,-165796510);l=md5_gg(l,o,n,m,p[g+6],9,-1069501632);m=md5_gg(m,l,o,n,p[g+11],14,643717713);n=md5_gg(n,m,l,o,p[g+0],20,-373897302);o=md5_gg(o,n,m,l,p[g+5],5,-701558691);l=md5_gg(l,o,n,m,p[g+10],9,38016083);m=md5_gg(m,l,o,n,p[g+15],14,-660478335);n=md5_gg(n,m,l,o,p[g+4],20,-405537848);o=md5_gg(o,n,m,l,p[g+9],5,568446438);l=md5_gg(l,o,n,m,p[g+14],9,-1019803690);m=md5_gg(m,l,o,n,p[g+3],14,-187363961);n=md5_gg(n,m,l,o,p[g+8],20,1163531501);o=md5_gg(o,n,m,l,p[g+13],5,-1444681467);l=md5_gg(l,o,n,m,p[g+2],9,-51403784);m=md5_gg(m,l,o,n,p[g+7],14,1735328473);n=md5_gg(n,m,l,o,p[g+12],20,-1926607734);o=md5_hh(o,n,m,l,p[g+5],4,-378558);l=md5_hh(l,o,n,m,p[g+8],11,-2022574463);m=md5_hh(m,l,o,n,p[g+11],16,1839030562);n=md5_hh(n,m,l,o,p[g+14],23,-35309556);o=md5_hh(o,n,m,l,p[g+1],4,-1530992060);l=md5_hh(l,o,n,m,p[g+4],11,1272893353);m=md5_hh(m,l,o,n,p[g+7],16,-155497632);n=md5_hh(n,m,l,o,p[g+10],23,-1094730640);o=md5_hh(o,n,m,l,p[g+13],4,681279174);l=md5_hh(l,o,n,m,p[g+0],11,-358537222);m=md5_hh(m,l,o,n,p[g+3],16,-722521979);n=md5_hh(n,m,l,o,p[g+6],23,76029189);o=md5_hh(o,n,m,l,p[g+9],4,-640364487);l=md5_hh(l,o,n,m,p[g+12],11,-421815835);m=md5_hh(m,l,o,n,p[g+15],16,530742520);n=md5_hh(n,m,l,o,p[g+2],23,-995338651);o=md5_ii(o,n,m,l,p[g+0],6,-198630844);l=md5_ii(l,o,n,m,p[g+7],10,1126891415);m=md5_ii(m,l,o,n,p[g+14],15,-1416354905);n=md5_ii(n,m,l,o,p[g+5],21,-57434055);o=md5_ii(o,n,m,l,p[g+12],6,1700485571);l=md5_ii(l,o,n,m,p[g+3],10,-1894986606);m=md5_ii(m,l,o,n,p[g+10],15,-1051523);n=md5_ii(n,m,l,o,p[g+1],21,-2054922799);o=md5_ii(o,n,m,l,p[g+8],6,1873313359);l=md5_ii(l,o,n,m,p[g+15],10,-30611744);m=md5_ii(m,l,o,n,p[g+6],15,-1560198380);n=md5_ii(n,m,l,o,p[g+13],21,1309151649);o=md5_ii(o,n,m,l,p[g+4],6,-145523070);l=md5_ii(l,o,n,m,p[g+11],10,-1120210379);m=md5_ii(m,l,o,n,p[g+2],15,718787259);n=md5_ii(n,m,l,o,p[g+9],21,-343485551);o=safe_add(o,j);n=safe_add(n,h);m=safe_add(m,f);l=safe_add(l,e)}
4181
return Array(o,n,m,l)}
4182
function md5_cmn(h,e,d,c,g,f){return safe_add(bit_rol(safe_add(safe_add(e,h),safe_add(c,f)),g),d)}
4183
function md5_ff(g,f,k,j,e,i,h){return md5_cmn((f&k)|((~f)&j),g,f,e,i,h)}
4184
function md5_gg(g,f,k,j,e,i,h){return md5_cmn((f&j)|(k&(~j)),g,f,e,i,h)}
4185
function md5_hh(g,f,k,j,e,i,h){return md5_cmn(f^k^j,g,f,e,i,h)}
4186
function md5_ii(g,f,k,j,e,i,h){return md5_cmn(k^(f|(~j)),g,f,e,i,h)}
4187
function safe_add(a,d){var c=(a&65535)+(d&65535);var b=(a>>16)+(d>>16)+(c>>16);return(b<<16)|(c&65535)}
4188
function bit_rol(a,b){return(a<<b)|(a>>>(32-b))};
4189
4190
4191
4192
4193
4194
var p = new panel("Youtube Radio", ["custom_background", "remap", "metadb"]);
4195
var im = new images(0, 0, 0, 0);
4196
var th = new thumbs();
4197
4198
on_item_focus_change();
4199
4200
function on_metadb_changed() {
4201
	im.metadb_changed();
4202
}
4203
4204
//Button
4205
4206
var Buttons;
4207
4208
var g_tooltip = window.CreateTooltip();
4209
var g_down = false;
4210
4211
var btn_down = null;
4212
var cur_btn = null;
4213
4214
ButtonStates = {
4215
	normal: 0,
4216
	hover: 1,
4217
	down: 2
4218
}
4219
4220
function Button(x, y, w, h, img_src, func, tiptext)  {
4221
	this.left = x;
4222
	this.top = y;
4223
	this.w = w;
4224
	this.h = h;
4225
	this.right = x + w;
4226
	this.bottom = y + h;
4227
	this.func = func;
4228
	this.tiptext = tiptext;
4229
	this.state = ButtonStates.normal;
4230
	this.img_normal = img_src && img_src.normal ? gdi.Image(img_src.normal) : null;
4231
	this.img_hover = img_src && img_src.hover ? gdi.Image(img_src.hover) : this.img_normal;
4232
	this.img_down = img_src && img_src.down ? gdi.Image(img_src.down) : this.img_hover;
4233
	this.img = this.img_normal;
4234
	
4235
	this.alterImage = function(img_src) {
4236
		this.img_normal = img_src && img_src.normal ? gdi.Image(img_src.normal) : null;
4237
		this.img_hover = img_src && img_src.hover ? gdi.Image(img_src.hover) : this.img_normal;
4238
		this.img_down = img_src && img_src.down ? gdi.Image(img_src.down) : this.img_hover;
4239
		
4240
		this.changeState(this.state);
4241
	}
4242
	
4243
	this.traceMouse = function (x, y) {
4244
		var b = (this.left < x) && (x < this.right) && (this.top < y) && (y < this.bottom);
4245
		if (b)
4246
			g_down ? this.changeState(ButtonStates.down) : this.changeState(ButtonStates.hover);
4247
		else
4248
			this.changeState(ButtonStates.normal);
4249
		return b;
4250
	}
4251
	
4252
	
4253
	this.changeState = function (newstate) {
4254
		if (newstate != this.state)
4255
			window.RepaintRect(this.left, this.top, this.w, this.h);
4256
		this.state = newstate;
4257
		switch (this.state)
4258
		{
4259
		case ButtonStates.normal:
4260
			this.img = this.img_normal;
4261
			break;
4262
			
4263
		case ButtonStates.hover:
4264
			this.img = this.img_hover;
4265
			break;
4266
			
4267
		case ButtonStates.down:
4268
			this.img = this.img_down;
4269
			break;
4270
			
4271
		default:
4272
			this.img = null;
4273
		}
4274
	}
4275
	
4276
	this.draw = function (gr) {
4277
		this.img && gr.DrawImage(this.img, this.left, this.top, this.w, this.h, 0, 0, this.w, this.h);
4278
	}
4279
	
4280
	this.onClick = function () {
4281
		this.func && this.func(x,y);
4282
	}
4283
	
4284
	this.onMouseIn = function() {
4285
		g_tooltip.Text = this.tiptext;
4286
		g_tooltip.Activate();
4287
	}
4288
	
4289
	this.onMouseOut = function() {
4290
		g_tooltip.Deactivate();
4291
	}
4292
}
4293
4294
function buttonsDraw(gr) {
4295
	for (i in Buttons) {
4296
		Buttons[i].draw(gr);
4297
	}
4298
}
4299
4300
function buttonsTraceMouse(x, y) {
4301
	var btn = null;
4302
	for (i in Buttons) {
4303
		if (Buttons[i].traceMouse(x, y) && !btn)
4304
			btn = Buttons[i];
4305
	}
4306
4307
	return btn;
4308
}
4309
4310
function on_mouse_move(x, y) {
4311
	var btn = buttonsTraceMouse(x, y);
4312
	
4313
	if (btn != cur_btn) {
4314
		cur_btn && cur_btn.onMouseOut();
4315
		btn && btn.onMouseIn();
4316
	}
4317
	
4318
	cur_btn = btn;
4319
}
4320
4321
function on_mouse_lbtn_down(x, y) {
4322
	g_down = true;
4323
	btn_down = cur_btn;
4324
4325
	if (cur_btn) {
4326
		cur_btn.changeState(ButtonStates.down);
4327
	}
4328
}
4329
4330
function on_mouse_lbtn_up(x, y) {
4331
	if (cur_btn) {
4332
		cur_btn.changeState(ButtonStates.hover);
4333
		if( btn_down == cur_btn )
4334
			cur_btn.onClick(x, y);
4335
	}
4336
	g_down = false;
4337
}
4338
4339
function on_mouse_leave() {
4340
	if (cur_btn) {
4341
		cur_btn.changeState(ButtonStates.normal);
4342
	}
4343
}
4344
4345
function on_size() {
4346
	ww = window.Width;
4347
	wh = window.Height;
4348
    window.Repaint();
4349
}
4350
4351
function on_paint(gr) {
4352
	/*switch(window.GetProperty("mode", 1)) {
4353
		case 1:
4354
			//col = window.GetColorDUI(1);
4355
			break;
4356
		case 2:
4357
			col = utils.GetSysColor(4);
4358
			break;
4359
		case 3:
4360
			col = custom;
4361
			break;
4362
	}*/
4363
	//gr.FillSolidRect(0, 0, ww, wh, col);
4364
	buttonsDraw(gr);
4365
	//gr.DrawRect(0,0, ww, wh, 1.0, -6250336);
4366
}
4367
4368
function RGB(r,g,b) {
4369
	return (0xff000000|(r<<16)|(g<<8)|(b)); 
4370
}
4371
4372
function on_colors_changed() {
4373
    window.Repaint();
4374
}
4375
4376
4377
//init Buttons
4378
4379
//custom colour accessed through the context menu
4380
var custom = RGB(255,255,255);
4381
4382
//button width
4383
var bw = 24;
4384
//button height
4385
var bh = 20;
4386
4387
//Button position
4388
var top_margin = -1;
4389
var left_margin = 0;
4390
4391
var image_path0 = window.GetProperty("Button Path", fb.ProfilePath + "image");
4392
var image_path = (image_path0 + "\\");
4393
4394
//these 2 lines of code lock the panel size. you can comment them out or change the dimensions to suit
4395
//window.MinWidth = window.MaxWidth = 24;
4396
//window.MinHeight = window.MaxHeight = 20;
4397
4398
4399
4400
Buttons = {
4401
	but1: new Button(left_margin,top_margin,bw,bh, {normal: image_path + "youtube0.png", hover: image_path + "youtube1.png"}, function(){
4402
        //if (p.artist.indexOf("3dydfy://")== 0 | p.artist.indexOf("www.youtube.com/")== 0 | p.artist.indexOf("youtube.com/")== 0 | p.artist.indexOf("http://www.youtube.com/")== 0)
4403
        p.rbtn_up(24, 17);
4404
        //im.downloadONE();
4405
        /*else
4406
        {
4407
        p.artist = p.eval("%artist% %title%");
4408
        p.browser("http://www.youtube.com/results?search_query=" + encodeURIComponent(p.artist) + "&ie=utf-8");
4409
    }*/
4410
        }, "Youtube")
4411
	
4412
}
4413
4414
//fb.RunMainMenuCommand("Library/Search");
4415
//fb.RunContextCommand("Open containing folder");
4416
4417
function on_mouse_rbtn_up(x, y) {
4418
return true;
4419
}