2
* Copyright (C) 2012 Kylin Ltd
4
* This program is free software: you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License version 3 as
6
* published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Authored by Weihua Zhang <fly2high@126.com>
17
* Authored by liuxing <liuxingcs@yeah.net>
18
* Modified Information:
19
* 1. Add is_in_China to decide wether you are in China
20
* 2. Add MusicBaiduCollection.collection function to search China music from music.baidu.com
24
* Copyright (C) 2011 Canonical Ltd
26
* This program is free software: you can redistribute it and/or modify
27
* it under the terms of the GNU General Public License version 3 as
28
* published by the Free Software Foundation.
30
* This program is distributed in the hope that it will be useful,
31
* but WITHOUT ANY WARRANTY; without even the implied warranty of
32
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33
* GNU General Public License for more details.
35
* You should have received a copy of the GNU General Public License
36
* along with this program. If not, see <http://www.gnu.org/licenses/>.
38
* Authored by Alex Launi <alex.launi@canonical.com>
45
namespace Unity.MusicLens
48
public class MusicBaiduCollection : Object
51
private const string MUSICBAIDU_BASE_URI = "http://music.baidu.com/search/";
52
private static string IS_IN_CHINA = "Unknown";
53
private const string ASK_IP_SERVER_URI_ONE = "http://ip.chinaz.com/";
54
private const string ASK_IP_SERVER_URI_TWO = "http://www.123myip.co.uk/";
56
const string SONG_MISSING_ICON_PATH = "/usr/share/unity/themes/baidu_song_missing.png";
59
public MusicBaiduCollection ()
64
private bool is_in_China (Cancellable? cancellable = null)
67
if(IS_IN_CHINA == "Unknown")
71
File file = File.new_for_uri (ASK_IP_SERVER_URI_ONE);
79
if( file.load_contents(cancellable, out data, out etag_out))
82
//Convert uint8[] to string.
83
content = (string) data;
85
var location = content.index_of("北京") + content.index_of("上海") + content.index_of("天津") + content.index_of("重庆") +
86
content.index_of("黑龙江") + content.index_of("吉林") + content.index_of("辽宁") + content.index_of("江苏") +
87
content.index_of("山东") + content.index_of("安徽") + content.index_of("河北") + content.index_of("河南") +
88
content.index_of("湖北") + content.index_of("湖南") + content.index_of("江西") + content.index_of("陕西") +
89
content.index_of("山西") + content.index_of("四川") + content.index_of("青海") + content.index_of("海南") +
90
content.index_of("广东") + content.index_of("贵州") + content.index_of("浙江") + content.index_of("福建") +
91
content.index_of("台湾") + content.index_of("甘肃") + content.index_of("云南") + content.index_of("内蒙古") +
92
content.index_of("宁夏") +content.index_of("新疆") + content.index_of("西藏") + content.index_of("广西") +
93
content.index_of("香港") + content.index_of("澳门");
99
//if ASK_IP_SERVER_URI_ONE server reposended failed,ask ASK_IP_SERVER_URI_TWO server.
100
file = File.new_for_uri (ASK_IP_SERVER_URI_TWO);
105
if( file.load_contents(cancellable, out data, out etag_out))
108
//Convert uint8[] to string.
109
content = (string) data;
111
location = content.index_of("China") ;
122
warning ("Error reading URL '%s': %s", file.get_uri (), e.message);
144
public async void search (LensSearch search, SearchType search_type,
145
owned List<FilterParser> filters, int max_results = -1, Cancellable cancellable) throws IOError
154
if(!is_in_China(cancellable))
156
warning("Error can not search music from Baidu !");
161
//Search the first page song from Baidu music
162
uri = build_search_uri(search.search_string, filters, 0, 0);
165
song_file = File.new_for_uri (uri);
166
if(yield song_file.load_contents_async(cancellable, out song_data, out etag_out))
167
read_song_search_result_from_Baidu(search,song_data);
169
//Search the next page song from Baidu music
170
uri = build_search_uri(search.search_string, filters, 0, 1);
173
song_file = File.new_for_uri (uri);
174
if(yield song_file.load_contents_async(cancellable, out song_data, out etag_out))
175
read_song_search_result_from_Baidu(search,song_data);
178
//Search the first page album from Baidu music
179
uri = build_search_uri(search.search_string, filters, 1, 0);
182
album_file = File.new_for_uri (uri);
183
if(yield album_file.load_contents_async(cancellable, out album_data, out etag_out))
184
read_album_search_result_from_Baidu(search,album_data);
186
//Search the next page album from Baidu music
187
uri = build_search_uri(search.search_string, filters, 1, 1);
190
album_file = File.new_for_uri (uri);
191
if(yield album_file.load_contents_async(cancellable, out album_data, out etag_out))
192
read_album_search_result_from_Baidu(search,album_data);
198
warning ("Error getting result from baidu: %s(Failed to Search music from Baidu)!", e.message);
203
public void get_song_details (string uri, out Album album,out SList<Track> tracks,Cancellable? cancellable = null)
206
album = new Album ();
207
tracks = new SList<Track> ();
210
string http_uri = uri.substring (7);// strip off "song://" from the uri
219
song_file = File.new_for_uri (http_uri);
220
if(song_file.load_contents(cancellable, out song_data, out etag_out))
225
//Convert uint8[] to string.
226
content = (string) song_data;
228
//Parse the contents to get results.
230
var iIndex = content.index_of("<div class=\"song");
234
var iEnd = content.index_of("</div>");
235
string song_name = content.substring(iIndex, iEnd-iIndex);
238
iIndex = song_name.index_of("name") + 6;
239
iEnd = song_name.substring(iIndex).index_of("</span>");
243
album.title = song_name.substring(iIndex, iEnd);
244
//Maybe song name append like this '审批文号:WJXXXXX',so must deal with.
245
iEnd = album.title.index_of("审批文号");
247
album.title = album.title.substring(0,iEnd);
252
iIndex = content.index_of("<span class=\"author_list");
256
iEnd = content.index_of("</span>");
257
content = content.substring(iIndex, iEnd-iIndex);
260
iIndex = content.index_of("title=") + 7;
261
iEnd = content.substring(iIndex).index_of("\"");
264
album.artist = content.substring(iIndex,iEnd);
266
//Because song icon_hint in Baidu no exist,so set SONG_MISSING_ICON_PATH.
267
album.artwork_path = SONG_MISSING_ICON_PATH;
271
var track = new Track ();
273
track.title = album.title ;
274
tracks.append (track);
282
warning ("Error fetching details for '%s': %s", uri, e.message);
287
public void get_album_details(string uri, out Album album, out SList<Track> tracks,Cancellable? cancellable = null)
289
album = new Album ();
290
tracks = new SList<Track> ();
293
string http_uri = uri.substring (8);// strip off "album://" from the uri
303
song_file = File.new_for_uri (http_uri);
304
if(song_file.load_contents(cancellable, out song_data, out etag_out))
309
//Convert uint8[] to string.
310
content = (string) song_data;
312
//Parse the contents to get results.
313
string album_content=content;
316
var iIndex = album_content.index_of("<div class=\"album-info");
320
var iEnd = album_content.substring(iIndex).index_of("</li>");
321
album_content = album_content.substring(iIndex, iEnd+5);
325
iIndex = album_content.index_of("img src=") + 9;
326
iEnd = album_content.substring(iIndex).index_of("\"");
330
album.artwork_path = album_content.substring(iIndex,iEnd);
331
album_content= album_content.substring(iIndex);
334
iIndex = album_content.index_of("album-name") + 12;
335
iEnd = album_content.substring(iIndex).index_of("</h2>");
338
album.title = album_content.substring(iIndex, iEnd);
340
iIndex = album_content.index_of("title=") + 7;
341
iEnd = album_content.substring(iIndex).index_of("\"");
344
album.artist = album_content.substring(iIndex,iEnd);
348
iIndex = content.index_of("<li data-songitem");
352
iEnd = content.last_index_of("<li data-songitem");
353
content = content.substring(iIndex, iEnd+3500- iIndex);
354
List<string> lilist = new List<string> ();
355
var liIndex = content.index_of("</li>");
358
lilist.append(content.substring(0,liIndex));
359
content = content.substring(liIndex+5);
360
liIndex = content.index_of("</li>");
364
//Get album information.
365
foreach (string li in lilist)
368
iIndex = li.index_of("/song");
369
iEnd = li.substring(iIndex).index_of("\"");
370
if(iIndex==-1||iEnd==-1)
373
var track = new Track ();
374
//FIXME drag n drop uri needs to be the song:// link
375
track.uri = string.join("","song://http://music.baidu.com",li.substring(iIndex, iEnd));
378
li = li.substring(iIndex);
379
iIndex = li.index_of("title=") + 7;
380
iEnd = li.substring(iIndex).index_of("\"");
381
track.title = li.substring(iIndex,iEnd);
382
//Maybe song name append like this '审批文号:WJXXXXX',so must deal with.
383
iEnd = track.title.index_of("审批文号");
385
track.title = track.title.substring(0,iEnd);
387
tracks.append (track);
395
warning ("Error fetching details for '%s': %s", uri, e.message);
402
private void read_song_search_result_from_Baidu(LensSearch search, uint8[] data)
404
var results_model = search.results_model;
406
Track track = new Track ();
408
//Convert uint8[] to string)
409
content = (string) data;
410
//Parse the contents to get results
411
var iIndex = content.index_of("<li data-songitem");
414
var iEnd = content.last_index_of("<li data-songitem");
415
content = content.substring(iIndex, iEnd+3500- iIndex);
417
List<string> lilist = new List<string> ();
418
var liIndex = content.index_of("</li>");
421
lilist.append(content.substring(0,liIndex));
422
content = content.substring(liIndex+5);
423
liIndex = content.index_of("</li>");
426
//Get song information.
427
foreach (string li in lilist)
429
iIndex = li.index_of("/song");
430
iEnd = li.substring(iIndex).index_of("\"");
431
if(iIndex==-1||iEnd==-1)
433
//FIXME drag n drop uri needs to be the song:// link
434
track.uri = string.join("","song://http://music.baidu.com",li.substring(iIndex, iEnd));
436
li = li.substring(iIndex);
437
iIndex = li.index_of("title=") + 7;
438
iEnd = li.substring(iIndex).index_of("\"");
439
track.title = li.substring(iIndex,iEnd);
440
//Maybe song name append like this '审批文号:WJXXXXX',so must deal with.
441
iEnd = track.title.index_of("审批文号");
443
track.title = track.title.substring(0,iEnd);
445
li = li.substring(iIndex);
446
iIndex = li.index_of("title=") + 7;
447
iEnd = li.substring(iIndex).index_of("\"");
448
track.artist = li.substring(iIndex,iEnd);
450
li = li.substring(iIndex);
451
//Maybe song album no exist,so get album name between ">" and "<".
452
//Get album-title from behind the second ">".
453
iIndex = li.index_of("album-title");
454
li = li.substring(iIndex);
455
li = li.substring(li.index_of(">")+1);
456
iIndex = li.index_of(">") + 1;
457
iEnd = li.substring(iIndex).index_of("<");
458
var albumMaybe = li.substring(iIndex,iEnd);
459
li = li.substring(iIndex);
460
if(albumMaybe == null)
462
iIndex = li.index_of(">") + 1;
463
iEnd = li.substring(iIndex).index_of("</span>");
464
track.album = li.substring(iIndex,iEnd);
465
li = li.substring(iIndex);
468
track.album = albumMaybe;
470
var comment = string.join("",track.artist,track.album);
472
//Because song icon_hint in Baidu no exist,so add SONG_MISSING_ICON_PATH.
473
var icon_hint = SONG_MISSING_ICON_PATH;
475
if(track.title.up().index_of(search.search_string.up()) != -1)
477
results_model.append (
489
private void read_album_search_result_from_Baidu(LensSearch search, uint8[] data)
491
var results_model = search.results_model;
492
Album album = new Album ();
495
//Convert uint8[] to string.
496
content = (string) data;
497
//Parse the contents to get results.
499
//Get album icon_hint.
500
var iIndex = content.index_of("<img org_src=");
503
var iEnd = content.last_index_of("<img org_src=");
504
content = content.substring(iIndex,iEnd+3200-iIndex);
505
List<string> lilist = new List<string> ();
506
var liIndex = content.index_of("</li>");
509
lilist.append(content.substring(0,liIndex));
510
content = content.substring(liIndex+5);
511
liIndex = content.index_of("</li>");
514
//Get album information.
515
foreach (string li in lilist)
518
iIndex = li.index_of("img org_src=") + 13;
519
iEnd = li.substring(iIndex).index_of("\"");
520
var icon_hint = li.substring(iIndex,iEnd);
521
li = li.substring(iIndex);
523
iIndex = li.index_of("/album");
524
iEnd = li.substring(iIndex).index_of("\"");
526
if(iIndex==-1||iEnd==-1)
529
//FIXME drag n drop uri needs to be the u1ms:// link.
530
album.uri = string.join("","album://http://music.baidu.com",li.substring(iIndex,iEnd));
531
li = li.substring(iIndex);
534
iIndex = li.index_of("title=") + 7;
535
iEnd = li.substring(iIndex).index_of("\"");
536
album.title = li.substring(iIndex, iEnd);
537
//Maybe album title append like this '审批文号:WJXXXXX',so must deal with.
538
iEnd = album.title.index_of("审批文号");
541
album.title = album.title.substring(0,iEnd);
543
li = li.substring(iIndex);
546
iIndex = li.index_of("title=") + 7;
547
iEnd = li.substring(iIndex).index_of("\"");
548
album.artist = li.substring(iIndex,iEnd);
549
li = li.substring(iIndex);
551
if(album.title.up().index_of(search.search_string.up()) != -1)
553
results_model.append (album.uri,
568
private string? build_search_uri (string query, List<FilterParser> filters, int index, int page)
571
if(query.strip() == "")
574
string musicbaidu_base_uri = MUSICBAIDU_BASE_URI;
575
if (GLib.Environment.get_variable("MUSICBAIDU_URI") != null)
576
musicbaidu_base_uri = GLib.Environment.get_variable("MUSICBAIDU_URI");
578
StringBuilder uri = new StringBuilder (musicbaidu_base_uri);
580
uri.append ("song?key=");
582
uri.append ("album?key=");
585
uri.append (Uri.escape_string (query, "", false));
587
//TODO: add filters of Chinese music
590
//At this moment, Baidu doesn't release API for filter and more search results
591
//20 results each time
594
uri.append ("&start=0&size=20");
599
str = "&start=%d&size=20".printf(page*20);