Update for sidebar
[gmpc-magnatune.git] / src / plugin.c
blob46776f54b7156bf1419e3cad145e2368e0405813
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 <plugin.h>
27 #include <gmpc_easy_download.h>
28 #include <metadata.h>
29 #include <gmpc-mpddata-model.h>
30 #include <gmpc-mpddata-treeview.h>
31 #include <gmpc-extras.h>
32 #include <config.h>
33 #include <playlist3-messages.h>
34 #include "magnatune.h"
35 #include <libmpd/debug_printf.h>
37 extern GtkBuilder *pl3_xml;
38 gmpcPlugin plugin;
39 /**
40 * Function decleration
42 static void magnatune_selected(GtkWidget *container);
43 static void magnatune_unselected(GtkWidget *container);
44 static void magnatune_add(GtkWidget *cat_tree);
45 static void magnatune_download_xml_callback(int download, int total,gpointer data);
46 static void magnatune_download();
47 static void magnatune_mpd_status_changed(MpdObj *mi, ChangedStatusType what, void *data);
48 static int magnatune_fetch_cover_priority(void);
49 static void magnatune_fetch_get_image(mpd_Song *song,MetaDataType type, void (*callback)(GList *list, gpointer data), gpointer user_data);
50 static int magnatune_cat_menu_popup(GtkWidget *menu, int type, GtkWidget *tree, GdkEventButton *event);
52 static int magnatune_button_release_event(GtkWidget *tree, GdkEventButton *event,gpointer data);
53 static int magnatune_button_handle_release_event_tag(GtkWidget *tree, GdkEventButton *event,gpointer data);
55 static int magnatune_key_press(GtkWidget *tree, GdkEventKey *event);
56 static void magnatune_show_album_list(GtkTreeSelection *selection, gpointer user_data);
57 static void magnatune_show_song_list(GtkTreeSelection *selection, gpointer user_data);
58 static int magnatune_button_handle_release_event_tag_add(GtkWidget *button, gpointer user_data);
59 static void magnatune_save_myself(void);
60 static GtkTreeRowReference *magnatune_ref = NULL;
61 static void magnatune_download_cancel(GtkWidget *button);
63 static int downloading = FALSE;
64 /**
65 * Get set enabled
67 static int magnatune_get_enabled()
69 return cfg_get_single_value_as_int_with_default(config, "magnatune", "enable", TRUE);
71 static void magnatune_set_enabled(int enabled)
73 cfg_set_single_value_as_int(config, "magnatune", "enable", enabled);
74 if (enabled)
76 if(magnatune_ref == NULL)
78 magnatune_add(GTK_WIDGET(playlist3_get_category_tree_view()));
81 else if (magnatune_ref)
83 GtkTreePath *path = gtk_tree_row_reference_get_path(magnatune_ref);
84 if (path){
85 GtkTreeIter iter;
86 magnatune_save_myself();
87 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist3_get_category_tree_store()), &iter, path)){
88 gtk_list_store_remove(playlist3_get_category_tree_store(), &iter);
90 gtk_tree_path_free(path);
91 gtk_tree_row_reference_free(magnatune_ref);
92 magnatune_ref = NULL;
95 pl3_update_go_menu();
102 /* Playlist window row reference */
104 GtkWidget *magnatune_pb = NULL, *magnatune_cancel = NULL;
105 GtkWidget *magnatune_vbox = NULL;
106 GtkTreeModel *mt_store = NULL;
108 GtkWidget *treeviews[3] = {NULL, NULL,NULL};
110 static GtkWidget *magnatune_logo=NULL;
112 static void magnatune_buy_album()
114 gchar *uri;
115 mpd_Song *song = NULL;
116 gchar *artist;
117 gchar *album;
119 if(mpd_check_connected(connection))
121 song = mpd_playlist_get_current_song(connection);
122 artist = __magnatune_process_string(song->artist);
123 album = __magnatune_process_string(song->album);
124 uri = g_strconcat("http://www.magnatune.com/buy/choose?artist=",artist,"&album=",album,NULL);
125 open_uri(uri);
126 g_free(artist);
127 g_free(album);
128 g_free(uri);
132 static void magnatune_logo_add()
134 mpd_Song *song = NULL;
135 GtkWidget *logo, *button;
136 GtkWidget *ali;
137 if(mpd_check_connected(connection))
138 song = mpd_playlist_get_current_song(connection);
140 magnatune_logo = gtk_vbox_new(FALSE,6);
142 button = gtk_button_new_with_label("Buy this album\nfrom magnatune");
143 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
145 ali = gtk_alignment_new(0,0.5,0,1);
146 gtk_container_add(GTK_CONTAINER(ali), button);
147 logo = gtk_image_new_from_icon_name("magnatune", GTK_ICON_SIZE_DND);
148 gtk_button_set_image(GTK_BUTTON(button), logo);
149 gtk_box_pack_start(GTK_BOX(magnatune_logo), ali, TRUE, TRUE,0);
150 gtk_box_pack_end(GTK_BOX(gtk_builder_get_object(pl3_xml, "vbox5")), magnatune_logo, FALSE,FALSE,0);
151 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(magnatune_buy_album), NULL);
152 if(song) {
153 if(strstr(song->file,"magnatune.com"))
155 gtk_widget_show_all(magnatune_logo);
156 return;
163 static void magnatune_logo_init()
165 gchar *path = gmpc_plugin_get_data_path(&plugin);
166 gchar *url = g_build_path(G_DIR_SEPARATOR_S,path, "magnatune", NULL);
167 debug_printf(DEBUG_WARNING,"Found url: %s\n", url);
168 gtk_icon_theme_append_search_path(gtk_icon_theme_get_default (),url);
169 g_free(url);
170 g_free(path);
173 bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
174 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
177 gtk_init_add((GtkFunction )magnatune_logo_add, NULL);
178 /**
179 * init the magnatune stuff
181 magnatune_db_init();
183 * open the db
185 magnatune_db_open();
187 gchar *un = cfg_get_single_value_as_string(config,"magnatune", "username");
188 gchar *up = cfg_get_single_value_as_string(config,"magnatune", "password");
189 magnatune_set_user_password(un, up);
190 g_free(un);
191 g_free(up);
196 static void magnatune_mpd_status_changed(MpdObj *mi, ChangedStatusType what, void *data)
198 if(!magnatune_logo)
199 return;
200 if(what&(MPD_CST_SONGID|MPD_CST_STATE))
202 mpd_Song *song = mpd_playlist_get_current_song(mi);
203 if(song && mpd_player_get_state(mi) == MPD_STATUS_STATE_PLAY) {
204 if(strstr(song->file,"magnatune.com"))
206 gtk_widget_show_all(magnatune_logo);
207 return;
210 gtk_widget_hide(magnatune_logo);
214 void magnatune_get_genre_list()
216 MpdData *data = NULL;
217 GTimer *timer;
218 data = magnatune_db_get_genre_list();
220 timer = g_timer_new();
221 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]))),data);
222 g_debug("%f seconds elapsed filling genre tree", g_timer_elapsed(timer,NULL)); g_timer_destroy(timer);
225 static void magnatune_show_album_list(GtkTreeSelection *selection, gpointer user_data)
227 MpdData *data = NULL;
228 GtkTreeIter piter;
229 GTimer *timer;
230 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]));
231 if(gtk_tree_selection_get_selected(selection, &model, &piter))
233 gchar *genre;
234 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&genre,-1);
235 data= magnatune_db_get_artist_list(genre);
237 g_free(genre);
239 timer = g_timer_new();
240 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[1]))),data);
241 g_debug("%f seconds elapsed filling artist tree", g_timer_elapsed(timer,NULL)); g_timer_destroy(timer);
244 static void magnatune_show_song_list(GtkTreeSelection *selection, gpointer user_data)
246 MpdData *data = NULL;
247 GtkTreeIter piter;
248 GtkTreeSelection *select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]));
249 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]));
250 GTimer *timer;
251 gchar *genre = NULL, *artist = NULL, *album = NULL;
252 if(gtk_tree_selection_get_selected(select, &model, &piter))
255 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]));
256 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&genre,-1);
257 /* model */
258 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[1]));
259 if(gtk_tree_selection_get_selected(select, &model, &piter))
261 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&artist,-1);
262 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[2]));
263 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[2]));
264 if(gtk_tree_selection_get_selected(select, &model, &piter))
266 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&album,-1);
270 data = magnatune_db_get_song_list(genre, artist, album,TRUE);
271 timer = g_timer_new();
272 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(mt_store), data);
273 g_debug("%f seconds elapsed filling song tree", g_timer_elapsed(timer,NULL)); g_timer_destroy(timer);
276 static void magnatune_show_artist_list(GtkTreeSelection *selection, gpointer user_data)
278 GtkTreeIter piter;
279 GTimer *timer;
280 MpdData *data = NULL;
281 GtkTreeSelection *select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]));
282 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]));
284 if(gtk_tree_selection_get_selected(select, &model, &piter))
286 GList *iter,*list = NULL;
287 gchar *genre;
289 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]));
290 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&genre,-1);
291 /* model */
292 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[1]));
293 if(gtk_tree_selection_get_selected(select, &model, &piter))
295 GList *iter,*list = NULL;
297 gchar *artist;
298 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&artist,-1);
299 data = magnatune_db_get_album_list(genre ,artist);
300 gmpc_mpddata_model_set_request_artist(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[2]))),artist);
301 GmpcMpdDataTreeviewTooltip *tool = (GmpcMpdDataTreeviewTooltip *)gtk_widget_get_tooltip_window(GTK_WIDGET(treeviews[2]));
302 if(tool->request_artist){
303 g_free(tool->request_artist);
305 tool->request_artist = g_strdup(artist);
307 g_free(artist);
309 g_free(genre);
311 timer = g_timer_new();
312 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[2]))),data);
313 g_debug("%f seconds elapsed filling album tree", g_timer_elapsed(timer,NULL)); g_timer_destroy(timer);
316 static void magnatune_add_album_row_activated(GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
318 GtkTreeModel *model = gtk_tree_view_get_model(tree);
319 GtkTreeIter iter_r;
321 if(gtk_tree_model_get_iter(model, &iter_r, path))
323 gchar *path;
324 gtk_tree_model_get(model, &iter_r, MPDDATA_MODEL_COL_PATH, &path, -1);
325 play_path(path);
326 g_free(path);
330 static gboolean magnatune_search_equal_func(GtkTreeModel *model, int column, const gchar *key, GtkTreeIter *iter, gpointer data)
332 gchar *compare = NULL;
333 gtk_tree_model_get(model,iter, column, &compare, -1);
334 if(compare){
335 gchar *a = g_utf8_casefold(key, -1);
336 gchar *b = g_utf8_casefold(compare, -1);
337 if(strstr(b,a))
339 g_free(a);
340 g_free(b);
341 return FALSE;
343 g_free(a);
344 g_free(b);
346 return TRUE;
349 static void magnatune_init()
351 int size;
352 GtkWidget *tree = NULL;
353 GtkWidget *sw = NULL;
354 GtkCellRenderer *renderer = NULL;
355 GtkWidget *paned = NULL;
356 GtkWidget *hbox = NULL;
357 GtkWidget *vbox = NULL;
358 GtkTreeModel *model = NULL;
359 GtkTreeViewColumn *column = NULL;
360 magnatune_vbox = gtk_hpaned_new();
361 gmpc_paned_size_group_add_paned(GMPC_PANED_SIZE_GROUP(paned_size_group), GTK_PANED(magnatune_vbox));
364 vbox = gtk_vbox_new(FALSE,6);
366 * Create list store
367 * 1. pointer
368 * 2. name
370 mt_store = (GtkTreeModel *)gmpc_mpddata_model_new();
372 /* Paned window */
373 paned = gtk_vbox_new(TRUE,6);
374 model = (GtkTreeModel *) gmpc_mpddata_model_new();
375 /* Genre list */
376 sw = gtk_scrolled_window_new(NULL, NULL);
377 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
378 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
379 treeviews[0] = gtk_tree_view_new_with_model(model);
380 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeviews[0]), TRUE);
382 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeviews[0]), MPDDATA_MODEL_COL_SONG_TITLE);
383 g_signal_connect(G_OBJECT(treeviews[0]), "button-press-event", G_CALLBACK(magnatune_button_handle_release_event_tag), GINT_TO_POINTER(0));
384 /* Add column */
385 column = gtk_tree_view_column_new();
386 gtk_tree_view_column_set_title(column, "Genre");
389 renderer = gtk_cell_renderer_pixbuf_new();
390 gtk_tree_view_column_pack_start(column, renderer, FALSE);
391 gtk_tree_view_column_add_attribute(column, renderer, "icon-name", MPDDATA_MODEL_COL_ICON_ID);
392 gtk_tree_view_column_set_sizing(column , GTK_TREE_VIEW_COLUMN_AUTOSIZE);
393 renderer = gtk_cell_renderer_text_new();
394 gtk_tree_view_column_pack_start(column, renderer, TRUE);
395 gtk_tree_view_column_add_attribute(column, renderer, "text", MPDDATA_MODEL_COL_SONG_TITLE);
396 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeviews[0]),column, -1);
398 gtk_container_add(GTK_CONTAINER(sw), treeviews[0]);
399 gtk_box_pack_start(GTK_BOX(paned), sw, TRUE, TRUE, 0);
401 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]))), "changed", G_CALLBACK(magnatune_show_album_list), NULL);
403 /* Artist list */
404 model = (GtkTreeModel *) gmpc_mpddata_model_new();
405 sw = gtk_scrolled_window_new(NULL, NULL);
406 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
407 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
408 treeviews[1] = gtk_tree_view_new_with_model(model);
409 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeviews[1]), TRUE);
410 gmpc_mpd_data_treeview_tooltip_new(GTK_TREE_VIEW(treeviews[1]), META_ARTIST_ART);
411 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeviews[1]), MPDDATA_MODEL_COL_SONG_TITLE);
412 g_signal_connect(G_OBJECT(treeviews[1]), "button-press-event", G_CALLBACK(magnatune_button_handle_release_event_tag), GINT_TO_POINTER(1));
413 /* Add column */
414 column = gtk_tree_view_column_new();
415 gtk_tree_view_column_set_title(column, "Artist");
416 size = cfg_get_single_value_as_int_with_default(config, "gmpc-mpddata-model", "icon-size", 64);
417 gtk_tree_view_column_set_sizing(column , GTK_TREE_VIEW_COLUMN_FIXED);
418 gtk_tree_view_set_fixed_height_mode(GTK_TREE_VIEW(treeviews[1]), TRUE);
421 renderer = gtk_cell_renderer_pixbuf_new();
422 gtk_cell_renderer_set_fixed_size(renderer, size,size);
424 gtk_tree_view_column_pack_start(column, renderer, FALSE);
425 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", MPDDATA_MODEL_META_DATA);
426 renderer = gtk_cell_renderer_text_new();
427 gtk_tree_view_column_pack_start(column, renderer, TRUE);
428 gtk_tree_view_column_add_attribute(column, renderer, "text", MPDDATA_MODEL_COL_SONG_TITLE);
429 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeviews[1]),column, -1);
431 gtk_container_add(GTK_CONTAINER(sw), treeviews[1]);
432 gtk_box_pack_start(GTK_BOX(paned), sw, TRUE, TRUE, 0);
434 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]))), "changed", G_CALLBACK(magnatune_show_artist_list), NULL);
436 /* Album list */
437 model = (GtkTreeModel *) gmpc_mpddata_model_new();
438 sw = gtk_scrolled_window_new(NULL, NULL);
439 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
440 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
441 treeviews[2] = gtk_tree_view_new_with_model(model);
442 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeviews[2]), TRUE);
443 gmpc_mpd_data_treeview_tooltip_new(GTK_TREE_VIEW(treeviews[2]), META_ALBUM_ART);
444 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeviews[2]), MPDDATA_MODEL_COL_SONG_TITLE);
446 g_signal_connect(G_OBJECT(treeviews[2]), "button-press-event", G_CALLBACK(magnatune_button_handle_release_event_tag), GINT_TO_POINTER(2));
447 /* Add column */
448 column = gtk_tree_view_column_new();
449 gtk_tree_view_column_set_title(column, "Album");
450 size = cfg_get_single_value_as_int_with_default(config, "gmpc-mpddata-model", "icon-size", 64);
451 gtk_tree_view_column_set_sizing(column , GTK_TREE_VIEW_COLUMN_FIXED);
452 gtk_tree_view_set_fixed_height_mode(GTK_TREE_VIEW(treeviews[2]), TRUE);
455 renderer = gtk_cell_renderer_pixbuf_new();
456 gtk_cell_renderer_set_fixed_size(renderer, size,size);
458 gtk_tree_view_column_pack_start(column, renderer, FALSE);
459 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", MPDDATA_MODEL_META_DATA);
460 renderer = gtk_cell_renderer_text_new();
461 gtk_tree_view_column_pack_start(column, renderer, TRUE);
462 gtk_tree_view_column_add_attribute(column, renderer, "text", MPDDATA_MODEL_COL_SONG_TITLE);
463 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeviews[2]),column, -1);
465 gtk_container_add(GTK_CONTAINER(sw), treeviews[2]);
466 gtk_box_pack_start(GTK_BOX(paned), sw, TRUE, TRUE, 0);
469 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]))), "changed", G_CALLBACK(magnatune_show_song_list), NULL);
470 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]))), "changed", G_CALLBACK(magnatune_show_song_list), NULL);
471 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[2]))), "changed", G_CALLBACK(magnatune_show_song_list), NULL);
473 gtk_paned_add1(GTK_PANED(magnatune_vbox), paned);
474 gtk_widget_show_all(paned);
476 * tree
478 sw = gtk_scrolled_window_new(NULL, NULL);
479 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
480 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
483 tree = (GtkWidget *)gmpc_mpddata_treeview_new("magnatune",TRUE,GTK_TREE_MODEL(mt_store));
484 g_signal_connect(G_OBJECT(tree), "row-activated", G_CALLBACK(magnatune_add_album_row_activated), NULL);
486 g_signal_connect(G_OBJECT(tree), "button-press-event", G_CALLBACK(magnatune_button_release_event), tree);
487 g_signal_connect(G_OBJECT(tree), "key-press-event", G_CALLBACK(magnatune_key_press), NULL);
489 gtk_container_add(GTK_CONTAINER(sw), tree);
490 gtk_box_pack_start(GTK_BOX(vbox),sw, TRUE, TRUE,0);
493 gtk_widget_show_all(sw);
494 gtk_widget_show(vbox);
496 * Progress Bar for the bottom
498 hbox = gtk_hbox_new(FALSE, 6);
499 magnatune_cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
500 g_signal_connect(G_OBJECT(magnatune_cancel), "clicked", G_CALLBACK(magnatune_download_cancel), NULL);
501 magnatune_pb = gtk_progress_bar_new();
502 gtk_box_pack_start(GTK_BOX(hbox), magnatune_pb, TRUE, TRUE, 0);
503 gtk_box_pack_start(GTK_BOX(hbox), magnatune_cancel, FALSE, TRUE, 0);
504 gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
505 gtk_paned_add2(GTK_PANED(magnatune_vbox), vbox);
508 g_object_ref(magnatune_vbox);
512 static void magnatune_selected(GtkWidget *container)
514 if(magnatune_vbox == NULL)
516 magnatune_init();
517 gtk_container_add(GTK_CONTAINER(container), magnatune_vbox);
518 gtk_widget_show(magnatune_vbox);
519 if(!magnatune_db_has_data())
521 magnatune_download();
523 else
524 magnatune_get_genre_list();
525 } else {
526 gtk_container_add(GTK_CONTAINER(container), magnatune_vbox);
527 gtk_widget_show(magnatune_vbox);
530 static void magnatune_unselected(GtkWidget *container)
532 gtk_container_remove(GTK_CONTAINER(container), magnatune_vbox);
534 static void magnatune_download_cancel(GtkWidget *button)
536 GEADAsyncHandler *handle = g_object_get_data(G_OBJECT(button), "handle");
537 if(handle)
539 gmpc_easy_async_cancel(handle);
540 g_object_set_data(G_OBJECT(button), "handle", NULL);
543 static void magnatune_download_callback(const GEADAsyncHandler *handle, const GEADStatus status, gpointer user_data)
545 GtkWidget *pb = user_data;
546 const gchar *uri = gmpc_easy_handler_get_uri(handle);
547 if(status == GEAD_DONE)
549 goffset length;
550 const char *data = gmpc_easy_handler_get_data(handle, &length);
552 magnatune_db_load_data(data, length);
553 if(length <= 0 || data == NULL) {
554 playlist3_show_error_message("Failed to download magnatune db: size is 0.",ERROR_WARNING);
556 gtk_widget_hide(gtk_widget_get_parent(pb));
557 magnatune_get_genre_list();
558 downloading = FALSE;
560 else if (status == GEAD_CANCELLED)
562 gtk_widget_hide(gtk_widget_get_parent(pb));
563 magnatune_get_genre_list();
564 downloading = FALSE;
566 else if (status == GEAD_PROGRESS)
568 goffset length;
569 goffset total = gmpc_easy_handler_get_content_size(handle);
570 /* Get downloaded length */
571 gmpc_easy_handler_get_data(handle, &length);
572 if(total > 0)
574 double fraction = (100*length)/(total);
575 gchar *size = g_format_size_for_display((goffset)length);
576 gchar *strtotal = g_format_size_for_display((goffset)total);
577 gchar *label = g_strdup_printf("Downloading music catalog (%s of %s done)",size,strtotal);
578 g_free(strtotal);
579 g_free(size);
580 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(pb), label);
581 g_free(label);
582 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pb),fraction/100.0);
584 else
586 gtk_progress_bar_pulse(GTK_PROGRESS_BAR(pb));
590 static void magnatune_download()
592 downloading = TRUE;
593 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]))),NULL);
594 gtk_widget_show_all(gtk_widget_get_parent(magnatune_pb));
595 const char *url = "http://he3.magnatune.com/info/sqlite_magnatune.db";
596 GEADAsyncHandler *handle = gmpc_easy_async_downloader(url, magnatune_download_callback,magnatune_pb);
597 g_object_set_data(G_OBJECT(magnatune_cancel), "handle", handle);
600 static void magnatune_add(GtkWidget *cat_tree)
602 GtkTreePath *path = NULL;
603 GtkTreeIter iter,child;
604 GtkListStore *pl3_tree = (GtkListStore *)gtk_tree_view_get_model(GTK_TREE_VIEW(cat_tree));
605 gint pos = cfg_get_single_value_as_int_with_default(config, "magnatune","position",20);
607 if(!cfg_get_single_value_as_int_with_default(config, "magnatune", "enable", TRUE)) return;
609 debug_printf(DEBUG_INFO,"Adding at position: %i", pos);
610 playlist3_insert_browser(&iter, PL3_CAT_BROWSER_ONLINE_MEDIA+pos%PL3_CAT_BROWSER_ONLINE_MEDIA);
611 gtk_list_store_set(GTK_LIST_STORE(pl3_tree), &iter,
612 PL3_CAT_TYPE, plugin.id,
613 PL3_CAT_TITLE, _("Magnatune Browser"),
614 PL3_CAT_INT_ID, "",
615 PL3_CAT_ICON_ID, "magnatune",
616 -1);
618 * Clean up old row reference if it exists
620 if (magnatune_ref)
622 gtk_tree_row_reference_free(magnatune_ref);
623 magnatune_ref = NULL;
626 * create row reference
628 path = gtk_tree_model_get_path(GTK_TREE_MODEL(playlist3_get_category_tree_store()), &iter);
629 if (path)
631 magnatune_ref = gtk_tree_row_reference_new(GTK_TREE_MODEL(playlist3_get_category_tree_store()), path);
632 gtk_tree_path_free(path);
636 char * __magnatune_process_string(const char *name)
638 int i = 0;
639 int j = 0;
640 int depth = 0;
641 int spaces = 0;
643 /* only gonna be smaller */
644 char *result = g_malloc0((strlen(name)+1+spaces*2)*sizeof(char));
645 for(i=0; i < strlen(name);i++)
647 if(name[i] == '(' || name[i] == '[') depth++;
648 else if (name[i] == ')' || name[i] == ']') depth--;
649 else if(!depth)
651 result[j] = name[i];
652 j++;
655 for(i=j-1;i>0 && result[i] == ' ';i--)
657 result[i] = '\0';
659 return result;
662 /*** COVER STUFF */
663 static int magnatune_fetch_cover_priority(void){
664 return cfg_get_single_value_as_int_with_default(config, "magnatune", "priority", 80);
666 static void magnatune_fetch_cover_priority_set(int priority){
667 cfg_set_single_value_as_int(config, "magnatune", "priority", priority);
671 static void magnatune_fetch_get_image(mpd_Song *song,MetaDataType type, void (*callback)(GList *list, gpointer data), gpointer user_data)
673 if(type == META_ARTIST_ART && song->artist)
675 char *value = magnatune_get_artist_image(song->artist);
676 if(value)
678 GList *list = NULL;
679 MetaData *mtd = meta_data_new();
680 mtd->type = type;
681 mtd->plugin_name = plugin.name;
682 mtd->content_type = META_DATA_CONTENT_URI;
683 mtd->content = value;
684 mtd->size = -1;
685 list = g_list_append(list, mtd);
686 callback(list, user_data);
687 return;
690 else if(type == META_ALBUM_ART && song->artist && song->album)
692 char *value = magnatune_get_album_image(song->artist,song->album);
693 if(value)
695 GList *list = NULL;
696 MetaData *mtd = meta_data_new();
697 mtd->type = type;
698 mtd->plugin_name = plugin.name;
699 mtd->content_type = META_DATA_CONTENT_URI;
700 mtd->content = value;
701 mtd->size = -1;
702 list = g_list_append(list, mtd);
703 callback(list, user_data);
704 return;
707 callback(NULL, user_data);
708 return ;
711 static void magnatune_redownload_reload_db()
713 GtkTreeIter iter;
714 GtkTreeModel *model = gtk_tree_row_reference_get_model(magnatune_ref);
715 GtkTreePath *path = gtk_tree_row_reference_get_path(magnatune_ref);
716 if(path && gtk_tree_model_get_iter(model, &iter, path))
718 GtkTreeIter citer;
719 while(gtk_tree_model_iter_children(model, &citer,&iter))
721 gtk_list_store_remove(GTK_LIST_STORE(model), &citer);
723 magnatune_download();
725 if(path)
726 gtk_tree_path_free(path);
728 static int magnatune_cat_menu_popup(GtkWidget *menu, int type, GtkWidget *tree, GdkEventButton *event)
730 GtkWidget *item;
731 if(type != plugin.id) return 0;
732 else if (!downloading)
734 /* add the clear widget */
735 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_REFRESH,NULL);
736 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
737 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(magnatune_redownload_reload_db), NULL);
738 return 1;
740 return 0;
743 static void magnatune_add_selected(GtkWidget *button, GtkTreeView *tree)
745 GtkTreeModel *model = GTK_TREE_MODEL(mt_store);
746 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
747 GList *list = gtk_tree_selection_get_selected_rows(sel,&model);
748 if(list)
750 GList *node ;
751 for(node = list; node; node = g_list_next(node))
753 GtkTreeIter iter;
754 if(gtk_tree_model_get_iter(model, &iter, node->data))
756 gchar *path;
757 gtk_tree_model_get(model, &iter, MPDDATA_MODEL_COL_PATH, &path, -1);
758 mpd_playlist_queue_add(connection, path);
759 g_free(path);
762 mpd_playlist_queue_commit(connection);
763 g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL);
764 g_list_free (list);
767 static void magnatune_replace_selected(GtkWidget *button , GtkTreeView *tree)
769 mpd_playlist_clear(connection);
770 magnatune_add_selected(button, tree);
771 mpd_player_play(connection);
775 static int magnatune_button_handle_release_event_tag_add(GtkWidget *button, gpointer userdata)
777 GList *list;
778 MpdData *data;
779 int position = GPOINTER_TO_INT(userdata);
780 gchar *genre=NULL, *artist=NULL, *album=NULL;
781 GtkTreeSelection *select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]));
782 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]));
783 GtkTreeIter piter;
784 if(gtk_tree_selection_get_selected(select, &model, &piter))
786 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&genre,-1);
788 if(position >= 1)
790 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]));
791 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[1]));
792 if(gtk_tree_selection_get_selected(select, &model, &piter))
794 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&artist,-1);
797 if(position >= 2)
799 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[2]));
800 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[2]));
801 if(gtk_tree_selection_get_selected(select, &model, &piter))
803 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&album,-1);
807 data = magnatune_db_get_song_list(genre,artist,album, TRUE);
808 for(data = mpd_data_get_first(data);data;data = mpd_data_get_next(data)) {
809 mpd_playlist_queue_add(connection, data->song->file);
811 mpd_playlist_queue_commit(connection);
812 if(genre)
813 g_free(genre);
814 if(artist)
815 g_free(artist);
816 if(album)
817 g_free(album);
821 static int magnatune_button_handle_release_event_tag_replace(GtkWidget *button, gpointer userdata)
823 mpd_playlist_clear(connection);
824 magnatune_button_handle_release_event_tag_add(button,userdata);
825 mpd_player_play(connection);
829 static int magnatune_button_handle_release_event_tag(GtkWidget *tree, GdkEventButton *event,gpointer data)
831 int i;
832 int position = GPOINTER_TO_INT(data);
833 if(event->button != 3) return FALSE;
834 GtkWidget *item;
836 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
837 if(gtk_tree_selection_count_selected_rows(sel)> 0)
839 GtkWidget *menu = gtk_menu_new();
842 /* Add */
843 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ADD,NULL);
844 gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), item);
845 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK( magnatune_button_handle_release_event_tag_add), data);
846 /* Replace */
847 item = gtk_image_menu_item_new_with_label("Replace");
848 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
849 gtk_image_new_from_stock(GTK_STOCK_REDO, GTK_ICON_SIZE_MENU));
850 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
851 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK( magnatune_button_handle_release_event_tag_replace), data);
852 gtk_widget_show_all(menu);
853 gtk_menu_popup(GTK_MENU(menu), NULL, NULL,NULL, NULL, event->button, event->time);
854 return TRUE;
856 return FALSE;
859 static int magnatune_button_release_event(GtkWidget *tree, GdkEventButton *event,gpointer data)
861 if(event->button != 3) return FALSE;
862 GtkWidget *item;
864 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
866 if(gtk_tree_selection_count_selected_rows(sel)> 0)
868 GtkWidget *menu = gtk_menu_new();
869 GtkTreeModel *model = GTK_TREE_MODEL(mt_store);
870 /* Add */
871 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ADD,NULL);
872 gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), item);
873 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(magnatune_add_selected), tree);
874 /* Replace */
875 item = gtk_image_menu_item_new_with_label("Replace");
876 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
877 gtk_image_new_from_stock(GTK_STOCK_REDO, GTK_ICON_SIZE_MENU));
878 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
880 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(magnatune_replace_selected), tree);
882 gmpc_mpddata_treeview_right_mouse_intergration(GMPC_MPDDATA_TREEVIEW(tree), GTK_MENU(menu));
884 gtk_widget_show_all(menu);
886 gtk_menu_popup(GTK_MENU(menu), NULL, NULL,NULL, NULL, event->button, event->time);
887 return TRUE;
889 return FALSE;
891 static int magnatune_key_press(GtkWidget *tree, GdkEventKey *event)
893 if(event->state&GDK_CONTROL_MASK && event->keyval == GDK_Insert)
895 magnatune_replace_selected(NULL, GTK_TREE_VIEW(tree));
897 else if(event->keyval == GDK_Insert)
899 magnatune_add_selected(NULL, GTK_TREE_VIEW(tree));
901 return FALSE;
903 static void magnatune_save_myself(void)
905 if (magnatune_ref)
907 GtkTreePath *path = gtk_tree_row_reference_get_path(magnatune_ref);
908 if(path)
910 gint *indices = gtk_tree_path_get_indices(path);
911 debug_printf(DEBUG_INFO,"Saving myself to position: %i\n", indices[0]);
912 cfg_set_single_value_as_int(config, "magnatune","position",indices[0]);
913 gtk_tree_path_free(path);
918 static void magnatune_destroy(void)
920 magnatune_db_destroy();
921 if(magnatune_vbox)
922 gtk_widget_destroy(magnatune_vbox);
925 static gboolean magnatune_integrate_search_field_supported(const int search_field)
927 switch(search_field)
929 case MPD_TAG_ITEM_ARTIST:
930 case MPD_TAG_ITEM_ALBUM:
931 case MPD_TAG_ITEM_GENRE:
932 case MPD_TAG_ITEM_TITLE:
933 return TRUE;
934 default:
935 return FALSE;
938 static MpdData * magnatune_integrate_search(const int search_field, const gchar *query,GError **error)
940 const gchar *genre = NULL, *artist=NULL, *album=NULL;
941 if(!magnatune_get_enabled()) return NULL;
942 if(!magnatune_db_has_data()){
943 g_set_error(error, 0,0, "Music catalog not yet available, please open magnatune browser first");
944 return NULL;
946 switch(search_field){
947 case MPD_TAG_ITEM_ARTIST:
948 artist = query;
949 break;
950 case MPD_TAG_ITEM_ALBUM:
951 album = query;
952 break;
953 case MPD_TAG_ITEM_GENRE:
954 genre = query;
955 break;
956 case MPD_TAG_ITEM_TITLE:
957 return magnatune_db_search_title(query);
958 break;
959 default:
960 g_set_error(error, 0,0, "This type of search query is not supported");
961 return NULL;
962 break;
964 return magnatune_db_get_song_list(genre, artist, album,FALSE);
967 gmpcMetaDataPlugin magnatune_cover = {
968 .get_priority = magnatune_fetch_cover_priority,
969 .set_priority = magnatune_fetch_cover_priority_set,
970 .get_metadata = magnatune_fetch_get_image
974 /* Needed plugin_wp stuff */
975 gmpcPlBrowserPlugin magnatune_gbp = {
976 .add = magnatune_add,
977 .selected = magnatune_selected,
978 .unselected = magnatune_unselected,
979 .cat_right_mouse_menu = magnatune_cat_menu_popup,
980 .integrate_search = magnatune_integrate_search,
981 .integrate_search_field_supported = magnatune_integrate_search_field_supported
984 int plugin_api_version = PLUGIN_API_VERSION;
986 static const gchar *magnatune_get_translation_domain(void)
988 return GETTEXT_PACKAGE;
991 static void magnatune_uentry_changed(GtkEntry *entry)
993 const gchar *text = gtk_entry_get_text(entry);
994 cfg_set_single_value_as_string(config,"magnatune", "username", text);
996 static void magnatune_pentry_changed(GtkEntry *entry)
998 const gchar *text = gtk_entry_get_text(entry);
999 cfg_set_single_value_as_string(config,"magnatune", "password", text);
1003 void magnatune_pref_construct (GtkWidget *container)
1005 GtkWidget *table;
1006 GtkWidget *label, *uentry, *pentry;
1007 gchar *un = cfg_get_single_value_as_string(config,"magnatune", "username");
1008 gchar *up = cfg_get_single_value_as_string(config,"magnatune", "password");
1010 table = gtk_table_new(3, 2, FALSE);
1012 /* Password */
1013 label = gtk_label_new(_("Username"));
1014 gtk_table_attach(GTK_TABLE(table), label, 0,1, 0,1, GTK_EXPAND|GTK_FILL, GTK_SHRINK|GTK_FILL, 0, 0);
1015 uentry = gtk_entry_new();
1016 if(un) gtk_entry_set_text(GTK_ENTRY(uentry), un);
1017 g_signal_connect(G_OBJECT(uentry), "changed", G_CALLBACK(magnatune_uentry_changed), NULL);
1018 gtk_table_attach(GTK_TABLE(table), uentry, 1,2, 0,1,GTK_EXPAND|GTK_FILL, GTK_SHRINK|GTK_FILL, 0, 0);
1021 label = gtk_label_new(_("Password"));
1022 gtk_table_attach(GTK_TABLE(table), label, 0,1, 1,2,GTK_EXPAND|GTK_FILL, GTK_SHRINK|GTK_FILL, 0, 0);
1024 pentry = gtk_entry_new();
1025 gtk_entry_set_visibility(GTK_ENTRY(pentry), FALSE);
1026 if(up) gtk_entry_set_text(GTK_ENTRY(pentry), up);
1027 g_signal_connect(G_OBJECT(pentry), "changed", G_CALLBACK(magnatune_pentry_changed), NULL);
1028 gtk_table_attach(GTK_TABLE(table), pentry, 1,2, 1,2, GTK_EXPAND|GTK_FILL, GTK_SHRINK|GTK_FILL, 0, 0);
1030 g_free(un);
1031 g_free(up);
1032 gtk_container_add(GTK_CONTAINER(container), table);
1033 gtk_widget_show_all(container);
1035 void magnatune_pref_destroy (GtkWidget *container)
1037 GtkWidget *child = gtk_bin_get_child(GTK_BIN(container));
1038 if(child) gtk_widget_destroy(child);
1041 gmpcPrefPlugin magnatune_gpp = {
1042 magnatune_pref_construct,
1043 magnatune_pref_destroy
1045 gmpcPlugin plugin = {
1046 .name = N_("Magnatune Stream Browser"),
1047 .version = {PLUGIN_MAJOR_VERSION,PLUGIN_MINOR_VERSION,PLUGIN_MICRO_VERSION},
1048 .plugin_type = GMPC_PLUGIN_PL_BROWSER|GMPC_PLUGIN_META_DATA,
1049 /* Creation and destruction */
1050 .init = magnatune_logo_init,
1051 .destroy = magnatune_destroy,
1052 .save_yourself = magnatune_save_myself,
1053 .mpd_status_changed = magnatune_mpd_status_changed,
1055 /* Browser extention */
1056 .browser = &magnatune_gbp,
1057 .metadata = &magnatune_cover,
1059 .pref = &magnatune_gpp,
1060 /* get/set enabled */
1061 .get_enabled = magnatune_get_enabled,
1062 .set_enabled = magnatune_set_enabled,
1065 .get_translation_domain = magnatune_get_translation_domain