Apply patch from bug 2596 and make password invisible.
[gmpc-magnatune.git] / src / magnatune.c
blobda5ee3121054f66ed98e407eec4c158bfb48c374
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 <playlist3-messages.h>
29 #include "magnatune.h"
31 static sqlite3 *magnatune_sqlhandle = NULL;
33 static gchar *user_name = NULL;
34 static gchar *user_password = NULL;
36 void magnatune_set_user_password(const gchar *name, const gchar *password)
38 if(user_name) g_free(user_name);
39 user_name = NULL;
41 if(name && strlen(name) > 0)
42 user_name = gmpc_easy_download_uri_escape(name);
44 if(user_password) g_free(user_password);
45 user_password = NULL;
47 if(password && strlen(password) > 0)
48 user_password = gmpc_easy_download_uri_escape(password);
51 static gchar *magnatune_get_url(const gchar *n)
53 if(user_name != NULL && user_password != NULL)
55 int len = strlen(n);
56 if (n > 4)
57 return g_strdup_printf("http://%s:%s@stream.magnatune.com/all/%*.*s_nospeech.mp3",user_name, user_password, len - 4, len - 4, n);
60 return g_strdup_printf("http://he3.magnatune.com/all/%s",n);
63 void magnatune_db_destroy(void)
65 if(magnatune_sqlhandle)
67 sqlite3_close(magnatune_sqlhandle);
68 magnatune_sqlhandle = NULL;
72 /* run this before using the other fucntions */
73 void magnatune_db_init()
77 void magnatune_db_open()
79 gchar *path = NULL;
80 const gchar *final = NULL;
83 /**
84 * if open close it
86 if(magnatune_sqlhandle)
88 sqlite3_close(magnatune_sqlhandle);
89 magnatune_sqlhandle = NULL;
92 final = g_get_user_cache_dir();
93 path = g_build_filename(final, "gmpc", "magnatune.sqlite3", NULL);
94 sqlite3_open(path, &(magnatune_sqlhandle));
95 g_free(path);
98 /* FIXME */
99 gboolean magnatune_db_has_data()
101 char *query = sqlite3_mprintf("SELECT * from 'sqlite_master'");
102 sqlite3_stmt *stmt = NULL;
103 const char *tail;
104 int r;
107 r= sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
108 sqlite3_free(query);
109 if(r == SQLITE_OK) {
110 while((r = sqlite3_step(stmt)) == SQLITE_ROW){
111 sqlite3_finalize(stmt);
112 return TRUE;
116 sqlite3_finalize(stmt);
117 return FALSE;
120 MpdData * magnatune_db_get_genre_list()
122 MpdData *list = NULL;
123 int i,r;
125 char *query = sqlite3_mprintf("SELECT genre from 'genres' group by genre");
126 sqlite3_stmt *stmt = NULL;
127 const char *tail;
128 GTimer *timer = g_timer_new();
129 r = sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
130 if(r ==SQLITE_OK) {
131 while((r = sqlite3_step(stmt)) == SQLITE_ROW)
133 list = mpd_new_data_struct_append(list);
134 list->type = MPD_DATA_TYPE_TAG;
135 list->tag_type = MPD_TAG_ITEM_GENRE;
136 list->tag = g_strdup(sqlite3_column_text(stmt,0));
140 sqlite3_finalize(stmt);
141 sqlite3_free(query);
142 g_debug("%f s elapsed getting genres\n", g_timer_elapsed(timer,NULL));
143 g_timer_reset(timer);
144 list = misc_mpddata_remove_duplicate_songs(list);
145 g_debug("%f s elapsed unique genres list\n", g_timer_elapsed(timer,NULL));
146 g_timer_destroy(timer);
147 return list;
150 void magnatune_db_load_data(const char *data, const goffset length)
152 gchar *error = NULL;
153 gchar *path;
156 const gchar *final = g_get_user_cache_dir();
157 path = g_build_filename(final, "gmpc", "magnatune.sqlite3", NULL);
158 if(magnatune_sqlhandle)
160 int status = sqlite3_close(magnatune_sqlhandle);
161 if(status != 0)
163 gchar *temp =g_strdup_printf("Failed to close magnatune db: %i\n", status);
164 playlist3_show_error_message(temp, ERROR_WARNING);
165 g_free(temp);
167 magnatune_sqlhandle = NULL;
169 if(data){
170 GError *error = NULL;
171 gssize size= (gssize)length;
172 g_file_set_contents(path, data, size, &error);
173 if(error) {
174 gchar *temp =g_strdup_printf("Failed to store magnatune db: %s\n", error->message);
175 playlist3_show_error_message(temp, ERROR_WARNING);
176 g_free(temp);
177 g_error_free(error);
180 /* open the db if it is closed */
181 if(!magnatune_sqlhandle) {
184 int retv = sqlite3_open(path, &(magnatune_sqlhandle));
185 if(retv != SQLITE_OK)
187 g_free(path);
189 playlist3_show_error_message("Failed to open the new magnatune database", ERROR_WARNING);
190 /* Cleanup */
191 return;
195 sqlite3_exec(magnatune_sqlhandle, "CREATE INDEX songsAlbumname ON songs(albumname);", NULL, NULL, &error);
196 if(error)printf("%i: %s",__LINE__, error);
197 sqlite3_exec(magnatune_sqlhandle, "CREATE INDEX genresAlbumname ON genres(albumname);", NULL, NULL, &error);
198 if(error)printf("%i: %s",__LINE__, error);
199 sqlite3_exec(magnatune_sqlhandle, "CREATE INDEX genresGenrename ON genres(genre);", NULL, NULL, &error);
200 if(error)printf("%i: %s",__LINE__, error);
201 sqlite3_exec(magnatune_sqlhandle, "CREATE INDEX albumsAlbumname ON albums(albumname);", NULL, NULL, &error);
202 if(error)printf("%i: %s",__LINE__, error);
204 g_free(path);
207 MpdData * magnatune_db_get_artist_list(char *wanted_genre)
209 MpdData *list = NULL;
210 int r;
211 /** check if there is data */
212 char *query = sqlite3_mprintf("SELECT albumname from 'genres' WHERE genre=%Q", wanted_genre);
213 sqlite3_stmt *stmt = NULL;
214 const char *tail;
215 GTimer *timer = g_timer_new();
216 r = sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
217 if(r ==SQLITE_OK) {
218 while((r = sqlite3_step(stmt)) == SQLITE_ROW)
220 sqlite3_stmt *stmt2 = NULL;
221 const char *tail2;
222 char *query2 = sqlite3_mprintf("SELECT artist from 'albums' WHERE albumname=%Q", sqlite3_column_text(stmt,0));
223 int r2 = sqlite3_prepare_v2(magnatune_sqlhandle, query2, -1, &stmt2, &tail2);
224 if(r2 ==SQLITE_OK) {
225 while((r2 = sqlite3_step(stmt2)) == SQLITE_ROW)
227 list = mpd_new_data_struct_append(list);
228 list->type = MPD_DATA_TYPE_TAG;
229 list->tag_type = MPD_TAG_ITEM_ARTIST;
230 list->tag = g_strdup(sqlite3_column_text(stmt2,0));
233 sqlite3_finalize(stmt2);
234 sqlite3_free(query2);
237 sqlite3_finalize(stmt);
238 sqlite3_free(query);
239 g_debug("%f s elapsed getting genres\n", g_timer_elapsed(timer,NULL));
240 g_timer_reset(timer);
241 list = misc_mpddata_remove_duplicate_songs(list);
243 g_debug("%f s elapsed unique artist list\n", g_timer_elapsed(timer,NULL));
244 g_timer_destroy(timer);
245 return list;
248 MpdData *magnatune_db_get_album_list(char *wanted_genre,char *wanted_artist)
250 int r;
251 MpdData *list = NULL;
252 /** check if there is data */
254 char *query = sqlite3_mprintf("SELECT albumname from 'albums' WHERE artist=%Q",wanted_artist);
255 sqlite3_stmt *stmt = NULL;
256 const char *tail;
257 GTimer *timer = g_timer_new();
258 r = sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
259 if(r ==SQLITE_OK) {
260 while((r = sqlite3_step(stmt)) == SQLITE_ROW)
262 sqlite3_stmt *stmt2 = NULL;
263 const char *tail2;
264 char *query2 = sqlite3_mprintf("SELECT albumname from 'genres' WHERE albumname=%Q AND genre=%Q", sqlite3_column_text(stmt,0),wanted_genre);
265 int r2 = sqlite3_prepare_v2(magnatune_sqlhandle, query2, -1, &stmt2, &tail2);
266 if(r2 ==SQLITE_OK) {
267 while((r2 = sqlite3_step(stmt2)) == SQLITE_ROW)
269 list = mpd_new_data_struct_append(list);
270 list->type = MPD_DATA_TYPE_TAG;
271 list->tag_type = MPD_TAG_ITEM_ALBUM;
272 list->tag = g_strdup(sqlite3_column_text(stmt2,0));
275 sqlite3_finalize(stmt2);
276 sqlite3_free(query2);
279 sqlite3_finalize(stmt);
280 sqlite3_free(query);
281 g_debug("%f s elapsed listing albums songs\n", g_timer_elapsed(timer,NULL));
282 g_timer_destroy(timer);
283 return mpd_data_get_first(list);
286 static char *__magnatune_get_artist_name(const char *album)
288 char *retv = NULL;
289 sqlite3_stmt *stmt = NULL;
290 const char *tail;
291 int r = 0;
292 char *query = NULL;
293 if(!album) return NULL;
294 query = sqlite3_mprintf("SELECT artist from 'albums' WHERE albumname=%Q limit 1",album);
295 r=sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
296 if(r ==SQLITE_OK) {
297 if((r = sqlite3_step(stmt)) == SQLITE_ROW)
299 retv = g_strdup(sqlite3_column_text(stmt, 0));
302 sqlite3_finalize(stmt);
303 sqlite3_free(query);
304 return retv;
306 static char *__magnatune_get_genre_name(const char *album)
308 char *retv = NULL;
309 sqlite3_stmt *stmt = NULL;
310 const char *tail;
311 int r = 0;
312 char *query = NULL;
313 if(!album) return NULL;
314 query = sqlite3_mprintf("SELECT genre from 'genres' WHERE albumname=%Q",album);
315 r=sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
316 if(r ==SQLITE_OK) {
317 while((r = sqlite3_step(stmt)) == SQLITE_ROW)
319 const char *temp= sqlite3_column_text(stmt, 0);
320 if(retv)
322 gchar *t = retv;
323 retv = g_strconcat(t, ", ",temp, NULL);
324 g_free(t);
326 else retv = g_strdup(temp);
330 sqlite3_finalize(stmt);
331 sqlite3_free(query);
332 return retv;
334 static MpdData *__magnatune_get_data_album_from_genre(const char *genre, gboolean exact)
336 MpdData *list = NULL;
337 char *query = NULL;
338 sqlite3_stmt *stmt = NULL;
339 const char *tail;
340 int r = 0;
341 GTimer *timer = g_timer_new();
342 if(exact)
344 query = sqlite3_mprintf("SELECT songs.albumname,duration,number,desc,mp3 from 'songs' JOIN 'genres' ON songs.albumname = genres.albumname "
345 "WHERE genres.genre=%Q",genre);
346 }else{
347 query = sqlite3_mprintf("SELECT songs.albumname,duration,number,desc,mp3 from 'songs' JOIN 'genres' ON songs.albumname = genres.albumname "
348 "WHERE genres.genre LIKE '%%%%%q%%%%'",genre);
350 r=sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
351 if(r ==SQLITE_OK) {
352 while((r = sqlite3_step(stmt)) == SQLITE_ROW)
354 gchar *temp = gmpc_easy_download_uri_escape(sqlite3_column_text(stmt,4));
355 list = mpd_new_data_struct_append(list);
356 list->type = MPD_DATA_TYPE_SONG;
357 list->song = mpd_newSong();
358 list->song->album = g_strdup(sqlite3_column_text(stmt,0));
359 list->song->artist = __magnatune_get_artist_name(list->song->album);
360 list->song->genre = __magnatune_get_genre_name(list->song->album);
361 list->song->title= g_strdup(sqlite3_column_text(stmt,3));
362 list->song->track = g_strdup(sqlite3_column_text(stmt,2));
363 list->song->time = sqlite3_column_int(stmt,1);
364 list->song->file = magnatune_get_url(temp);
365 g_free(temp);
367 }else{
368 g_warning("Sqlite error: %s\n", tail);
371 sqlite3_finalize(stmt);
372 sqlite3_free(query);
373 g_debug("%f s elapsed getting album songs from genre\n", g_timer_elapsed(timer,NULL));
374 g_timer_destroy(timer);
375 return list;
378 static MpdData *__magnatune_get_data_album(const char *album, gboolean exact)
380 MpdData *list = NULL;
381 char *query = NULL;
382 sqlite3_stmt *stmt = NULL;
383 const char *tail;
384 int r = 0;
385 GTimer *timer = g_timer_new();
386 if(exact)
388 query = sqlite3_mprintf("SELECT songs.albumname,duration,number,desc,mp3 from 'songs' "
389 "WHERE songs.albumname=%Q",album);
390 }else{
391 query = sqlite3_mprintf("SELECT songs.albumname,duration,number,desc,mp3 from 'songs' "
392 "WHERE songs.albumname LIKE '%%%%%q%%%%'",album);
394 r=sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
395 if(r ==SQLITE_OK) {
396 while((r = sqlite3_step(stmt)) == SQLITE_ROW)
398 gchar *temp = gmpc_easy_download_uri_escape(sqlite3_column_text(stmt,4));
399 list = mpd_new_data_struct_append(list);
400 list->type = MPD_DATA_TYPE_SONG;
401 list->song = mpd_newSong();
402 list->song->album = g_strdup(sqlite3_column_text(stmt,0));
403 list->song->artist = __magnatune_get_artist_name(list->song->album);
404 list->song->genre = __magnatune_get_genre_name(list->song->album);
405 list->song->title= g_strdup(sqlite3_column_text(stmt,3));
406 list->song->track = g_strdup(sqlite3_column_text(stmt,2));
407 list->song->time = sqlite3_column_int(stmt,1);
408 list->song->file = magnatune_get_url(temp);
409 g_free(temp);
412 else{
413 g_warning("Sqlite error: %s\n", tail);
415 sqlite3_finalize(stmt);
416 sqlite3_free(query);
417 g_debug("%f s elapsed getting album songs\n", g_timer_elapsed(timer,NULL));
418 g_timer_destroy(timer);
419 return list;
421 static gchar ** __magnatune_get_albums(const char *genre, const char *artist, gboolean exact)
423 char **retv = NULL;
424 sqlite3_stmt *stmt = NULL;
425 const char *tail;
426 int items = 0;
427 int r = 0;
428 char *query = NULL;
430 if(genre && !artist) {
431 if(exact)
432 query = sqlite3_mprintf("SELECT albumname FROM 'genres' WHERE genre=%Q", genre);
433 else
434 query = sqlite3_mprintf("SELECT albumname FROM 'genres' WHERE genre LIKE '%%%%%q%%%%'", genre);
436 else if (artist && !genre) {
437 if(exact)
438 query = sqlite3_mprintf("SELECT albumname FROM 'albums' WHERE artist=%Q", artist);
439 else
440 query = sqlite3_mprintf("SELECT albumname FROM 'albums' WHERE artist LIKE '%%%%%q%%%%'", artist);
442 else if (artist && genre) {
443 if(exact)
444 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);
445 else
446 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);
450 r=sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
451 if(r ==SQLITE_OK) {
452 while((r = sqlite3_step(stmt)) == SQLITE_ROW)
454 items++;
455 retv = g_realloc(retv, (items+1)*sizeof(*retv));
456 retv[items] = NULL;
457 retv[items-1] = g_strdup(sqlite3_column_text(stmt, 0));
460 sqlite3_finalize(stmt);
461 sqlite3_free(query);
462 return retv;
465 MpdData* magnatune_db_get_song_list(const char *wanted_genre,const char *wanted_artist, const char *wanted_album, gboolean exact)
467 MpdData *data = NULL;
468 char *query;
470 if(!wanted_genre && !wanted_artist && !wanted_album) return NULL;
472 GTimer *timer = g_timer_new();
473 if(wanted_album) /* album seems to be unique */
475 data = __magnatune_get_data_album(wanted_album, exact);
476 }else if (wanted_genre && !wanted_artist)
478 data = __magnatune_get_data_album_from_genre(wanted_genre, exact);
480 else
482 char **albums = __magnatune_get_albums(wanted_genre, wanted_artist, exact);
483 if(albums)
485 int i;
486 for(i=0; albums[i];i++)
488 MpdData *data2 = __magnatune_get_data_album(albums[i], exact);
489 data = mpd_data_concatenate(data, data2);
491 g_strfreev(albums);
495 g_debug("%f s elapsed song list\n", g_timer_elapsed(timer,NULL));
496 g_timer_destroy(timer);
497 return mpd_data_get_first(data);
500 MpdData * magnatune_db_search_title(const gchar *title)
503 MpdData *list = NULL;
504 char *query = NULL;
505 sqlite3_stmt *stmt = NULL;
506 const char *tail;
507 int r = 0;
508 query = sqlite3_mprintf("SELECT songs.albumname,duration,number,desc,mp3 from 'songs' "
509 "WHERE songs.desc LIKE '%%%%%q%%%%'",title);
510 r=sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
511 if(r ==SQLITE_OK) {
512 while((r = sqlite3_step(stmt)) == SQLITE_ROW)
514 gchar *temp = gmpc_easy_download_uri_escape(sqlite3_column_text(stmt,4));
515 list = mpd_new_data_struct_append(list);
516 list->type = MPD_DATA_TYPE_SONG;
517 list->song = mpd_newSong();
518 list->song->album = g_strdup(sqlite3_column_text(stmt,0));
519 list->song->artist = __magnatune_get_artist_name(list->song->album);
520 list->song->genre = __magnatune_get_genre_name(list->song->album);
521 list->song->title= g_strdup(sqlite3_column_text(stmt,3));
522 list->song->track = g_strdup(sqlite3_column_text(stmt,2));
523 list->song->time = sqlite3_column_int(stmt,1);
524 list->song->file = magnatune_get_url(temp);
525 g_free(temp);
528 sqlite3_finalize(stmt);
529 sqlite3_free(query);
530 return list;
535 gchar *magnatune_get_artist_image(const gchar *wanted_artist)
537 char *retv = NULL;
538 sqlite3_stmt *stmt = NULL;
539 char *artist = __magnatune_process_string(wanted_artist);
540 const char *tail;
541 int r = 0;
542 char *query = NULL;
543 query = sqlite3_mprintf("SELECT homepage from 'artists' WHERE artist LIKE '%%%%%q%%%%' limit 1",artist);
544 r=sqlite3_prepare_v2(magnatune_sqlhandle, query, -1, &stmt, &tail);
545 if(r ==SQLITE_OK) {
546 if((r = sqlite3_step(stmt)) == SQLITE_ROW)
548 gchar *temp = gmpc_easy_download_uri_escape( sqlite3_column_text(stmt, 0));
549 retv = g_strdup_printf("http://he3.magnatune.com/artists/img/%s_1.jpg", temp);
550 g_free(temp);
553 sqlite3_finalize(stmt);
554 sqlite3_free(query);
555 g_free(artist);
556 return retv;
559 gchar *magnatune_get_album_url(const gchar *wanted_artist, const gchar *wanted_album)
565 gchar *magnatune_get_album_image(const gchar *wanted_artist, const gchar *wanted_album)
567 char *retv = NULL;
568 char *artist = __magnatune_process_string(wanted_artist);
569 char *album = __magnatune_process_string(wanted_album);
570 gchar *artist_enc = gmpc_easy_download_uri_escape(artist);
571 gchar *album_enc = gmpc_easy_download_uri_escape(album);
572 retv = g_strdup_printf("http://he3.magnatune.com/music/%s/%s/cover_600.jpg",artist_enc, album_enc);
573 g_free(artist);
574 g_free(album);
575 g_free(artist_enc);
576 g_free(album_enc);
577 return retv;