Fix missing header thx Seb
[gmpc-magnatune.git] / src / plugin.c
blob3f16eedcef1f1d163283898ab4de9caec47aa532
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 <gdk/gdkkeysyms.h>
23 #include <config.h>
24 #include <glib.h>
25 #include <glib/gi18n-lib.h>
26 #include <glade/glade.h>
27 #include <plugin.h>
28 #include <gmpc_easy_download.h>
29 #include <metadata.h>
30 #include <gmpc-mpddata-model.h>
31 #include <gmpc-mpddata-treeview.h>
32 #include <gmpc-extras.h>
33 #include <config.h>
34 #include <playlist3-messages.h>
35 #include "magnatune.h"
36 #include <libmpd/debug_printf.h>
38 extern GladeXML *pl3_xml;
40 gmpcPlugin plugin;
41 /**
42 * Function decleration
44 static void magnatune_selected(GtkWidget *container);
45 static void magnatune_unselected(GtkWidget *container);
46 static void magnatune_add(GtkWidget *cat_tree);
47 static void magnatune_download_xml_callback(int download, int total,gpointer data);
48 static void magnatune_download();
49 static void magnatune_mpd_status_changed(MpdObj *mi, ChangedStatusType what, void *data);
50 static int magnatune_fetch_cover_priority(void);
51 static void magnatune_fetch_get_image(mpd_Song *song,MetaDataType type, void (*callback)(GList *list, gpointer data), gpointer user_data);
52 static int magnatune_cat_menu_popup(GtkWidget *menu, int type, GtkWidget *tree, GdkEventButton *event);
54 static int magnatune_button_release_event(GtkWidget *tree, GdkEventButton *event,gpointer data);
55 static int magnatune_button_handle_release_event_tag(GtkWidget *tree, GdkEventButton *event,gpointer data);
57 static int magnatune_key_press(GtkWidget *tree, GdkEventKey *event);
58 static void magnatune_show_album_list(GtkTreeSelection *selection, gpointer user_data);
59 static void magnatune_show_song_list(GtkTreeSelection *selection, gpointer user_data);
60 static int magnatune_button_handle_release_event_tag_add(GtkWidget *button, gpointer user_data);
61 static void magnatune_save_myself(void);
62 static GtkTreeRowReference *magnatune_ref = NULL;
63 static void magnatune_download_cancel(GtkWidget *button);
65 static int downloading = FALSE;
66 /**
67 * Get set enabled
69 static int magnatune_get_enabled()
71 return cfg_get_single_value_as_int_with_default(config, "magnatune", "enable", TRUE);
73 static void magnatune_set_enabled(int enabled)
75 cfg_set_single_value_as_int(config, "magnatune", "enable", enabled);
76 if (enabled)
78 if(magnatune_ref == NULL)
80 magnatune_add(GTK_WIDGET(playlist3_get_category_tree_view()));
83 else if (magnatune_ref)
85 GtkTreePath *path = gtk_tree_row_reference_get_path(magnatune_ref);
86 if (path){
87 GtkTreeIter iter;
88 magnatune_save_myself();
89 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist3_get_category_tree_store()), &iter, path)){
90 gtk_list_store_remove(playlist3_get_category_tree_store(), &iter);
92 gtk_tree_path_free(path);
93 gtk_tree_row_reference_free(magnatune_ref);
94 magnatune_ref = NULL;
97 pl3_update_go_menu();
104 /* Playlist window row reference */
106 GtkWidget *magnatune_pb = NULL, *magnatune_cancel = NULL;
107 GtkWidget *magnatune_vbox = NULL;
108 GtkTreeModel *mt_store = NULL;
110 GtkWidget *treeviews[3] = {NULL, NULL,NULL};
112 static GtkWidget *magnatune_logo=NULL;
113 extern GladeXML *pl3_xml;
115 static void magnatune_buy_album()
117 gchar *uri;
118 mpd_Song *song = NULL;
119 gchar *artist;
120 gchar *album;
122 if(mpd_check_connected(connection))
124 song = mpd_playlist_get_current_song(connection);
125 artist = __magnatune_process_string(song->artist);
126 album = __magnatune_process_string(song->album);
127 uri = g_strconcat("http://www.magnatune.com/buy/choose?artist=",artist,"&album=",album,NULL);
128 open_uri(uri);
129 g_free(artist);
130 g_free(album);
131 g_free(uri);
135 static void magnatune_logo_add()
137 mpd_Song *song = NULL;
138 GtkWidget *logo, *button;
139 GtkWidget *ali;
140 if(mpd_check_connected(connection))
141 song = mpd_playlist_get_current_song(connection);
143 magnatune_logo = gtk_vbox_new(FALSE,6);
145 button = gtk_button_new_with_label("Buy this album\nfrom magnatune");
146 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
148 ali = gtk_alignment_new(0,0.5,0,1);
149 gtk_container_add(GTK_CONTAINER(ali), button);
150 logo = gtk_image_new_from_icon_name("magnatune", GTK_ICON_SIZE_DND);
151 gtk_button_set_image(GTK_BUTTON(button), logo);
152 gtk_box_pack_start(GTK_BOX(magnatune_logo), ali, TRUE, TRUE,0);
153 gtk_box_pack_end(GTK_BOX(glade_xml_get_widget(pl3_xml, "vbox5")), magnatune_logo, FALSE,FALSE,0);
154 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(magnatune_buy_album), NULL);
155 if(song) {
156 if(strstr(song->file,"magnatune.com"))
158 gtk_widget_show_all(magnatune_logo);
159 return;
166 static void magnatune_logo_init()
168 gchar *path = gmpc_plugin_get_data_path(&plugin);
169 gchar *url = g_build_path(G_DIR_SEPARATOR_S,path, "magnatune", NULL);
170 debug_printf(DEBUG_WARNING,"Found url: %s\n", url);
171 gtk_icon_theme_append_search_path(gtk_icon_theme_get_default (),url);
172 g_free(url);
173 g_free(path);
176 bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
177 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
180 gtk_init_add((GtkFunction )magnatune_logo_add, NULL);
181 /**
182 * init the magnatune stuff
184 magnatune_db_init();
186 * open the db
188 magnatune_db_open();
190 gchar *un = cfg_get_single_value_as_string(config,"magnatune", "username");
191 gchar *up = cfg_get_single_value_as_string(config,"magnatune", "password");
192 magnatune_set_user_password(un, up);
193 g_free(un);
194 g_free(up);
199 static void magnatune_mpd_status_changed(MpdObj *mi, ChangedStatusType what, void *data)
201 if(!magnatune_logo)
202 return;
203 if(what&(MPD_CST_SONGID|MPD_CST_STATE))
205 mpd_Song *song = mpd_playlist_get_current_song(mi);
206 if(song && mpd_player_get_state(mi) == MPD_STATUS_STATE_PLAY) {
207 if(strstr(song->file,"magnatune.com"))
209 gtk_widget_show_all(magnatune_logo);
210 return;
213 gtk_widget_hide(magnatune_logo);
217 void magnatune_get_genre_list()
219 MpdData *data = NULL;
220 GTimer *timer;
221 data = magnatune_db_get_genre_list();
223 timer = g_timer_new();
224 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]))),data);
225 g_debug("%f seconds elapsed filling genre tree", g_timer_elapsed(timer,NULL)); g_timer_destroy(timer);
228 static void magnatune_show_album_list(GtkTreeSelection *selection, gpointer user_data)
230 MpdData *data = NULL;
231 GtkTreeIter piter;
232 GTimer *timer;
233 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]));
234 if(gtk_tree_selection_get_selected(selection, &model, &piter))
236 gchar *genre;
237 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&genre,-1);
238 data= magnatune_db_get_artist_list(genre);
240 g_free(genre);
242 timer = g_timer_new();
243 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[1]))),data);
244 g_debug("%f seconds elapsed filling artist tree", g_timer_elapsed(timer,NULL)); g_timer_destroy(timer);
247 static void magnatune_show_song_list(GtkTreeSelection *selection, gpointer user_data)
249 MpdData *data = NULL;
250 GtkTreeIter piter;
251 GtkTreeSelection *select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]));
252 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]));
253 GTimer *timer;
254 gchar *genre = NULL, *artist = NULL, *album = NULL;
255 if(gtk_tree_selection_get_selected(select, &model, &piter))
258 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]));
259 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&genre,-1);
260 /* model */
261 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[1]));
262 if(gtk_tree_selection_get_selected(select, &model, &piter))
264 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&artist,-1);
265 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[2]));
266 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[2]));
267 if(gtk_tree_selection_get_selected(select, &model, &piter))
269 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&album,-1);
273 data = magnatune_db_get_song_list(genre, artist, album,TRUE);
274 timer = g_timer_new();
275 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(mt_store), data);
276 g_debug("%f seconds elapsed filling song tree", g_timer_elapsed(timer,NULL)); g_timer_destroy(timer);
279 static void magnatune_show_artist_list(GtkTreeSelection *selection, gpointer user_data)
281 GtkTreeIter piter;
282 GTimer *timer;
283 MpdData *data = NULL;
284 GtkTreeSelection *select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]));
285 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]));
287 if(gtk_tree_selection_get_selected(select, &model, &piter))
289 GList *iter,*list = NULL;
290 gchar *genre;
292 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]));
293 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&genre,-1);
294 /* model */
295 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[1]));
296 if(gtk_tree_selection_get_selected(select, &model, &piter))
298 GList *iter,*list = NULL;
300 gchar *artist;
301 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&artist,-1);
302 data = magnatune_db_get_album_list(genre ,artist);
303 gmpc_mpddata_model_set_request_artist(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[2]))),artist);
304 GmpcMpdDataTreeviewTooltip *tool = (GmpcMpdDataTreeviewTooltip *)gtk_widget_get_tooltip_window(GTK_WIDGET(treeviews[2]));
305 if(tool->request_artist){
306 g_free(tool->request_artist);
308 tool->request_artist = g_strdup(artist);
310 g_free(artist);
312 g_free(genre);
314 timer = g_timer_new();
315 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[2]))),data);
316 g_debug("%f seconds elapsed filling album tree", g_timer_elapsed(timer,NULL)); g_timer_destroy(timer);
319 static void magnatune_add_album_row_activated(GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
321 GtkTreeModel *model = gtk_tree_view_get_model(tree);
322 GtkTreeIter iter_r;
324 if(gtk_tree_model_get_iter(model, &iter_r, path))
326 gchar *path;
327 gtk_tree_model_get(model, &iter_r, MPDDATA_MODEL_COL_PATH, &path, -1);
328 play_path(path);
329 g_free(path);
333 static gboolean magnatune_search_equal_func(GtkTreeModel *model, int column, const gchar *key, GtkTreeIter *iter, gpointer data)
335 gchar *compare = NULL;
336 gtk_tree_model_get(model,iter, column, &compare, -1);
337 if(compare){
338 gchar *a = g_utf8_casefold(key, -1);
339 gchar *b = g_utf8_casefold(compare, -1);
340 if(strstr(b,a))
342 g_free(a);
343 g_free(b);
344 return FALSE;
346 g_free(a);
347 g_free(b);
349 return TRUE;
352 static void magnatune_init()
354 int size;
355 GtkWidget *tree = NULL;
356 GtkWidget *sw = NULL;
357 GtkCellRenderer *renderer = NULL;
358 GtkWidget *paned = NULL;
359 GtkWidget *hbox = NULL;
360 GtkWidget *vbox = NULL;
361 GtkTreeModel *model = NULL;
362 GtkTreeViewColumn *column = NULL;
363 magnatune_vbox = gtk_hpaned_new();
364 gmpc_paned_size_group_add_paned(GMPC_PANED_SIZE_GROUP(paned_size_group), GTK_PANED(magnatune_vbox));
367 vbox = gtk_vbox_new(FALSE,6);
369 * Create list store
370 * 1. pointer
371 * 2. name
373 mt_store = (GtkTreeModel *)gmpc_mpddata_model_new();
375 /* Paned window */
376 paned = gtk_vbox_new(TRUE,6);
377 model = (GtkTreeModel *) gmpc_mpddata_model_new();
378 /* Genre list */
379 sw = gtk_scrolled_window_new(NULL, NULL);
380 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
381 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
382 treeviews[0] = gtk_tree_view_new_with_model(model);
383 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeviews[0]), TRUE);
385 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeviews[0]), MPDDATA_MODEL_COL_SONG_TITLE);
386 g_signal_connect(G_OBJECT(treeviews[0]), "button-press-event", G_CALLBACK(magnatune_button_handle_release_event_tag), GINT_TO_POINTER(0));
387 /* Add column */
388 column = gtk_tree_view_column_new();
389 gtk_tree_view_column_set_title(column, "Genre");
392 renderer = gtk_cell_renderer_pixbuf_new();
393 gtk_tree_view_column_pack_start(column, renderer, FALSE);
394 gtk_tree_view_column_add_attribute(column, renderer, "icon-name", MPDDATA_MODEL_COL_ICON_ID);
395 gtk_tree_view_column_set_sizing(column , GTK_TREE_VIEW_COLUMN_AUTOSIZE);
396 renderer = gtk_cell_renderer_text_new();
397 gtk_tree_view_column_pack_start(column, renderer, TRUE);
398 gtk_tree_view_column_add_attribute(column, renderer, "text", MPDDATA_MODEL_COL_SONG_TITLE);
399 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeviews[0]),column, -1);
401 gtk_container_add(GTK_CONTAINER(sw), treeviews[0]);
402 gtk_box_pack_start(GTK_BOX(paned), sw, TRUE, TRUE, 0);
404 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]))), "changed", G_CALLBACK(magnatune_show_album_list), NULL);
406 /* Artist list */
407 model = (GtkTreeModel *) gmpc_mpddata_model_new();
408 sw = gtk_scrolled_window_new(NULL, NULL);
409 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
410 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
411 treeviews[1] = gtk_tree_view_new_with_model(model);
412 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeviews[1]), TRUE);
413 gmpc_mpd_data_treeview_tooltip_new(GTK_TREE_VIEW(treeviews[1]), META_ARTIST_ART);
414 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeviews[1]), MPDDATA_MODEL_COL_SONG_TITLE);
415 g_signal_connect(G_OBJECT(treeviews[1]), "button-press-event", G_CALLBACK(magnatune_button_handle_release_event_tag), GINT_TO_POINTER(1));
416 /* Add column */
417 column = gtk_tree_view_column_new();
418 gtk_tree_view_column_set_title(column, "Artist");
419 size = cfg_get_single_value_as_int_with_default(config, "gmpc-mpddata-model", "icon-size", 64);
420 gtk_tree_view_column_set_sizing(column , GTK_TREE_VIEW_COLUMN_FIXED);
421 gtk_tree_view_set_fixed_height_mode(GTK_TREE_VIEW(treeviews[1]), TRUE);
424 renderer = gtk_cell_renderer_pixbuf_new();
425 gtk_cell_renderer_set_fixed_size(renderer, size,size);
427 gtk_tree_view_column_pack_start(column, renderer, FALSE);
428 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", MPDDATA_MODEL_META_DATA);
429 renderer = gtk_cell_renderer_text_new();
430 gtk_tree_view_column_pack_start(column, renderer, TRUE);
431 gtk_tree_view_column_add_attribute(column, renderer, "text", MPDDATA_MODEL_COL_SONG_TITLE);
432 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeviews[1]),column, -1);
434 gtk_container_add(GTK_CONTAINER(sw), treeviews[1]);
435 gtk_box_pack_start(GTK_BOX(paned), sw, TRUE, TRUE, 0);
437 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]))), "changed", G_CALLBACK(magnatune_show_artist_list), NULL);
439 /* Album list */
440 model = (GtkTreeModel *) gmpc_mpddata_model_new();
441 sw = gtk_scrolled_window_new(NULL, NULL);
442 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
443 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
444 treeviews[2] = gtk_tree_view_new_with_model(model);
445 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeviews[2]), TRUE);
446 gmpc_mpd_data_treeview_tooltip_new(GTK_TREE_VIEW(treeviews[2]), META_ALBUM_ART);
447 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeviews[2]), MPDDATA_MODEL_COL_SONG_TITLE);
449 g_signal_connect(G_OBJECT(treeviews[2]), "button-press-event", G_CALLBACK(magnatune_button_handle_release_event_tag), GINT_TO_POINTER(2));
450 /* Add column */
451 column = gtk_tree_view_column_new();
452 gtk_tree_view_column_set_title(column, "Album");
453 size = cfg_get_single_value_as_int_with_default(config, "gmpc-mpddata-model", "icon-size", 64);
454 gtk_tree_view_column_set_sizing(column , GTK_TREE_VIEW_COLUMN_FIXED);
455 gtk_tree_view_set_fixed_height_mode(GTK_TREE_VIEW(treeviews[2]), TRUE);
458 renderer = gtk_cell_renderer_pixbuf_new();
459 gtk_cell_renderer_set_fixed_size(renderer, size,size);
461 gtk_tree_view_column_pack_start(column, renderer, FALSE);
462 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", MPDDATA_MODEL_META_DATA);
463 renderer = gtk_cell_renderer_text_new();
464 gtk_tree_view_column_pack_start(column, renderer, TRUE);
465 gtk_tree_view_column_add_attribute(column, renderer, "text", MPDDATA_MODEL_COL_SONG_TITLE);
466 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeviews[2]),column, -1);
468 gtk_container_add(GTK_CONTAINER(sw), treeviews[2]);
469 gtk_box_pack_start(GTK_BOX(paned), sw, TRUE, TRUE, 0);
472 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]))), "changed", G_CALLBACK(magnatune_show_song_list), NULL);
473 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]))), "changed", G_CALLBACK(magnatune_show_song_list), NULL);
474 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[2]))), "changed", G_CALLBACK(magnatune_show_song_list), NULL);
476 gtk_paned_add1(GTK_PANED(magnatune_vbox), paned);
477 gtk_widget_show_all(paned);
479 * tree
481 sw = gtk_scrolled_window_new(NULL, NULL);
482 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
483 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
486 tree = (GtkWidget *)gmpc_mpddata_treeview_new("magnatune",TRUE,GTK_TREE_MODEL(mt_store));
487 g_signal_connect(G_OBJECT(tree), "row-activated", G_CALLBACK(magnatune_add_album_row_activated), NULL);
489 g_signal_connect(G_OBJECT(tree), "button-press-event", G_CALLBACK(magnatune_button_release_event), tree);
490 g_signal_connect(G_OBJECT(tree), "key-press-event", G_CALLBACK(magnatune_key_press), NULL);
492 gtk_container_add(GTK_CONTAINER(sw), tree);
493 gtk_box_pack_start(GTK_BOX(vbox),sw, TRUE, TRUE,0);
496 gtk_widget_show_all(sw);
497 gtk_widget_show(vbox);
499 * Progress Bar for the bottom
501 hbox = gtk_hbox_new(FALSE, 6);
502 magnatune_cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
503 g_signal_connect(G_OBJECT(magnatune_cancel), "clicked", G_CALLBACK(magnatune_download_cancel), NULL);
504 magnatune_pb = gtk_progress_bar_new();
505 gtk_box_pack_start(GTK_BOX(hbox), magnatune_pb, TRUE, TRUE, 0);
506 gtk_box_pack_start(GTK_BOX(hbox), magnatune_cancel, FALSE, TRUE, 0);
507 gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
508 gtk_paned_add2(GTK_PANED(magnatune_vbox), vbox);
511 g_object_ref(magnatune_vbox);
515 static void magnatune_selected(GtkWidget *container)
517 if(magnatune_vbox == NULL)
519 magnatune_init();
520 gtk_container_add(GTK_CONTAINER(container), magnatune_vbox);
521 gtk_widget_show(magnatune_vbox);
522 if(!magnatune_db_has_data())
524 magnatune_download();
526 else
527 magnatune_get_genre_list();
528 } else {
529 gtk_container_add(GTK_CONTAINER(container), magnatune_vbox);
530 gtk_widget_show(magnatune_vbox);
533 static void magnatune_unselected(GtkWidget *container)
535 gtk_container_remove(GTK_CONTAINER(container), magnatune_vbox);
537 static void magnatune_download_cancel(GtkWidget *button)
539 GEADAsyncHandler *handle = g_object_get_data(G_OBJECT(button), "handle");
540 if(handle)
542 gmpc_easy_async_cancel(handle);
543 g_object_set_data(G_OBJECT(button), "handle", NULL);
546 static void magnatune_download_callback(const GEADAsyncHandler *handle, const GEADStatus status, gpointer user_data)
548 GtkWidget *pb = user_data;
549 const gchar *uri = gmpc_easy_handler_get_uri(handle);
550 if(status == GEAD_DONE)
552 goffset length;
553 const char *data = gmpc_easy_handler_get_data(handle, &length);
555 magnatune_db_load_data(data, length);
556 if(length <= 0 || data == NULL) {
557 playlist3_show_error_message("Failed to download magnatune db: size is 0.",ERROR_WARNING);
559 gtk_widget_hide(gtk_widget_get_parent(pb));
560 magnatune_get_genre_list();
561 downloading = FALSE;
563 else if (status == GEAD_CANCELLED)
565 gtk_widget_hide(gtk_widget_get_parent(pb));
566 magnatune_get_genre_list();
567 downloading = FALSE;
569 else if (status == GEAD_PROGRESS)
571 goffset length;
572 goffset total = gmpc_easy_handler_get_content_size(handle);
573 /* Get downloaded length */
574 gmpc_easy_handler_get_data(handle, &length);
575 if(total > 0)
577 double fraction = (100*length)/(total);
578 gchar *size = g_format_size_for_display((goffset)length);
579 gchar *strtotal = g_format_size_for_display((goffset)total);
580 gchar *label = g_strdup_printf("Downloading music catalog (%s of %s done)",size,strtotal);
581 g_free(strtotal);
582 g_free(size);
583 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(pb), label);
584 g_free(label);
585 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pb),fraction/100.0);
587 else
589 gtk_progress_bar_pulse(GTK_PROGRESS_BAR(pb));
593 static void magnatune_download()
595 downloading = TRUE;
596 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]))),NULL);
597 gtk_widget_show_all(gtk_widget_get_parent(magnatune_pb));
598 const char *url = "http://he3.magnatune.com/info/sqlite_magnatune.db";
599 GEADAsyncHandler *handle = gmpc_easy_async_downloader(url, magnatune_download_callback,magnatune_pb);
600 g_object_set_data(G_OBJECT(magnatune_cancel), "handle", handle);
603 static void magnatune_add(GtkWidget *cat_tree)
605 GtkTreePath *path = NULL;
606 GtkTreeIter iter,child;
607 GtkListStore *pl3_tree = (GtkListStore *)gtk_tree_view_get_model(GTK_TREE_VIEW(cat_tree));
608 gint pos = cfg_get_single_value_as_int_with_default(config, "magnatune","position",20);
610 if(!cfg_get_single_value_as_int_with_default(config, "magnatune", "enable", TRUE)) return;
612 debug_printf(DEBUG_INFO,"Adding at position: %i", pos);
613 playlist3_insert_browser(&iter, pos);
614 gtk_list_store_set(GTK_LIST_STORE(pl3_tree), &iter,
615 PL3_CAT_TYPE, plugin.id,
616 PL3_CAT_TITLE, _("Magnatune Browser"),
617 PL3_CAT_INT_ID, "",
618 PL3_CAT_ICON_ID, "magnatune",
619 -1);
621 * Clean up old row reference if it exists
623 if (magnatune_ref)
625 gtk_tree_row_reference_free(magnatune_ref);
626 magnatune_ref = NULL;
629 * create row reference
631 path = gtk_tree_model_get_path(GTK_TREE_MODEL(playlist3_get_category_tree_store()), &iter);
632 if (path)
634 magnatune_ref = gtk_tree_row_reference_new(GTK_TREE_MODEL(playlist3_get_category_tree_store()), path);
635 gtk_tree_path_free(path);
639 char * __magnatune_process_string(const char *name)
641 int i = 0;
642 int j = 0;
643 int depth = 0;
644 int spaces = 0;
646 /* only gonna be smaller */
647 char *result = g_malloc0((strlen(name)+1+spaces*2)*sizeof(char));
648 for(i=0; i < strlen(name);i++)
650 if(name[i] == '(' || name[i] == '[') depth++;
651 else if (name[i] == ')' || name[i] == ']') depth--;
652 else if(!depth)
654 result[j] = name[i];
655 j++;
658 for(i=j-1;i>0 && result[i] == ' ';i--)
660 result[i] = '\0';
662 return result;
665 /*** COVER STUFF */
666 static int magnatune_fetch_cover_priority(void){
667 return cfg_get_single_value_as_int_with_default(config, "magnatune", "priority", 80);
669 static void magnatune_fetch_cover_priority_set(int priority){
670 cfg_set_single_value_as_int(config, "magnatune", "priority", priority);
674 static void magnatune_fetch_get_image(mpd_Song *song,MetaDataType type, void (*callback)(GList *list, gpointer data), gpointer user_data)
676 if(type == META_ARTIST_ART && song->artist)
678 char *value = magnatune_get_artist_image(song->artist);
679 if(value)
681 GList *list = NULL;
682 MetaData *mtd = meta_data_new();
683 mtd->type = type;
684 mtd->plugin_name = plugin.name;
685 mtd->content_type = META_DATA_CONTENT_URI;
686 mtd->content = value;
687 mtd->size = -1;
688 list = g_list_append(list, mtd);
689 callback(list, user_data);
690 return;
693 else if(type == META_ALBUM_ART && song->artist && song->album)
695 char *value = magnatune_get_album_image(song->artist,song->album);
696 if(value)
698 GList *list = NULL;
699 MetaData *mtd = meta_data_new();
700 mtd->type = type;
701 mtd->plugin_name = plugin.name;
702 mtd->content_type = META_DATA_CONTENT_URI;
703 mtd->content = value;
704 mtd->size = -1;
705 list = g_list_append(list, mtd);
706 callback(list, user_data);
707 return;
710 callback(NULL, user_data);
711 return ;
714 static void magnatune_redownload_reload_db()
716 GtkTreeIter iter;
717 GtkTreeModel *model = gtk_tree_row_reference_get_model(magnatune_ref);
718 GtkTreePath *path = gtk_tree_row_reference_get_path(magnatune_ref);
719 if(path && gtk_tree_model_get_iter(model, &iter, path))
721 GtkTreeIter citer;
722 while(gtk_tree_model_iter_children(model, &citer,&iter))
724 gtk_list_store_remove(GTK_LIST_STORE(model), &citer);
726 magnatune_download();
728 if(path)
729 gtk_tree_path_free(path);
731 static int magnatune_cat_menu_popup(GtkWidget *menu, int type, GtkWidget *tree, GdkEventButton *event)
733 GtkWidget *item;
734 if(type != plugin.id) return 0;
735 else if (!downloading)
737 /* add the clear widget */
738 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_REFRESH,NULL);
739 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
740 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(magnatune_redownload_reload_db), NULL);
741 return 1;
743 return 0;
746 static void magnatune_add_selected(GtkWidget *button, GtkTreeView *tree)
748 GtkTreeModel *model = GTK_TREE_MODEL(mt_store);
749 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
750 GList *list = gtk_tree_selection_get_selected_rows(sel,&model);
751 if(list)
753 GList *node ;
754 for(node = list; node; node = g_list_next(node))
756 GtkTreeIter iter;
757 if(gtk_tree_model_get_iter(model, &iter, node->data))
759 gchar *path;
760 gtk_tree_model_get(model, &iter, MPDDATA_MODEL_COL_PATH, &path, -1);
761 mpd_playlist_queue_add(connection, path);
762 g_free(path);
765 mpd_playlist_queue_commit(connection);
766 g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL);
767 g_list_free (list);
770 static void magnatune_replace_selected(GtkWidget *button , GtkTreeView *tree)
772 mpd_playlist_clear(connection);
773 magnatune_add_selected(button, tree);
774 mpd_player_play(connection);
778 static int magnatune_button_handle_release_event_tag_add(GtkWidget *button, gpointer userdata)
780 GList *list;
781 MpdData *data;
782 int position = GPOINTER_TO_INT(userdata);
783 gchar *genre=NULL, *artist=NULL, *album=NULL;
784 GtkTreeSelection *select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]));
785 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]));
786 GtkTreeIter piter;
787 if(gtk_tree_selection_get_selected(select, &model, &piter))
789 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&genre,-1);
791 if(position >= 1)
793 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]));
794 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[1]));
795 if(gtk_tree_selection_get_selected(select, &model, &piter))
797 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&artist,-1);
800 if(position >= 2)
802 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[2]));
803 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[2]));
804 if(gtk_tree_selection_get_selected(select, &model, &piter))
806 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&album,-1);
810 data = magnatune_db_get_song_list(genre,artist,album, TRUE);
811 for(data = mpd_data_get_first(data);data;data = mpd_data_get_next(data)) {
812 mpd_playlist_queue_add(connection, data->song->file);
814 mpd_playlist_queue_commit(connection);
815 if(genre)
816 g_free(genre);
817 if(artist)
818 g_free(artist);
819 if(album)
820 g_free(album);
824 static int magnatune_button_handle_release_event_tag_replace(GtkWidget *button, gpointer userdata)
826 mpd_playlist_clear(connection);
827 magnatune_button_handle_release_event_tag_add(button,userdata);
828 mpd_player_play(connection);
832 static int magnatune_button_handle_release_event_tag(GtkWidget *tree, GdkEventButton *event,gpointer data)
834 int i;
835 int position = GPOINTER_TO_INT(data);
836 if(event->button != 3) return FALSE;
837 GtkWidget *item;
839 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
840 if(gtk_tree_selection_count_selected_rows(sel)> 0)
842 GtkWidget *menu = gtk_menu_new();
845 /* Add */
846 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ADD,NULL);
847 gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), item);
848 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK( magnatune_button_handle_release_event_tag_add), data);
849 /* Replace */
850 item = gtk_image_menu_item_new_with_label("Replace");
851 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
852 gtk_image_new_from_stock(GTK_STOCK_REDO, GTK_ICON_SIZE_MENU));
853 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
854 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK( magnatune_button_handle_release_event_tag_replace), data);
855 gtk_widget_show_all(menu);
856 gtk_menu_popup(GTK_MENU(menu), NULL, NULL,NULL, NULL, event->button, event->time);
857 return TRUE;
859 return FALSE;
862 static int magnatune_button_release_event(GtkWidget *tree, GdkEventButton *event,gpointer data)
864 if(event->button != 3) return FALSE;
865 GtkWidget *item;
867 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
869 if(gtk_tree_selection_count_selected_rows(sel)> 0)
871 GtkWidget *menu = gtk_menu_new();
872 GtkTreeModel *model = GTK_TREE_MODEL(mt_store);
873 /* Add */
874 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ADD,NULL);
875 gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), item);
876 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(magnatune_add_selected), tree);
877 /* Replace */
878 item = gtk_image_menu_item_new_with_label("Replace");
879 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
880 gtk_image_new_from_stock(GTK_STOCK_REDO, GTK_ICON_SIZE_MENU));
881 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
883 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(magnatune_replace_selected), tree);
885 gmpc_mpddata_treeview_right_mouse_intergration(GMPC_MPDDATA_TREEVIEW(tree), GTK_MENU(menu));
887 gtk_widget_show_all(menu);
889 gtk_menu_popup(GTK_MENU(menu), NULL, NULL,NULL, NULL, event->button, event->time);
890 return TRUE;
892 return FALSE;
894 static int magnatune_key_press(GtkWidget *tree, GdkEventKey *event)
896 if(event->state&GDK_CONTROL_MASK && event->keyval == GDK_Insert)
898 magnatune_replace_selected(NULL, GTK_TREE_VIEW(tree));
900 else if(event->keyval == GDK_Insert)
902 magnatune_add_selected(NULL, GTK_TREE_VIEW(tree));
904 return FALSE;
906 static void magnatune_save_myself(void)
908 if (magnatune_ref)
910 GtkTreePath *path = gtk_tree_row_reference_get_path(magnatune_ref);
911 if(path)
913 gint *indices = gtk_tree_path_get_indices(path);
914 debug_printf(DEBUG_INFO,"Saving myself to position: %i\n", indices[0]);
915 cfg_set_single_value_as_int(config, "magnatune","position",indices[0]);
916 gtk_tree_path_free(path);
921 static void magnatune_destroy(void)
923 magnatune_db_destroy();
924 if(magnatune_vbox)
925 gtk_widget_destroy(magnatune_vbox);
928 static gboolean magnatune_integrate_search_field_supported(const int search_field)
930 switch(search_field)
932 case MPD_TAG_ITEM_ARTIST:
933 case MPD_TAG_ITEM_ALBUM:
934 case MPD_TAG_ITEM_GENRE:
935 case MPD_TAG_ITEM_TITLE:
936 return TRUE;
937 default:
938 return FALSE;
941 static MpdData * magnatune_integrate_search(const int search_field, const gchar *query,GError **error)
943 const gchar *genre = NULL, *artist=NULL, *album=NULL;
944 if(!magnatune_get_enabled()) return NULL;
945 if(!magnatune_db_has_data()){
946 g_set_error(error, 0,0, "Music catalog not yet available, please open magnatune browser first");
947 return NULL;
949 switch(search_field){
950 case MPD_TAG_ITEM_ARTIST:
951 artist = query;
952 break;
953 case MPD_TAG_ITEM_ALBUM:
954 album = query;
955 break;
956 case MPD_TAG_ITEM_GENRE:
957 genre = query;
958 break;
959 case MPD_TAG_ITEM_TITLE:
960 return magnatune_db_search_title(query);
961 break;
962 default:
963 g_set_error(error, 0,0, "This type of search query is not supported");
964 return NULL;
965 break;
967 return magnatune_db_get_song_list(genre, artist, album,FALSE);
970 gmpcMetaDataPlugin magnatune_cover = {
971 .get_priority = magnatune_fetch_cover_priority,
972 .set_priority = magnatune_fetch_cover_priority_set,
973 .get_metadata = magnatune_fetch_get_image
977 /* Needed plugin_wp stuff */
978 gmpcPlBrowserPlugin magnatune_gbp = {
979 .add = magnatune_add,
980 .selected = magnatune_selected,
981 .unselected = magnatune_unselected,
982 .cat_right_mouse_menu = magnatune_cat_menu_popup,
983 .integrate_search = magnatune_integrate_search,
984 .integrate_search_field_supported = magnatune_integrate_search_field_supported
987 int plugin_api_version = PLUGIN_API_VERSION;
989 static const gchar *magnatune_get_translation_domain(void)
991 return GETTEXT_PACKAGE;
994 static void magnatune_uentry_changed(GtkEntry *entry)
996 const gchar *text = gtk_entry_get_text(entry);
997 cfg_set_single_value_as_string(config,"magnatune", "username", text);
999 static void magnatune_pentry_changed(GtkEntry *entry)
1001 const gchar *text = gtk_entry_get_text(entry);
1002 cfg_set_single_value_as_string(config,"magnatune", "password", text);
1006 void magnatune_pref_construct (GtkWidget *container)
1008 GtkWidget *table;
1009 GtkWidget *label, *uentry, *pentry;
1010 gchar *un = cfg_get_single_value_as_string(config,"magnatune", "username");
1011 gchar *up = cfg_get_single_value_as_string(config,"magnatune", "password");
1013 table = gtk_table_new(3, 2, FALSE);
1015 /* Password */
1016 label = gtk_label_new(_("Username"));
1017 gtk_table_attach(GTK_TABLE(table), label, 0,1, 0,1, GTK_EXPAND|GTK_FILL, GTK_SHRINK|GTK_FILL, 0, 0);
1018 uentry = gtk_entry_new();
1019 if(un) gtk_entry_set_text(GTK_ENTRY(uentry), un);
1020 g_signal_connect(G_OBJECT(uentry), "changed", G_CALLBACK(magnatune_uentry_changed), NULL);
1021 gtk_table_attach(GTK_TABLE(table), uentry, 1,2, 0,1,GTK_EXPAND|GTK_FILL, GTK_SHRINK|GTK_FILL, 0, 0);
1024 label = gtk_label_new(_("Password"));
1025 gtk_table_attach(GTK_TABLE(table), label, 0,1, 1,2,GTK_EXPAND|GTK_FILL, GTK_SHRINK|GTK_FILL, 0, 0);
1027 pentry = gtk_entry_new();
1028 gtk_entry_set_visibility(GTK_ENTRY(pentry), FALSE);
1029 if(up) gtk_entry_set_text(GTK_ENTRY(pentry), up);
1030 g_signal_connect(G_OBJECT(pentry), "changed", G_CALLBACK(magnatune_pentry_changed), NULL);
1031 gtk_table_attach(GTK_TABLE(table), pentry, 1,2, 1,2, GTK_EXPAND|GTK_FILL, GTK_SHRINK|GTK_FILL, 0, 0);
1033 g_free(un);
1034 g_free(up);
1035 gtk_container_add(GTK_CONTAINER(container), table);
1036 gtk_widget_show_all(container);
1038 void magnatune_pref_destroy (GtkWidget *container)
1040 GtkWidget *child = gtk_bin_get_child(GTK_BIN(container));
1041 if(child) gtk_widget_destroy(child);
1044 gmpcPrefPlugin magnatune_gpp = {
1045 magnatune_pref_construct,
1046 magnatune_pref_destroy
1048 gmpcPlugin plugin = {
1049 .name = N_("Magnatune Stream Browser"),
1050 .version = {PLUGIN_MAJOR_VERSION,PLUGIN_MINOR_VERSION,PLUGIN_MICRO_VERSION},
1051 .plugin_type = GMPC_PLUGIN_PL_BROWSER|GMPC_PLUGIN_META_DATA,
1052 /* Creation and destruction */
1053 .init = magnatune_logo_init,
1054 .destroy = magnatune_destroy,
1055 .save_yourself = magnatune_save_myself,
1056 .mpd_status_changed = magnatune_mpd_status_changed,
1058 /* Browser extention */
1059 .browser = &magnatune_gbp,
1060 .metadata = &magnatune_cover,
1062 .pref = &magnatune_gpp,
1063 /* get/set enabled */
1064 .get_enabled = magnatune_get_enabled,
1065 .set_enabled = magnatune_set_enabled,
1068 .get_translation_domain = magnatune_get_translation_domain