From e93a9b2d9677b7ef3142a03f370ef545659b5773 Mon Sep 17 00:00:00 2001 From: Alexey Yakovenko Date: Wed, 16 Oct 2013 22:43:52 +0200 Subject: gtkui: several fixes/improvements in playlist cover rendering --- plugins/artwork/artwork.c | 2 +- plugins/artwork/artwork.h | 5 ++++ plugins/gtkui/coverart.c | 56 +++++++++++++++++++++++++++++++++++++++++---- plugins/gtkui/coverart.h | 5 ++++ plugins/gtkui/ddblistview.c | 3 +++ plugins/gtkui/plcommon.c | 17 +++++++++----- 6 files changed, 76 insertions(+), 12 deletions(-) (limited to 'plugins') diff --git a/plugins/artwork/artwork.c b/plugins/artwork/artwork.c index cf4b25e0..23d05886 100644 --- a/plugins/artwork/artwork.c +++ b/plugins/artwork/artwork.c @@ -90,7 +90,6 @@ static const char *get_default_cover (void) { int make_cache_dir_path (char *path, int size, const char *artist, int img_size) { const char *cache = getenv ("XDG_CACHE_HOME"); - int sz; if (img_size == -1) { @@ -1484,4 +1483,5 @@ static DB_artwork_plugin_t plugin = { .reset = artwork_reset, .get_default_cover = get_default_cover, .get_album_art_sync = get_album_art_sync, + .make_cache_path = make_cache_path, }; diff --git a/plugins/artwork/artwork.h b/plugins/artwork/artwork.h index 1c60475c..117e263d 100644 --- a/plugins/artwork/artwork.h +++ b/plugins/artwork/artwork.h @@ -10,6 +10,8 @@ typedef void (*artwork_callback) (const char *fname, const char *artist, const c typedef struct { DB_misc_t plugin; // returns filename of cached image, or NULL + // negative size has special meanings: + // -1: return default cover if not available (otherwise NULL will be returned) char* (*get_album_art) (const char *fname, const char *artist, const char *album, int size, artwork_callback callback, void *user_data); // this has to be called to clear queue on exit, before caller terminates @@ -19,6 +21,9 @@ typedef struct { // synchronously get filename char* (*get_album_art_sync) (const char *fname, const char *artist, const char *album, int size); + + // creates full path string for cache storage + void (*make_cache_path) (char *path, int size, const char *album, const char *artist, int img_size); } DB_artwork_plugin_t; #endif /*__ARTWORK_H*/ diff --git a/plugins/gtkui/coverart.c b/plugins/gtkui/coverart.c index c3d93b8d..0e08d180 100644 --- a/plugins/gtkui/coverart.c +++ b/plugins/gtkui/coverart.c @@ -65,15 +65,19 @@ static void queue_add (const char *fname, int width, void (*callback) (void *user_data), void *user_data) { deadbeef->mutex_lock (mutex); load_query_t *q; - for (q = queue; q; q = q->next) { - if (!strcmp (q->fname, fname) && width == q->width) { - deadbeef->mutex_unlock (mutex); - return; // dupe + if (fname) { + for (q = queue; q; q = q->next) { + if (!strcmp (q->fname, fname) && width == q->width) { + deadbeef->mutex_unlock (mutex); + return; // dupe + } } } q = malloc (sizeof (load_query_t)); memset (q, 0, sizeof (load_query_t)); - q->fname = strdup (fname); + if (fname) { + q->fname = strdup (fname); + } q->width = width; q->callback = callback; q->user_data = user_data; @@ -138,6 +142,14 @@ loading_thread (void *none) { } } deadbeef->mutex_unlock (mutex); + if (!queue->fname) { + if (queue->callback) { + queue->callback (queue->user_data); + } + queue_pop (); + continue; + } + if (cache_min == -1) { trace ("coverart pixbuf cache overflow, waiting...\n"); usleep (500000); @@ -250,12 +262,46 @@ get_pixbuf (const char *fname, int width, void (*callback)(void *user_data), voi return NULL; } +void +queue_cover_callback (void (*callback)(void *user_data), void *user_data) { + queue_add (NULL, -1, callback, user_data); +} + GdkPixbuf * get_cover_art_callb (const char *fname, const char *artist, const char *album, int width, void (*callback) (void *user_data), void *user_data) { if (!coverart_plugin) { return NULL; } + + if (width == -1) { + char path[2048]; + coverart_plugin->make_cache_path (path, sizeof (path), album, artist, -1); + deadbeef->mutex_lock (mutex); + int i_largest = -1; + int size_largest = -1; + for (int i = 0; i < CACHE_SIZE; i++) { + if (!cache[i].pixbuf) { + continue; + } + if (!strcmp (cache[i].fname, path)) { + gettimeofday (&cache[i].tm, NULL); + if (cache[i].width > size_largest) { + size_largest = cache[i].width; + i_largest = i; + } + } + } + if (i_largest != -1) { + GdkPixbuf *pb = cache[i_largest].pixbuf; + g_object_ref (pb); + deadbeef->mutex_unlock (mutex); + return pb; + } + deadbeef->mutex_unlock (mutex); + return NULL; + } + cover_avail_info_t *dt = malloc (sizeof (cover_avail_info_t)); dt->width = width; dt->callback = callback; diff --git a/plugins/gtkui/coverart.h b/plugins/gtkui/coverart.h index 5f6bc2ef..d3658caf 100644 --- a/plugins/gtkui/coverart.h +++ b/plugins/gtkui/coverart.h @@ -40,5 +40,10 @@ cover_art_init (void); void cover_art_free (void); +// simply inserts callback point into queue +// the callback will be called when the loading queue reaches this request +void +queue_cover_callback (void (*callback)(void *user_data), void *user_data); + #endif diff --git a/plugins/gtkui/ddblistview.c b/plugins/gtkui/ddblistview.c index e3027654..103971fb 100644 --- a/plugins/gtkui/ddblistview.c +++ b/plugins/gtkui/ddblistview.c @@ -662,8 +662,11 @@ ddb_listview_list_pickpoint_y (DdbListview *listview, int y, DdbListviewGroup ** return -1; } +int render_idx = 0; + void ddb_listview_list_render (DdbListview *listview, cairo_t *cr, int x, int y, int w, int h) { + render_idx = 0; cairo_set_line_width (cr, 1); cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE); GtkWidget *treeview = theme_treeview; diff --git a/plugins/gtkui/plcommon.c b/plugins/gtkui/plcommon.c index 041593e0..b509cbd7 100644 --- a/plugins/gtkui/plcommon.c +++ b/plugins/gtkui/plcommon.c @@ -138,7 +138,10 @@ deferred_cover_load_cb (void *ctx) { printf ("queue redraw for cover size %d\n", lv->new_cover_size); last = 1; } - GdkPixbuf *pixbuf = get_cover_art_callb (deadbeef->pl_find_meta (((DB_playItem_t *)group_it), ":URI"), artist, album, lv->new_cover_size, last ? redraw_playlist : NULL, lv); + GdkPixbuf *pixbuf = get_cover_art_callb (deadbeef->pl_find_meta (((DB_playItem_t *)group_it), ":URI"), artist, album, lv->new_cover_size, NULL, NULL); + if (last) { + queue_cover_callback (redraw_playlist, lv); + } if (pixbuf) { g_object_unref (pixbuf); } @@ -209,7 +212,6 @@ void draw_column_data (DdbListview *listview, cairo_t *cr, DdbListviewIter it, D } } int art_width = listview->cover_size; - float art_scale = (float)real_art_width / art_width; int art_y = y; // dest y int art_h = height; int sy; // source y @@ -224,8 +226,10 @@ void draw_column_data (DdbListview *listview, cairo_t *cr, DdbListviewIter it, D int h = cwidth - group_y; h = min (height, art_h); - GdkPixbuf *pixbuf = get_cover_art_callb (deadbeef->pl_find_meta (((DB_playItem_t *)group_it), ":URI"), artist, album, art_width, redraw_playlist_single, listview); + GdkPixbuf *pixbuf = get_cover_art_callb (deadbeef->pl_find_meta (((DB_playItem_t *)group_it), ":URI"), artist, album, real_art_width == art_width ? art_width : -1, redraw_playlist_single, listview); if (pixbuf) { + art_width = gdk_pixbuf_get_width (pixbuf); + float art_scale = (float)real_art_width / art_width; int pw = real_art_width; int ph; if (group_pinned == 1 && gtkui_groups_pinned) { @@ -240,9 +244,9 @@ void draw_column_data (DdbListview *listview, cairo_t *cr, DdbListviewIter it, D cairo_save (cr); if (group_pinned == 1 && gtkui_groups_pinned) { int ph_real = gdk_pixbuf_get_height (pixbuf); - if (grp_next_y <= ph_real + listview->grouptitle_height) { - cairo_rectangle (cr, x + ART_PADDING_HORZ, grp_next_y - ph_real, pw, ph); - cairo_translate (cr, (x + ART_PADDING_HORZ)-0, grp_next_y - ph_real); + if (grp_next_y <= ph_real * art_scale + listview->grouptitle_height) { + cairo_rectangle (cr, x + ART_PADDING_HORZ, grp_next_y - ph_real * art_scale, pw, ph); + cairo_translate (cr, (x + ART_PADDING_HORZ)-0, grp_next_y - ph_real * art_scale); } else { cairo_rectangle (cr, x + ART_PADDING_HORZ, listview->grouptitle_height, pw, ph); @@ -261,6 +265,7 @@ void draw_column_data (DdbListview *listview, cairo_t *cr, DdbListviewIter it, D cairo_fill (cr); cairo_restore (cr); } + g_object_unref (pixbuf); } } } -- cgit v1.2.3