· 3 years ago · Sep 21, 2022, 08:50 AM
1// Alsong Lyric Source for ESLyric
2// Original code by Berrzebb (2020-03-03, v0.3.0)
3// Modified by TetraTheta (2022-09-21)
4
5// Original comment:
6// File Hash Finish
7// 외부 서버로 md5 계산 Pass
8// FileStream 객체에서 데이터를 읽어 올때 utf-16 대응 추가.
9
10// Changelog
11// - Find lyrics by file hash first, then metadata
12// - Calculate MD5 locally, instead of request
13
14var dbg = false;
15
16export function getConfig(cfg) {
17 cfg.name = "Alsong Lyric Source";
18 cfg.version = "0.3.0";
19 cfg.author = "Berrzebb";
20 cfg.useRawMeta = false;
21}
22
23export function getLyrics(meta, man) {
24 // TODO: move code to here
25}
26
27var encData = '8582df6473c019a3186a2974aa1e034ae1b2bbb2e7c99575aadc475fcddd997d74bbc1ce3d50b9900282903ee9eb60ae8c5bbf27484441bacb41ecf9128402696641655ff38c2cbbf3c81396034a883af2d82e0545ec32170bddc7c141208e7255e367e5b5ebd81750226856f5405ec3ad7b6f8600c32c2718c4c525bfe34666'
28function md5(d) {
29 return rstr2hex(binl2rstr(binl_md5(rstr2binl(d), 8 * d.length)))
30}
31
32function rstr2hex(d) {
33 for (var _, m = "0123456789ABCDEF", f = "", r = 0; r < d.length; r++) _ = d.charCodeAt(r), f += m.charAt(_ >>> 4 & 15) + m.charAt(15 & _);
34 return f
35}
36
37function rstr2binl(d) {
38 for (var _ = Array(d.length >> 2), m = 0; m < _.length; m++) _[m] = 0;
39 for (m = 0; m < 8 * d.length; m += 8) _[m >> 5] |= (255 & d.charCodeAt(m / 8)) << m % 32;
40 return _
41}
42
43function binl2rstr(d) {
44 for (var _ = "", m = 0; m < 32 * d.length; m += 8) _ += String.fromCharCode(d[m >> 5] >>> m % 32 & 255);
45 return _
46}
47
48function binl_md5(d, _) {
49 d[_ >> 5] |= 128 << _ % 32, d[14 + (_ + 64 >>> 9 << 4)] = _;
50 for (var m = 1732584193, f = -271733879, r = -1732584194, i = 271733878, n = 0; n < d.length; n += 16) {
51 var h = m,
52 t = f,
53 g = r,
54 e = i;
55 f = md5_ii(f = md5_ii(f = md5_ii(f = md5_ii(f = md5_hh(f = md5_hh(f = md5_hh(f = md5_hh(f = md5_gg(f = md5_gg(f = md5_gg(f = md5_gg(f = md5_ff(f = md5_ff(f = md5_ff(f = md5_ff(f, r = md5_ff(r, i = md5_ff(i, m = md5_ff(m, f, r, i, d[n + 0], 7, -680876936), f, r, d[n + 1], 12, -389564586), m, f, d[n + 2], 17, 606105819), i, m, d[n + 3], 22, -1044525330), r = md5_ff(r, i = md5_ff(i, m = md5_ff(m, f, r, i, d[n + 4], 7, -176418897), f, r, d[n + 5], 12, 1200080426), m, f, d[n + 6], 17, -1473231341), i, m, d[n + 7], 22, -45705983), r = md5_ff(r, i = md5_ff(i, m = md5_ff(m, f, r, i, d[n + 8], 7, 1770035416), f, r, d[n + 9], 12, -1958414417), m, f, d[n + 10], 17, -42063), i, m, d[n + 11], 22, -1990404162), r = md5_ff(r, i = md5_ff(i, m = md5_ff(m, f, r, i, d[n + 12], 7, 1804603682), f, r, d[n + 13], 12, -40341101), m, f, d[n + 14], 17, -1502002290), i, m, d[n + 15], 22, 1236535329), r = md5_gg(r, i = md5_gg(i, m = md5_gg(m, f, r, i, d[n + 1], 5, -165796510), f, r, d[n + 6], 9, -1069501632), m, f, d[n + 11], 14, 643717713), i, m, d[n + 0], 20, -373897302), r = md5_gg(r, i = md5_gg(i, m = md5_gg(m, f, r, i, d[n + 5], 5, -701558691), f, r, d[n + 10], 9, 38016083), m, f, d[n + 15], 14, -660478335), i, m, d[n + 4], 20, -405537848), r = md5_gg(r, i = md5_gg(i, m = md5_gg(m, f, r, i, d[n + 9], 5, 568446438), f, r, d[n + 14], 9, -1019803690), m, f, d[n + 3], 14, -187363961), i, m, d[n + 8], 20, 1163531501), r = md5_gg(r, i = md5_gg(i, m = md5_gg(m, f, r, i, d[n + 13], 5, -1444681467), f, r, d[n + 2], 9, -51403784), m, f, d[n + 7], 14, 1735328473), i, m, d[n + 12], 20, -1926607734), r = md5_hh(r, i = md5_hh(i, m = md5_hh(m, f, r, i, d[n + 5], 4, -378558), f, r, d[n + 8], 11, -2022574463), m, f, d[n + 11], 16, 1839030562), i, m, d[n + 14], 23, -35309556), r = md5_hh(r, i = md5_hh(i, m = md5_hh(m, f, r, i, d[n + 1], 4, -1530992060), f, r, d[n + 4], 11, 1272893353), m, f, d[n + 7], 16, -155497632), i, m, d[n + 10], 23, -1094730640), r = md5_hh(r, i = md5_hh(i, m = md5_hh(m, f, r, i, d[n + 13], 4, 681279174), f, r, d[n + 0], 11, -358537222), m, f, d[n + 3], 16, -722521979), i, m, d[n + 6], 23, 76029189), r = md5_hh(r, i = md5_hh(i, m = md5_hh(m, f, r, i, d[n + 9], 4, -640364487), f, r, d[n + 12], 11, -421815835), m, f, d[n + 15], 16, 530742520), i, m, d[n + 2], 23, -995338651), r = md5_ii(r, i = md5_ii(i, m = md5_ii(m, f, r, i, d[n + 0], 6, -198630844), f, r, d[n + 7], 10, 1126891415), m, f, d[n + 14], 15, -1416354905), i, m, d[n + 5], 21, -57434055), r = md5_ii(r, i = md5_ii(i, m = md5_ii(m, f, r, i, d[n + 12], 6, 1700485571), f, r, d[n + 3], 10, -1894986606), m, f, d[n + 10], 15, -1051523), i, m, d[n + 1], 21, -2054922799), r = md5_ii(r, i = md5_ii(i, m = md5_ii(m, f, r, i, d[n + 8], 6, 1873313359), f, r, d[n + 15], 10, -30611744), m, f, d[n + 6], 15, -1560198380), i, m, d[n + 13], 21, 1309151649), r = md5_ii(r, i = md5_ii(i, m = md5_ii(m, f, r, i, d[n + 4], 6, -145523070), f, r, d[n + 11], 10, -1120210379), m, f, d[n + 2], 15, 718787259), i, m, d[n + 9], 21, -343485551), m = safe_add(m, h), f = safe_add(f, t), r = safe_add(r, g), i = safe_add(i, e)
56 }
57 return Array(m, f, r, i)
58}
59
60function md5_cmn(d, _, m, f, r, i) {
61 return safe_add(bit_rol(safe_add(safe_add(_, d), safe_add(f, i)), r), m)
62}
63
64function md5_ff(d, _, m, f, r, i, n) {
65 return md5_cmn(_ & m | ~_ & f, d, _, r, i, n)
66}
67
68function md5_gg(d, _, m, f, r, i, n) {
69 return md5_cmn(_ & f | m & ~f, d, _, r, i, n)
70}
71
72function md5_hh(d, _, m, f, r, i, n) {
73 return md5_cmn(_ ^ m ^ f, d, _, r, i, n)
74}
75
76function md5_ii(d, _, m, f, r, i, n) {
77 return md5_cmn(m ^ (_ | ~f), d, _, r, i, n)
78}
79
80function safe_add(d, _) {
81 var m = (65535 & d) + (65535 & _);
82 return (d >> 16) + (_ >> 16) + (m >> 16) << 16 | 65535 & m
83}
84
85function bit_rol(d, _) {
86 return d << _ | d >>> 32 - _
87}
88
89/*== Array Extensions ==*/
90Array.prototype.IntB = function (offset, len) {
91 len = len || 4
92 var buff = this;
93 if (len-- > 4) {
94 len = 3;
95 }
96 var a = 0;
97 for (var i = 0; i <= len; i++) {
98 a |= buff[offset + i] << 8 * (len - i)
99 }
100 return a;
101}
102
103
104/*== ECMA262 Backport ==*/
105Array.prototype.map = function (callback, thisArg) {
106
107 var T, A, k;
108
109 if (this == null) {
110 throw new TypeError(' this is null or not defined');
111 }
112
113 // 1. Let O be the result of calling ToObject passing the |this|
114 // value as the argument.
115 var O = Object(this);
116
117 // 2. Let lenValue be the result of calling the Get internal
118 // method of O with the argument "length".
119 // 3. Let len be ToUint32(lenValue).
120 var len = O.length >>> 0;
121
122 // 4. If IsCallable(callback) is false, throw a TypeError exception.
123 // See: http://es5.github.com/#x9.11
124 if (typeof callback !== 'function') {
125 throw new TypeError(callback + ' is not a function');
126 }
127
128 // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
129 if (arguments.length > 1) {
130 T = thisArg;
131 }
132
133 // 6. Let A be a new array created as if by the expression new Array(len)
134 // where Array is the standard built-in constructor with that name and
135 // len is the value of len.
136 A = new Array(len);
137
138 // 7. Let k be 0
139 k = 0;
140
141 // 8. Repeat, while k < len
142 while (k < len) {
143
144 var kValue, mappedValue;
145
146 // a. Let Pk be ToString(k).
147 // This is implicit for LHS operands of the in operator
148 // b. Let kPresent be the result of calling the HasProperty internal
149 // method of O with argument Pk.
150 // This step can be combined with c
151 // c. If kPresent is true, then
152 if (k in O) {
153
154 // i. Let kValue be the result of calling the Get internal
155 // method of O with argument Pk.
156 kValue = O[k];
157
158 // ii. Let mappedValue be the result of calling the Call internal
159 // method of callback with T as the this value and argument
160 // list containing kValue, k, and O.
161 mappedValue = callback.call(T, kValue, k, O);
162
163 // iii. Call the DefineOwnProperty internal method of A with arguments
164 // Pk, Property Descriptor
165 // { Value: mappedValue,
166 // Writable: true,
167 // Enumerable: true,
168 // Configurable: true },
169 // and false.
170
171 // In browsers that support Object.defineProperty, use the following:
172 // Object.defineProperty(A, k, {
173 // value: mappedValue,
174 // writable: true,
175 // enumerable: true,
176 // configurable: true
177 // });
178
179 // For best browser support, use the following:
180 A[k] = mappedValue;
181 }
182 // d. Increase k by 1.
183 k++;
184 }
185
186 // 9. return A
187 return A;
188};
189/*== XMLParser Module ==*/
190var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
191xmlDoc.async = false;
192xmlDoc.validateOnParse = false;
193
194var XMLParser = function (xml) {
195 var not_whitespace = /[^\s]/;
196 var xml2array = function (xmlDoc, parent_count) {
197 var arr = {};
198 var parent = "";
199 parent_count = parent_count || {};
200
201 var attribute_inside = 0;
202
203 if (xmlDoc.nodeName && xmlDoc.nodeName.charAt(0) != "#") {
204 if (xmlDoc.childNodes.length > 1) {
205 arr = {};
206 parent = xmlDoc.nodeName;
207 }
208 }
209 var value = xmlDoc.nodeValue;
210 if (xmlDoc.parentNode && xmlDoc.parentNode.nodeName && value) {
211 if (not_whitespace.test(value)) { // if its a child
212 arr = {};
213 arr[xmlDoc.parentNode.nodeName] = value;
214 }
215 }
216
217 if (xmlDoc.childNodes.length) {
218 if (xmlDoc.childNodes.length == 1) { // Tag?
219 arr = xml2array(xmlDoc.childNodes[0], parent_count); // RECURSION
220 } else {
221 var index = 0;
222
223 for (var i = 0; i < xmlDoc.childNodes.length; i++) {
224 var currentNodes = xmlDoc.childNodes[i];
225 var t = xml2array(currentNodes, parent_count);
226 if (t) {
227 var assoc = false;
228 var arr_count = 0;
229 for (key in t) {
230 if (isNaN(key)) assoc = true;
231 arr_count++;
232 if (arr_count > 2) break;
233 }
234
235 if (assoc && arr_count == 1) {
236 if (arr[key]) {
237 if (!parent_count || !parent_count[key]) {
238 parent_count[key] = 0;
239
240 var ta = arr[key];
241 arr[key] = {};
242 arr[key][0] = ta;
243 }
244 parent_count[key]++;
245 arr[key][parent_count[key]] = t[key];
246 } else {
247 parent_count[key] = 0;
248 arr[key] = t[key];
249 if (currentNodes.attributes && currentNodes.attributes.length) {
250 for (var j = 0; j < currentNodes.attributes.length; j++) {
251 var nname = currentNodes.attributes[j].nodeName;
252 if (nname) {
253 if (attribute_inside) {
254 var ta = arr[key];
255 arr[key] = {};
256 arr[key]['value'] = ta;
257 arr[key]['attribute_' + nname] = currentNodes.attributes[j].nodeValue;
258 } else {
259 arr['attributes_' + key + '_' + nname] = currentNodes.attributes[j].nodeValue;
260 }
261 }
262 } // for(var j = 0)
263 } // if(currentNodes
264 }
265 } else {
266 arr[index] = t;
267 index++;
268 }
269 } // if(t)
270 } // for(var i = 0)
271 }
272 }
273
274 if (parent && arr) {
275 var t = arr;
276 arr = {};
277 arr[parent] = t;
278 }
279 return arr;
280 }
281 xmlDoc.loadXML(xml);
282 return xml2array(xmlDoc);
283}
284
285/*== File Stream Module ==*/
286
287var SeekOrigin = {
288 Begin: 0,
289 Current: 1,
290 End: 2
291}
292var Encoding = {};
293Encoding.GetString = function (buf) {
294 return buf.map(function (b) {
295 return String.fromCharCode(b);
296 }).join('');
297}
298Encoding.GetSymbols = function (charCode) {
299 switch (charCode) {
300 case 0x152: return 0xbc;
301 case 0x153: return 0xbd;
302 case 0x160: return 0xa6;
303 case 0x161: return 0xa8;
304 case 0x178: return 0xbe;
305 case 0x17d: return 0xb4;
306 case 0x17e: return 0xb8;
307 case 0x20ac: return 0xa4;
308 default: return charCode;
309 }
310}
311var FileStream = function () {
312 var stream = new ActiveXObject("ADODB.Stream");
313 var isLittleEndian = false;
314 this.position = 0;
315 this.Open = function () {
316 stream.Type = 2;
317 stream.Charset = "iso-8859-15";
318 stream.Open();
319 }
320 this.Current = function () {
321 return stream.Position;
322 }
323 this.Close = function () {
324 stream.Close();
325 }
326 this.EOS = function () {
327 return stream.EOS;
328 }
329 this.Size = function () {
330 return stream.Size;
331 }
332 this.LoadFromFile = function (filename) {
333 stream.LoadFromFile(filename);
334 }
335 this.SaveToFile = function (filename, option) {
336 var option = option || 2;
337 stream.SaveToFile(filename, option);
338 }
339 this.Seek = function (pos, origin) {
340 switch (origin) {
341 case SeekOrigin.Begin:
342 stream.Position = pos;
343 break;
344 case SeekOrigin.Current:
345 stream.Position = stream.Position + pos;
346 break;
347 case SeekOrigin.End:
348 stream.Position = stream.Size + pos;
349 break;
350 }
351 }
352 this.Read = function (size) {
353 var bytes = [];
354 //console("Prev: " + stream.Position + "Req:" + size);
355 var s = stream.ReadText(size);
356 //console("Next: " + stream.Position);
357 for (var i = 0; i < s.length; ++i) {
358 var charCode = s.charCodeAt(i);
359 var intc = charCode;
360 if (charCode < 0x80) {
361 intc = charCode;
362 } else {
363 intc = Encoding.GetSymbols(charCode) | 0x80;
364 }
365 var st = ('0' + intc.toString(16)).slice(-2).split();
366 if (isLittleEndian) st = st.reverse();
367 bytes.push(parseInt(st.join(''), 16));
368 }
369
370 return bytes;
371 }
372}
373
374/*== Audio Hashing Module ==*/
375var client = utils.CreateHttpClient();
376var AudioHash = function () {
377 var RawPosition = 0;
378 var Hash = "";
379 var Done = {};
380 var SetHash = function (s) {
381 s.Seek(RawPosition, SeekOrigin.Begin);
382 //console(RawPosition);
383 var buff = s.Read(0x28000);
384 //client.addHttpHeader("Content-Type", "application/octet-stream; charset=iso-8859-15");
385 //client.addHttpHeader("Accept", "*");
386 //client.addPostData(buff);
387 buff = Encoding.GetString(buff);
388 Hash = md5(buff);
389 //Hash = md5(buff);
390 var ret = client.Request("https://md5.astralgate.net", "POST");
391 client.Reset();
392 Hash = ret;
393 console(Hash);
394 }
395 var Mpeg = function (s) {
396 var ParseVersion = function (header) {
397 return (header >> 19) & 3;
398 }
399 var ParseLayer = function (header) {
400 return (header >> 17) & 3;
401 }
402 var ParseBitRate = function (header) {
403 return (header >> 12) & 0xF;
404 }
405 var ParseSampleRate = function (header) {
406 return (header >> 10) & 3;
407 }
408 var ParseMode = function (header) {
409 return (header >> 6) & 3;
410 }
411 var ParseEmphasis = function (header) {
412 return header & 3;
413 }
414 var Validate = function (header) {
415 var version = ParseVersion(header);
416 var layer = ParseLayer(header);
417 var bitrate = ParseBitRate(header);
418 var samplerate = ParseSampleRate(header);
419 var Emphasis = ParseEmphasis(header);
420
421 return ((header >> 21) & 0x7FF) === 0x7FF && version !== 1 && layer !== 0 &&
422 bitrate !== 0 && bitrate !== 0xF && samplerate !== 3 &&
423 Emphasis !== 2;
424 }
425 s.Seek(0, SeekOrigin.Begin);
426 var buff = [];
427 var read = 0;
428 do {
429 buff = s.Read(10);
430 read = buff.length;
431 var what = Encoding.GetString(buff.slice(0, 3)).replace(/\u0003/, '');
432 if (what == "ID3") // "ID3"
433 {
434 s.Seek(buff[6] << 21 | buff[7] << 14 | buff[8] << 7 | buff[9], SeekOrigin.Current);
435 break;
436 } else {
437 s.Seek(-buff.length, SeekOrigin.Current);
438 break;
439 }
440 } while (read === buff.length);
441 do {
442 buff = s.Read(4096);
443 read = buff.length;
444 for (var i = 3; i < read; i++) {
445 var header = buff.IntB(i - 3);
446 if (Validate(header)) {
447 RawPosition = s.Current() - read + i - 3;
448 //console(s.Current() + "," + read + "," + RawPosition);
449 read = 0;
450 }
451 }
452 s.Seek(-4, SeekOrigin.Current);
453 } while (read == buff.length);
454
455 SetHash(s);
456 }
457 this.Load = function (Path) {
458 var fs = new FileStream();
459 fs.Open();
460 fs.LoadFromFile(Path);
461 var buf = fs.Read(4);
462 var what = Encoding.GetString(buf).replace(/\u0003/, '');
463 switch (what) {
464 case 'ID3':
465 Mpeg(fs, Path);
466 break;
467 default:
468 SetHash(fs, Path);
469 break;
470 }
471 fs.Close();
472 return { Hash: Hash };
473 }
474}
475function escapeHtml(s) {
476 return s.replace(/&/g, "&").replace(/</g, "<").replace(/\"/g, """);
477}
478/*== Alsong API Module ==*/
479var AlsongAPI = function () {
480 // Properties
481 var GetResembleLyricsParser = function (result) {
482 var lyrics = [];
483 var xmlParser = new XMLParser(result);
484 var resultNodes = xmlParser["GetResembleLyric2Result"];
485 if (resultNodes && resultNodes.length != 0) {
486 resultNodes = resultNodes["ST_GET_RESEMBLELYRIC2_RETURN"];
487 for (var key in resultNodes) {
488 if (IsAborting()) {
489 break;
490 }
491 var lyric = resultNodes[key];
492 lyrics.push({
493 Source: "MetaData",
494 Title: lyric["strTitle"],
495 Artist: lyric["strArtistName"],
496 Album: lyric["strAlbumName"],
497 Lyric: lyric["strLyric"].replace(/<br>/g, '\r\n')
498 });
499 }
500 }
501 return lyrics;
502 }
503 var GetLyricsParser = function (result) {
504 var lyrics = [];
505 var xmlParser = new XMLParser(result);
506 //console(result);
507 var resultNodes = xmlParser["GetLyric7Result"];
508 if (resultNodes["strStatusID"] != 2) {
509 lyrics.push({
510 Source: "FileHash",
511 Title: resultNodes["strTitle"],
512 Artist: resultNodes["strArtist"],
513 Album: resultNodes["strAlbum"],
514 Lyric: resultNodes["strLyric"].replace(/<br>/g, '\r\n')
515 })
516 }
517 return lyrics;
518 }
519 var Request = function (action, req) {
520 var content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:SOAP-ENC=\"http://www.w3.org/2003/05/soap-encoding\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:ns2=\"ALSongWebServer/Service1Soap\" xmlns:ns1=\"ALSongWebServer\" xmlns:ns3=\"ALSongWebServer/Service1Soap12\"><SOAP-ENV:Body>" + req + "</SOAP-ENV:Body></SOAP-ENV:Envelope>";
521 client.addHttpHeader("Accept-Charset", "utf-8");
522 client.addHttpHeader("content-type", "application/soap+xml; charset=UTF-8");
523 client.addHttpHeader("User-Agent", "gSOAP/2.7");
524 client.addHttpHeader("SOAPAction", "AlsongWebServer/" + action);
525 client.addPostData(content);
526 var ret = client.Request("http://lyrics.alsong.co.kr/alsongwebservice/service1.asmx", "POST");
527 client.Reset();
528 return ret;
529 }
530 this.RequestFileHash = function (fileName) {
531 var Hash = new AudioHash().Load(fileName).Hash;
532 //console(Hash)
533 var content = "<ns1:GetLyric7>\
534 <ns1:encData>"+ encData + "</ns1:encData>\
535 <ns1:stQuery>\
536 <ns1:strChecksum>"+ Hash + "</ns1:strChecksum>\
537 <ns1:strVersion>3.46</ns1:strVersion>\
538 <ns1:strMACAddress></ns1:strMACAddress>\
539 <ns1:strIPAddress></ns1:strIPAddress>\
540 </ns1:stQuery></ns1:GetLyric7>";
541 return GetLyricsParser(Request("GetLyric7", content));
542 }
543 this.RequestMetaData = function (title, artist) {
544 var results = [];
545 var content = "<ns1:GetResembleLyric2>\
546 <ns1:encData>"+ encData + "</ns1:encData>\
547 <ns1:stQuery>\
548 <ns1:strTitle>"+ escapeHtml(title) + "</ns1:strTitle>\
549 <ns1:strArtistName>"+ escapeHtml(artist) + "</ns1:strArtistName>\
550 <ns1:nCurPage>0</ns1:nCurPage>\
551 </ns1:stQuery></ns1:GetResembleLyric2>";
552 return GetResembleLyricsParser(Request('GetResembleLyric2', content));
553 }
554}
555
556/*== Main Lyrics Module ==*/
557
558
559function console(s) {
560 if (dbg) { return; }
561 fb.trace(get_my_name() + " $> " + s);
562}
563var IsAborting = {};
564function start_search(info, callback) {
565 //add your codes here
566 IsAborting = function () {
567 var r = callback.IsAborting();
568 if (r) console("Search Aborting..");
569 return r;
570 }
571 var API = new AlsongAPI();
572 var RegisterLyric = function (callback, Lyric) {
573 var new_lyric = callback.CreateLyric();
574 new_lyric.Source = get_my_name() + "(" + Lyric.Source + ")";
575 //new_lyric.Title = Lyric.Title;
576 //new_lyric.Artist = Lyric.Artist;
577 new_lyric.Title = info.Title;
578 new_lyric.Artist = info.Artist;
579 new_lyric.Album = Lyric.Album;
580 new_lyric.LyricText = Lyric.Lyric;
581 //console(new_lyric.LyricText);
582 callback.AddLyric(new_lyric);
583 new_lyric.Dispose();
584 }
585 console('Title : ' + info.Title + ' Artist : ' + info.Artist);
586
587 console("Search File Hash");
588 var lyrics = API.RequestFileHash(info.RawPath.replace(/file:\/\//, ""));
589 if (lyrics.length != 0) {
590 console("Found Alsong Lyrics : " + lyrics.length);
591 }
592 for (var i in lyrics) {
593 if (IsAborting()) {
594 console("User Aborting");
595 break;
596 }
597 RegisterLyric(callback, lyrics[i]);
598 }
599 console("Search MetaData");
600 lyrics = API.RequestMetaData(info.Title, info.Artist);
601 if (lyrics.length != 0) {
602 console("Found Alsong Lyrics : " + lyrics.length);
603 }
604 for (var i in lyrics) {
605 if (IsAborting()) {
606 console("User Aborting");
607 break;
608 }
609 RegisterLyric(callback, lyrics[i]);
610 }
611
612 console("Alsong Search Done");
613}