/* * Copyright 2016 (c) Anna Schumaker. */ #include #include #include #define ARTWORK_PREVIEW_SIZE 150 static struct album *__artwork_cur_album = NULL; static unsigned int __artwork_timeo_id = 0; static cairo_surface_t *__artwork_scale_pixbuf(GdkPixbuf *pix) { int old_h = gdk_pixbuf_get_height(pix); int old_w = gdk_pixbuf_get_width(pix); int new_h = gui_builder_widget_height("o_position") + gui_builder_widget_height("o_tags"); int new_w = (old_w * new_h) / old_h; int scale = gtk_widget_get_scale_factor(gui_builder_widget("o_cover")); cairo_surface_t *orig = gdk_cairo_surface_create_from_pixbuf(pix, 0, NULL); cairo_content_t content = cairo_surface_get_content(orig); cairo_surface_t *new = cairo_surface_create_similar(orig, content, new_w, new_h); cairo_t *cairo = cairo_create(new); cairo_scale(cairo, (double)(scale * new_w) / old_w, (double)(scale * new_h) / old_h); cairo_set_source_surface(cairo, orig, 0, 0); cairo_paint(cairo); cairo_destroy(cairo); cairo_surface_destroy(orig); return new; } static cairo_surface_t *__artwork_get_surface(struct track *track) { gchar *path = album_artwork_path(track->tr_album); cairo_surface_t *surface; GdkPixbuf *pix; if (!path) return NULL; pix = gdk_pixbuf_new_from_file(path, NULL); if (!pix) return NULL; surface = __artwork_scale_pixbuf(pix); g_object_unref(G_OBJECT(pix)); g_free(path); return surface; } static bool __artwork_set_pixbuf(void) { GtkImage *cover = GTK_IMAGE(gui_builder_widget("o_cover")); struct track *track = audio_cur_track(); cairo_surface_t *surface; if (!track || track->tr_album == __artwork_cur_album) return true; surface = __artwork_get_surface(track); if (surface) { gtk_image_set_from_surface(cover, surface); cairo_surface_destroy(surface); } else gtk_image_set_from_icon_name(cover, "image-missing", GTK_ICON_SIZE_DIALOG); gtk_widget_set_sensitive(GTK_WIDGET(cover), surface != NULL); __artwork_cur_album = surface ? track->tr_album : NULL; return (surface != NULL); } static gboolean __artwork_timeout(gpointer data) { if (__artwork_set_pixbuf()) { __artwork_timeo_id = 0; return G_SOURCE_REMOVE; } return G_SOURCE_CONTINUE; } void gui_artwork_set_cover(void) { if (!__artwork_set_pixbuf() && __artwork_timeo_id == 0) __artwork_timeo_id = g_timeout_add(2000, __artwork_timeout, NULL); } void __artwork_update_preview(GtkFileChooser *chooser, gpointer data) { GtkWidget *preview = gtk_file_chooser_get_preview_widget(chooser); gchar *path = gtk_file_chooser_get_preview_filename(chooser); GdkPixbuf *pix = gdk_pixbuf_new_from_file(path, NULL); unsigned int old_w, scale; cairo_surface_t *surface; if (pix) { old_w = gdk_pixbuf_get_width(pix); scale = old_w / ARTWORK_PREVIEW_SIZE; surface = gdk_cairo_surface_create_from_pixbuf(pix, scale, NULL); if (surface) { gtk_image_set_from_surface(GTK_IMAGE(preview), surface); cairo_surface_destroy(surface); } } g_free(path); } void __artwork_select_cover(GtkButton *button) { struct track *track = audio_cur_track(); GtkFileFilter *filter; GtkWidget *dialog; GtkWidget *preview; gchar *path; if (!track) return; filter = gtk_file_filter_new(); preview = gtk_image_new_from_icon_name("", GTK_ICON_SIZE_DIALOG); dialog = gtk_file_chooser_dialog_new("Choose an image", GTK_WINDOW(gui_builder_widget("o_window")), GTK_FILE_CHOOSER_ACTION_OPEN, _("_Cancel"), GTK_RESPONSE_CANCEL, _("_Open"), GTK_RESPONSE_ACCEPT, NULL); gtk_file_filter_add_mime_type(filter, "image/*"); gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(dialog), true); gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(dialog), preview); gtk_file_chooser_set_use_preview_label(GTK_FILE_CHOOSER(dialog), false); g_signal_connect(dialog, "update-preview", (GCallback)__artwork_update_preview, NULL); if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); album_artwork_import(track->tr_album, path); __artwork_cur_album = NULL; gui_artwork_set_cover(); g_free(path); } gtk_widget_destroy(dialog); }