Fix small bug
[gmpc-magnatune.git] / src / magnatune.c
blob09eb8f9ff3b07ee90877f145d224b9d65936dba7
1 /* gmpc-magnatune (GMPC plugin)
2 * Copyright (C) 2006-2009 Qball Cow <qball@sarine.nl>
3 * Project homepage: http://gmpcwiki.sarine.nl/
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include <stdio.h>
21 #include <string.h>
22 #include <gtk/gtk.h>
23 #include <gmpc/plugin.h>
24 #include <gmpc/gmpc_easy_download.h>
25 #include <gmpc/misc.h>
26 #include <libmpd/libmpd-internal.h>
27 #include <sqlite3.h>
28 #include <libxml/xmlreader.h>
29 #include <libxml/tree.h>
30 #include <playlist3-messages.h>
31 #include "magnatune.h"
33 static void magnatune_cleanup_xml();
34 static sqlite3 *magnatune_sqlhandle = NULL;
37 void magnatune_db_destroy(void)
39 if(magnatune_sqlhandle)
41 sqlite3_close(magnatune_sqlhandle);
42 magnatune_sqlhandle = NULL;
46 /* run this before using the other fucntions */
47 void magnatune_db_init()
51 void magnatune_db_open()
53 gchar *path = NULL;
56 /**
57 * if open close it
59 if(magnatune_sqlhandle)
61 sqlite3_close(magnatune_sqlhandle);
62 magnatune_sqlhandle = NULL;
65 g_free(path);
66 path = gmpc_get_user_path("magnatune.sqlite3");
67 sqlite3_open(path, &(magnatune_sqlhandle));
68 g_free(path);
71 /* FIXME */
72 gboolean magnatune_db_has_data()
74 char *query = sqlite3_mprintf("SELECT * from 'sqlite_master'");
75 sqlite3_stmt *stmt = NULL;
76 const char *tail;
77 int r;
80 r= sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
81 sqlite3_free(query);
82 if(r == SQLITE_OK) {
83 while((r = sqlite3_step(stmt)) == SQLITE_ROW){
84 sqlite3_finalize(stmt);
85 return TRUE;
89 sqlite3_finalize(stmt);
90 return FALSE;
93 MpdData * magnatune_db_get_genre_list()
95 MpdData *list = NULL;
96 xmlNodePtr **root;
97 xmlNodePtr **cur;
98 int i,r;
100 char *query = sqlite3_mprintf("SELECT genre from 'genres' group by genre");
101 sqlite3_stmt *stmt = NULL;
102 const char *tail;
103 GTimer *timer = g_timer_new();
104 r = sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
105 if(r ==SQLITE_OK) {
106 while((r = sqlite3_step(stmt)) == SQLITE_ROW)
108 list = mpd_new_data_struct_append(list);
109 list->type = MPD_DATA_TYPE_TAG;
110 list->tag_type = MPD_TAG_ITEM_GENRE;
111 list->tag = g_strdup(sqlite3_column_text(stmt,0));
115 sqlite3_finalize(stmt);
116 sqlite3_free(query);
117 g_debug("%f s elapsed getting genres\n", g_timer_elapsed(timer,NULL));
118 g_timer_reset(timer);
119 list = misc_mpddata_remove_duplicate_songs(list);
120 g_debug("%f s elapsed unique genres list\n", g_timer_elapsed(timer,NULL));
121 g_timer_destroy(timer);
122 return list;
125 void magnatune_db_load_data(const char *data, const goffset length)
127 gchar *error = NULL;
128 xmlTextReaderPtr reader = NULL;
129 gchar *path;
132 path = gmpc_get_user_path("magnatune.sqlite3");
133 if(magnatune_sqlhandle)
135 int status = sqlite3_close(magnatune_sqlhandle);
136 if(status != 0)
138 gchar *temp =g_strdup_printf("Failed to close magnatune db: %i\n", status);
139 playlist3_show_error_message(temp, ERROR_WARNING);
140 g_free(temp);
142 magnatune_sqlhandle = NULL;
144 // if(gmpc_easy_download("http://he3.magnatune.com/info/sqlite_magnatune.db", dld))
145 if(data){
146 GError *error = NULL;
147 gssize size= (gssize)length;
148 g_file_set_contents(path, data, size, &error);
149 if(error) {
150 gchar *temp =g_strdup_printf("Failed to store magnatune db: %s\n", error->message);
151 playlist3_show_error_message(temp, ERROR_WARNING);
152 g_free(temp);
153 printf("%s\n", error->message);
154 g_error_free(error);
156 printf("%s\n", path);
157 // gmpc_easy_download_clean(dld);
159 /* open the db if it is closed */
160 if(!magnatune_sqlhandle) {
163 int retv = sqlite3_open(path, &(magnatune_sqlhandle));
164 if(retv != SQLITE_OK)
166 g_free(path);
168 playlist3_show_error_message("Failed to open the new magnatune database", ERROR_WARNING);
169 /* Cleanup */
170 return;
174 sqlite3_exec(magnatune_sqlhandle, "CREATE INDEX songsAlbumname ON songs(albumname);", NULL, NULL, &error);
175 if(error)printf("%i: %s",__LINE__, error);
176 sqlite3_exec(magnatune_sqlhandle, "CREATE INDEX genresAlbumname ON genres(albumname);", NULL, NULL, &error);
177 if(error)printf("%i: %s",__LINE__, error);
178 sqlite3_exec(magnatune_sqlhandle, "CREATE INDEX genresGenrename ON genres(genre);", NULL, NULL, &error);
179 if(error)printf("%i: %s",__LINE__, error);
180 sqlite3_exec(magnatune_sqlhandle, "CREATE INDEX albumsAlbumname ON albums(albumname);", NULL, NULL, &error);
181 if(error)printf("%i: %s",__LINE__, error);
183 // g_idle_add(magnatune_end_download, NULL);
184 g_free(path);
187 MpdData * magnatune_db_get_artist_list(char *wanted_genre)
189 MpdData *list = NULL;
190 xmlNodePtr root;
191 xmlNodePtr cur;
192 int r;
193 /** check if there is data */
194 char *query = sqlite3_mprintf("SELECT albumname from 'genres' WHERE genre=%Q", wanted_genre);
195 sqlite3_stmt *stmt = NULL;
196 const char *tail;
197 GTimer *timer = g_timer_new();
198 r = sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
199 if(r ==SQLITE_OK) {
200 while((r = sqlite3_step(stmt)) == SQLITE_ROW)
202 sqlite3_stmt *stmt2 = NULL;
203 const char *tail2;
204 char *query2 = sqlite3_mprintf("SELECT artist from 'albums' WHERE albumname=%Q", sqlite3_column_text(stmt,0));
205 int r2 = sqlite3_prepare_v2(magnatune_sqlhandle, query2, -1, &stmt2, &tail2);
206 if(r2 ==SQLITE_OK) {
207 while((r2 = sqlite3_step(stmt2)) == SQLITE_ROW)
209 list = mpd_new_data_struct_append(list);
210 list->type = MPD_DATA_TYPE_TAG;
211 list->tag_type = MPD_TAG_ITEM_ARTIST;
212 list->tag = g_strdup(sqlite3_column_text(stmt2,0));
215 sqlite3_finalize(stmt2);
216 sqlite3_free(query2);
219 sqlite3_finalize(stmt);
220 sqlite3_free(query);
221 g_debug("%f s elapsed getting genres\n", g_timer_elapsed(timer,NULL));
222 g_timer_reset(timer);
223 list = misc_mpddata_remove_duplicate_songs(list);
225 g_debug("%f s elapsed unique artist list\n", g_timer_elapsed(timer,NULL));
226 g_timer_destroy(timer);
227 return list;
230 MpdData *magnatune_db_get_album_list(char *wanted_genre,char *wanted_artist)
232 int r;
233 MpdData *list = NULL;
234 xmlNodePtr **root;
235 xmlNodePtr **cur;
236 /** check if there is data */
238 char *query = sqlite3_mprintf("SELECT albumname from 'albums' WHERE artist=%Q",wanted_artist);
239 sqlite3_stmt *stmt = NULL;
240 const char *tail;
241 GTimer *timer = g_timer_new();
242 r = sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
243 if(r ==SQLITE_OK) {
244 while((r = sqlite3_step(stmt)) == SQLITE_ROW)
246 sqlite3_stmt *stmt2 = NULL;
247 const char *tail2;
248 char *query2 = sqlite3_mprintf("SELECT albumname from 'genres' WHERE albumname=%Q AND genre=%Q", sqlite3_column_text(stmt,0),wanted_genre);
249 int r2 = sqlite3_prepare_v2(magnatune_sqlhandle, query2, -1, &stmt2, &tail2);
250 if(r2 ==SQLITE_OK) {
251 while((r2 = sqlite3_step(stmt2)) == SQLITE_ROW)
253 list = mpd_new_data_struct_append(list);
254 list->type = MPD_DATA_TYPE_TAG;
255 list->tag_type = MPD_TAG_ITEM_ALBUM;
256 list->tag = g_strdup(sqlite3_column_text(stmt2,0));
259 sqlite3_finalize(stmt2);
260 sqlite3_free(query2);
263 sqlite3_finalize(stmt);
264 sqlite3_free(query);
265 g_debug("%f s elapsed listing albums songs\n", g_timer_elapsed(timer,NULL));
266 g_timer_destroy(timer);
267 return mpd_data_get_first(list);
270 static char *__magnatune_get_artist_name(const char *album)
272 char *retv = NULL;
273 sqlite3_stmt *stmt = NULL;
274 const char *tail;
275 int r = 0;
276 char *query = NULL;
277 if(!album) return NULL;
278 query = sqlite3_mprintf("SELECT artist from 'albums' WHERE albumname=%Q limit 1",album);
279 r=sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
280 if(r ==SQLITE_OK) {
281 if((r = sqlite3_step(stmt)) == SQLITE_ROW)
283 retv = g_strdup(sqlite3_column_text(stmt, 0));
286 sqlite3_finalize(stmt);
287 sqlite3_free(query);
288 return retv;
290 static char *__magnatune_get_genre_name(const char *album)
292 char *retv = NULL;
293 sqlite3_stmt *stmt = NULL;
294 const char *tail;
295 int r = 0;
296 char *query = NULL;
297 if(!album) return NULL;
298 query = sqlite3_mprintf("SELECT genre from 'genres' WHERE albumname=%Q",album);
299 r=sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
300 if(r ==SQLITE_OK) {
301 while((r = sqlite3_step(stmt)) == SQLITE_ROW)
303 const char *temp= sqlite3_column_text(stmt, 0);
304 if(retv)
306 gchar *t = retv;
307 retv = g_strconcat(t, ", ",temp, NULL);
308 g_free(t);
310 else retv = g_strdup(temp);
314 sqlite3_finalize(stmt);
315 sqlite3_free(query);
316 return retv;
318 static MpdData *__magnatune_get_data_album_from_genre(const char *genre, gboolean exact)
320 MpdData *list = NULL;
321 char *query = NULL;
322 sqlite3_stmt *stmt = NULL;
323 const char *tail;
324 int r = 0;
325 GTimer *timer = g_timer_new();
326 if(exact)
328 query = sqlite3_mprintf("SELECT songs.albumname,duration,number,desc,mp3 from 'songs' JOIN 'genres' ON songs.albumname = genres.albumname "
329 "WHERE genres.genre=%Q",genre);
330 }else{
331 query = sqlite3_mprintf("SELECT songs.albumname,duration,number,desc,mp3 from 'songs' JOIN 'genres' ON songs.albumname = genres.albumname "
332 "WHERE genres.genre LIKE '%%%%%q%%%%'",genre);
334 r=sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
335 if(r ==SQLITE_OK) {
336 while((r = sqlite3_step(stmt)) == SQLITE_ROW)
338 gchar *temp = gmpc_easy_download_uri_escape(sqlite3_column_text(stmt,4));
339 list = mpd_new_data_struct_append(list);
340 list->type = MPD_DATA_TYPE_SONG;
341 list->song = mpd_newSong();
342 list->song->album = g_strdup(sqlite3_column_text(stmt,0));
343 list->song->artist = __magnatune_get_artist_name(list->song->album);
344 list->song->genre = __magnatune_get_genre_name(list->song->album);
345 list->song->title= g_strdup(sqlite3_column_text(stmt,3));
346 list->song->track = g_strdup(sqlite3_column_text(stmt,2));
347 list->song->time = sqlite3_column_int(stmt,1);
348 list->song->file = g_strdup_printf("http://he3.magnatune.com/all/%s",temp);
349 g_free(temp);
351 }else{
352 g_warning("Sqlite error: %s\n", tail);
355 sqlite3_finalize(stmt);
356 sqlite3_free(query);
357 g_debug("%f s elapsed getting album songs from genre\n", g_timer_elapsed(timer,NULL));
358 g_timer_destroy(timer);
359 return list;
362 static MpdData *__magnatune_get_data_album(const char *album, gboolean exact)
364 MpdData *list = NULL;
365 char *query = NULL;
366 sqlite3_stmt *stmt = NULL;
367 const char *tail;
368 int r = 0;
369 GTimer *timer = g_timer_new();
370 if(exact)
372 query = sqlite3_mprintf("SELECT songs.albumname,duration,number,desc,mp3 from 'songs' "
373 "WHERE songs.albumname=%Q",album);
374 }else{
375 query = sqlite3_mprintf("SELECT songs.albumname,duration,number,desc,mp3 from 'songs' "
376 "WHERE songs.albumname LIKE '%%%%%q%%%%'",album);
378 r=sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
379 if(r ==SQLITE_OK) {
380 while((r = sqlite3_step(stmt)) == SQLITE_ROW)
382 gchar *temp = gmpc_easy_download_uri_escape(sqlite3_column_text(stmt,4));
383 list = mpd_new_data_struct_append(list);
384 list->type = MPD_DATA_TYPE_SONG;
385 list->song = mpd_newSong();
386 list->song->album = g_strdup(sqlite3_column_text(stmt,0));
387 list->song->artist = __magnatune_get_artist_name(list->song->album);
388 list->song->genre = __magnatune_get_genre_name(list->song->album);
389 list->song->title= g_strdup(sqlite3_column_text(stmt,3));
390 list->song->track = g_strdup(sqlite3_column_text(stmt,2));
391 list->song->time = sqlite3_column_int(stmt,1);
392 list->song->file = g_strdup_printf("http://he3.magnatune.com/all/%s",temp);
393 g_free(temp);
396 else{
397 g_warning("Sqlite error: %s\n", tail);
399 sqlite3_finalize(stmt);
400 sqlite3_free(query);
401 g_debug("%f s elapsed getting album songs\n", g_timer_elapsed(timer,NULL));
402 g_timer_destroy(timer);
403 return list;
405 static gchar ** __magnatune_get_albums(const char *genre, const char *artist, gboolean exact)
407 char **retv = NULL;
408 sqlite3_stmt *stmt = NULL;
409 const char *tail;
410 int items = 0;
411 int r = 0;
412 char *query = NULL;
414 if(genre && !artist) {
415 if(exact)
416 query = sqlite3_mprintf("SELECT albumname FROM 'genres' WHERE genre=%Q", genre);
417 else
418 query = sqlite3_mprintf("SELECT albumname FROM 'genres' WHERE genre LIKE '%%%%%q%%%%'", genre);
420 else if (artist && !genre) {
421 if(exact)
422 query = sqlite3_mprintf("SELECT albumname FROM 'albums' WHERE artist=%Q", artist);
423 else
424 query = sqlite3_mprintf("SELECT albumname FROM 'albums' WHERE artist LIKE '%%%%%q%%%%'", artist);
426 else if (artist && genre) {
427 if(exact)
428 query = sqlite3_mprintf("SELECT genres.albumname FROM 'albums' JOIN 'genres' on albums.albumname = genres.albumname WHERE albums.artist=%Q AND genres.genre=%Q", artist,genre);
429 else
430 query = sqlite3_mprintf("SELECT genres.albumname FROM 'albums' JOIN 'genres' on albums.albumname = genres.albumname WHERE albums.artist LIKE '%%%%%q%%%%' AND genres.genre LIKE '%%%%%q%%%%'", artist,genre);
434 r=sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
435 if(r ==SQLITE_OK) {
436 while((r = sqlite3_step(stmt)) == SQLITE_ROW)
438 items++;
439 retv = g_realloc(retv, (items+1)*sizeof(*retv));
440 retv[items] = NULL;
441 retv[items-1] = g_strdup(sqlite3_column_text(stmt, 0));
444 sqlite3_finalize(stmt);
445 sqlite3_free(query);
446 return retv;
449 MpdData* magnatune_db_get_song_list(const char *wanted_genre,const char *wanted_artist, const char *wanted_album, gboolean exact)
451 MpdData *data = NULL;
452 xmlNodePtr * root;
453 xmlNodePtr * cur;
454 char *query;
456 if(!wanted_genre && !wanted_artist && !wanted_album) return NULL;
458 GTimer *timer = g_timer_new();
459 if(wanted_album) /* album seems to be unique */
461 data = __magnatune_get_data_album(wanted_album, exact);
462 }else if (wanted_genre && !wanted_artist)
464 data = __magnatune_get_data_album_from_genre(wanted_genre, exact);
466 else
468 char **albums = __magnatune_get_albums(wanted_genre, wanted_artist, exact);
469 if(albums)
471 int i;
472 for(i=0; albums[i];i++)
474 MpdData *data2 = __magnatune_get_data_album(albums[i], exact);
475 data = mpd_data_concatenate(data, data2);
477 g_strfreev(albums);
481 g_debug("%f s elapsed song list\n", g_timer_elapsed(timer,NULL));
482 g_timer_destroy(timer);
483 return mpd_data_get_first(data);
486 MpdData * magnatune_db_search_title(const gchar *title)
489 MpdData *list = NULL;
490 char *query = NULL;
491 sqlite3_stmt *stmt = NULL;
492 const char *tail;
493 int r = 0;
494 query = sqlite3_mprintf("SELECT songs.albumname,duration,number,desc,mp3 from 'songs' "
495 "WHERE songs.desc LIKE '%%%%%q%%%%'",title);
496 r=sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
497 if(r ==SQLITE_OK) {
498 while((r = sqlite3_step(stmt)) == SQLITE_ROW)
500 gchar *temp = gmpc_easy_download_uri_escape(sqlite3_column_text(stmt,4));
501 list = mpd_new_data_struct_append(list);
502 list->type = MPD_DATA_TYPE_SONG;
503 list->song = mpd_newSong();
504 list->song->album = g_strdup(sqlite3_column_text(stmt,0));
505 list->song->artist = __magnatune_get_artist_name(list->song->album);
506 list->song->genre = __magnatune_get_genre_name(list->song->album);
507 list->song->title= g_strdup(sqlite3_column_text(stmt,3));
508 list->song->track = g_strdup(sqlite3_column_text(stmt,2));
509 list->song->time = sqlite3_column_int(stmt,1);
510 list->song->file = g_strdup_printf("http://he3.magnatune.com/all/%s",temp);
511 g_free(temp);
514 sqlite3_finalize(stmt);
515 sqlite3_free(query);
516 return list;
521 gchar *magnatune_get_artist_image(const gchar *wanted_artist)
523 char *retv = NULL;
524 sqlite3_stmt *stmt = NULL;
525 char *artist = __magnatune_process_string(wanted_artist);
526 const char *tail;
527 int r = 0;
528 char *query = NULL;
529 query = sqlite3_mprintf("SELECT homepage from 'artists' WHERE artist LIKE '%%%%%q%%%%' limit 1",artist);
530 r=sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
531 if(r ==SQLITE_OK) {
532 if((r = sqlite3_step(stmt)) == SQLITE_ROW)
534 gchar *temp = gmpc_easy_download_uri_escape( sqlite3_column_text(stmt, 0));
535 retv = g_strdup_printf("http://he3.magnatune.com/artists/img/%s_1.jpg", temp);
536 g_free(temp);
539 sqlite3_finalize(stmt);
540 sqlite3_free(query);
541 g_free(artist);
542 return retv;
545 gchar *magnatune_get_album_url(const gchar *wanted_artist, const gchar *wanted_album)
551 gchar *magnatune_get_album_image(const gchar *wanted_artist, const gchar *wanted_album)
553 char *retv = NULL;
554 char *artist = __magnatune_process_string(wanted_artist);
555 char *album = __magnatune_process_string(wanted_album);
556 gchar *artist_enc = gmpc_easy_download_uri_escape(artist);
557 gchar *album_enc = gmpc_easy_download_uri_escape(album);
558 retv = g_strdup_printf("http://he3.magnatune.com/music/%s/%s/cover_600.jpg",artist_enc, album_enc);
559 g_free(artist);
560 g_free(album);
561 g_free(artist_enc);
562 g_free(album_enc);
563 return retv;