diff --git a/CHANGELOG b/CHANGELOG index 19d42066..c920f054 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,5 @@ 6.4.16: +- Fix blurry album art - Reduce time spent polling for album art - Split album art code into a new file - Fix PKGBUILD dependencies diff --git a/gui/artwork.c b/gui/artwork.c index 7fd92952..ec38999c 100644 --- a/gui/artwork.c +++ b/gui/artwork.c @@ -8,42 +8,69 @@ static struct album *__artwork_cur_album = NULL; static unsigned int __artwork_timeo_id = 0; -static GdkPixbuf *__artwork_get_pixbuf(struct track *track) +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; - int height; if (!path) return NULL; - height = gui_builder_widget_height("o_position") + - gui_builder_widget_height("o_tags"); - pix = gdk_pixbuf_new_from_file_at_scale(path, -1, height, true, NULL); - g_free(path); + pix = gdk_pixbuf_new_from_file(path, NULL); + if (!pix) + return NULL; + surface = __artwork_scale_pixbuf(pix); - return 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(); - GdkPixbuf *pix; + cairo_surface_t *surface; if (!track || track->tr_album == __artwork_cur_album) return true; - pix = __artwork_get_pixbuf(track); - if (pix) { - gtk_image_set_from_pixbuf(cover, pix); - g_object_unref(G_OBJECT(pix)); + 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), pix != NULL); - __artwork_cur_album = pix ? track->tr_album : NULL; - return (pix != NULL); + 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)