diff options
author | waker <wakeroid@gmail.com> | 2011-06-22 21:55:47 +0200 |
---|---|---|
committer | waker <wakeroid@gmail.com> | 2011-06-22 21:55:47 +0200 |
commit | f2870a342dd922325aef7b1af3e6db238055593d (patch) | |
tree | e5bba09dba29823ad64a89e337a507139ef9504b | |
parent | bb81b0d2ad0192e241a3c4b6f57e6bc2a28de781 (diff) |
added coverart widget
-rw-r--r-- | plugins/gtkui/coverart.c | 47 | ||||
-rw-r--r-- | plugins/gtkui/coverart.h | 4 | ||||
-rw-r--r-- | plugins/gtkui/gtkui.c | 1 | ||||
-rw-r--r-- | plugins/gtkui/widgets.c | 95 | ||||
-rw-r--r-- | plugins/gtkui/widgets.h | 3 |
5 files changed, 141 insertions, 9 deletions
diff --git a/plugins/gtkui/coverart.c b/plugins/gtkui/coverart.c index 4118aa66..20ad87d7 100644 --- a/plugins/gtkui/coverart.c +++ b/plugins/gtkui/coverart.c @@ -45,6 +45,8 @@ typedef struct { typedef struct load_query_s { char *fname; int width; + void (*callback) (void *user_data); + void *user_data; struct load_query_s *next; } load_query_t; @@ -57,7 +59,7 @@ load_query_t *queue; load_query_t *tail; static void -queue_add (const char *fname, int width) { +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) { @@ -70,6 +72,8 @@ queue_add (const char *fname, int width) { memset (q, 0, sizeof (load_query_t)); q->fname = strdup (fname); q->width = width; + q->callback = callback; + q->user_data = user_data; if (tail) { tail->next = q; tail = q; @@ -108,7 +112,7 @@ loading_thread (void *none) { for (;;) { trace ("covercache: waiting for signal\n"); deadbeef->cond_wait (cond, mutex); - trace ("covercache: signal received\n"); + trace ("covercache: signal received (terminate=%d, queue=%p)\n", terminate, queue); deadbeef->mutex_unlock (mutex); while (!terminate && queue) { int cache_min = 0; @@ -144,6 +148,7 @@ loading_thread (void *none) { if (stat (queue->fname, &stat_buf) < 0) { trace ("failed to stat file %s\n", queue->fname); } + trace ("covercache: caching pixbuf for %s\n", queue->fname); GdkPixbuf *pixbuf = NULL; GError *error = NULL; pixbuf = gdk_pixbuf_new_from_file_at_scale (queue->fname, queue->width, queue->width, TRUE, &error); @@ -182,8 +187,12 @@ loading_thread (void *none) { struct stat stat_buf; deadbeef->mutex_unlock (mutex); } + + if (queue->callback) { + queue->callback (queue->user_data); + } queue_pop (); - g_idle_add (redraw_playlist_cb, NULL); + //g_idle_add (redraw_playlist_cb, NULL); } if (terminate) { break; @@ -191,20 +200,20 @@ loading_thread (void *none) { } } -void +static void cover_avail_callback (const char *fname, const char *artist, const char *album, void *user_data) { // means requested image is now in disk cache // load it into main memory GdkPixbuf *pb = get_cover_art (fname, artist, album, (intptr_t)user_data); if (pb) { g_object_unref (pb); - // already in cache, redraw - g_idle_add (redraw_playlist_cb, NULL); +// // already in cache, redraw +// g_idle_add (redraw_playlist_cb, NULL); } } static GdkPixbuf * -get_pixbuf (const char *fname, int width) { +get_pixbuf (const char *fname, int width, void (*callback)(void *user_data), void *user_data) { int requested_width = width; // find in cache deadbeef->mutex_lock (mutex); @@ -232,10 +241,15 @@ get_pixbuf (const char *fname, int width) { } #endif deadbeef->mutex_unlock (mutex); - queue_add (fname, width); + queue_add (fname, width, callback, user_data); return NULL; } +static void +redraw_playlist (void *user_data) { + g_idle_add (redraw_playlist_cb, NULL); +} + GdkPixbuf * get_cover_art (const char *fname, const char *artist, const char *album, int width) { if (!coverart_plugin) { @@ -243,7 +257,22 @@ get_cover_art (const char *fname, const char *artist, const char *album, int wid } char *image_fname = coverart_plugin->get_album_art (fname, artist, album, -1, cover_avail_callback, (void *)(intptr_t)width); if (image_fname) { - GdkPixbuf *pb = get_pixbuf (image_fname, width); + GdkPixbuf *pb = get_pixbuf (image_fname, width, redraw_playlist, NULL); + free (image_fname); + return pb; + } + return NULL; +} + +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; + } + char *image_fname = coverart_plugin->get_album_art (fname, artist, album, -1, cover_avail_callback, (void *)(intptr_t)width); + if (image_fname) { + GdkPixbuf *pb = get_pixbuf (image_fname, width, callback, user_data); free (image_fname); return pb; } diff --git a/plugins/gtkui/coverart.h b/plugins/gtkui/coverart.h index 689e0f80..aafec0d6 100644 --- a/plugins/gtkui/coverart.h +++ b/plugins/gtkui/coverart.h @@ -32,6 +32,10 @@ GdkPixbuf * get_cover_art (const char *fname, const char *artist, const char *album, int width); +GdkPixbuf * +get_cover_art_callb (const char *fname, const char *artist, const char *album, int width, void +(*cover_avail_callback) (void *user_data), void *user_data); + void coverart_reset_queue (void); diff --git a/plugins/gtkui/gtkui.c b/plugins/gtkui/gtkui.c index a9f643fd..a7378953 100644 --- a/plugins/gtkui/gtkui.c +++ b/plugins/gtkui/gtkui.c @@ -990,6 +990,7 @@ gtkui_thread (void *ctx) { w_reg_widget ("tabstrip", _("Playlist tabs"), w_tabstrip_create); w_reg_widget ("playlist", _("Playlist"), w_playlist_create); w_reg_widget ("selproperties", _("Selection properties"), w_selproperties_create); + w_reg_widget ("coverart", _("Album art display"), w_coverart_create); mainwin = create_mainwin (); diff --git a/plugins/gtkui/widgets.c b/plugins/gtkui/widgets.c index f914dd8f..fad930ef 100644 --- a/plugins/gtkui/widgets.c +++ b/plugins/gtkui/widgets.c @@ -28,6 +28,10 @@ #include "../../gettext.h" #include "parser.h" #include "trkproperties.h" +#include "coverart.h" + +#define min(x,y) ((x)<(y)?(x):(y)) +#define max(x,y) ((x)>(y)?(x):(y)) typedef struct w_creator_s { const char *type; @@ -73,6 +77,11 @@ typedef struct { GtkWidget *tree; } w_selproperties_t; +typedef struct { + ddb_gtkui_widget_t base; + GtkWidget *drawarea; +} w_coverart_t; + static int design_mode; static ddb_gtkui_widget_t *rootwidget; @@ -358,11 +367,17 @@ on_paste_activate (GtkMenuItem *menuitem, gpointer user_data) { void hide_widget (GtkWidget *widget, gpointer data) { + if (GTK_IS_CONTAINER (widget)) { + gtk_container_foreach (GTK_CONTAINER (widget), hide_widget, NULL); + } gtk_widget_hide (widget); } void show_widget (GtkWidget *widget, gpointer data) { + if (GTK_IS_CONTAINER (widget)) { + gtk_container_foreach (GTK_CONTAINER (widget), show_widget, NULL); + } gtk_widget_show (widget); } @@ -1066,6 +1081,86 @@ w_selproperties_create (void) { GtkCellRenderer *rend_propkey = gtk_cell_renderer_text_new (); GtkCellRenderer *rend_propvalue = gtk_cell_renderer_text_new (); gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (w->tree), TRUE); + w_override_signals (w->base.widget, w); return (ddb_gtkui_widget_t *)w; } + +///// cover art display +static void +cover_avail_callback (void *user_data) { + printf ("cover avail\n"); + w_coverart_t *w = user_data; + gtk_widget_queue_draw (w->drawarea); +} + +static gboolean +coverart_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { + printf ("coverart_expose_event\n"); + DB_playItem_t *it = deadbeef->streamer_get_playing_track (); + if (!it) { + return FALSE; + } + int width = widget->allocation.width; + int height = widget->allocation.height; + const char *album = deadbeef->pl_find_meta (it, "album"); + const char *artist = deadbeef->pl_find_meta (it, "artist"); + if (!album || !*album) { + album = deadbeef->pl_find_meta (it, "title"); + } + GdkPixbuf *pixbuf = get_cover_art_callb (deadbeef->pl_find_meta ((it), ":URI"), artist, album, min(width,height), cover_avail_callback, user_data); + if (pixbuf) { + printf ("found\n"); + int pw = gdk_pixbuf_get_width (pixbuf); + int ph = gdk_pixbuf_get_height (pixbuf); + gdk_draw_pixbuf (widget->window, widget->style->white_gc, pixbuf, 0, 0, widget->allocation.width/2-pw/2, widget->allocation.height/2-ph/2, pw, ph, GDK_RGB_DITHER_NONE, 0, 0); + g_object_unref (pixbuf); + } + else { + printf ("not found\n"); + } + deadbeef->pl_item_unref (it); + return TRUE; +} + +static gboolean +coverart_redraw_cb (void *user_data) { + w_coverart_t *w = user_data; + gtk_widget_queue_draw (w->drawarea); + return FALSE; +} + +static int +coverart_message (ddb_gtkui_widget_t *w, uint32_t id, uintptr_t ctx, uint32_t p1, uint32_t p2) { + w_coverart_t *ca = (w_coverart_t *)w; + switch (id) { + case DB_EV_TRACKINFOCHANGED: + { + ddb_event_track_t *ev = (ddb_event_track_t *)ctx; + DB_playItem_t *it = deadbeef->streamer_get_playing_track (); + if (it == ev->track) { + g_idle_add (coverart_redraw_cb, w); + deadbeef->pl_item_unref (it); + } + } + break; + } + return 0; +} + +ddb_gtkui_widget_t * +w_coverart_create (void) { + w_coverart_t *w = malloc (sizeof (w_coverart_t)); + memset (w, 0, sizeof (w_coverart_t)); + + w->base.widget = gtk_event_box_new (); + w->base.message = coverart_message; + w->drawarea = gtk_drawing_area_new (); + gtk_widget_show (w->drawarea); + gtk_container_add (GTK_CONTAINER (w->base.widget), w->drawarea); + g_signal_connect_after ((gpointer) w->drawarea, "expose_event", G_CALLBACK (coverart_expose_event), w); + w_override_signals (w->base.widget, w); + return (ddb_gtkui_widget_t *)w; +} + + diff --git a/plugins/gtkui/widgets.h b/plugins/gtkui/widgets.h index c690e168..9263eb92 100644 --- a/plugins/gtkui/widgets.h +++ b/plugins/gtkui/widgets.h @@ -81,4 +81,7 @@ w_tabs_create (void); ddb_gtkui_widget_t * w_selproperties_create (void); +ddb_gtkui_widget_t * +w_coverart_create (void); + #endif |