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