summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <waker@users.sourceforge.net>2013-10-15 21:25:47 +0200
committerGravatar Alexey Yakovenko <waker@users.sourceforge.net>2013-10-15 21:25:47 +0200
commit226bd9637fdd4e2f7b40fd8919bde892b42f0065 (patch)
treea031708722d190df6285a604feac9a4d4f0b0346 /plugins
parent8ecacd2c3bc00fe784e14dbbfd552d616d5ac108 (diff)
gtkui: flicker-free cover art rendering
Diffstat (limited to 'plugins')
-rw-r--r--plugins/artwork/artwork.c2
-rw-r--r--plugins/gtkui/ddblistview.c14
-rw-r--r--plugins/gtkui/ddblistview.h17
-rw-r--r--plugins/gtkui/plcommon.c142
4 files changed, 128 insertions, 47 deletions
diff --git a/plugins/artwork/artwork.c b/plugins/artwork/artwork.c
index 60f1f000..cf4b25e0 100644
--- a/plugins/artwork/artwork.c
+++ b/plugins/artwork/artwork.c
@@ -875,7 +875,7 @@ fetcher_thread (void *none)
continue;
}
if (*mime_end != 3) {
- trace ("artwork: picture type=%d, skipped: %s\n", *mime_end);
+ trace ("artwork: picture type=%d\n", *mime_end);
continue;
}
trace ("artwork: mime-type=%s, picture type: %d\n", data, *mime_end);
diff --git a/plugins/gtkui/ddblistview.c b/plugins/gtkui/ddblistview.c
index 9f9f53b3..8f10e4b0 100644
--- a/plugins/gtkui/ddblistview.c
+++ b/plugins/gtkui/ddblistview.c
@@ -66,14 +66,6 @@ struct _DdbListviewColumn {
};
typedef struct _DdbListviewColumn DdbListviewColumn;
-struct _DdbListviewGroup {
- DdbListviewIter head;
- int32_t height;
- int32_t num_items;
- struct _DdbListviewGroup *next;
-};
-typedef struct _DdbListviewGroup DdbListviewGroup;
-
static void ddb_listview_class_init(DdbListviewClass *klass);
static void ddb_listview_init(DdbListview *listview);
//static void ddb_listview_size_request(GtkWidget *widget, GtkRequisition *requisition);
@@ -335,6 +327,10 @@ ddb_listview_init(DdbListview *listview)
listview->area_selection_start = 0;
listview->area_selection_end = 0;
+ listview->cover_size = -1;
+ listview->new_cover_size = -1;
+ listview->cover_refresh_timeout_id = 0;
+
GtkWidget *hbox;
GtkWidget *vbox;
@@ -596,7 +592,7 @@ ddb_listview_list_configure_event (GtkWidget *widget,
return FALSE;
}
-static void
+void
ddb_listview_groupcheck (DdbListview *listview) {
int idx = listview->binding->modification_idx ();
if (idx != listview->groups_build_idx) {
diff --git a/plugins/gtkui/ddblistview.h b/plugins/gtkui/ddblistview.h
index 84627209..3e54bc07 100644
--- a/plugins/gtkui/ddblistview.h
+++ b/plugins/gtkui/ddblistview.h
@@ -43,6 +43,15 @@ typedef struct _DdbListviewClass DdbListviewClass;
typedef void * DdbListviewIter;
typedef void * DdbPlaylistHandle;
+
+struct _DdbListviewGroup {
+ DdbListviewIter head;
+ int32_t height;
+ int32_t num_items;
+ struct _DdbListviewGroup *next;
+};
+
+typedef struct _DdbListviewGroup DdbListviewGroup;
//typedef void * DdbListviewColIter;
typedef struct {
@@ -161,6 +170,11 @@ struct _DdbListview {
// drawing contexts
drawctx_t listctx;
drawctx_t hdrctx;
+
+ // cover art size
+ int cover_size;
+ int new_cover_size;
+ guint cover_refresh_timeout_id;
};
struct _DdbListviewClass {
@@ -270,6 +284,9 @@ ddb_listview_lock_columns (DdbListview *lv, gboolean lock);
int
ddb_listview_get_row_pos (DdbListview *listview, int row_idx);
+void
+ddb_listview_groupcheck (DdbListview *listview);
+
G_END_DECLS
#endif // __DDBLISTVIEW_H
diff --git a/plugins/gtkui/plcommon.c b/plugins/gtkui/plcommon.c
index 84338cc5..20c2ea5c 100644
--- a/plugins/gtkui/plcommon.c
+++ b/plugins/gtkui/plcommon.c
@@ -74,21 +74,70 @@ rewrite_column_config (DdbListview *listview, const char *name) {
}
static gboolean
-redraw_playlist_cb (gpointer dt) {
- void main_refresh (void);
- main_refresh ();
+redraw_playlist_cb (gpointer user_data) {
+ DDB_LISTVIEW(user_data)->cover_size = DDB_LISTVIEW(user_data)->new_cover_size;
+ gtk_widget_queue_draw (GTK_WIDGET(user_data));
return FALSE;
}
static void
redraw_playlist (void *user_data) {
- g_idle_add (redraw_playlist_cb, NULL);
+ g_idle_add (redraw_playlist_cb, user_data);
}
#define ART_PADDING_HORZ 8
#define ART_PADDING_VERT 0
+static gboolean
+deferred_cover_load_cb (void *ctx) {
+ DdbListview *lv = ctx;
+ lv->cover_refresh_timeout_id = 0;
+ deadbeef->pl_lock ();
+ ddb_listview_groupcheck (lv);
+ // find 1st group
+ DdbListviewGroup *grp = lv->groups;
+ int idx = 0;
+ int abs_idx = 0;
+ int grp_y = 0;
+ while (grp && grp_y + grp->height < lv->scrollpos) {
+ grp_y += grp->height;
+ idx += grp->num_items + 1;
+ abs_idx += grp->num_items;
+ grp = grp->next;
+ }
+ GtkAllocation a;
+ gtk_widget_get_allocation (GTK_WIDGET (lv), &a);
+ while (grp && grp_y < a.height + lv->scrollpos) {
+ // render title
+ DdbListviewIter group_it = grp->head;
+ int grpheight = grp->height;
+ if (grp_y >= a.height + lv->scrollpos) {
+ break;
+ }
+ const char *album = deadbeef->pl_find_meta (group_it, "album");
+ const char *artist = deadbeef->pl_find_meta (group_it, "artist");
+ if (!album || !*album) {
+ album = deadbeef->pl_find_meta (group_it, "title");
+ }
+
+ grp_y += grpheight;
+ grp = grp->next;
+ int last = 0;
+ if (!grp || grp_y >= a.height + lv->scrollpos) {
+ 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);
+ if (pixbuf) {
+ g_object_unref (pixbuf);
+ }
+ }
+ deadbeef->pl_unlock ();
+
+ return FALSE;
+}
+
void draw_column_data (DdbListview *listview, cairo_t *cr, DdbListviewIter it, DdbListviewIter group_it, int column, int group_y, int x, int y, int width, int height) {
const char *ctitle;
int cwidth;
@@ -126,43 +175,62 @@ void draw_column_data (DdbListview *listview, cairo_t *cr, DdbListviewIter it, D
cairo_rectangle (cr, x, y, width, height);
cairo_fill (cr);
}
- int art_width = width - ART_PADDING_HORZ * 2;
- int art_y = y; // dest y
- int art_h = height;
- int sy; // source y
- if (group_y < ART_PADDING_VERT) {
- art_y = y - group_y + ART_PADDING_VERT;
- art_h = height - (art_y - y);
- sy = group_y;
- }
- else {
- sy = group_y - ART_PADDING_VERT;
- }
- if (art_width > 0) {
- if (group_it) {
- int h = cwidth - group_y;
- h = min (height, art_h);
- const char *album = deadbeef->pl_find_meta (group_it, "album");
- const char *artist = deadbeef->pl_find_meta (group_it, "artist");
- if (!album || !*album) {
- album = deadbeef->pl_find_meta (group_it, "title");
+ int real_art_width = width - ART_PADDING_HORZ * 2;
+ if (real_art_width > 0 && group_it) {
+ const char *album = deadbeef->pl_find_meta (group_it, "album");
+ const char *artist = deadbeef->pl_find_meta (group_it, "artist");
+ if (!album || !*album) {
+ album = deadbeef->pl_find_meta (group_it, "title");
+ }
+ if (listview->new_cover_size != real_art_width) {
+ listview->new_cover_size = real_art_width;
+ if (listview->cover_refresh_timeout_id) {
+ g_source_remove (listview->cover_refresh_timeout_id);
+ listview->cover_refresh_timeout_id = 0;
+ }
+ if (listview->cover_size == -1) {
+ listview->cover_size = real_art_width;
}
- GdkPixbuf *pixbuf = get_cover_art_callb (deadbeef->pl_find_meta (((DB_playItem_t *)group_it), ":URI"), artist, album, art_width, redraw_playlist, NULL);
- if (pixbuf) {
- int pw = gdk_pixbuf_get_width (pixbuf);
- int ph = gdk_pixbuf_get_height (pixbuf);
- if (sy < ph)
- {
- pw = min (art_width, pw);
- ph -= sy;
- ph = min (ph, h);
- gdk_cairo_set_source_pixbuf (cr, pixbuf, (x + ART_PADDING_HORZ)-0, (art_y)-sy);
- cairo_rectangle (cr, x + ART_PADDING_HORZ, art_y, pw, ph);
- cairo_fill (cr);
+ else {
+ if (!listview->cover_refresh_timeout_id) {
+ listview->cover_refresh_timeout_id = g_timeout_add (1000, deferred_cover_load_cb, listview);
}
- g_object_unref (pixbuf);
}
}
+ 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
+ if (group_y < ART_PADDING_VERT) {
+ art_y = y - group_y + ART_PADDING_VERT;
+ art_h = height - (art_y - y);
+ sy = group_y;
+ }
+ else {
+ sy = group_y - ART_PADDING_VERT;
+ }
+ 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, NULL, NULL);
+ if (pixbuf) {
+ int pw = real_art_width;
+ int ph = pw;
+ if (sy < ph)
+ {
+ ph -= sy;
+ ph = min (ph, h);
+ cairo_rectangle (cr, x + ART_PADDING_HORZ, art_y, pw, ph);
+ cairo_save (cr);
+ cairo_translate (cr, ((x + ART_PADDING_HORZ)-0), ((art_y)-sy));
+ cairo_scale (cr, (float)art_scale, (float)art_scale);
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+ cairo_pattern_set_filter (cairo_get_source(cr), art_width == real_art_width ? CAIRO_FILTER_GAUSSIAN : CAIRO_FILTER_FAST);
+ cairo_fill (cr);
+ cairo_restore (cr);
+ }
+ g_object_unref (pixbuf);
+ }
}
}
else if (it && it == playing_track && cinf->id == DB_COLUMN_PLAYING) {