Move to sqlite
[gmpc-magnatune.git] / src / plugin.c
blobe388c0199a15edeaae40ea30029a747f80714f59
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 char * __magnatune_process_string(char *name);
58 static GtkTreeRowReference *magnatune_ref = NULL;
61 static int downloading = FALSE;
62 /**
63 * Get set enabled
65 static int magnatune_get_enabled()
67 return cfg_get_single_value_as_int_with_default(config, "magnatune", "enable", TRUE);
69 static void magnatune_set_enabled(int enabled)
71 cfg_set_single_value_as_int(config, "magnatune", "enable", enabled);
72 if (enabled)
74 if(magnatune_ref == NULL)
76 magnatune_add(GTK_WIDGET(playlist3_get_category_tree_view()));
79 else if (magnatune_ref)
81 GtkTreePath *path = gtk_tree_row_reference_get_path(magnatune_ref);
82 if (path){
83 GtkTreeIter iter;
84 magnatune_save_myself();
85 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist3_get_category_tree_store()), &iter, path)){
86 gtk_list_store_remove(playlist3_get_category_tree_store(), &iter);
88 gtk_tree_path_free(path);
89 gtk_tree_row_reference_free(magnatune_ref);
90 magnatune_ref = NULL;
93 pl3_update_go_menu();
100 /* Playlist window row reference */
102 GtkWidget *magnatune_pb = NULL;
103 GtkWidget *magnatune_vbox = NULL;
104 GtkTreeModel *mt_store = NULL;
105 TreeSearch *mt_tree_search = NULL;
107 GtkWidget *treeviews[3] = {NULL, NULL,NULL};
109 static GtkWidget *magnatune_logo=NULL;
110 extern GladeXML *pl3_xml;
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_hbox_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(glade_xml_get_widget(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);
172 gtk_init_add((GtkFunction )magnatune_logo_add, NULL);
173 /**
174 * init the magnatune stuff
176 magnatune_db_init();
178 * open the db
180 magnatune_db_open();
184 static void magnatune_mpd_status_changed(MpdObj *mi, ChangedStatusType what, void *data)
186 if(!magnatune_logo)
187 return;
188 if(what&(MPD_CST_SONGID|MPD_CST_STATE))
190 mpd_Song *song = mpd_playlist_get_current_song(mi);
191 if(song && mpd_player_get_state(mi) == MPD_STATUS_STATE_PLAY) {
192 if(strstr(song->file,"magnatune.com"))
194 gtk_widget_show_all(magnatune_logo);
195 return;
198 gtk_widget_hide(magnatune_logo);
202 void magnatune_get_genre_list()
204 MpdData *data = NULL;
205 data = magnatune_db_get_genre_list();
206 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]))),data);
209 static void magnatune_show_album_list(GtkTreeSelection *selection, gpointer user_data)
211 MpdData *data = NULL;
212 GtkTreeIter piter;
213 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]));
214 if(gtk_tree_selection_get_selected(selection, &model, &piter))
216 gchar *genre;
217 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&genre,-1);
218 data= magnatune_db_get_artist_list(genre);
220 g_free(genre);
222 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[1]))),data);
225 static void magnatune_show_song_list(GtkTreeSelection *selection, gpointer user_data)
227 MpdData *data = NULL;
228 GtkTreeIter piter;
229 GtkTreeSelection *select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]));
230 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]));
231 gchar *genre = NULL, *artist = NULL, *album = NULL;
232 if(gtk_tree_selection_get_selected(select, &model, &piter))
235 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]));
236 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&genre,-1);
237 /* model */
238 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[1]));
239 if(gtk_tree_selection_get_selected(select, &model, &piter))
241 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&artist,-1);
242 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[2]));
243 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[2]));
244 if(gtk_tree_selection_get_selected(select, &model, &piter))
246 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&album,-1);
250 data = magnatune_db_get_song_list(genre, artist, album,TRUE);
251 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(mt_store), data);
254 static void magnatune_show_artist_list(GtkTreeSelection *selection, gpointer user_data)
256 GtkTreeIter piter;
257 MpdData *data = NULL;
258 GtkTreeSelection *select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]));
259 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]));
261 if(gtk_tree_selection_get_selected(select, &model, &piter))
263 GList *iter,*list = NULL;
264 gchar *genre;
266 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]));
267 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&genre,-1);
268 /* model */
269 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[1]));
270 if(gtk_tree_selection_get_selected(select, &model, &piter))
272 GList *iter,*list = NULL;
274 gchar *artist;
275 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&artist,-1);
276 data = magnatune_db_get_album_list(genre ,artist);
277 gmpc_mpddata_model_set_request_artist(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[2]))),artist);
278 g_free(artist);
280 g_free(genre);
282 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[2]))),data);
285 static void magnatune_add_album_row_activated(GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
287 GtkTreeModel *model = gtk_tree_view_get_model(tree);
288 GtkTreeIter iter_r;
290 if(gtk_tree_model_get_iter(model, &iter_r, path))
292 gchar *path;
293 gtk_tree_model_get(model, &iter_r, MPDDATA_MODEL_COL_PATH, &path, -1);
294 play_path(path);
295 g_free(path);
299 static gboolean magnatune_search_equal_func(GtkTreeModel *model, int column, const gchar *key, GtkTreeIter *iter, gpointer data)
301 gchar *compare = NULL;
302 gtk_tree_model_get(model,iter, column, &compare, -1);
303 if(compare){
304 gchar *a = g_utf8_casefold(key, -1);
305 gchar *b = g_utf8_casefold(compare, -1);
306 if(strstr(b,a))
308 g_free(a);
309 g_free(b);
310 return FALSE;
312 g_free(a);
313 g_free(b);
315 return TRUE;
318 static void magnatune_search_activate(TreeSearch *ts)
320 GtkTreeModel *model = GTK_TREE_MODEL(mt_store);
321 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ts->treeview));
322 if (gtk_tree_selection_count_selected_rows (selection) == 1)
324 GList *list = gtk_tree_selection_get_selected_rows (selection, &model);
325 magnatune_add_album_row_activated(GTK_TREE_VIEW(ts->treeview),(GtkTreePath *)list->data, NULL,NULL);
326 /* free list */
327 g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
328 g_list_free (list);
332 static void magnatune_init()
334 int size;
335 GtkWidget *tree = NULL;
336 GtkWidget *sw = NULL;
337 GtkCellRenderer *renderer = NULL;
338 GtkWidget *paned = NULL;
339 GtkWidget *hbox = NULL;
340 GtkWidget *vbox = NULL;
341 GtkTreeModel *model = NULL;
342 GtkTreeViewColumn *column = NULL;
343 int position = cfg_get_single_value_as_int_with_default(config, "magnatune", "pane-pos", 150);
344 magnatune_vbox = gtk_vpaned_new();
345 gtk_paned_set_position(GTK_PANED(magnatune_vbox), position);
348 vbox = gtk_vbox_new(FALSE,6);
350 * Create list store
351 * 1. pointer
352 * 2. name
354 mt_store = (GtkTreeModel *)gmpc_mpddata_model_new();
356 /* Paned window */
357 paned = gtk_hbox_new(TRUE,6);
358 model = (GtkTreeModel *) gmpc_mpddata_model_new();
359 /* Genre list */
360 sw = gtk_scrolled_window_new(NULL, NULL);
361 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
362 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
363 treeviews[0] = gtk_tree_view_new_with_model(model);
364 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeviews[0]), MPDDATA_MODEL_COL_SONG_TITLE);
365 g_signal_connect(G_OBJECT(treeviews[0]), "button-press-event", G_CALLBACK(magnatune_button_handle_release_event_tag), GINT_TO_POINTER(0));
366 /* Add column */
367 column = gtk_tree_view_column_new();
368 gtk_tree_view_column_set_title(column, "Genre");
371 renderer = gtk_cell_renderer_pixbuf_new();
372 gtk_tree_view_column_pack_start(column, renderer, FALSE);
373 gtk_tree_view_column_add_attribute(column, renderer, "icon-name", MPDDATA_MODEL_COL_ICON_ID);
374 gtk_tree_view_column_set_sizing(column , GTK_TREE_VIEW_COLUMN_AUTOSIZE);
375 renderer = gtk_cell_renderer_text_new();
376 gtk_tree_view_column_pack_start(column, renderer, TRUE);
377 gtk_tree_view_column_add_attribute(column, renderer, "text", MPDDATA_MODEL_COL_SONG_TITLE);
378 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeviews[0]),column, -1);
380 gtk_container_add(GTK_CONTAINER(sw), treeviews[0]);
381 gtk_box_pack_start(GTK_BOX(paned), sw, TRUE, TRUE, 0);
383 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]))), "changed", G_CALLBACK(magnatune_show_album_list), NULL);
385 /* Artist list */
386 model = (GtkTreeModel *) gmpc_mpddata_model_new();
387 sw = gtk_scrolled_window_new(NULL, NULL);
388 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
389 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
390 treeviews[1] = gtk_tree_view_new_with_model(model);
392 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeviews[1]), MPDDATA_MODEL_COL_SONG_TITLE);
393 g_signal_connect(G_OBJECT(treeviews[1]), "button-press-event", G_CALLBACK(magnatune_button_handle_release_event_tag), GINT_TO_POINTER(1));
394 /* Add column */
395 column = gtk_tree_view_column_new();
396 gtk_tree_view_column_set_title(column, "Artist");
397 size = cfg_get_single_value_as_int_with_default(config, "gmpc-mpddata-model", "icon-size", 64);
398 gtk_tree_view_column_set_sizing(column , GTK_TREE_VIEW_COLUMN_FIXED);
399 gtk_tree_view_set_fixed_height_mode(GTK_TREE_VIEW(treeviews[1]), TRUE);
402 renderer = gtk_cell_renderer_pixbuf_new();
403 gtk_cell_renderer_set_fixed_size(renderer, size,size);
405 gtk_tree_view_column_pack_start(column, renderer, FALSE);
406 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", MPDDATA_MODEL_META_DATA);
407 renderer = gtk_cell_renderer_text_new();
408 gtk_tree_view_column_pack_start(column, renderer, TRUE);
409 gtk_tree_view_column_add_attribute(column, renderer, "text", MPDDATA_MODEL_COL_SONG_TITLE);
410 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeviews[1]),column, -1);
412 gtk_container_add(GTK_CONTAINER(sw), treeviews[1]);
413 gtk_box_pack_start(GTK_BOX(paned), sw, TRUE, TRUE, 0);
415 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]))), "changed", G_CALLBACK(magnatune_show_artist_list), NULL);
417 /* Album list */
418 model = (GtkTreeModel *) gmpc_mpddata_model_new();
419 sw = gtk_scrolled_window_new(NULL, NULL);
420 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
421 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
422 treeviews[2] = gtk_tree_view_new_with_model(model);
423 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeviews[2]), MPDDATA_MODEL_COL_SONG_TITLE);
425 g_signal_connect(G_OBJECT(treeviews[2]), "button-press-event", G_CALLBACK(magnatune_button_handle_release_event_tag), GINT_TO_POINTER(2));
426 /* Add column */
427 column = gtk_tree_view_column_new();
428 gtk_tree_view_column_set_title(column, "Album");
429 size = cfg_get_single_value_as_int_with_default(config, "gmpc-mpddata-model", "icon-size", 64);
430 gtk_tree_view_column_set_sizing(column , GTK_TREE_VIEW_COLUMN_FIXED);
431 gtk_tree_view_set_fixed_height_mode(GTK_TREE_VIEW(treeviews[2]), TRUE);
434 renderer = gtk_cell_renderer_pixbuf_new();
435 gtk_cell_renderer_set_fixed_size(renderer, size,size);
437 gtk_tree_view_column_pack_start(column, renderer, FALSE);
438 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", MPDDATA_MODEL_META_DATA);
439 renderer = gtk_cell_renderer_text_new();
440 gtk_tree_view_column_pack_start(column, renderer, TRUE);
441 gtk_tree_view_column_add_attribute(column, renderer, "text", MPDDATA_MODEL_COL_SONG_TITLE);
442 gtk_tree_view_insert_column(GTK_TREE_VIEW(treeviews[2]),column, -1);
444 gtk_container_add(GTK_CONTAINER(sw), treeviews[2]);
445 gtk_box_pack_start(GTK_BOX(paned), sw, TRUE, TRUE, 0);
448 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]))), "changed", G_CALLBACK(magnatune_show_song_list), NULL);
449 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]))), "changed", G_CALLBACK(magnatune_show_song_list), NULL);
450 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[2]))), "changed", G_CALLBACK(magnatune_show_song_list), NULL);
452 gtk_paned_add1(GTK_PANED(magnatune_vbox), paned);
453 gtk_widget_show_all(paned);
455 * tree
457 sw = gtk_scrolled_window_new(NULL, NULL);
458 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
459 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
462 tree = (GtkWidget *)gmpc_mpddata_treeview_new("magnatune",TRUE,GTK_TREE_MODEL(mt_store));
463 g_signal_connect(G_OBJECT(tree), "row-activated", G_CALLBACK(magnatune_add_album_row_activated), NULL);
465 g_signal_connect(G_OBJECT(tree), "button-press-event", G_CALLBACK(magnatune_button_release_event), tree);
466 g_signal_connect(G_OBJECT(tree), "key-press-event", G_CALLBACK(magnatune_key_press), NULL);
468 gtk_container_add(GTK_CONTAINER(sw), tree);
469 gtk_box_pack_start(GTK_BOX(vbox),sw, TRUE, TRUE,0);
471 mt_tree_search = (TreeSearch *)treesearch_new(GTK_TREE_VIEW(tree), MPDDATA_MODEL_COL_SONG_TITLE);
472 gtk_box_pack_end(GTK_BOX(vbox), GTK_WIDGET(mt_tree_search), FALSE, TRUE, 0);
473 g_signal_connect(G_OBJECT(mt_tree_search), "result-activate", G_CALLBACK(magnatune_search_activate),NULL);
476 gtk_widget_show_all(sw);
477 gtk_widget_show(vbox);
479 * Progress Bar for the bottom
481 magnatune_pb = gtk_progress_bar_new();
482 gtk_box_pack_end(GTK_BOX(vbox), magnatune_pb, FALSE, TRUE, 0);
483 gtk_paned_add2(GTK_PANED(magnatune_vbox), vbox);
486 g_object_ref(magnatune_vbox);
490 static void magnatune_selected(GtkWidget *container)
492 if(magnatune_vbox == NULL)
494 magnatune_init();
495 gtk_container_add(GTK_CONTAINER(container), magnatune_vbox);
496 gtk_widget_show(magnatune_vbox);
497 if(!magnatune_db_has_data())
499 magnatune_download();
501 else
502 magnatune_get_genre_list();
503 } else {
504 gtk_container_add(GTK_CONTAINER(container), magnatune_vbox);
505 gtk_widget_show(magnatune_vbox);
508 static void magnatune_unselected(GtkWidget *container)
510 gtk_container_remove(GTK_CONTAINER(container), magnatune_vbox);
513 int magnatune_end_download()
515 downloading = FALSE;
517 magnatune_get_genre_list();
518 gtk_widget_hide(magnatune_pb);
519 gtk_widget_set_sensitive(glade_xml_get_widget(pl3_xml, "pl3_win"), TRUE);
520 return FALSE;
523 typedef struct _Pass{
524 GtkWidget *pb;
525 int download;
526 int total;
527 }Pass;
529 static int magnatune_download_xml_callback_real(Pass *p);
530 /* Move it to main thread, by pushing in idle */
531 static void magnatune_download_xml_callback(int download, int total,gpointer data)
533 Pass *p= g_malloc0(sizeof(*p));
534 p->pb = data;
535 p->download = download;
536 p->total =total;
537 g_idle_add((GSourceFunc)magnatune_download_xml_callback_real, p);
540 static int magnatune_download_xml_callback_real(Pass *p)
542 GtkWidget *pb = p->pb;
543 int download = p->download;
544 int total = p->total;
545 gchar *label = NULL;
546 gchar *size = NULL;
547 // gdk_threads_enter();
548 if(total > 0)
549 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pb), download/(float)total);
550 else
551 gtk_progress_bar_pulse(GTK_PROGRESS_BAR(pb));
553 size = g_format_size_for_display((goffset)download);
554 label = g_strdup_printf("Downloading music catalog (%s done)",size);
555 g_free(size);
556 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(pb), label);
557 g_free(label);
558 // while(gtk_events_pending())
559 // gtk_main_iteration();
560 // gdk_threads_leave();
561 g_free(p);
562 return FALSE;
565 static void magnatune_download()
567 downloading = TRUE;
568 // gtk_widget_set_sensitive(glade_xml_get_widget(pl3_xml, "pl3_win"), FALSE);
569 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]))),NULL);
570 gtk_widget_show(magnatune_pb);
571 magnatune_db_download_xml(magnatune_download_xml_callback, magnatune_pb);
572 // gtk_widget_hide(magnatune_pb);
573 // gtk_widget_set_sensitive(glade_xml_get_widget(pl3_xml, "pl3_win"), TRUE);
576 static void magnatune_add(GtkWidget *cat_tree)
578 GtkTreePath *path = NULL;
579 GtkTreeIter iter,child;
580 GtkListStore *pl3_tree = (GtkListStore *)gtk_tree_view_get_model(GTK_TREE_VIEW(cat_tree));
581 gint pos = cfg_get_single_value_as_int_with_default(config, "magnatune","position",20);
583 if(!cfg_get_single_value_as_int_with_default(config, "magnatune", "enable", TRUE)) return;
585 debug_printf(DEBUG_INFO,"Adding at position: %i", pos);
586 playlist3_insert_browser(&iter, pos);
587 gtk_list_store_set(GTK_LIST_STORE(pl3_tree), &iter,
588 PL3_CAT_TYPE, plugin.id,
589 PL3_CAT_TITLE, "Magnatune Browser",
590 PL3_CAT_INT_ID, "",
591 PL3_CAT_ICON_ID, "magnatune",
592 PL3_CAT_PROC, TRUE,
593 PL3_CAT_ICON_SIZE,GTK_ICON_SIZE_DND,-1);
595 * Clean up old row reference if it exists
597 if (magnatune_ref)
599 gtk_tree_row_reference_free(magnatune_ref);
600 magnatune_ref = NULL;
603 * create row reference
605 path = gtk_tree_model_get_path(GTK_TREE_MODEL(playlist3_get_category_tree_store()), &iter);
606 if (path)
608 magnatune_ref = gtk_tree_row_reference_new(GTK_TREE_MODEL(playlist3_get_category_tree_store()), path);
609 gtk_tree_path_free(path);
613 char * __magnatune_process_string(char *name)
615 int i = 0;
616 int j = 0;
617 int depth = 0;
618 int spaces = 0;
620 /* only gonna be smaller */
621 char *result = g_malloc0((strlen(name)+1+spaces*2)*sizeof(char));
622 for(i=0; i < strlen(name);i++)
624 if(name[i] == '(' || name[i] == '[') depth++;
625 else if (name[i] == ')' || name[i] == ']') depth--;
626 else if(!depth)
628 result[j] = name[i];
629 j++;
632 for(i=j-1;i>0 && result[i] == ' ';i--)
634 result[i] = '\0';
636 return result;
639 /*** COVER STUFF */
640 static int magnatune_fetch_cover_priority(void){
641 return cfg_get_single_value_as_int_with_default(config, "magnatune", "priority", 80);
643 static void magnatune_fetch_cover_priority_set(int priority){
644 cfg_set_single_value_as_int(config, "magnatune", "priority", priority);
647 static int magnatune_fetch_get_image(mpd_Song *song,MetaDataType type, char **path)
649 int result = 0;
650 printf("try magnatune\n");
652 if(type == META_ARTIST_ART && song->artist)
654 char *value = magnatune_get_artist_image(song->artist);
655 if(value)
657 if(strlen(value) > 0)
659 gmpc_easy_download_struct dld = {NULL, 0, -1, NULL,NULL};
660 printf("artist image: %s\n", value);
661 *path = gmpc_get_metadata_filename(META_ARTIST_ART, song, NULL);
662 if(gmpc_easy_download(value, &dld))
664 g_file_set_contents(*path, dld.data, dld.size, NULL);
665 g_free(value);
666 gmpc_easy_download_clean(&dld);
667 return META_DATA_AVAILABLE;
669 gmpc_easy_download_clean(&dld);
670 g_free(*path);
671 *path = NULL;
672 g_free(value);
676 else*/ if(type == META_ALBUM_ART && song->artist && song->album)
678 printf("try magnatune album\n");
679 char *value = magnatune_get_album_image(song->artist,song->album);
680 if(value)
682 gmpc_easy_download_struct dld = {NULL, 0, -1, NULL,NULL};
683 printf("album image: %s\n", value);
684 *path = gmpc_get_metadata_filename(META_ALBUM_ART, song, NULL);
685 if(gmpc_easy_download(value, &dld))
687 g_file_set_contents(*path, dld.data, dld.size, NULL);
688 g_free(value);
689 gmpc_easy_download_clean(&dld);
690 return META_DATA_AVAILABLE;
692 gmpc_easy_download_clean(&dld);
693 g_free(*path);
694 *path = NULL;
695 g_free(value);
698 return META_DATA_UNAVAILABLE;
701 static void magnatune_redownload_reload_db()
703 GtkTreeIter iter;
704 GtkTreeModel *model = gtk_tree_row_reference_get_model(magnatune_ref);
705 GtkTreePath *path = gtk_tree_row_reference_get_path(magnatune_ref);
706 if(path && gtk_tree_model_get_iter(model, &iter, path))
708 GtkTreeIter citer;
709 while(gtk_tree_model_iter_children(model, &citer,&iter))
711 gtk_list_store_remove(GTK_LIST_STORE(model), &citer);
713 magnatune_download();
714 //magnatune_get_genre_list();
716 if(path)
717 gtk_tree_path_free(path);
720 static void magnatune_cat_menu_add()
722 GtkTreeIter citer;
723 GtkTreeSelection *sel = gtk_tree_view_get_selection(playlist3_get_category_tree_view());
724 GtkTreeModel *model = (GtkTreeModel *)playlist3_get_category_tree_store();
725 GtkTreePath *tpath;
726 int depth = 0;
727 if(!gtk_tree_selection_get_selected(sel,&model,&citer))
729 return ;
731 */ /**
732 * Get the level we are on.
734 /* tpath = gtk_tree_model_get_path(model, &citer);
735 depth = gtk_tree_path_get_depth(tpath);
736 gtk_tree_path_free(tpath);
737 */ /** Genre level */
738 /* if(depth == 2)
740 GList *list, *node;
741 gchar *genre;
742 gtk_tree_model_get(model, &citer, PL3_CAT_INT_ID,&genre, -1);
743 if(genre)
745 list = magnatune_db_get_url_list(genre, NULL ,NULL);
746 for(node = list; node; node = node->next)
748 mpd_playlist_queue_add(connection, node->data);
750 mpd_playlist_queue_commit(connection);
751 g_list_foreach(list, (GFunc)g_free, NULL);
752 g_list_free(list);
753 g_free(genre);
756 */ /** Artist */
757 /* else if(depth == 3)
759 gchar *artist;
760 gchar *genre;
761 GtkTreeIter iter;
762 if(gtk_tree_model_iter_parent(model, &iter, &citer))
764 GList *list, *node;
765 gtk_tree_model_get(model, &iter, PL3_CAT_INT_ID,&genre, -1);
766 gtk_tree_model_get(model, &citer, PL3_CAT_INT_ID,&artist, -1);
767 list = magnatune_db_get_url_list(genre, artist,NULL);
768 for(node = list; node; node = node->next)
770 mpd_playlist_queue_add(connection, node->data);
772 mpd_playlist_queue_commit(connection);
773 g_list_foreach(list, (GFunc)g_free, NULL);
774 g_list_free(list);
775 g_free(genre);
776 g_free(artist);
786 static void magnatune_cat_menu_replace()
788 mpd_playlist_clear(connection);
789 magnatune_cat_menu_add();
790 mpd_player_play(connection);
794 static int magnatune_cat_menu_popup(GtkWidget *menu, int type, GtkWidget *tree, GdkEventButton *event)
796 GtkWidget *item;
797 if(type != plugin.id) return 0;
798 else if (!downloading)
800 /* add the clear widget */
801 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_REFRESH,NULL);
802 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
803 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(magnatune_redownload_reload_db), NULL);
804 return 1;
806 return 0;
809 static void magnatune_add_selected(GtkWidget *button, GtkTreeView *tree)
811 GtkTreeModel *model = GTK_TREE_MODEL(mt_store);
812 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
813 GList *list = gtk_tree_selection_get_selected_rows(sel,&model);
814 if(list)
816 GList *node ;
817 for(node = list; node; node = g_list_next(node))
819 GtkTreeIter iter;
820 if(gtk_tree_model_get_iter(model, &iter, node->data))
822 gchar *path;
823 gtk_tree_model_get(model, &iter, MPDDATA_MODEL_COL_PATH, &path, -1);
824 mpd_playlist_queue_add(connection, path);
825 g_free(path);
828 mpd_playlist_queue_commit(connection);
829 g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL);
830 g_list_free (list);
833 static void magnatune_replace_selected(GtkWidget *button , GtkTreeView *tree)
835 mpd_playlist_clear(connection);
836 magnatune_add_selected(button, tree);
837 mpd_player_play(connection);
841 static void magnatune_list_edit_columns(GtkMenuItem *item, GtkWidget *widget)
843 gmpc_mpddata_treeview_edit_columns(GMPC_MPDDATA_TREEVIEW(widget));
845 static int magnatune_button_handle_release_event_tag_add(GtkWidget *button, gpointer userdata)
847 GList *list;
848 MpdData *data;
849 int position = GPOINTER_TO_INT(userdata);
850 gchar *genre=NULL, *artist=NULL, *album=NULL;
851 GtkTreeSelection *select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[0]));
852 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[0]));
853 GtkTreeIter piter;
854 if(gtk_tree_selection_get_selected(select, &model, &piter))
856 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&genre,-1);
858 if(position >= 1)
860 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[1]));
861 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[1]));
862 if(gtk_tree_selection_get_selected(select, &model, &piter))
864 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&artist,-1);
867 if(position >= 2)
869 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeviews[2]));
870 model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeviews[2]));
871 if(gtk_tree_selection_get_selected(select, &model, &piter))
873 gtk_tree_model_get(model, &piter, MPDDATA_MODEL_COL_SONG_TITLE,&album,-1);
877 list = magnatune_db_get_url_list(genre, artist, album);
878 for(;list; list = list->next)
880 mpd_playlist_queue_add(connection, list->data);
884 data = magnatune_db_get_song_list(genre,artist,album, TRUE);
885 for(data = mpd_data_get_first(data);data;data = mpd_data_get_next(data)) {
886 mpd_playlist_queue_add(connection, data->song->file);
888 mpd_playlist_queue_commit(connection);
890 if(list)
892 g_list_foreach(list, (GFunc)g_free, NULL);
893 g_list_free(list);
896 if(genre)
897 g_free(genre);
898 if(artist)
899 g_free(artist);
900 if(album)
901 g_free(album);
905 static int magnatune_button_handle_release_event_tag_replace(GtkWidget *button, gpointer userdata)
907 mpd_playlist_clear(connection);
908 magnatune_button_handle_release_event_tag_add(button,userdata);
909 mpd_player_play(connection);
913 static int magnatune_button_handle_release_event_tag(GtkWidget *tree, GdkEventButton *event,gpointer data)
915 int i;
916 int position = GPOINTER_TO_INT(data);
917 if(event->button != 3) return FALSE;
918 GtkWidget *item;
920 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
921 if(gtk_tree_selection_count_selected_rows(sel)> 0)
923 GtkWidget *menu = gtk_menu_new();
926 /* Add */
927 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ADD,NULL);
928 gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), item);
929 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK( magnatune_button_handle_release_event_tag_add), data);
930 /* Replace */
931 item = gtk_image_menu_item_new_with_label("Replace");
932 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
933 gtk_image_new_from_stock(GTK_STOCK_REDO, GTK_ICON_SIZE_MENU));
934 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
935 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK( magnatune_button_handle_release_event_tag_replace), data);
936 gtk_widget_show_all(menu);
937 gtk_menu_popup(GTK_MENU(menu), NULL, NULL,NULL, NULL, event->button, event->time);
938 return TRUE;
940 return FALSE;
943 static int magnatune_button_release_event(GtkWidget *tree, GdkEventButton *event,gpointer data)
945 if(event->button != 3) return FALSE;
946 GtkWidget *item;
948 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
950 if(gtk_tree_selection_count_selected_rows(sel)> 0)
952 GtkWidget *menu = gtk_menu_new();
953 GtkTreeModel *model = GTK_TREE_MODEL(mt_store);
954 /* Add */
955 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ADD,NULL);
956 gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), item);
957 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(magnatune_add_selected), tree);
958 /* Replace */
959 item = gtk_image_menu_item_new_with_label("Replace");
960 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
961 gtk_image_new_from_stock(GTK_STOCK_REDO, GTK_ICON_SIZE_MENU));
962 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
964 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(magnatune_replace_selected), tree);
966 /* Separator */
967 item = gtk_separator_menu_item_new();
968 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
969 /* Edit columns */
970 item = gtk_image_menu_item_new_with_label(("Edit Columns"));
971 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
972 gtk_image_new_from_stock(GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU));
973 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
974 g_signal_connect(G_OBJECT(item), "activate",
975 G_CALLBACK(magnatune_list_edit_columns), tree);
977 gtk_widget_show_all(menu);
979 gtk_menu_popup(GTK_MENU(menu), NULL, NULL,NULL, NULL, event->button, event->time);
980 return TRUE;
982 return FALSE;
985 static void magnatune_cat_key_press(GtkWidget *tree, GdkEventKey *event, int selected_type)
987 if(selected_type != plugin.id) return;
988 if(event->state&GDK_CONTROL_MASK && event->keyval == GDK_Insert)
990 magnatune_cat_menu_replace();
992 else if(event->keyval == GDK_Insert)
994 magnatune_cat_menu_add();
999 static int magnatune_key_press(GtkWidget *tree, GdkEventKey *event)
1001 if(event->state&GDK_CONTROL_MASK && event->keyval == GDK_Insert)
1003 magnatune_replace_selected(NULL, GTK_TREE_VIEW(tree));
1005 else if(event->keyval == GDK_Insert)
1007 magnatune_add_selected(NULL, GTK_TREE_VIEW(tree));
1009 else if (event->keyval == GDK_f && event->state&GDK_CONTROL_MASK)
1011 treesearch_start(mt_tree_search);
1012 return TRUE;
1014 else if((event->state&(GDK_CONTROL_MASK|GDK_MOD1_MASK)) == 0 &&
1015 ((event->keyval >= GDK_space && event->keyval <= GDK_z)))
1017 char data[2];
1018 data[0] = (char)gdk_keyval_to_unicode(event->keyval);
1019 data[1] = '\0';
1020 treesearch_start(TREESEARCH(mt_tree_search));
1021 gtk_entry_set_text(GTK_ENTRY(TREESEARCH(mt_tree_search)->entry),data);
1022 gtk_editable_set_position(GTK_EDITABLE(TREESEARCH(mt_tree_search)->entry),1);
1023 return TRUE;
1025 return FALSE;
1027 static void magnatune_save_myself(void)
1029 if(magnatune_vbox)
1031 int position = gtk_paned_get_position(GTK_PANED(magnatune_vbox));
1032 cfg_set_single_value_as_int(config, "magnatune", "pane-pos", position);
1034 if (magnatune_ref)
1036 GtkTreePath *path = gtk_tree_row_reference_get_path(magnatune_ref);
1037 if(path)
1039 gint *indices = gtk_tree_path_get_indices(path);
1040 debug_printf(DEBUG_INFO,"Saving myself to position: %i\n", indices[0]);
1041 cfg_set_single_value_as_int(config, "magnatune","position",indices[0]);
1042 gtk_tree_path_free(path);
1047 static void magnatune_destroy(void)
1049 magnatune_db_destroy();
1050 if(magnatune_vbox)
1051 gtk_widget_destroy(magnatune_vbox);
1054 static MpdData * magnatune_integrate_search(const int search_field, const gchar *query,GError **error)
1056 const gchar *genre = NULL, *artist=NULL, *album=NULL;
1057 if(!magnatune_get_enabled()) return NULL;
1058 if(!magnatune_db_has_data()){
1059 g_set_error(error, 0,0, "Music catalog not yet available, please open magnatune browser first");
1060 return NULL;
1062 switch(search_field){
1063 case MPD_TAG_ITEM_ARTIST:
1064 artist = query;
1065 break;
1066 case MPD_TAG_ITEM_ALBUM:
1067 album = query;
1068 break;
1069 case MPD_TAG_ITEM_GENRE:
1070 genre = query;
1071 break;
1072 case MPD_TAG_ITEM_TITLE:
1073 return magnatune_db_search_title(query);
1074 break;
1075 default:
1076 g_set_error(error, 0,0, "This type of search query is not supported");
1077 return NULL;
1078 break;
1080 return magnatune_db_get_song_list(genre, artist, album,FALSE);
1083 gmpcMetaDataPlugin magnatune_cover = {
1084 .get_priority = magnatune_fetch_cover_priority,
1085 .set_priority = magnatune_fetch_cover_priority_set,
1086 .get_image = magnatune_fetch_get_image
1090 /* Needed plugin_wp stuff */
1091 gmpcPlBrowserPlugin magnatune_gbp = {
1092 .add = magnatune_add,
1093 .selected = magnatune_selected,
1094 .unselected = magnatune_unselected,
1095 .cat_right_mouse_menu = magnatune_cat_menu_popup,
1096 .integrate_search = magnatune_integrate_search
1099 int plugin_api_version = PLUGIN_API_VERSION;
1101 gmpcPlugin plugin = {
1102 .name = "Magnatune Stream Browser",
1103 .version = {PLUGIN_MAJOR_VERSION,PLUGIN_MINOR_VERSION,PLUGIN_MICRO_VERSION},
1104 .plugin_type = GMPC_PLUGIN_PL_BROWSER|GMPC_PLUGIN_META_DATA,
1105 /* Creation and destruction */
1106 .init = magnatune_logo_init,
1107 .destroy = magnatune_destroy,
1108 .save_yourself = magnatune_save_myself,
1109 .mpd_status_changed = magnatune_mpd_status_changed,
1111 /* Browser extention */
1112 .browser = &magnatune_gbp,
1113 .metadata = &magnatune_cover,
1115 /* get/set enabled */
1116 .get_enabled = magnatune_get_enabled,
1117 .set_enabled = magnatune_set_enabled