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