summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-02-28 21:46:13 +0100
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-02-28 21:46:13 +0100
commit736c68a680d001271c19a2c45fbad5a35579f96c (patch)
tree7a5db907a9b42531f6760691a3390d96b8bf3649
parentdc16ab2da7065f82230087a84654167aec5444dc (diff)
cover art WIP
-rw-r--r--deadbeef.h1
-rw-r--r--pixmaps/Makefile.am3
-rw-r--r--pixmaps/blank_cd.jpgbin0 -> 9577 bytes
-rw-r--r--plugins.c1
-rw-r--r--plugins/artwork/artwork.c195
-rw-r--r--plugins/gtkui/coverart.c79
-rw-r--r--plugins/gtkui/ddblistview.c45
-rw-r--r--plugins/gtkui/ddblistview.h2
-rw-r--r--plugins/gtkui/mainplaylist.c29
-rw-r--r--threading.h3
-rw-r--r--threading_pthread.c4
11 files changed, 289 insertions, 73 deletions
diff --git a/deadbeef.h b/deadbeef.h
index 89578987..16c114ae 100644
--- a/deadbeef.h
+++ b/deadbeef.h
@@ -270,6 +270,7 @@ typedef struct {
intptr_t (*thread_start) (void (*fn)(void *ctx), void *ctx);
int (*thread_join) (intptr_t tid);
uintptr_t (*mutex_create) (void);
+ uintptr_t (*mutex_create_nonrecursive) (void);
void (*mutex_free) (uintptr_t mtx);
int (*mutex_lock) (uintptr_t mtx);
int (*mutex_unlock) (uintptr_t mtx);
diff --git a/pixmaps/Makefile.am b/pixmaps/Makefile.am
index fd8452cd..024279af 100644
--- a/pixmaps/Makefile.am
+++ b/pixmaps/Makefile.am
@@ -9,7 +9,8 @@ pause_24.png\
play_24.png\
prev_24.png\
random_24.png\
-stop_24.png
+stop_24.png\
+blank_cd.jpg
EXTRA_DIST = $(pixmaps_DATA)
diff --git a/pixmaps/blank_cd.jpg b/pixmaps/blank_cd.jpg
new file mode 100644
index 00000000..53d62cb6
--- /dev/null
+++ b/pixmaps/blank_cd.jpg
Binary files differ
diff --git a/plugins.c b/plugins.c
index b9d327e2..748f1e9e 100644
--- a/plugins.c
+++ b/plugins.c
@@ -93,6 +93,7 @@ static DB_functions_t deadbeef_api = {
.thread_start = thread_start,
.thread_join = thread_join,
.mutex_create = mutex_create,
+ .mutex_create_nonrecursive = mutex_create_nonrecursive,
.mutex_free = mutex_free,
.mutex_lock = mutex_lock,
.mutex_unlock = mutex_unlock,
diff --git a/plugins/artwork/artwork.c b/plugins/artwork/artwork.c
index a136d29e..6f34b8ce 100644
--- a/plugins/artwork/artwork.c
+++ b/plugins/artwork/artwork.c
@@ -5,17 +5,85 @@
#include <curl/curl.h>
#include <errno.h>
#include <dirent.h>
+#include <unistd.h>
#include "../../deadbeef.h"
#include "artwork.h"
#include "lastfm.h"
#include "albumartorg.h"
+#define min(x,y) ((x)<(y)?(x):(y))
//#define trace(...) { fprintf(stderr, __VA_ARGS__); }
#define trace(...)
+#define DEFAULT_COVER_PATH (PREFIX "/share/deadbeef/pixmaps/blank_cd.jpg")
+
static DB_artwork_plugin_t plugin;
DB_functions_t *deadbeef;
+
+typedef struct cover_query_s {
+ char *artist;
+ char *album;
+ artwork_callback callback;
+ struct cover_query_s *next;
+} cover_query_t;
+
+cover_query_t *queue;
+cover_query_t *queue_tail;
+uintptr_t mutex;
+int terminate;
+intptr_t tid;
+
+void
+queue_add (const char *artist, const char *album, artwork_callback callback) {
+ if (!artist) {
+ artist = "";
+ }
+ if (!album) {
+ album = "";
+ }
+ printf ("queue_add %s %s\n", album, artist);
+ deadbeef->mutex_lock (mutex);
+
+ for (cover_query_t *q = queue; q; q = q->next) {
+ if (!strcasecmp (artist, q->artist) || !strcasecmp (album, q->album)) {
+ deadbeef->mutex_unlock (mutex);
+ return; // already in queue
+ }
+ }
+
+ cover_query_t *q = malloc (sizeof (cover_query_t));
+ memset (q, 0, sizeof (cover_query_t));
+ q->artist = strdup (artist);
+ q->album = strdup (album);
+ q->callback = callback;
+ if (queue_tail) {
+ queue_tail->next = q;
+ queue_tail = q;
+ }
+ else {
+ queue = queue_tail = q;
+ }
+ deadbeef->mutex_unlock (mutex);
+ printf ("queue_added %s %s\n", album, artist);
+}
+
+void
+queue_pop (void) {
+ printf ("queue_pop\n");
+ deadbeef->mutex_lock (mutex);
+ cover_query_t *next = queue ? queue->next : NULL;
+ free (queue->artist);
+ free (queue->album);
+ free (queue);
+ queue = next;
+ if (!queue) {
+ queue_tail = NULL;
+ }
+ deadbeef->mutex_unlock (mutex);
+ printf ("queue_popped\n");
+}
+
int
fetch_to_stream (const char *url, FILE *stream)
{
@@ -47,8 +115,9 @@ fetch_to_file (const char *url, const char *filename)
return 0;
}
ret = fetch_to_stream (url, stream);
- if (ret != 0)
- printf ("Failed to fetch %s\n", url);
+ if (ret != 0) {
+// printf ("Failed to fetch %s\n", url);
+ }
fclose (stream);
if (0 == ret)
{
@@ -99,34 +168,90 @@ check_dir (const char *dir, mode_t mode)
return 1;
}
-typedef struct
-{
- const char *artist;
- const char *album;
- artwork_callback callback;
-} fetcher_thread_param_t;
+#define BUFFER_SIZE 4096
+
+static int
+copy_file (const char *in, const char *out) {
+ char *buf = malloc (BUFFER_SIZE);
+ if (!buf) {
+ fprintf (stderr, "artwork: failed to alloc %d bytes\n", BUFFER_SIZE);
+ return -1;
+ }
+ FILE *fin = fopen (in, "rb");
+ if (!fin) {
+ fprintf (stderr, "artwork: failed to open file %s\n", in);
+ return -1;
+ }
+ FILE *fout = fopen (out, "w+b");
+ if (!fout) {
+ fclose (fin);
+ fprintf (stderr, "artwork: failed to open file %s\n", out);
+ return -1;
+ }
+
+ fseek (fin, 0, SEEK_END);
+ size_t sz = ftell (fin);
+ rewind (fin);
+
+ while (sz > 0) {
+ int rs = min (sz, BUFFER_SIZE);
+ if (fread (buf, rs, 1, fin) != 1) {
+ fprintf (stderr, "artwork: failed to read file %s\n", in);
+ break;
+ }
+ if (fwrite (buf, rs, 1, fout) != 1) {
+ fprintf (stderr, "artwork: failed to write file %s\n", out);
+ break;
+ }
+ sz -= rs;
+ }
+ free (buf);
+ fclose (fin);
+ fclose (fout);
+ if (sz > 0) {
+ unlink (out);
+ }
+ return 0;
+}
static void
-fetcher_thread (fetcher_thread_param_t *param)
+fetcher_thread (void *none)
{
- char path [1024];
+ while (!terminate) {
+ if (!queue) {
+ usleep (100000);
+ continue;
+ }
+ cover_query_t *param = queue;
- snprintf (path, sizeof (path), "%s/artcache/%s", deadbeef->get_config_dir (), param->artist);
- if (!check_dir (path, 0755))
- goto finalize;
+ printf ("fetching cover for %s %s\n", param->album, param->artist);
- snprintf (path, sizeof (path), "%s/artcache/%s/%s.jpg", deadbeef->get_config_dir (), param->artist, param->album);
+ char path [1024];
+ snprintf (path, sizeof (path), "%s/artcache/%s", deadbeef->get_config_dir (), param->artist);
+ if (!check_dir (path, 0755)) {
+ queue_pop ();
+ printf ("failed to create folder for %s %s\n", param->album, param->artist);
+ continue;
+ }
- if (!fetch_from_lastfm (param->artist, param->album, path))
- if (!fetch_from_albumart_org (param->artist, param->album, path))
- goto finalize;
+ snprintf (path, sizeof (path), "%s/artcache/%s/%s.jpg", deadbeef->get_config_dir (), param->artist, param->album);
- if (param->callback)
- param->callback (param->artist, param->album);
+ if (!fetch_from_lastfm (param->artist, param->album, path)) {
+ if (!fetch_from_albumart_org (param->artist, param->album, path)) {
+ printf ("art not found for %s %s\n", param->album, param->artist);
+ queue_pop ();
+ copy_file (DEFAULT_COVER_PATH, path);
+ continue;
+ }
+ }
-finalize:
- free (param);
- return;
+ printf ("downloaded art for %s %s\n", param->album, param->artist);
+ if (param->callback) {
+ param->callback (param->artist, param->album);
+ }
+ queue_pop ();
+ }
+ tid = 0;
}
static int
@@ -177,27 +302,22 @@ get_album_art (DB_playItem_t *track, artwork_callback callback)
if (!artist || !*artist || !album || !*album)
{
//give up
- return PREFIX "/share/deadbeef/pixmaps/blank_cd.jpg";
+ return strdup (DEFAULT_COVER_PATH);
}
snprintf (path, sizeof (path), "%s/artcache/%s/%s.jpg", deadbeef->get_config_dir (), artist, album);
+// printf ("looking for %s in cache\n", path);
struct stat stat_buf;
if (0 == stat (path, &stat_buf))
{
char *res = strdup (path);
-// printf ("Found in cache: %s\n", res);
+// printf ("found %s in cache\n", path);
return res;
}
- /* Downloading from internet */
- trace ("Downloading: %s %s\n", artist, album);
- fetcher_thread_param_t *param = malloc (sizeof (fetcher_thread_param_t));
- param->artist = artist;
- param->album = album;
- param->callback = callback;
- deadbeef->thread_start ((void (*)(void *))fetcher_thread, param);
- return PREFIX "/share/deadbeef/pixmaps/blank_cd.jpg";
+ queue_add (artist, album, callback);
+ return strdup (DEFAULT_COVER_PATH);
}
DB_plugin_t *
@@ -209,11 +329,22 @@ artwork_load (DB_functions_t *api) {
static int
artwork_plugin_start (void)
{
+ terminate = 0;
+ mutex = deadbeef->mutex_create ();
+ tid = deadbeef->thread_start (fetcher_thread, NULL);
}
static int
artwork_plugin_stop (void)
{
+ if (tid) {
+ terminate = 1;
+ deadbeef->thread_join (tid);
+ }
+ if (mutex) {
+ deadbeef->mutex_free (mutex);
+ mutex = 0;
+ }
}
// define plugin interface
diff --git a/plugins/gtkui/coverart.c b/plugins/gtkui/coverart.c
index 7d042e5f..27c9e953 100644
--- a/plugins/gtkui/coverart.c
+++ b/plugins/gtkui/coverart.c
@@ -17,43 +17,88 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <gtk/gtk.h>
+#include <sys/time.h>
+#include <string.h>
+#include <stdlib.h>
#include "coverart.h"
#include "../artwork/artwork.h"
extern DB_artwork_plugin_t *coverart_plugin;
+#define MAX_ID 256
+#define CACHE_SIZE 20
+
+typedef struct {
+ struct timeval tm;
+ char *fname;
+ int width;
+ GdkPixbuf *pixbuf;
+} cached_pixbuf_t;
+
+static cached_pixbuf_t cache[CACHE_SIZE];
+
void
cover_avail_callback (const char *artist, const char *album) {
}
static GdkPixbuf *
get_pixbuf (const char *fname, int width) {
+ int requested_width = width;
+ // find in cache
+ int cache_min = 0;
+ for (int i = 0; i < CACHE_SIZE; i++) {
+ if (!cache[i].pixbuf) {
+ cache_min = i;
+ }
+ if (cache[i].pixbuf) {
+ if (!strcmp (fname, cache[i].fname) && cache[i].width == width) {
+ gettimeofday (&cache[i].tm, NULL);
+ return cache[i].pixbuf;
+ }
+ }
+ if (cache[cache_min].pixbuf && cache[i].pixbuf) {
+ if (cache[cache_min].tm.tv_sec < cache[i].tm.tv_sec) {
+ cache_min = i;
+ }
+ }
+ }
+
+ printf ("loading image %s\n", fname);
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (fname, NULL);
if (!pixbuf) {
return NULL;
}
+
int w, h;
w = gdk_pixbuf_get_width (pixbuf);
h = gdk_pixbuf_get_height (pixbuf);
- if (w == width) {
- return pixbuf;
+ if (w != width) {
+ int height;
+ if (w > h) {
+ height = width * h / w;
+ }
+ else if (h > w) {
+ height = width;
+ width = height * w / h;
+ }
+ else {
+ height = width;
+ }
+ GdkPixbuf *scaled = gdk_pixbuf_scale_simple (pixbuf, width, height, GDK_INTERP_BILINEAR);
+ g_object_unref (pixbuf);
+ pixbuf = scaled;
}
- int height;
- if (w > h) {
- height = width * h / w;
+ if (cache[cache_min].pixbuf) {
+ g_object_unref (cache[cache_min].pixbuf);
}
- else if (h > w) {
- height = width;
- width = height * w / h;
+ if (cache[cache_min].fname) {
+ free (cache[cache_min].fname);
}
- else {
- height = width;
- }
- printf ("width=%d/%d, height=%d/%d\n", width, w, height, h);
-
- GdkPixbuf *scaled = gdk_pixbuf_scale_simple (pixbuf, width, height, GDK_INTERP_BILINEAR);
- g_object_unref (pixbuf);
- return scaled;
+ cache[cache_min].pixbuf = pixbuf;
+ cache[cache_min].fname = strdup (fname);
+ gettimeofday (&cache[cache_min].tm, NULL);
+ cache[cache_min].width = requested_width;
+ return pixbuf;
}
GdkPixbuf *
@@ -63,7 +108,7 @@ get_cover_art (DB_playItem_t *it, int width) {
}
const char *fname = coverart_plugin->get_album_art (it, cover_avail_callback);
if (fname) {
- printf ("loading %s\n", fname);
+// printf ("loading %s\n", fname);
return get_pixbuf (fname, width);
}
return NULL;
diff --git a/plugins/gtkui/ddblistview.c b/plugins/gtkui/ddblistview.c
index b8b419f7..71f4bd1c 100644
--- a/plugins/gtkui/ddblistview.c
+++ b/plugins/gtkui/ddblistview.c
@@ -106,7 +106,7 @@ ddb_listview_list_expose (DdbListview *ps, int x, int y, int w, int h);
void
ddb_listview_list_render_row_background (DdbListview *ps, DdbListviewIter it, int even, int cursor, int x, int y, int w, int h);
void
-ddb_listview_list_render_row_foreground (DdbListview *ps, DdbListviewIter it, int even, int cursor, int group_y, int x, int y, int w, int h);
+ddb_listview_list_render_row_foreground (DdbListview *ps, DdbListviewIter it, DdbListviewIter group_it, int even, int cursor, int group_y, int x, int y, int w, int h);
void
ddb_listview_list_render_row (DdbListview *ps, int row, DdbListviewIter it, int expose);
void
@@ -595,31 +595,46 @@ ddb_listview_list_render (DdbListview *listview, int x, int y, int w, int h) {
}
draw_begin ((uintptr_t)listview->backbuf);
+ int ii = 0;
while (grp && grp_y < y + h + listview->scrollpos) {
// render title
DdbListviewIter it = grp->head;
listview->binding->ref (it);
int grpheight = grp->height;
+ if (grp_y >= y + h + listview->scrollpos) {
+ break;
+ }
if (grp_y + GROUP_TITLE_HEIGHT >= y + listview->scrollpos && grp_y < y + h + listview->scrollpos) {
ddb_listview_list_render_row_background (listview, NULL, idx & 1, 0, -listview->hscrollpos, grp_y - listview->scrollpos, listview->totalwidth, GROUP_TITLE_HEIGHT);
listview->binding->draw_group_title (listview, listview->backbuf, it, -listview->hscrollpos, grp_y - listview->scrollpos, listview->totalwidth, GROUP_TITLE_HEIGHT);
}
for (int i = 0; i < grp->num_items; i++) {
- if (grp_y + GROUP_TITLE_HEIGHT + (i+1) * listview->rowheight >= y + listview->scrollpos && grp_y + GROUP_TITLE_HEIGHT + i * listview->rowheight< y + h + listview->scrollpos) {
+ ii++;
+// if (grp_y + GROUP_TITLE_HEIGHT + (i+1) * listview->rowheight >= y + h + listview->scrollpos) {
+// break;
+// }
+ if (grp_y + GROUP_TITLE_HEIGHT + i * listview->rowheight >= y + h + listview->scrollpos) {
+ break;
+ }
+ if (grp_y + GROUP_TITLE_HEIGHT + (i+1) * listview->rowheight >= y + listview->scrollpos
+ && grp_y + GROUP_TITLE_HEIGHT + i * listview->rowheight < y + h + listview->scrollpos) {
gdk_draw_rectangle (listview->backbuf, listview->list->style->bg_gc[GTK_STATE_NORMAL], TRUE, -listview->hscrollpos, grp_y + GROUP_TITLE_HEIGHT + i * listview->rowheight - listview->scrollpos, listview->totalwidth, listview->rowheight);
ddb_listview_list_render_row_background (listview, it, (idx + 1 + i) & 1, (idx+i) == listview->binding->cursor () ? 1 : 0, -listview->hscrollpos, grp_y + GROUP_TITLE_HEIGHT + i * listview->rowheight - listview->scrollpos, listview->totalwidth, listview->rowheight);
- ddb_listview_list_render_row_foreground (listview, it, (idx + 1 + i) & 1, (idx+i) == listview->binding->cursor () ? 1 : 0, i * listview->rowheight, -listview->hscrollpos, grp_y + GROUP_TITLE_HEIGHT + i * listview->rowheight - listview->scrollpos, listview->totalwidth, listview->rowheight);
+ ddb_listview_list_render_row_foreground (listview, it, grp->head, (idx + 1 + i) & 1, (idx+i) == listview->binding->cursor () ? 1 : 0, i * listview->rowheight, -listview->hscrollpos, grp_y + GROUP_TITLE_HEIGHT + i * listview->rowheight - listview->scrollpos, listview->totalwidth, listview->rowheight);
}
DdbListviewIter next = listview->binding->next (it);
listview->binding->unref (it);
it = next;
}
+ if (it) {
+ listview->binding->unref (it);
+ }
idx += grp->num_items + 1;
int filler = grpheight - (GROUP_TITLE_HEIGHT + listview->rowheight * grp->num_items);
if (filler > 0) {
gtk_paint_flat_box (treeview->style, listview->backbuf, GTK_STATE_NORMAL, GTK_SHADOW_NONE, NULL, treeview, "cell_even_ruled", x, grp_y - listview->scrollpos + GROUP_TITLE_HEIGHT + listview->rowheight * grp->num_items, w, filler);
- ddb_listview_list_render_row_foreground (listview, NULL, 0, 0, grp->num_items * listview->rowheight, -listview->hscrollpos, grp_y - listview->scrollpos + GROUP_TITLE_HEIGHT + listview->rowheight * grp->num_items, listview->totalwidth, filler);
+ ddb_listview_list_render_row_foreground (listview, NULL, grp->head, 0, 0, grp->num_items * listview->rowheight, -listview->hscrollpos, grp_y - listview->scrollpos + GROUP_TITLE_HEIGHT + listview->rowheight * grp->num_items, listview->totalwidth, filler);
}
grp_y += grpheight;
@@ -692,12 +707,12 @@ ddb_listview_vscroll_value_changed (GtkRange *widget,
// redraw other part
int start = height-d-1;
ps->scrollpos = newscroll;
- ddb_listview_list_render (ps, 0, start, ps->list->allocation.width, height);
+ ddb_listview_list_render (ps, 0, start, ps->list->allocation.width, widget->allocation.height-start);
}
else {
// scroll up
// copy scrolled part of buffer
- draw_drawable (ps->backbuf, widget->style->black_gc, ps->backbuf, 0, 0, 0, d, widget->allocation.width, widget->allocation.height);
+ draw_drawable (ps->backbuf, widget->style->black_gc, ps->backbuf, 0, 0, 0, d, widget->allocation.width, widget->allocation.height-d);
// redraw other part
ps->scrollpos = newscroll;
ddb_listview_list_render (ps, 0, 0, ps->list->allocation.width, d+1);
@@ -1017,7 +1032,7 @@ ddb_listview_list_setup_hscroll (DdbListview *ps) {
// returns -1 if row not found
int
-ddb_listview_list_get_drawinfo (DdbListview *listview, int row, int *even, int *cursor, int *group_y, int *x, int *y, int *w, int *h) {
+ddb_listview_list_get_drawinfo (DdbListview *listview, int row, DdbListviewGroup **pgrp, int *even, int *cursor, int *group_y, int *x, int *y, int *w, int *h) {
DdbListviewGroup *grp = listview->groups;
int idx = 0;
int idx2 = 0;
@@ -1027,6 +1042,7 @@ ddb_listview_list_get_drawinfo (DdbListview *listview, int row, int *even, int *
if (idx <= row && idx + grp->num_items > row) {
// found
int idx_in_group = row - idx;
+ *pgrp = grp;
*even = (idx2 + 1 + idx_in_group) & 1;
*cursor = (row == listview->binding->cursor ()) ? 1 : 0;
*group_y = idx_in_group * listview->rowheight;
@@ -1046,18 +1062,19 @@ ddb_listview_list_get_drawinfo (DdbListview *listview, int row, int *even, int *
void
ddb_listview_list_render_row (DdbListview *listview, int row, DdbListviewIter it, int expose) {
+ DdbListviewGroup *grp;
int even;
int cursor;
int x, y, w, h;
int group_y;
- if (ddb_listview_list_get_drawinfo (listview, row, &even, &cursor, &group_y, &x, &y, &w, &h) == -1) {
+ if (ddb_listview_list_get_drawinfo (listview, row, &grp, &even, &cursor, &group_y, &x, &y, &w, &h) == -1) {
return;
}
draw_begin ((uintptr_t)listview->backbuf);
ddb_listview_list_render_row_background (listview, it, even, cursor, x, y, w, h);
if (it) {
- ddb_listview_list_render_row_foreground (listview, it, even, cursor, group_y, x, y, w, h);
+ ddb_listview_list_render_row_foreground (listview, it, grp->head, even, cursor, group_y, x, y, w, h);
}
draw_end ();
if (expose) {
@@ -1092,7 +1109,7 @@ ddb_listview_list_render_row_background (DdbListview *ps, DdbListviewIter it, in
}
void
-ddb_listview_list_render_row_foreground (DdbListview *ps, DdbListviewIter it, int even, int cursor, int group_y, int x, int y, int w, int h) {
+ddb_listview_list_render_row_foreground (DdbListview *ps, DdbListviewIter it, DdbListviewIter group_it, int even, int cursor, int group_y, int x, int y, int w, int h) {
int width, height;
draw_get_canvas_size ((uintptr_t)ps->backbuf, &width, &height);
if (it && ps->binding->is_selected (it)) {
@@ -1109,7 +1126,7 @@ ddb_listview_list_render_row_foreground (DdbListview *ps, DdbListviewIter it, in
int cidx = 0;
for (c = ps->columns; c; c = c->next, cidx++) {
int cw = c->width;
- ps->binding->draw_column_data (ps, ps->backbuf, it, cidx, group_y, x, y, cw, h);
+ ps->binding->draw_column_data (ps, ps->backbuf, it, GROUP_TITLE_HEIGHT > 0 ? group_it : NULL, cidx, group_y, x, y, cw, h);
x += cw;
}
}
@@ -2528,4 +2545,10 @@ ddb_listview_build_groups (DdbListview *listview) {
listview->binding->unref (it);
it = next;
}
+ if (grp) {
+ if (grp->height - GROUP_TITLE_HEIGHT < min_height) {
+ grp->height = min_height + GROUP_TITLE_HEIGHT;
+ }
+ listview->fullheight += grp->height;
+ }
}
diff --git a/plugins/gtkui/ddblistview.h b/plugins/gtkui/ddblistview.h
index a39e4fa7..c3e98141 100644
--- a/plugins/gtkui/ddblistview.h
+++ b/plugins/gtkui/ddblistview.h
@@ -73,7 +73,7 @@ typedef struct {
// callbacks
void (*draw_group_title) (DdbListview *listview, GdkDrawable *drawable, DdbListviewIter iter, int x, int y, int width, int height);
- void (*draw_column_data) (DdbListview *listview, GdkDrawable *drawable, DdbListviewIter iter, int column, int group_y, int x, int y, int width, int height);
+ void (*draw_column_data) (DdbListview *listview, GdkDrawable *drawable, DdbListviewIter iter, DdbListviewIter group_iter, int column, int group_y, int x, int y, int width, int height);
void (*list_context_menu) (DdbListview *listview, DdbListviewIter iter, int idx);
void (*header_context_menu) (DdbListview *listview, int col);
void (*handle_doubleclick) (DdbListview *listview, DdbListviewIter iter, int idx);
diff --git a/plugins/gtkui/mainplaylist.c b/plugins/gtkui/mainplaylist.c
index 61fbef50..7f4f6769 100644
--- a/plugins/gtkui/mainplaylist.c
+++ b/plugins/gtkui/mainplaylist.c
@@ -279,7 +279,7 @@ void main_selection_changed (DdbListviewIter it, int idx) {
ddb_listview_draw_row (search, idx, it);
}
-void main_draw_column_data (DdbListview *listview, GdkDrawable *drawable, DdbListviewIter it, int column, int group_y, int x, int y, int width, int height) {
+void main_draw_column_data (DdbListview *listview, GdkDrawable *drawable, DdbListviewIter it, DdbListviewIter group_it, int column, int group_y, int x, int y, int width, int height) {
const char *ctitle;
int cwidth;
int calign_right;
@@ -291,14 +291,25 @@ void main_draw_column_data (DdbListview *listview, GdkDrawable *drawable, DdbLis
}
if (cinf->id == DB_COLUMN_ALBUM_ART) {
if (group_y < cwidth) {
- int h = cwidth - group_y;
- h = min (height, h);
- gdk_draw_rectangle (drawable, GTK_WIDGET (listview)->style->white_gc, TRUE, x, y, width, h);
-// GdkPixbuf *pixbuf = gdk_pixbuf_scale_simple ((GdkPixbuf *)play16_pixbuf, width, width, GDK_INTERP_BILINEAR);
- if (it) {
- GdkPixbuf *pixbuf = get_cover_art (it, width);
- gdk_draw_pixbuf (drawable, GTK_WIDGET (listview)->style->white_gc, pixbuf, 0, group_y, x, y, width, h, GDK_RGB_DITHER_NONE, 0, 0);
- g_object_unref (pixbuf);
+ if (group_it) {
+ int h = cwidth - group_y;
+ h = min (height, h);
+ gdk_draw_rectangle (drawable, GTK_WIDGET (listview)->style->white_gc, TRUE, x, y, width, h);
+ GdkPixbuf *pixbuf = get_cover_art (group_it, width);
+ if (pixbuf) {
+ int pw = gdk_pixbuf_get_width (pixbuf);
+ int ph = gdk_pixbuf_get_height (pixbuf);
+ if (group_y < ph) {
+ pw = min (width, pw);
+ if (group_y + h >= ph) {
+ ph = ph - group_y;
+ }
+ else {
+ ph = h;
+ }
+ gdk_draw_pixbuf (drawable, GTK_WIDGET (listview)->style->white_gc, pixbuf, 0, group_y, x, y, pw, ph, GDK_RGB_DITHER_NONE, 0, 0);
+ }
+ }
}
}
}
diff --git a/threading.h b/threading.h
index f8767360..f0988574 100644
--- a/threading.h
+++ b/threading.h
@@ -30,6 +30,9 @@ uintptr_t
mutex_create (void);
uintptr_t
+mutex_create_nonrecursive (void);
+
+uintptr_t
mutex_create_recursive (void);
void
diff --git a/threading_pthread.c b/threading_pthread.c
index c3e4e8fb..3b04e7c8 100644
--- a/threading_pthread.c
+++ b/threading_pthread.c
@@ -58,7 +58,7 @@ thread_join (intptr_t tid) {
}
uintptr_t
-mutex_create (void) {
+mutex_create_nonrecursive (void) {
pthread_mutex_t *mtx = malloc (sizeof (pthread_mutex_t));
pthread_mutexattr_t attr = {0};
pthread_mutexattr_init (&attr);
@@ -73,7 +73,7 @@ mutex_create (void) {
}
uintptr_t
-mutex_create_recursive (void) {
+mutex_create (void) {
pthread_mutex_t *mtx = malloc (sizeof (pthread_mutex_t));
pthread_mutexattr_t attr = {0};
pthread_mutexattr_init (&attr);