summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar waker <wakeroid@gmail.com>2011-06-22 21:55:47 +0200
committerGravatar waker <wakeroid@gmail.com>2011-06-22 21:55:47 +0200
commitf2870a342dd922325aef7b1af3e6db238055593d (patch)
treee5bba09dba29823ad64a89e337a507139ef9504b
parentbb81b0d2ad0192e241a3c4b6f57e6bc2a28de781 (diff)
added coverart widget
-rw-r--r--plugins/gtkui/coverart.c47
-rw-r--r--plugins/gtkui/coverart.h4
-rw-r--r--plugins/gtkui/gtkui.c1
-rw-r--r--plugins/gtkui/widgets.c95
-rw-r--r--plugins/gtkui/widgets.h3
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