1 /* Gnome Music Player Client (GMPC)
2 * Copyright (C) 2004-2012 Qball Cow <qball@gmpclient.org>
3 * Project homepage: http://gmpclient.org/
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.
25 #define LOG_DOMAIN "MetaImage"
31 #include <libmpd/libmpd.h>
32 #include "gmpc-extras.h"
36 static unsigned int num_drag_targets = 4; /* skip hyperlinks for now */
37 static GtkTargetEntry data_image_drag_target[] =
39 { (gchar *)"image/jpeg", 0, 0 },
40 { (gchar *)"image/png", 0, 1 },
41 { (gchar *)"image/gif", 0, 2 },
42 { (gchar *)"text/uri-list", 0, 3},
43 { (gchar *)"_NETSCAPE_URL", 0,4},
44 { (gchar *)"x-url/http", 0,5}
53 typedef enum _GmpcMetaImageState{
68 class Gmpc:MetaImage from Gtk:Event:Box{
69 private GmpcMetaImageState state = {STATE_EMPTY};
70 private int refresh = FALSE;
71 private gulong status_signal = {0};
72 private gulong connect_signal = {0};
73 private gulong meta_id = {0};
75 private gulong metadata_force_reload = {0};
77 private gchar *image_url = {NULL};
79 private mpd_Song *song = {NULL} destroywith mpd_freeSong;
83 public int size = {48};
84 public MetaDataType image_type = {META_ALBUM_ART};
85 public MpdObj *connection= {NULL};
86 public gboolean hide_on_na = {FALSE};
87 public gboolean squared = {TRUE};
88 public gchar *no_cover_icon = {g_strdup("gmpc-no-cover")} destroywith g_free;
89 public gchar *loading_cover_icon = {g_strdup("gmpc-loading-cover")} destroywith g_free;
91 private gulong expose_id = {0};
92 public gboolean scale_up = FALSE;
94 * I want fully set/get control,so I don't use property stuff,
95 * is there a way around this?
97 public gboolean is_visible = {TRUE};
99 property INT image_type
100 (nick = "Image type",
101 blurb = "Type of the image, like artist art",
102 default_value = META_ALBUM_ART,
108 blurb = "Size of the image",
113 property BOOLEAN hide_on_na
115 blurb = "Hide the image when not available",
116 default_value = FALSE,
120 property BOOLEAN scale_up
121 (nick = "Scale image up",
122 blurb = "Scale cover art up",
123 default_value = FALSE,
127 property BOOLEAN squared
129 blurb = "Keep the widget squared",
130 default_value = TRUE,
132 public void set_no_cover_icon (self, const gchar *name)
134 if(self->no_cover_icon) {
135 q_free(self->no_cover_icon);
137 self->no_cover_icon = g_strdup(name);
139 public void set_loading_cover_icon (self, const gchar *name)
141 if(self->loading_cover_icon) {
142 q_free(self->loading_cover_icon);
144 self->loading_cover_icon = g_strdup(name);
146 public void set_squared (self, const gboolean item)
148 self->squared = item;
150 public void set_connection(self, MpdObj *conn)
152 self->connection = conn;
155 self->_priv->status_signal = g_signal_connect_swapped(G_OBJECT(gmpcconn),
157 G_CALLBACK(self_update_cover),
160 self->_priv->connect_signal = g_signal_connect_swapped(G_OBJECT(gmpcconn),
161 "connection_changed",
162 G_CALLBACK(self_connection_changed),
166 private GtkWidget *image = { (GtkWidget *)gmpc_meta_image_async_new()} ;
167 private GtkWidget *tooltip_image = { (GtkWidget *)gmpc_meta_image_async_new()} ;
171 GtkWidget *win = NULL;
172 gtk_container_add(GTK_CONTAINER(self), self->_priv->image);
173 gtk_container_set_resize_mode(GTK_CONTAINER(self), GTK_RESIZE_IMMEDIATE);
174 gtk_widget_show_all(GTK_WIDGET(self));
176 g_signal_connect_swapped(G_OBJECT(self/*->_priv->image*/), "button-press-event", G_CALLBACK(self_menu_populate_callback), self);
177 self->_priv->meta_id = g_signal_connect(G_OBJECT(gmw), "data-changed", G_CALLBACK(self_meta_callback), self);
178 gtk_widget_add_events(GTK_WIDGET(self->_priv->image), GDK_POINTER_MOTION_MASK);
179 gtk_widget_set_no_show_all(GTK_WIDGET(self),TRUE);
181 win = gtk_window_new(GTK_WINDOW_POPUP);
182 gtk_window_set_resizable(GTK_WINDOW(win), FALSE);
183 gtk_widget_modify_bg(win, GTK_STATE_NORMAL, &(GTK_WIDGET(self)->style->black));
184 gtk_container_set_border_width(GTK_CONTAINER(win), 6);
185 gtk_container_add(GTK_CONTAINER(win), GTK_WIDGET(self->_priv->tooltip_image));
187 gtk_widget_set_tooltip_window(GTK_WIDGET(self), GTK_WINDOW(win));
188 g_signal_connect(G_OBJECT(self), "query-tooltip", G_CALLBACK(self_tooltip_query), win);
191 gboolean tooltip_query(self, gint x, gint y,gboolean keyboard_mode, GtkTooltip *tip, GtkWidget *win)
193 if(self->_priv->state == STATE_IMAGE)
195 gtk_widget_show(self->_priv->tooltip_image);
203 dispose(G:Object *obj)
205 Self *self = GMPC_METAIMAGE(obj);
206 if(self->_priv->meta_id)
208 g_signal_handler_disconnect(G_OBJECT(gmw),self->_priv->meta_id);
209 self->_priv->meta_id = 0;
211 if(self->_priv->metadata_force_reload)
213 g_signal_handler_disconnect(G_OBJECT(gmw),self->_priv->metadata_force_reload);
214 self->_priv->metadata_force_reload = 0;
216 if(self->_priv->image_url) {
217 q_free(self->_priv->image_url);
219 if(self->_priv->status_signal){
220 g_signal_handler_disconnect(G_OBJECT(gmpcconn), self->_priv->status_signal);
221 self->_priv->status_signal =0;
223 if(self->_priv->connect_signal){
224 g_signal_handler_disconnect(G_OBJECT(gmpcconn), self->_priv->connect_signal);
225 self->_priv->connect_signal=0;
231 drag_data_recieved (self,
232 GdkDragContext *context,
235 GtkSelectionData *data,
242 if(self->_priv->song)
244 if(info < num_drag_targets)
246 gchar **uri = gtk_selection_data_get_uris(data);
247 /* Only one uri is interresting */
250 gchar *path = g_filename_from_uri(uri[0], NULL, NULL);
253 if(path && gdk_pixbuf_get_file_info(path, NULL,NULL))
255 /* Create MetaData object */
256 MetaData* met = meta_data_new();
257 met->type = self->image_type;
258 met->plugin_name = g_strdup("User set");
259 met->content_type = META_DATA_CONTENT_URI;
260 meta_data_set_uri(met, path);
262 meta_data_set_entry(self->_priv->song, met);
263 /* free Metadata object */
272 gtk_drag_finish(context, found, FALSE, dnd_time);
274 /* hack to make the "delayed" image load when it gets visible"
278 expose_event(self, GdkEventExpose *event, gpointer data)
280 g_signal_handler_disconnect(G_OBJECT(self), self->_priv->expose_id);
281 self->_priv->expose_id = 0;
282 self_update_cover_from_song_delayed_real(self);
287 Gmpc:Meta:Image *new_size(int type, int size)
290 gmi->image_type = type;
291 gmi->size = size;//pixbuf_cache_get_closest_size(size);
294 gtk_event_box_set_visible_window(GTK_EVENT_BOX(gmi), FALSE);
295 gtk_drag_dest_set(GTK_WIDGET(gmi),
296 GTK_DEST_DEFAULT_ALL,
297 data_image_drag_target, num_drag_targets,
298 GDK_ACTION_COPY|GDK_ACTION_LINK|GDK_ACTION_DEFAULT|GDK_ACTION_MOVE);
300 g_signal_connect_swapped (G_OBJECT (gmi),"drag-data-received",
301 GTK_SIGNAL_FUNC (self_drag_data_recieved),gmi);
303 gmi->_priv->metadata_force_reload = g_signal_connect_swapped(G_OBJECT(gmw), "force-reload", G_CALLBACK(self_reload_image), gmi);
308 GtkWidget * new (int type)
311 gmi->image_type = type;
313 gtk_event_box_set_visible_window(GTK_EVENT_BOX(gmi), FALSE);
314 gtk_drag_dest_set(GTK_WIDGET(gmi),
315 GTK_DEST_DEFAULT_ALL,
316 data_image_drag_target, num_drag_targets,
317 GDK_ACTION_COPY|GDK_ACTION_LINK|GDK_ACTION_DEFAULT|GDK_ACTION_MOVE);
318 g_signal_connect_swapped (G_OBJECT (gmi),"drag-data-received",
319 GTK_SIGNAL_FUNC (self_drag_data_recieved),gmi);
320 gmi->_priv->metadata_force_reload = g_signal_connect_swapped(G_OBJECT(gmw), "force-reload", G_CALLBACK(self_reload_image), gmi);
321 return (GtkWidget *)gmi;
326 update_cover(self, MpdObj *mi, ChangedStatusType what, GmpcConnection *gc)
329 if(self->connection && what&(MPD_CST_STATE|MPD_CST_SONGID|MPD_CST_SONGPOS|MPD_CST_PLAYLIST) && self->is_visible)
331 int state = mpd_player_get_state(self->connection);
332 if(state == MPD_PLAYER_STOP || state == MPD_PLAYER_UNKNOWN)
334 self->_priv->refresh = TRUE;
335 self_set_cover_na(self);
338 mpd_Song *song = mpd_playlist_get_current_song(self->connection);
341 if( self->_priv->refresh == FALSE &&
343 self->_priv->song->artist &&
345 strcmp(song->artist, self->_priv->song->artist) == 0)
347 /* If we are artist iamge, don't update, same artist */
348 if(self->image_type == META_ARTIST_ART ) return;
349 /* If we are album, check if album matches too */
350 else if(self->image_type == META_ALBUM_ART &&
351 self->_priv->song->album && song->album &&
352 strcmp(self->_priv->song->album, song->album) == 0){
356 self_update_cover_from_song(self, song);
360 self_set_cover_na(self);
362 self->_priv->refresh = FALSE;
369 connection_changed(self,MpdObj *mi, int connect, GmpcConnection *gmpconn)
373 self_set_cover_na(self);
379 int state = mpd_player_get_state(self->connection);
380 if(state != MPD_PLAYER_STOP && state != MPD_PLAYER_UNKNOWN)
382 mpd_Song *song = mpd_playlist_get_current_song(self->connection);
384 self_update_cover_from_song(self, song);
395 update_cover_from_song(self, const mpd_Song *song)
401 if(self->_priv->song)
402 mpd_freeSong(self->_priv->song);
403 self->_priv->song = NULL;
407 self_set_cover_na(self);
410 self->_priv->song = mpd_songDup(song);
412 ret = meta_data_get_path(self->_priv->song, self->image_type, &met, NULL, NULL);
413 if(ret == META_DATA_FETCHING)
415 self_set_cover_fetching(self);
416 }else if (ret == META_DATA_AVAILABLE) {
417 if (met->content_type == META_DATA_CONTENT_RAW) {
418 self_set_cover_raw(self, met->content, met->size,met->md5sum);
420 self_set_cover_na(self);
422 } else if (ret == META_DATA_INVALID_QUERY) {
423 self_set_cover_invalid_query(self);
425 self_set_cover_na(self);
434 update_cover_from_song_delayed_real(self)
437 int ret = meta_data_get_path(self->_priv->song, self->image_type, &met, NULL, NULL);
438 if(ret == META_DATA_FETCHING)
440 self_set_cover_fetching(self);
441 }else if (ret == META_DATA_AVAILABLE) {
442 if (met->content_type == META_DATA_CONTENT_RAW) {
443 self_set_cover_raw(self, met->content, met->size,met->md5sum);
445 self_set_cover_na(self);
447 } else if (ret == META_DATA_INVALID_QUERY) {
448 self_set_cover_invalid_query(self);
450 self_set_cover_na(self);
460 update_cover_from_song_delayed(self, mpd_Song *song)
462 if(self->_priv->song)
463 mpd_freeSong(self->_priv->song);
465 gtk_widget_set_size_request(GTK_WIDGET(self), self->size, self->size);
466 self->_priv->song = mpd_songDup(song);
467 /* hack to make it load when it gets visible */
468 self->_priv->expose_id = g_signal_connect(G_OBJECT(self), "expose-event", G_CALLBACK(self_expose_event) , NULL);
473 meta_callback(GmpcMetaWatcher *gmv, mpd_Song *song, MetaDataType type, MetaDataResult ret, MetaData *met,gpointer data)
476 if(!song || !self || !self->_priv || !self->_priv->song)
482 if(self->image_type != type)
485 // Compare if callback is about 'our' song.
486 // TODO: optimize, by keeping checksum of current song around?
488 char *ck_a = mpd_song_checksum_type(self->_priv->song, self->image_type);
489 char *ck_b = mpd_song_checksum_type(song, self->image_type);
490 if(ck_a == NULL || ck_b == NULL || strcmp(ck_a, ck_b) != 0) {
500 * If mpd is stopped before the result is back, set the cover to na, and ignore the result
502 if(self->connection && mpd_player_get_state(self->connection) == MPD_PLAYER_STOP)
504 self_set_cover_na(self);
508 if(ret == META_DATA_AVAILABLE) {
509 if (met->content_type == META_DATA_CONTENT_RAW) {
510 self_set_cover_raw(self, met->content, met->size,met->md5sum);
512 self_set_cover_na(self);
513 g_log(LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Method not implemented: %i", met->content_type);
515 } else if (ret == META_DATA_FETCHING) {
516 self_set_cover_fetching(self);
517 } else if (ret == META_DATA_INVALID_QUERY) {
518 self_set_cover_invalid_query(self);
520 self_set_cover_na(self);
528 set_cover_invalid_query(self)
531 GError *error = NULL;
532 GdkPixbuf *pb2 = NULL;
535 if(self->_priv->state == STATE_INVALID_QUERY) {
538 self->_priv->state = STATE_INVALID_QUERY;
539 gmpc_meta_image_async_clear_now(GMPC_META_IMAGE_ASYNC(self->_priv->tooltip_image));
541 if(self->_priv->image_url)
543 q_free(self->_priv->image_url);
544 self->_priv->image_url = NULL;
548 gtk_widget_hide(GTK_WIDGET(self));
552 if(cfg_get_single_value_as_int_with_default(config, "metaimage", "addcase",TRUE) && self->image_type == META_ALBUM_ART){
553 pb2 = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "stylized-invalid-tags-cover", self->size, 0,&error);
556 g_log(LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Following error loading stylized-no-cover: %s", error->message);
562 pb2 = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), self->no_cover_icon, self->size, 0,&error);
564 g_log(LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Following error loading stylized-no-cover: %s", error->message);
573 gtk_widget_set_size_request(GTK_WIDGET(self), self->size, self->size);
575 // gtk_widget_set_size_request(GTK_WIDGET(self), gdk_pixbuf_get_width(pb2), gdk_pixbuf_get_height(pb2));
577 gmpc_meta_image_async_set_pixbuf(GMPC_META_IMAGE_ASYNC(self->_priv->image), pb2);
580 /* If failed to load an image, clear it */
581 gmpc_meta_image_async_clear_now(GMPC_META_IMAGE_ASYNC(self->_priv->image));
589 GError *error = NULL;
590 GdkPixbuf *pb2 = NULL;
593 if(self->_priv->state == STATE_NA) {
596 self->_priv->state = STATE_NA;
597 gmpc_meta_image_async_clear_now(GMPC_META_IMAGE_ASYNC(self->_priv->tooltip_image));
599 if(self->_priv->image_url)
601 q_free(self->_priv->image_url);
602 self->_priv->image_url = NULL;
606 gtk_widget_hide(GTK_WIDGET(self));
610 if(cfg_get_single_value_as_int_with_default(config, "metaimage", "addcase",TRUE) && self->image_type == META_ALBUM_ART){
611 pb2 = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "stylized-no-cover", self->size, 0,&error);
614 g_log(LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Following error loading stylized-no-cover: %s", error->message);
620 pb2 = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), self->no_cover_icon, self->size, 0,&error);
622 g_log(LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Following error loading stylized-no-cover: %s", error->message);
631 gtk_widget_set_size_request(GTK_WIDGET(self), self->size, self->size);
633 // gtk_widget_set_size_request(GTK_WIDGET(self), gdk_pixbuf_get_width(pb2), gdk_pixbuf_get_height(pb2));
635 gmpc_meta_image_async_set_pixbuf(GMPC_META_IMAGE_ASYNC(self->_priv->image), pb2);
638 /* If failed to load an image, clear it */
639 gmpc_meta_image_async_clear_now(GMPC_META_IMAGE_ASYNC(self->_priv->image));
644 set_cover_fetching(self)
647 GError *error = NULL;
648 GdkPixbuf *pb2 = NULL;
650 if(self->_priv->state == STATE_FETCHING) {
653 self->_priv->state = STATE_FETCHING;
654 gmpc_meta_image_async_clear_now(GMPC_META_IMAGE_ASYNC(self->_priv->tooltip_image));
655 if(self->_priv->image_url)
657 q_free(self->_priv->image_url);
658 self->_priv->image_url = NULL;
662 gtk_widget_hide(GTK_WIDGET(self));
666 if(cfg_get_single_value_as_int_with_default(config, "metaimage", "addcase",TRUE) && self->image_type == META_ALBUM_ART){
667 pb2 = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "stylized-fetching-cover", self->size, 0,&error);
669 g_log(LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Following error loading stylized-no-cover: %s", error->message);
676 pb2 = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), self->loading_cover_icon, self->size, 0,&error);
678 g_log(LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Following error loading stylized-no-cover: %s", error->message);
687 gtk_widget_set_size_request(GTK_WIDGET(self), self->size, self->size);
689 gmpc_meta_image_async_clear_now(GMPC_META_IMAGE_ASYNC(self->_priv->image));
693 gmpc_meta_image_async_set_pixbuf(GMPC_META_IMAGE_ASYNC(self->_priv->image), pb2);
696 /* If failed to load an image, clear it */
697 gmpc_meta_image_async_clear_now(GMPC_META_IMAGE_ASYNC(self->_priv->image));
703 set_cover_raw(self, unsigned char *data, unsigned int size, unsigned char *md5sum)
705 self->_priv->state = STATE_IMAGE;
706 gmpc_meta_image_async_set_from_raw(GMPC_META_IMAGE_ASYNC(self->_priv->image),data, size, self->size,
707 ((cfg_get_single_value_as_int_with_default(config, "metaimage", "addcase",TRUE) && self->image_type == META_ALBUM_ART))?
708 GMPC_MODIFICATION_TYPE_CASING:GMPC_MODIFICATION_TYPE_BORDER,
712 gtk_widget_set_size_request(GTK_WIDGET(self), self->size, self->size);
715 if(gtk_widget_get_has_tooltip(GTK_WIDGET(self)))
717 gmpc_meta_image_async_set_from_raw(GMPC_META_IMAGE_ASYNC(self->_priv->tooltip_image),
727 set_is_visible(self, gboolean is_visible)
729 self->is_visible = is_visible;
734 self_update_cover(self,self->connection, MPD_CST_STATE, NULL);
737 gtk_widget_hide(GTK_WIDGET(self));
745 if(self->_priv->song)
748 MetaData *met = NULL;
750 ret = meta_data_get_path(self->_priv->song, self->image_type|META_QUERY_NO_CACHE, &met, NULL, NULL);
751 if(ret == META_DATA_FETCHING)
753 self_set_cover_fetching(self);
754 }else if (ret == META_DATA_AVAILABLE) {
755 if (met->content_type == META_DATA_CONTENT_RAW) {
756 self_set_cover_raw(self, met->content, met->size,met->md5sum);
758 g_log(LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Not implemented");
759 self_set_cover_na(self);
761 } else if (ret == META_DATA_INVALID_QUERY) {
762 self_set_cover_invalid_query(self);
764 self_set_cover_na(self);
773 signal last NONE (POINTER)
774 void menu_populate_client(self, GtkMenu *menu)
781 menu_populate_callback(self,GdkEventButton *event, gpointer data)
783 if(self->_priv->song && event->button == 3 && self->_priv->state != STATE_INVALID_QUERY)
785 GtkWidget *menu = gtk_menu_new();
786 GtkWidget *item = NULL;
788 self_menu_populate_client(self,GTK_MENU(menu));
790 item = gtk_image_menu_item_new_with_label(_("Refetch"));
791 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), gtk_image_new_from_stock(GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU));
792 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(self_query_refetch),self);
793 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
795 item = gtk_image_menu_item_new_with_label(_("Select file"));
796 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU));
797 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(self_select_file),self);
798 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
800 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLEAR, NULL);
801 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(self_clear_entry),self);
802 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
804 item = gtk_image_menu_item_new_with_label(_("Metadata selector"));
805 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), gtk_image_new_from_stock(GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU));
806 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(self_select_metadata_editor),self);
807 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
809 gtk_widget_show_all(menu);
810 gtk_menu_popup(GTK_MENU(menu), NULL, NULL,NULL, NULL, event->button, event->time);
813 else if (self->_priv->state == STATE_INVALID_QUERY)
815 playlist3_show_error_message(_("Insufficient tags available to get image."), ERROR_WARNING);
825 meta_data_clear_entry(self->_priv->song, self->image_type);
829 select_metadata_editor(self)
831 gmpc_meta_data_edit_window_new(self->_priv->song,self->image_type);
839 mpd_Song *song = mpd_songDup(self->_priv->song);
840 GtkFileFilter *gff = gtk_file_filter_new();
841 GtkWidget *fcd = gtk_file_chooser_dialog_new(_("Select File"),NULL,
842 GTK_FILE_CHOOSER_ACTION_OPEN,
843 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
844 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
846 gtk_file_filter_set_name(gff, _("Images"));
847 gtk_file_filter_add_pixbuf_formats(gff);
848 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fcd), gff);
850 gff = gtk_file_filter_new();
851 gtk_file_filter_set_name(gff, _("All"));
852 gtk_file_filter_add_pattern(gff, "*");
853 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fcd), gff);
855 gtk_widget_show_all(fcd);
857 p = cfg_get_single_value_as_string(config, "MetaData", "image-file-chooser");
859 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(fcd), p);
862 switch(gtk_dialog_run(GTK_DIALOG(fcd)))
864 case GTK_RESPONSE_ACCEPT:
866 gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fcd));
868 /* Create MetaData object */
869 MetaData* met = meta_data_new();
870 met->type = self->image_type;
871 met->plugin_name = g_strdup("User set");
872 met->content_type = META_DATA_CONTENT_URI;
873 meta_data_set_uri(met, filename);
875 meta_data_set_entry(self->_priv->song, met);
876 /* free Metadata object */
879 cfg_set_single_value_as_string(config, "MetaData", "image-file-chooser", filename);
886 gtk_widget_destroy(fcd);
894 gmpc_meta_image_async_clear_now(GMPC_META_IMAGE_ASYNC(self->_priv->image));
895 switch(self->_priv->state)
898 self->_priv->state = STATE_EMPTY;
899 self_set_cover_na(self);
902 self->_priv->state = STATE_EMPTY;
903 self_set_cover_fetching(self);
907 self_set_dirty(self);
908 if(self->_priv->song != NULL) {
910 mpd_Song *song = self->_priv->song;
911 self->_priv->song = NULL;
913 self_update_cover_from_song(self,song);
917 self_set_cover_na(self);
927 public void set_dirty(self)
929 self->_priv->state = STATE_EMPTY;