Use right_mouse_integration of GmpcMpdDataTreeView
[gmpc-magnatune.git] / src / plugin.c
blobc3fe0bafb835a40f932417ca5d8686d4c399dc61
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 <glade/glade.h>
24 #include <gmpc/plugin.h>
25 #include <gmpc/gmpc_easy_download.h>
26 #include <gmpc/metadata.h>
27 #include <gmpc/gmpc-mpddata-model.h>
28 #include <gmpc/gmpc-mpddata-treeview.h>
29 #include <gmpc/TreeSearchWidget.h>
30 #include <config.h>
31 #include "magnatune.h"
33 extern GladeXML *pl3_xml;
35 gmpcPlugin plugin;
36 /**
37 * Function decleration
39 static void magnatune_selected(GtkWidget *container);
40 static void magnatune_unselected(GtkWidget *container);
41 static void magnatune_add(GtkWidget *cat_tree);
42 static void magnatune_download_xml_callback(int download, int total,gpointer data);
43 static void magnatune_download();
44 static void magnatune_mpd_status_changed(MpdObj *mi, ChangedStatusType what, void *data);
45 static int magnatune_fetch_cover_priority(void);
46 static int magnatune_fetch_get_image(mpd_Song *song,MetaDataType type, char **path);
47 static int magnatune_cat_menu_popup(GtkWidget *menu, int type, GtkWidget *tree, GdkEventButton *event);
49 static int magnatune_button_release_event(GtkWidget *tree, GdkEventButton *event,gpointer data);
50 static int magnatune_button_handle_release_event_tag(GtkWidget *tree, GdkEventButton *event,gpointer data);
52 static int magnatune_key_press(GtkWidget *tree, GdkEventKey *event);
53 static void magnatune_show_album_list(GtkTreeSelection *selection, gpointer user_data);
54 static void magnatune_show_song_list(GtkTreeSelection *selection, gpointer user_data);
55 static int magnatune_button_handle_release_event_tag_add(GtkWidget *button, gpointer user_data);
56 static void magnatune_save_myself(void);
57 static GtkTreeRowReference *magnatune_ref = NULL;
58 static void magnatune_download_cancel(GtkWidget *button);
60 static int downloading = FALSE;
61 /**
62 * Get set enabled
64 static int magnatune_get_enabled()
66 return cfg_get_single_value_as_int_with_default(config, "magnatune", "enable", TRUE);
68 static void magnatune_set_enabled(int enabled)
70 cfg_set_single_value_as_int(config, "magnatune", "enable", enabled);
71 if (enabled)
73 if(magnatune_ref == NULL)
75 magnatune_add(GTK_WIDGET(playlist3_get_category_tree_view()));
78 else if (magnatune_ref)
80 GtkTreePath *path = gtk_tree_row_reference_get_path(magnatune_ref);
81 if (path){
82 GtkTreeIter iter;
83 magnatune_save_myself();
84 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist3_get_category_tree_store()), &iter, path)){
85 gtk_list_store_remove(playlist3_get_category_tree_store(), &iter);
87 gtk_tree_path_free(path);
88 gtk_tree_row_reference_free(magnatune_ref);
89 magnatune_ref = NULL;
92 pl3_update_go_menu();
99 /* Playlist window row reference */
101 GtkWidget *magnatune_pb = NULL, *magnatune_cancel = NULL;
102 GtkWidget *magnatune_vbox = NULL;
103 GtkTreeModel *mt_store = NULL;
104 TreeSearch *mt_tree_search = NULL;
106 GtkWidget *treeviews[3] = {NULL, NULL,NULL};
108 static GtkWidget *magnatune_logo=NULL;
109 extern GladeXML *pl3_xml;
111 static void magnatune_buy_album()
113 gchar *uri;
114 mpd_Song *song = NULL;
115 gchar *artist;
116 gchar *album;
118 if(mpd_check_connected(connection))
120 song = mpd_playlist_get_current_song(connection);
121 artist = __magnatune_process_string(song->artist);
122 album = __magnatune_process_string(song->album);
123 uri = g_strconcat("http://www.magnatune.com/buy/choose?artist=",artist,"&album=",album,NULL);
124 open_uri(uri);
125 g_free(artist);
126 g_free(album);
127 g_free(uri);
131 static void magnatune_logo_add()
133 mpd_Song *song = NULL;
134 GtkWidget *logo, *button;
135 GtkWidget *ali;
136 if(mpd_check_connected(connection))
137 song = mpd_playlist_get_current_song(connection);
139 magnatune_logo = gtk_hbox_new(FALSE,6);
141 button = gtk_button_new_with_label("Buy this album\nfrom magnatune");
142 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
144 ali = gtk_alignment_new(0,0.5,0,1);
145 gtk_container_add(GTK_CONTAINER(ali), button);
146 logo = gtk_image_new_from_icon_name("magnatune", GTK_ICON_SIZE_DND);
147 gtk_button_set_image(GTK_BUTTON(button), logo);
148 gtk_box_pack_start(GTK_BOX(magnatune_logo), ali, TRUE, TRUE,0);
149 gtk_box_pack_end(GTK_BOX(glade_xml_get_widget(pl3_xml, "vbox5")), magnatune_logo, FALSE,FALSE,0);
150 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(magnatune_buy_album), NULL);
151 if(song) {
152 if(strstr(song->file,"magnatune.com"))
154 gtk_widget_show_all(magnatune_logo);
155 return;
162 static void magnatune_logo_init()
164 gchar *path = gmpc_plugin_get_data_path(&plugin);
165 gchar *url = g_build_path(G_DIR_SEPARATOR_S,path, "magnatune", NULL);
166 debug_printf(DEBUG_WARNING,"Found url: %s\n", url);
167 gtk_icon_theme_append_search_path(gtk_icon_theme_get_default (),url);
168 g_free(url);
169 g_free(path);
171 gtk_init_add((GtkFunction )magnatune_logo_add, NULL);
172 /**
173 * init the magnatune stuff
175 magnatune_db_init();
177 * open the db
179 magnatune_db_open();
183 static void magnatune_mpd_status_changed(MpdObj *mi, ChangedStatusType what, void *data)
185 if(!magnatune_logo)
186 return;
187 if(what&(MPD_CST_SONGID|MPD_CST_STATE))
189 mpd_Song *song = mpd_playlist_get_current_song(mi);
190 if(song && mpd_player_get_state(mi) == MPD_STATUS_STATE_PLAY) {
191 if(strstr(song->file,"magnatune.com"))
193 gtk_widget_show_all(magnatune_logo);
194 return;
197 gtk_widget_hide(magnatune_logo);
201 void magnatune_get_genre_list()
203 MpdData *data = NULL;
204 data = magnatune_db_get_genre_list();
205 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]))),data);
208 static void magnatune_show_album_list(GtkTreeSelection *selection, gpointer user_data)
210 MpdData *data = NULL;
211 GtkTreeIter piter;
212 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]));
213 if(gtk_tree_selection_get_selected(selection, &model, &piter))
215 gchar *genre;
216 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&genre,-1);
217 data= magnatune_db_get_artist_list(genre);
219 g_free(genre);
221 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[1]))),data);
224 static void magnatune_show_song_list(GtkTreeSelection *selection, gpointer user_data)
226 MpdData *data = NULL;
227 GtkTreeIter piter;
228 GtkTreeSelection *select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]));
229 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]));
230 gchar *genre = NULL, *artist = NULL, *album = NULL;
231 if(gtk_tree_selection_get_selected(select, &model, &piter))
234 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]));
235 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&genre,-1);
236 /* model */
237 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[1]));
238 if(gtk_tree_selection_get_selected(select, &model, &piter))
240 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&artist,-1);
241 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[2]));
242 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[2]));
243 if(gtk_tree_selection_get_selected(select, &model, &piter))
245 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&album,-1);
249 data = magnatune_db_get_song_list(genre, artist, album,TRUE);
250 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(mt_store), data);
253 static void magnatune_show_artist_list(GtkTreeSelection *selection, gpointer user_data)
255 GtkTreeIter piter;
256 MpdData *data = NULL;
257 GtkTreeSelection *select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]));
258 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]));
260 if(gtk_tree_selection_get_selected(select, &model, &piter))
262 GList *iter,*list = NULL;
263 gchar *genre;
265 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]));
266 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&genre,-1);
267 /* model */
268 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[1]));
269 if(gtk_tree_selection_get_selected(select, &model, &piter))
271 GList *iter,*list = NULL;
273 gchar *artist;
274 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&artist,-1);
275 data = magnatune_db_get_album_list(genre ,artist);
276 gmpc_mpddata_model_set_request_artist(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[2]))),artist);
277 g_free(artist);
279 g_free(genre);
281 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[2]))),data);
284 static void magnatune_add_album_row_activated(GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
286 GtkTreeModel *model = gtk_tree_view_get_model(tree);
287 GtkTreeIter iter_r;
289 if(gtk_tree_model_get_iter(model, &iter_r, path))
291 gchar *path;
292 gtk_tree_model_get(model, &iter_r, MPDDATA_MODEL_COL_PATH, &path, -1);
293 play_path(path);
294 g_free(path);
298 static gboolean magnatune_search_equal_func(GtkTreeModel *model, int column, const gchar *key, GtkTreeIter *iter, gpointer data)
300 gchar *compare = NULL;
301 gtk_tree_model_get(model,iter, column, &compare, -1);
302 if(compare){
303 gchar *a = g_utf8_casefold(key, -1);
304 gchar *b = g_utf8_casefold(compare, -1);
305 if(strstr(b,a))
307 g_free(a);
308 g_free(b);
309 return FALSE;
311 g_free(a);
312 g_free(b);
314 return TRUE;
317 static void magnatune_search_activate(TreeSearch *ts)
319 GtkTreeModel *model = GTK_TREE_MODEL(mt_store);
320 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ts->treeview));
321 if (gtk_tree_selection_count_selected_rows (selection) == 1)
323 GList *list = gtk_tree_selection_get_selected_rows (selection, &model);
324 magnatune_add_album_row_activated(GTK_TREE_VIEW(ts->treeview),(GtkTreePath *)list->data, NULL,NULL);
325 /* free list */
326 g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
327 g_list_free (list);
331 static void magnatune_init()
333 int size;
334 GtkWidget *tree = NULL;
335 GtkWidget *sw = NULL;
336 GtkCellRenderer *renderer = NULL;
337 GtkWidget *paned = NULL;
338 GtkWidget *hbox = NULL;
339 GtkWidget *vbox = NULL;
340 GtkTreeModel *model = NULL;
341 GtkTreeViewColumn *column = NULL;
342 int position = cfg_get_single_value_as_int_with_default(config, "magnatune", "pane-pos", 150);
343 magnatune_vbox = gtk_vpaned_new();
344 gtk_paned_set_position(GTK_PANED(magnatune_vbox), position);
347 vbox = gtk_vbox_new(FALSE,6);
349 * Create list store
350 * 1. pointer
351 * 2. name
353 mt_store = (GtkTreeModel *)gmpc_mpddata_model_new();
355 /* Paned window */
356 paned = gtk_hbox_new(TRUE,6);
357 model = (GtkTreeModel *) gmpc_mpddata_model_new();
358 /* Genre list */
359 sw = gtk_scrolled_window_new(NULL, NULL);
360 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
361 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
362 treeviews[0] = gtk_tree_view_new_with_model(model);
363 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeviews[0]), MPDDATA_MODEL_COL_SONG_TITLE);
364 g_signal_connect(G_OBJECT(treeviews[0]), "button-press-event", G_CALLBACK(magnatune_button_handle_release_event_tag), GINT_TO_POINTER(0));
365 /* Add column */
366 column = gtk_tree_view_column_new();
367 gtk_tree_view_column_set_title(column, "Genre");
370 renderer = gtk_cell_renderer_pixbuf_new();
371 gtk_tree_view_column_pack_start(column, renderer, FALSE);
372 gtk_tree_view_column_add_attribute(column, renderer, "icon-name", MPDDATA_MODEL_COL_ICON_ID);
373 gtk_tree_view_column_set_sizing(column , GTK_TREE_VIEW_COLUMN_AUTOSIZE);
374 renderer = gtk_cell_renderer_text_new();
375 gtk_tree_view_column_pack_start(column, renderer, TRUE);
376 gtk_tree_view_column_add_attribute(column, renderer, "text", MPDDATA_MODEL_COL_SONG_TITLE);
377 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeviews[0]),column, -1);
379 gtk_container_add(GTK_CONTAINER(sw), treeviews[0]);
380 gtk_box_pack_start(GTK_BOX(paned), sw, TRUE, TRUE, 0);
382 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]))), "changed", G_CALLBACK(magnatune_show_album_list), NULL);
384 /* Artist list */
385 model = (GtkTreeModel *) gmpc_mpddata_model_new();
386 sw = gtk_scrolled_window_new(NULL, NULL);
387 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
388 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
389 treeviews[1] = gtk_tree_view_new_with_model(model);
391 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeviews[1]), MPDDATA_MODEL_COL_SONG_TITLE);
392 g_signal_connect(G_OBJECT(treeviews[1]), "button-press-event", G_CALLBACK(magnatune_button_handle_release_event_tag), GINT_TO_POINTER(1));
393 /* Add column */
394 column = gtk_tree_view_column_new();
395 gtk_tree_view_column_set_title(column, "Artist");
396 size = cfg_get_single_value_as_int_with_default(config, "gmpc-mpddata-model", "icon-size", 64);
397 gtk_tree_view_column_set_sizing(column , GTK_TREE_VIEW_COLUMN_FIXED);
398 gtk_tree_view_set_fixed_height_mode(GTK_TREE_VIEW(treeviews[1]), TRUE);
401 renderer = gtk_cell_renderer_pixbuf_new();
402 gtk_cell_renderer_set_fixed_size(renderer, size,size);
404 gtk_tree_view_column_pack_start(column, renderer, FALSE);
405 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", MPDDATA_MODEL_META_DATA);
406 renderer = gtk_cell_renderer_text_new();
407 gtk_tree_view_column_pack_start(column, renderer, TRUE);
408 gtk_tree_view_column_add_attribute(column, renderer, "text", MPDDATA_MODEL_COL_SONG_TITLE);
409 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeviews[1]),column, -1);
411 gtk_container_add(GTK_CONTAINER(sw), treeviews[1]);
412 gtk_box_pack_start(GTK_BOX(paned), sw, TRUE, TRUE, 0);
414 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]))), "changed", G_CALLBACK(magnatune_show_artist_list), NULL);
416 /* Album list */
417 model = (GtkTreeModel *) gmpc_mpddata_model_new();
418 sw = gtk_scrolled_window_new(NULL, NULL);
419 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
420 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
421 treeviews[2] = gtk_tree_view_new_with_model(model);
422 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeviews[2]), MPDDATA_MODEL_COL_SONG_TITLE);
424 g_signal_connect(G_OBJECT(treeviews[2]), "button-press-event", G_CALLBACK(magnatune_button_handle_release_event_tag), GINT_TO_POINTER(2));
425 /* Add column */
426 column = gtk_tree_view_column_new();
427 gtk_tree_view_column_set_title(column, "Album");
428 size = cfg_get_single_value_as_int_with_default(config, "gmpc-mpddata-model", "icon-size", 64);
429 gtk_tree_view_column_set_sizing(column , GTK_TREE_VIEW_COLUMN_FIXED);
430 gtk_tree_view_set_fixed_height_mode(GTK_TREE_VIEW(treeviews[2]), TRUE);
433 renderer = gtk_cell_renderer_pixbuf_new();
434 gtk_cell_renderer_set_fixed_size(renderer, size,size);
436 gtk_tree_view_column_pack_start(column, renderer, FALSE);
437 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", MPDDATA_MODEL_META_DATA);
438 renderer = gtk_cell_renderer_text_new();
439 gtk_tree_view_column_pack_start(column, renderer, TRUE);
440 gtk_tree_view_column_add_attribute(column, renderer, "text", MPDDATA_MODEL_COL_SONG_TITLE);
441 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeviews[2]),column, -1);
443 gtk_container_add(GTK_CONTAINER(sw), treeviews[2]);
444 gtk_box_pack_start(GTK_BOX(paned), sw, TRUE, TRUE, 0);
447 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]))), "changed", G_CALLBACK(magnatune_show_song_list), NULL);
448 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]))), "changed", G_CALLBACK(magnatune_show_song_list), NULL);
449 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[2]))), "changed", G_CALLBACK(magnatune_show_song_list), NULL);
451 gtk_paned_add1(GTK_PANED(magnatune_vbox), paned);
452 gtk_widget_show_all(paned);
454 * tree
456 sw = gtk_scrolled_window_new(NULL, NULL);
457 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
458 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
461 tree = (GtkWidget *)gmpc_mpddata_treeview_new("magnatune",TRUE,GTK_TREE_MODEL(mt_store));
462 g_signal_connect(G_OBJECT(tree), "row-activated", G_CALLBACK(magnatune_add_album_row_activated), NULL);
464 g_signal_connect(G_OBJECT(tree), "button-press-event", G_CALLBACK(magnatune_button_release_event), tree);
465 g_signal_connect(G_OBJECT(tree), "key-press-event", G_CALLBACK(magnatune_key_press), NULL);
467 gtk_container_add(GTK_CONTAINER(sw), tree);
468 gtk_box_pack_start(GTK_BOX(vbox),sw, TRUE, TRUE,0);
470 mt_tree_search = (TreeSearch *)treesearch_new(GTK_TREE_VIEW(tree), MPDDATA_MODEL_COL_SONG_TITLE);
471 gtk_box_pack_end(GTK_BOX(vbox), GTK_WIDGET(mt_tree_search), FALSE, TRUE, 0);
472 g_signal_connect(G_OBJECT(mt_tree_search), "result-activate", G_CALLBACK(magnatune_search_activate),NULL);
475 gtk_widget_show_all(sw);
476 gtk_widget_show(vbox);
478 * Progress Bar for the bottom
480 hbox = gtk_hbox_new(FALSE, 6);
481 magnatune_cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
482 g_signal_connect(G_OBJECT(magnatune_cancel), "clicked", G_CALLBACK(magnatune_download_cancel), NULL);
483 magnatune_pb = gtk_progress_bar_new();
484 gtk_box_pack_start(GTK_BOX(hbox), magnatune_pb, TRUE, TRUE, 0);
485 gtk_box_pack_start(GTK_BOX(hbox), magnatune_cancel, FALSE, TRUE, 0);
486 gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
487 gtk_paned_add2(GTK_PANED(magnatune_vbox), vbox);
490 g_object_ref(magnatune_vbox);
494 static void magnatune_selected(GtkWidget *container)
496 if(magnatune_vbox == NULL)
498 magnatune_init();
499 gtk_container_add(GTK_CONTAINER(container), magnatune_vbox);
500 gtk_widget_show(magnatune_vbox);
501 if(!magnatune_db_has_data())
503 magnatune_download();
505 else
506 magnatune_get_genre_list();
507 } else {
508 gtk_container_add(GTK_CONTAINER(container), magnatune_vbox);
509 gtk_widget_show(magnatune_vbox);
512 static void magnatune_unselected(GtkWidget *container)
514 gtk_container_remove(GTK_CONTAINER(container), magnatune_vbox);
516 static void magnatune_download_cancel(GtkWidget *button)
518 GEADAsyncHandler *handle = g_object_get_data(G_OBJECT(button), "handle");
519 if(handle)
521 gmpc_easy_async_cancel(handle);
522 g_object_set_data(G_OBJECT(button), "handle", NULL);
525 static void magnatune_download_callback(GEADAsyncHandler *handle, const GEADStatus status, gpointer user_data)
527 GtkWidget *pb = user_data;
528 gchar *uri = gmpc_easy_handler_get_uri(handle);
529 if(status == GEAD_DONE)
531 goffset length;
532 const char *data = gmpc_easy_handler_get_data(handle, &length);
534 magnatune_db_load_data(data, length);
535 gtk_widget_hide(gtk_widget_get_parent(pb));
536 magnatune_get_genre_list();
537 gmpc_easy_async_free_handler(handle);
539 downloading = FALSE;
541 else if (status == GEAD_CANCELLED)
543 gtk_widget_hide(gtk_widget_get_parent(pb));
544 gmpc_easy_async_free_handler(handle);
545 magnatune_get_genre_list();
546 downloading = FALSE;
548 else if (status == GEAD_PROGRESS)
550 goffset length;
551 goffset total = gmpc_easy_handler_get_content_size(handle);
552 /* Get downloaded length */
553 gmpc_easy_handler_get_data(handle, &length);
554 if(total > 0)
556 double fraction = (100*length)/(total);
557 gchar *size = g_format_size_for_display((goffset)length);
558 gchar *strtotal = g_format_size_for_display((goffset)total);
559 gchar *label = g_strdup_printf("Downloading music catalog (%s of %s done)",size,strtotal);
560 g_free(strtotal);
561 g_free(size);
562 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(pb), label);
563 g_free(label);
564 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pb),fraction/100.0);
566 else
568 gtk_progress_bar_pulse(GTK_PROGRESS_BAR(pb));
572 static void magnatune_download()
574 downloading = TRUE;
575 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]))),NULL);
576 gtk_widget_show_all(gtk_widget_get_parent(magnatune_pb));
577 const char *url = "http://he3.magnatune.com/info/sqlite_magnatune.db";
578 GEADAsyncHandler *handle = gmpc_easy_async_downloader(url, magnatune_download_callback,magnatune_pb);
579 g_object_set_data(G_OBJECT(magnatune_cancel), "handle", handle);
582 static void magnatune_add(GtkWidget *cat_tree)
584 GtkTreePath *path = NULL;
585 GtkTreeIter iter,child;
586 GtkListStore *pl3_tree = (GtkListStore *)gtk_tree_view_get_model(GTK_TREE_VIEW(cat_tree));
587 gint pos = cfg_get_single_value_as_int_with_default(config, "magnatune","position",20);
589 if(!cfg_get_single_value_as_int_with_default(config, "magnatune", "enable", TRUE)) return;
591 debug_printf(DEBUG_INFO,"Adding at position: %i", pos);
592 playlist3_insert_browser(&iter, pos);
593 gtk_list_store_set(GTK_LIST_STORE(pl3_tree), &iter,
594 PL3_CAT_TYPE, plugin.id,
595 PL3_CAT_TITLE, "Magnatune Browser",
596 PL3_CAT_INT_ID, "",
597 PL3_CAT_ICON_ID, "magnatune",
598 PL3_CAT_PROC, TRUE,
599 PL3_CAT_ICON_SIZE,GTK_ICON_SIZE_DND,-1);
601 * Clean up old row reference if it exists
603 if (magnatune_ref)
605 gtk_tree_row_reference_free(magnatune_ref);
606 magnatune_ref = NULL;
609 * create row reference
611 path = gtk_tree_model_get_path(GTK_TREE_MODEL(playlist3_get_category_tree_store()), &iter);
612 if (path)
614 magnatune_ref = gtk_tree_row_reference_new(GTK_TREE_MODEL(playlist3_get_category_tree_store()), path);
615 gtk_tree_path_free(path);
619 char * __magnatune_process_string(const char *name)
621 int i = 0;
622 int j = 0;
623 int depth = 0;
624 int spaces = 0;
626 /* only gonna be smaller */
627 char *result = g_malloc0((strlen(name)+1+spaces*2)*sizeof(char));
628 for(i=0; i < strlen(name);i++)
630 if(name[i] == '(' || name[i] == '[') depth++;
631 else if (name[i] == ')' || name[i] == ']') depth--;
632 else if(!depth)
634 result[j] = name[i];
635 j++;
638 for(i=j-1;i>0 && result[i] == ' ';i--)
640 result[i] = '\0';
642 return result;
645 /*** COVER STUFF */
646 static int magnatune_fetch_cover_priority(void){
647 return cfg_get_single_value_as_int_with_default(config, "magnatune", "priority", 80);
649 static void magnatune_fetch_cover_priority_set(int priority){
650 cfg_set_single_value_as_int(config, "magnatune", "priority", priority);
653 static int magnatune_fetch_get_image(mpd_Song *song,MetaDataType type, char **path)
655 int result = 0;
657 if(type == META_ARTIST_ART && song->artist)
659 char *value = magnatune_get_artist_image(song->artist);
660 if(value)
662 if(strlen(value) > 0)
664 gmpc_easy_download_struct dld = {NULL, 0, -1, NULL,NULL};
665 printf("artist image: %s\n", value);
666 *path = gmpc_get_metadata_filename(META_ARTIST_ART, song, NULL);
667 if(gmpc_easy_download(value, &dld))
669 g_file_set_contents(*path, dld.data, dld.size, NULL);
670 g_free(value);
671 gmpc_easy_download_clean(&dld);
672 return META_DATA_AVAILABLE;
674 gmpc_easy_download_clean(&dld);
675 g_free(*path);
676 *path = NULL;
677 g_free(value);
681 else*/
683 if(type == META_ARTIST_ART && song->artist)
685 char *value = magnatune_get_artist_image(song->artist);
686 if(value)
688 gmpc_easy_download_struct dld = {NULL, 0, -1, NULL,NULL};
689 *path = gmpc_get_metadata_filename(META_ARTIST_ART,song, NULL);
690 if(gmpc_easy_download(value, &dld))
692 g_file_set_contents(*path, dld.data, dld.size, NULL);
693 g_free(value);
694 gmpc_easy_download_clean(&dld);
695 if(gdk_pixbuf_get_file_info(*path, NULL, NULL) == NULL)
697 g_free(*path);
698 *path = NULL;
699 return META_DATA_UNAVAILABLE;
701 return META_DATA_AVAILABLE;
703 gmpc_easy_download_clean(&dld);
704 g_free(*path);
705 *path = NULL;
706 g_free(value);
709 else if(type == META_ALBUM_ART && song->artist && song->album)
711 char *value = magnatune_get_album_image(song->artist,song->album);
712 if(value)
714 gmpc_easy_download_struct dld = {NULL, 0, -1, NULL,NULL};
715 *path = gmpc_get_metadata_filename(META_ALBUM_ART, song, NULL);
716 if(gmpc_easy_download(value, &dld))
718 g_file_set_contents(*path, dld.data, dld.size, NULL);
719 g_free(value);
720 gmpc_easy_download_clean(&dld);
721 if(gdk_pixbuf_get_file_info(*path, NULL, NULL) == NULL)
723 g_free(*path);
724 *path = NULL;
725 return META_DATA_UNAVAILABLE;
727 return META_DATA_AVAILABLE;
729 gmpc_easy_download_clean(&dld);
730 g_free(*path);
731 *path = NULL;
732 g_free(value);
735 return META_DATA_UNAVAILABLE;
738 static void magnatune_redownload_reload_db()
740 GtkTreeIter iter;
741 GtkTreeModel *model = gtk_tree_row_reference_get_model(magnatune_ref);
742 GtkTreePath *path = gtk_tree_row_reference_get_path(magnatune_ref);
743 if(path && gtk_tree_model_get_iter(model, &iter, path))
745 GtkTreeIter citer;
746 while(gtk_tree_model_iter_children(model, &citer,&iter))
748 gtk_list_store_remove(GTK_LIST_STORE(model), &citer);
750 magnatune_download();
751 //magnatune_get_genre_list();
753 if(path)
754 gtk_tree_path_free(path);
757 static void magnatune_cat_menu_add()
759 GtkTreeIter citer;
760 GtkTreeSelection *sel = gtk_tree_view_get_selection(playlist3_get_category_tree_view());
761 GtkTreeModel *model = (GtkTreeModel *)playlist3_get_category_tree_store();
762 GtkTreePath *tpath;
763 int depth = 0;
764 if(!gtk_tree_selection_get_selected(sel,&model,&citer))
766 return ;
768 */ /**
769 * Get the level we are on.
771 /* tpath = gtk_tree_model_get_path(model, &citer);
772 depth = gtk_tree_path_get_depth(tpath);
773 gtk_tree_path_free(tpath);
774 */ /** Genre level */
775 /* if(depth == 2)
777 GList *list, *node;
778 gchar *genre;
779 gtk_tree_model_get(model, &citer, PL3_CAT_INT_ID,&genre, -1);
780 if(genre)
782 list = magnatune_db_get_url_list(genre, NULL ,NULL);
783 for(node = list; node; node = node->next)
785 mpd_playlist_queue_add(connection, node->data);
787 mpd_playlist_queue_commit(connection);
788 g_list_foreach(list, (GFunc)g_free, NULL);
789 g_list_free(list);
790 g_free(genre);
793 */ /** Artist */
794 /* else if(depth == 3)
796 gchar *artist;
797 gchar *genre;
798 GtkTreeIter iter;
799 if(gtk_tree_model_iter_parent(model, &iter, &citer))
801 GList *list, *node;
802 gtk_tree_model_get(model, &iter, PL3_CAT_INT_ID,&genre, -1);
803 gtk_tree_model_get(model, &citer, PL3_CAT_INT_ID,&artist, -1);
804 list = magnatune_db_get_url_list(genre, artist,NULL);
805 for(node = list; node; node = node->next)
807 mpd_playlist_queue_add(connection, node->data);
809 mpd_playlist_queue_commit(connection);
810 g_list_foreach(list, (GFunc)g_free, NULL);
811 g_list_free(list);
812 g_free(genre);
813 g_free(artist);
823 static void magnatune_cat_menu_replace()
825 mpd_playlist_clear(connection);
826 magnatune_cat_menu_add();
827 mpd_player_play(connection);
831 static int magnatune_cat_menu_popup(GtkWidget *menu, int type, GtkWidget *tree, GdkEventButton *event)
833 GtkWidget *item;
834 if(type != plugin.id) return 0;
835 else if (!downloading)
837 /* add the clear widget */
838 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_REFRESH,NULL);
839 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
840 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(magnatune_redownload_reload_db), NULL);
841 return 1;
843 return 0;
846 static void magnatune_add_selected(GtkWidget *button, GtkTreeView *tree)
848 GtkTreeModel *model = GTK_TREE_MODEL(mt_store);
849 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
850 GList *list = gtk_tree_selection_get_selected_rows(sel,&model);
851 if(list)
853 GList *node ;
854 for(node = list; node; node = g_list_next(node))
856 GtkTreeIter iter;
857 if(gtk_tree_model_get_iter(model, &iter, node->data))
859 gchar *path;
860 gtk_tree_model_get(model, &iter, MPDDATA_MODEL_COL_PATH, &path, -1);
861 mpd_playlist_queue_add(connection, path);
862 g_free(path);
865 mpd_playlist_queue_commit(connection);
866 g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL);
867 g_list_free (list);
870 static void magnatune_replace_selected(GtkWidget *button , GtkTreeView *tree)
872 mpd_playlist_clear(connection);
873 magnatune_add_selected(button, tree);
874 mpd_player_play(connection);
878 static int magnatune_button_handle_release_event_tag_add(GtkWidget *button, gpointer userdata)
880 GList *list;
881 MpdData *data;
882 int position = GPOINTER_TO_INT(userdata);
883 gchar *genre=NULL, *artist=NULL, *album=NULL;
884 GtkTreeSelection *select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]));
885 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]));
886 GtkTreeIter piter;
887 if(gtk_tree_selection_get_selected(select, &model, &piter))
889 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&genre,-1);
891 if(position >= 1)
893 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]));
894 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[1]));
895 if(gtk_tree_selection_get_selected(select, &model, &piter))
897 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&artist,-1);
900 if(position >= 2)
902 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[2]));
903 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[2]));
904 if(gtk_tree_selection_get_selected(select, &model, &piter))
906 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&album,-1);
910 list = magnatune_db_get_url_list(genre, artist, album);
911 for(;list; list = list->next)
913 mpd_playlist_queue_add(connection, list->data);
917 data = magnatune_db_get_song_list(genre,artist,album, TRUE);
918 for(data = mpd_data_get_first(data);data;data = mpd_data_get_next(data)) {
919 mpd_playlist_queue_add(connection, data->song->file);
921 mpd_playlist_queue_commit(connection);
923 if(list)
925 g_list_foreach(list, (GFunc)g_free, NULL);
926 g_list_free(list);
929 if(genre)
930 g_free(genre);
931 if(artist)
932 g_free(artist);
933 if(album)
934 g_free(album);
938 static int magnatune_button_handle_release_event_tag_replace(GtkWidget *button, gpointer userdata)
940 mpd_playlist_clear(connection);
941 magnatune_button_handle_release_event_tag_add(button,userdata);
942 mpd_player_play(connection);
946 static int magnatune_button_handle_release_event_tag(GtkWidget *tree, GdkEventButton *event,gpointer data)
948 int i;
949 int position = GPOINTER_TO_INT(data);
950 if(event->button != 3) return FALSE;
951 GtkWidget *item;
953 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
954 if(gtk_tree_selection_count_selected_rows(sel)> 0)
956 GtkWidget *menu = gtk_menu_new();
959 /* Add */
960 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ADD,NULL);
961 gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), item);
962 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK( magnatune_button_handle_release_event_tag_add), data);
963 /* Replace */
964 item = gtk_image_menu_item_new_with_label("Replace");
965 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
966 gtk_image_new_from_stock(GTK_STOCK_REDO, GTK_ICON_SIZE_MENU));
967 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
968 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK( magnatune_button_handle_release_event_tag_replace), data);
969 gtk_widget_show_all(menu);
970 gtk_menu_popup(GTK_MENU(menu), NULL, NULL,NULL, NULL, event->button, event->time);
971 return TRUE;
973 return FALSE;
976 static int magnatune_button_release_event(GtkWidget *tree, GdkEventButton *event,gpointer data)
978 if(event->button != 3) return FALSE;
979 GtkWidget *item;
981 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
983 if(gtk_tree_selection_count_selected_rows(sel)> 0)
985 GtkWidget *menu = gtk_menu_new();
986 GtkTreeModel *model = GTK_TREE_MODEL(mt_store);
987 /* Add */
988 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ADD,NULL);
989 gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), item);
990 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(magnatune_add_selected), tree);
991 /* Replace */
992 item = gtk_image_menu_item_new_with_label("Replace");
993 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
994 gtk_image_new_from_stock(GTK_STOCK_REDO, GTK_ICON_SIZE_MENU));
995 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
997 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(magnatune_replace_selected), tree);
999 gmpc_mpddata_treeview_right_mouse_intergration(GMPC_MPDDATA_TREEVIEW(tree), GTK_MENU(menu));
1001 gtk_widget_show_all(menu);
1003 gtk_menu_popup(GTK_MENU(menu), NULL, NULL,NULL, NULL, event->button, event->time);
1004 return TRUE;
1006 return FALSE;
1009 static void magnatune_cat_key_press(GtkWidget *tree, GdkEventKey *event, int selected_type)
1011 if(selected_type != plugin.id) return;
1012 if(event->state&GDK_CONTROL_MASK && event->keyval == GDK_Insert)
1014 magnatune_cat_menu_replace();
1016 else if(event->keyval == GDK_Insert)
1018 magnatune_cat_menu_add();
1023 static int magnatune_key_press(GtkWidget *tree, GdkEventKey *event)
1025 if(event->state&GDK_CONTROL_MASK && event->keyval == GDK_Insert)
1027 magnatune_replace_selected(NULL, GTK_TREE_VIEW(tree));
1029 else if(event->keyval == GDK_Insert)
1031 magnatune_add_selected(NULL, GTK_TREE_VIEW(tree));
1033 else if (event->keyval == GDK_f && event->state&GDK_CONTROL_MASK)
1035 treesearch_start(mt_tree_search);
1036 return TRUE;
1038 else if((event->state&(GDK_CONTROL_MASK|GDK_MOD1_MASK)) == 0 &&
1039 ((event->keyval >= GDK_space && event->keyval <= GDK_z)))
1041 char data[2];
1042 data[0] = (char)gdk_keyval_to_unicode(event->keyval);
1043 data[1] = '\0';
1044 treesearch_start(TREESEARCH(mt_tree_search));
1045 gtk_entry_set_text(GTK_ENTRY(TREESEARCH(mt_tree_search)->entry),data);
1046 gtk_editable_set_position(GTK_EDITABLE(TREESEARCH(mt_tree_search)->entry),1);
1047 return TRUE;
1049 return FALSE;
1051 static void magnatune_save_myself(void)
1053 if(magnatune_vbox)
1055 int position = gtk_paned_get_position(GTK_PANED(magnatune_vbox));
1056 cfg_set_single_value_as_int(config, "magnatune", "pane-pos", position);
1058 if (magnatune_ref)
1060 GtkTreePath *path = gtk_tree_row_reference_get_path(magnatune_ref);
1061 if(path)
1063 gint *indices = gtk_tree_path_get_indices(path);
1064 debug_printf(DEBUG_INFO,"Saving myself to position: %i\n", indices[0]);
1065 cfg_set_single_value_as_int(config, "magnatune","position",indices[0]);
1066 gtk_tree_path_free(path);
1071 static void magnatune_destroy(void)
1073 magnatune_db_destroy();
1074 if(magnatune_vbox)
1075 gtk_widget_destroy(magnatune_vbox);
1078 static gboolean magnatune_integrate_search_field_supported(const int search_field)
1080 switch(search_field)
1082 case MPD_TAG_ITEM_ARTIST:
1083 case MPD_TAG_ITEM_ALBUM:
1084 case MPD_TAG_ITEM_GENRE:
1085 case MPD_TAG_ITEM_TITLE:
1086 return TRUE;
1087 default:
1088 return FALSE;
1091 static MpdData * magnatune_integrate_search(const int search_field, const gchar *query,GError **error)
1093 const gchar *genre = NULL, *artist=NULL, *album=NULL;
1094 if(!magnatune_get_enabled()) return NULL;
1095 if(!magnatune_db_has_data()){
1096 g_set_error(error, 0,0, "Music catalog not yet available, please open magnatune browser first");
1097 return NULL;
1099 switch(search_field){
1100 case MPD_TAG_ITEM_ARTIST:
1101 artist = query;
1102 break;
1103 case MPD_TAG_ITEM_ALBUM:
1104 album = query;
1105 break;
1106 case MPD_TAG_ITEM_GENRE:
1107 genre = query;
1108 break;
1109 case MPD_TAG_ITEM_TITLE:
1110 return magnatune_db_search_title(query);
1111 break;
1112 default:
1113 g_set_error(error, 0,0, "This type of search query is not supported");
1114 return NULL;
1115 break;
1117 return magnatune_db_get_song_list(genre, artist, album,FALSE);
1120 gmpcMetaDataPlugin magnatune_cover = {
1121 .get_priority = magnatune_fetch_cover_priority,
1122 .set_priority = magnatune_fetch_cover_priority_set,
1123 .get_image = magnatune_fetch_get_image
1127 /* Needed plugin_wp stuff */
1128 gmpcPlBrowserPlugin magnatune_gbp = {
1129 .add = magnatune_add,
1130 .selected = magnatune_selected,
1131 .unselected = magnatune_unselected,
1132 .cat_right_mouse_menu = magnatune_cat_menu_popup,
1133 .integrate_search = magnatune_integrate_search,
1134 .integrate_search_field_supported = magnatune_integrate_search_field_supported
1137 int plugin_api_version = PLUGIN_API_VERSION;
1139 gmpcPlugin plugin = {
1140 .name = "Magnatune Stream Browser",
1141 .version = {PLUGIN_MAJOR_VERSION,PLUGIN_MINOR_VERSION,PLUGIN_MICRO_VERSION},
1142 .plugin_type = GMPC_PLUGIN_PL_BROWSER|GMPC_PLUGIN_META_DATA,
1143 /* Creation and destruction */
1144 .init = magnatune_logo_init,
1145 .destroy = magnatune_destroy,
1146 .save_yourself = magnatune_save_myself,
1147 .mpd_status_changed = magnatune_mpd_status_changed,
1149 /* Browser extention */
1150 .browser = &magnatune_gbp,
1151 .metadata = &magnatune_cover,
1153 /* get/set enabled */
1154 .get_enabled = magnatune_get_enabled,
1155 .set_enabled = magnatune_set_enabled