summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/artwork/Makefile.am2
-rw-r--r--plugins/artwork/artwork.c93
-rw-r--r--plugins/artwork/artwork.h2
-rw-r--r--plugins/gtkui/coverart.c2
-rw-r--r--plugins/gtkui/gtkui.c2
-rw-r--r--plugins/notify/notify.c247
6 files changed, 215 insertions, 133 deletions
diff --git a/plugins/artwork/Makefile.am b/plugins/artwork/Makefile.am
index b60c86cb..4ca2ed19 100644
--- a/plugins/artwork/Makefile.am
+++ b/plugins/artwork/Makefile.am
@@ -5,6 +5,6 @@ artwork_la_SOURCES = artwork.c artwork.h albumartorg.c albumartorg.h lastfm.c la
artwork_la_LDFLAGS = -module
-artwork_la_LIBADD = $(LDADD) $(ARTWORK_DEPS_LIBS)
+artwork_la_LIBADD = $(LDADD) $(ARTWORK_DEPS_LIBS) -lImlib2
AM_CFLAGS = -std=c99 $(ARTWORK_DEPS_CFLAGS)
endif
diff --git a/plugins/artwork/artwork.c b/plugins/artwork/artwork.c
index b8258957..c9d5c964 100644
--- a/plugins/artwork/artwork.c
+++ b/plugins/artwork/artwork.c
@@ -7,6 +7,7 @@
#include <unistd.h>
#include <fnmatch.h>
#include <inttypes.h>
+#include <Imlib2.h>
#include "../../deadbeef.h"
#include "artwork.h"
#include "lastfm.h"
@@ -29,6 +30,7 @@ typedef struct cover_query_s {
char *fname;
char *artist;
char *album;
+ int size;
artwork_callback callback;
void *user_data;
struct cover_query_s *next;
@@ -54,10 +56,17 @@ static const char *get_default_cover (void) {
}
int
-make_cache_dir_path (char *path, int size, const char *artist) {
+make_cache_dir_path (char *path, int size, const char *artist, int img_size) {
const char *cache = getenv ("XDG_CACHE_HOME");
- int sz = snprintf (path, size, "%s/deadbeef/", cache ? cache : getenv ("HOME"));
+ int sz;
+
+ if (img_size == -1) {
+ sz = snprintf (path, size, "%s/deadbeef/covers/", cache ? cache : getenv ("HOME"));
+ }
+ else {
+ sz = snprintf (path, size, "%s/deadbeef/covers-%d/", cache ? cache : getenv ("HOME"), img_size);
+ }
path += sz;
sz += snprintf (path, size-sz, "%s", artist);
@@ -70,9 +79,9 @@ make_cache_dir_path (char *path, int size, const char *artist) {
}
void
-make_cache_path (char *path, int size, const char *album, const char *artist) {
+make_cache_path (char *path, int size, const char *album, const char *artist, int img_size) {
char *p = path;
- int sz = make_cache_dir_path (path, size, artist);
+ int sz = make_cache_dir_path (path, size, artist, img_size);
size -= sz;
path += sz;
sz = snprintf (path, size, "/%s.jpg", album);
@@ -84,7 +93,7 @@ make_cache_path (char *path, int size, const char *album, const char *artist) {
}
void
-queue_add (const char *fname, const char *artist, const char *album, artwork_callback callback, void *user_data) {
+queue_add (const char *fname, const char *artist, const char *album, int img_size, artwork_callback callback, void *user_data) {
if (!artist) {
artist = "";
}
@@ -105,6 +114,7 @@ queue_add (const char *fname, const char *artist, const char *album, artwork_cal
q->fname = strdup (fname);
q->artist = strdup (artist);
q->album = strdup (album);
+ q->size = img_size;
q->callback = callback;
q->user_data = user_data;
if (queue_tail) {
@@ -165,8 +175,47 @@ check_dir (const char *dir, mode_t mode)
#define BUFFER_SIZE 4096
static int
-copy_file (const char *in, const char *out) {
+copy_file (const char *in, const char *out, int img_size) {
trace ("copying %s to %s\n", in, out);
+
+ if (img_size != -1) {
+ // need to scale, use imlib2
+ Imlib_Image img = imlib_load_image_immediately (in);
+ if (!img) {
+ trace ("file %s not found, or imlib2 can't load it\n", in);
+ return -1;
+ }
+ imlib_context_set_image(img);
+ int w = imlib_image_get_width ();
+ int h = imlib_image_get_height ();
+ int sw, sh;
+ if (w < h) {
+ sh = img_size;
+ sw = img_size * w / h;
+ }
+ else {
+ sw = img_size;
+ sh = img_size * h / w;
+ }
+ Imlib_Image scaled = imlib_create_image (sw, sh);
+ imlib_context_set_image (scaled);
+ imlib_blend_image_onto_image (img, 1, 0, 0, w, h, 0, 0, sw, sh);
+ Imlib_Load_Error err = 0;
+ imlib_image_set_format ("jpg");
+ imlib_save_image_with_error_return (out, &err);
+ if (err != 0) {
+ imlib_free_image ();
+ imlib_context_set_image(img);
+ imlib_free_image ();
+ return -1;
+ }
+ imlib_free_image ();
+ imlib_context_set_image(img);
+ imlib_free_image ();
+
+ return 0;
+ }
+
FILE *fin = fopen (in, "rb");
if (!fin) {
trace ("artwork: failed to open file %s for reading\n", in);
@@ -290,7 +339,7 @@ fetcher_thread (void *none)
struct dirent **files;
int files_count;
- make_cache_dir_path (path, sizeof (path), param->artist);
+ make_cache_dir_path (path, sizeof (path), param->artist, param->size);
trace ("cache folder: %s\n", path);
if (!check_dir (path, 0755)) {
queue_pop ();
@@ -349,7 +398,7 @@ fetcher_thread (void *none)
char tmp_path[1024];
char cache_path[1024];
- make_cache_path (cache_path, sizeof (cache_path), param->album, param->artist);
+ make_cache_path (cache_path, sizeof (cache_path), param->album, param->artist, param->size);
trace ("will write id3v2 APIC into %s\n", cache_path);
snprintf (tmp_path, sizeof (tmp_path), "%s.part", cache_path);
FILE *out = fopen (tmp_path, "w+b");
@@ -430,7 +479,7 @@ fetcher_thread (void *none)
trace ("found apev2 cover art of %d bytes (%s)\n", sz, ext);
char tmp_path[1024];
char cache_path[1024];
- make_cache_path (cache_path, sizeof (cache_path), param->album, param->artist);
+ make_cache_path (cache_path, sizeof (cache_path), param->album, param->artist, param->size);
trace ("will write apev2 cover art into %s\n", cache_path);
snprintf (tmp_path, sizeof (tmp_path), "%s.part", cache_path);
FILE *out = fopen (tmp_path, "w+b");
@@ -491,9 +540,9 @@ fetcher_thread (void *none)
strcat (path, files[0]->d_name);
char cache_path[1024];
char tmp_path[1024];
- make_cache_path (cache_path, sizeof (cache_path), param->album, param->artist);
+ make_cache_path (cache_path, sizeof (cache_path), param->album, param->artist, param->size);
snprintf (tmp_path, sizeof (tmp_path), "%s.part", cache_path);
- copy_file (path, tmp_path);
+ copy_file (path, tmp_path, param->size);
int err = rename (tmp_path, cache_path);
if (err != 0) {
trace ("Failed not move %s to %s: %s\n", tmp_path, cache_path, strerror (err));
@@ -513,7 +562,7 @@ fetcher_thread (void *none)
}
}
- make_cache_path (path, sizeof (path), param->album, param->artist);
+ make_cache_path (path, sizeof (path), param->album, param->artist, param->size);
if (artwork_enable_lfm && !fetch_from_lastfm (param->artist, param->album, path)) {
trace ("art found on last.fm for %s %s\n", param->album, param->artist);
@@ -552,7 +601,7 @@ fetcher_thread (void *none)
}
char*
-get_album_art (const char *fname, const char *artist, const char *album, artwork_callback callback, void *user_data)
+get_album_art (const char *fname, const char *artist, const char *album, int size, artwork_callback callback, void *user_data)
{
// trace ("get_album_art: %s (%s - %s)\n", fname, artist, album);
char path [1024];
@@ -567,14 +616,14 @@ get_album_art (const char *fname, const char *artist, const char *album, artwork
if (!*artist || !*album)
{
//give up
- return strdup (get_default_cover ());
+ return size == -1 ? strdup (get_default_cover ()) : NULL;
}
if (!deadbeef->is_local_file (fname)) {
- return strdup (get_default_cover ());
+ return size == -1 ? strdup (get_default_cover ()) : NULL;
}
- make_cache_path (path, sizeof (path), album, artist);
+ make_cache_path (path, sizeof (path), album, artist, size);
struct stat stat_buf;
if (0 == stat (path, &stat_buf)) {
int cache_period = deadbeef->conf_get_int ("artwork.cache.period", 48);
@@ -584,16 +633,16 @@ get_album_art (const char *fname, const char *artist, const char *album, artwork
|| artwork_reset_time > stat_buf.st_mtime) {
trace ("reloading cached file %s\n", path);
unlink (path);
- queue_add (fname, artist, album, callback, user_data);
- return strdup (get_default_cover ());
+ queue_add (fname, artist, album, size, callback, user_data);
+ return size == -1 ? strdup (get_default_cover ()) : NULL;
}
// trace ("found %s in cache, resettime %" PRId64 ", filetime %" PRId64 ", time %" PRId64 "\n", path, artwork_reset_time, stat_buf.st_mtime, tm);
return strdup (path);
}
- queue_add (fname, artist, album, callback, user_data);
- return strdup (get_default_cover ());
+ queue_add (fname, artist, album, size, callback, user_data);
+ return size == -1 ? strdup (get_default_cover ()) : NULL;
}
DB_plugin_t *
@@ -647,7 +696,7 @@ artwork_on_configchanged (DB_event_t *ev, uintptr_t data) {
|| new_artwork_enable_lfm != artwork_enable_lfm
|| new_artwork_enable_aao != artwork_enable_aao
|| strcmp (new_artwork_filemask, artwork_filemask)) {
- printf ("artwork config changed, invalidating cache...\n");
+ trace ("artwork config changed, invalidating cache...\n");
artwork_enable_embedded = new_artwork_enable_embedded;
artwork_enable_local = new_artwork_enable_local;
artwork_enable_lfm = new_artwork_enable_lfm;
@@ -736,7 +785,7 @@ static DB_artwork_plugin_t plugin = {
.plugin.plugin.version_major = 1,
.plugin.plugin.version_minor = 0,
.plugin.plugin.type = DB_PLUGIN_MISC,
- .plugin.plugin.id = "cover_loader",
+ .plugin.plugin.id = "artwork",
.plugin.plugin.name = "Album Artwork",
.plugin.plugin.descr = "Loads album artwork either from local directories or from internet",
.plugin.plugin.author = "Viktor Semykin, Alexey Yakovenko",
diff --git a/plugins/artwork/artwork.h b/plugins/artwork/artwork.h
index ed5357df..130bf3fe 100644
--- a/plugins/artwork/artwork.h
+++ b/plugins/artwork/artwork.h
@@ -10,7 +10,7 @@ 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
- char* (*get_album_art) (const char *fname, const char *artist, const char *album, artwork_callback callback, void *user_data);
+ 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
// `fast=1' means "don't wait, just flush queue"
void (*reset) (int fast);
diff --git a/plugins/gtkui/coverart.c b/plugins/gtkui/coverart.c
index 158d7a1e..4118aa66 100644
--- a/plugins/gtkui/coverart.c
+++ b/plugins/gtkui/coverart.c
@@ -241,7 +241,7 @@ get_cover_art (const char *fname, const char *artist, const char *album, int wid
if (!coverart_plugin) {
return NULL;
}
- char *image_fname = coverart_plugin->get_album_art (fname, artist, album, cover_avail_callback, (void *)(intptr_t)width);
+ 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);
free (image_fname);
diff --git a/plugins/gtkui/gtkui.c b/plugins/gtkui/gtkui.c
index d95592cf..b85dca4a 100644
--- a/plugins/gtkui/gtkui.c
+++ b/plugins/gtkui/gtkui.c
@@ -1187,7 +1187,7 @@ gtkui_connect_cb (void *none) {
DB_plugin_t **plugins = deadbeef->plug_get_list ();
for (int i = 0; plugins[i]; i++) {
DB_plugin_t *p = plugins[i];
- if (p->id && !strcmp (p->id, "cover_loader")) {
+ if (p->id && !strcmp (p->id, "artwork")) {
trace ("gtkui: found cover-art loader plugin\n");
coverart_plugin = (DB_artwork_plugin_t *)p;
break;
diff --git a/plugins/notify/notify.c b/plugins/notify/notify.c
index 2b9bfadc..193f6bef 100644
--- a/plugins/notify/notify.c
+++ b/plugins/notify/notify.c
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <string.h>
#include "../../gettext.h"
+#include "../artwork/artwork.h"
#define E_NOTIFICATION_BUS_NAME "org.freedesktop.Notifications"
#define E_NOTIFICATION_INTERFACE "org.freedesktop.Notifications"
@@ -29,10 +30,12 @@
DB_functions_t *deadbeef;
DB_misc_t plugin;
+DB_artwork_plugin_t *artwork_plugin;
static dbus_uint32_t replaces_id = 0;
-#define NOTIFY_DEFAULT_FORMAT "%a - %t"
+#define NOTIFY_DEFAULT_TITLE "%t"
+#define NOTIFY_DEFAULT_CONTENT "%a - %b"
static void
notify_thread (void *ctx) {
@@ -114,116 +117,130 @@ notify_marshal_dict_string(DBusMessageIter *iter, const char *key, const char *v
}
#endif
+static void
+esc_xml (const char *cmd, char *esc, int size) {
+ const char *src = cmd;
+ char *dst = esc;
+ char *end = dst + size - 1;
+ while (*src && dst < end) {
+ if (*src == '&') {
+ if (end - dst < 5) {
+ break;
+ }
+ strcpy (dst, "&amp;");
+ dst += 5;
+ src++;
+ }
+ else if (*src == '<') {
+ if (end - dst < 4) {
+ break;
+ }
+ strcpy (dst, "&lt;");
+ dst += 4;
+ src++;
+ }
+ else if (*src == '>') {
+ if (end - dst < 4) {
+ break;
+ }
+ strcpy (dst, "&gt;");
+ dst += 4;
+ src++;
+ }
+ else if (*src == '\'') {
+ if (end - dst < 6) {
+ break;
+ }
+ strcpy (dst, "&apos;");
+ dst += 6;
+ src++;
+ }
+ else if (*src == '"') {
+ if (end - dst < 6) {
+ break;
+ }
+ strcpy (dst, "&quot;");
+ dst += 6;
+ src++;
+ }
+ else {
+ *dst++ = *src++;
+ }
+ }
+ *dst = 0;
+}
+
+
+static void
+cover_avail_callback (const char *fname, const char *artist, const char *album, void *user_data) {
+// show_notification (track);
+}
+
+static void show_notification (DB_playItem_t *track) {
+ char title[1024];
+ char content[1024];
+ deadbeef->pl_format_title (track, -1, title, sizeof (title), -1, deadbeef->conf_get_str ("notify.format", NOTIFY_DEFAULT_TITLE));
+ deadbeef->pl_format_title (track, -1, content, sizeof (content), -1, deadbeef->conf_get_str ("notify.format_content", NOTIFY_DEFAULT_CONTENT));
+
+ // escape &
+ char esc_title[1024];
+ char esc_content[1024];
+ esc_xml (title, esc_title, sizeof (esc_title));
+ esc_xml (content, esc_content, sizeof (esc_content));
+ DBusMessage *msg = dbus_message_new_method_call (E_NOTIFICATION_BUS_NAME, E_NOTIFICATION_PATH, E_NOTIFICATION_INTERFACE, "Notify");
+
+ const char *v_appname = "DeaDBeeF";
+ dbus_uint32_t v_id = 0;
+ char *v_iconname = NULL;
+ if (deadbeef->conf_get_int("notify.albumart", 0) && artwork_plugin) {
+ const char *album = deadbeef->pl_find_meta (track, "album");
+ const char *artist = deadbeef->pl_find_meta (track, "artist");
+ v_iconname = artwork_plugin->get_album_art (track->fname, artist, album, 48, cover_avail_callback, NULL);
+ }
+ if (!v_iconname) {
+ v_iconname = strdup ("deadbeef");
+ }
+ const char *v_summary = esc_title;
+ const char *v_body = esc_content;
+ dbus_int32_t v_timeout = -1;
+
+ dbus_message_append_args (msg
+ , DBUS_TYPE_STRING, &v_appname
+ , DBUS_TYPE_UINT32, &replaces_id
+ , DBUS_TYPE_STRING, &v_iconname
+ , DBUS_TYPE_STRING, &v_summary
+ , DBUS_TYPE_STRING, &v_body
+ , DBUS_TYPE_INVALID
+ );
+
+ DBusMessageIter iter, sub;
+ // actions
+ dbus_message_iter_init_append(msg, &iter);
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub);
+ dbus_message_iter_close_container(&iter, &sub);
+ // hints
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub);
+ dbus_message_iter_close_container(&iter, &sub);
+
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &v_timeout);
+
+ intptr_t tid = 0;
+ if ((tid=deadbeef->thread_start(notify_thread, msg)) != 0) {
+ dbus_message_ref (msg);
+ deadbeef->thread_detach (tid);
+ }
+ dbus_message_unref (msg);
+ if (v_iconname) {
+ free (v_iconname);
+ }
+}
+
static int
on_songchanged (DB_event_trackchange_t *ev, uintptr_t data) {
if (ev->to && deadbeef->conf_get_int ("notify.enable", 0)) {
DB_playItem_t *track = ev->to;
if (track) {
- char cmd[1024];
- deadbeef->pl_format_title (track, -1, cmd, sizeof (cmd), -1, deadbeef->conf_get_str ("notify.format", NOTIFY_DEFAULT_FORMAT));
-
- // escape &
- char esc[1024];
-
- char *src = cmd;
- char *dst = esc;
- char *end = dst + sizeof (esc) - 1;
- while (*src && dst < end) {
- if (*src == '&') {
- if (end - dst < 5) {
- break;
- }
- strcpy (dst, "&amp;");
- dst += 5;
- src++;
- }
- else if (*src == '<') {
- if (end - dst < 4) {
- break;
- }
- strcpy (dst, "&lt;");
- dst += 4;
- src++;
- }
- else if (*src == '>') {
- if (end - dst < 4) {
- break;
- }
- strcpy (dst, "&gt;");
- dst += 4;
- src++;
- }
- else if (*src == '\'') {
- if (end - dst < 6) {
- break;
- }
- strcpy (dst, "&apos;");
- dst += 6;
- src++;
- }
- else if (*src == '"') {
- if (end - dst < 6) {
- break;
- }
- strcpy (dst, "&quot;");
- dst += 6;
- src++;
- }
- else {
- *dst++ = *src++;
- }
- }
- *dst = 0;
-/*
- DBusError error;
- dbus_error_init (&error);
- DBusConnection *conn = dbus_bus_get (DBUS_BUS_SESSION, &error);
- if(conn == NULL) {
- printf("connection failed: %s",error.message);
- exit(1);
- }
-*/
- DBusMessage *msg = dbus_message_new_method_call (E_NOTIFICATION_BUS_NAME, E_NOTIFICATION_PATH, E_NOTIFICATION_INTERFACE, "Notify");
-
- const char *v_appname = "DeaDBeeF";
- dbus_uint32_t v_id = 0;
- const char *v_iconname = "deadbeef";
- const char *v_summary = _("DeaDBeeF now playing");
- const char *v_body = esc;
- dbus_int32_t v_timeout = -1;
-
- dbus_message_append_args (msg
- , DBUS_TYPE_STRING, &v_appname
-// , DBUS_TYPE_UINT32, &v_id
- , DBUS_TYPE_UINT32, &replaces_id
- , DBUS_TYPE_STRING, &v_iconname
- , DBUS_TYPE_STRING, &v_summary
- , DBUS_TYPE_STRING, &v_body
- , DBUS_TYPE_INVALID
- );
-
- DBusMessageIter iter, sub;
- // actions
- dbus_message_iter_init_append(msg, &iter);
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub);
- dbus_message_iter_close_container(&iter, &sub);
- // hints
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub);
- dbus_message_iter_close_container(&iter, &sub);
-
- dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &v_timeout);
-
- //int serial;
- //dbus_bool_t retval = dbus_connection_send(conn,msg,&serial);
- //dbus_connection_flush (conn);
- //dbus_message_unref (msg);
-
- intptr_t tid = 0;
- if ((tid=deadbeef->thread_start(notify_thread, msg)) != 0) {
- dbus_message_ref (msg);
- deadbeef->thread_detach (tid);
- }
- dbus_message_unref (msg);
+ show_notification (track);
}
}
return 0;
@@ -241,9 +258,23 @@ notify_stop (void) {
return 0;
}
+static int
+notify_connect (void) {
+ artwork_plugin = (DB_artwork_plugin_t *)deadbeef->plug_get_for_id ("artwork");
+ return 0;
+}
+
+static int
+notify_disconnect (void) {
+ artwork_plugin = NULL;
+ return 0;
+}
+
static const char settings_dlg[] =
"property \"Enable\" checkbox notify.enable 0;\n"
- "property \"Notification format\" entry notify.format \"" NOTIFY_DEFAULT_FORMAT "\";\n"
+ "property \"Notification title format\" entry notify.format \"" NOTIFY_DEFAULT_TITLE "\";\n"
+ "property \"Notification content format\" entry notify.format_content \"" NOTIFY_DEFAULT_CONTENT "\";\n"
+ "property \"Show album art\" checkbox notify.albumart 1;\n"
;
DB_misc_t plugin = {
@@ -259,6 +290,8 @@ DB_misc_t plugin = {
.plugin.website = "http://deadbeef.sourceforge.net",
.plugin.start = notify_start,
.plugin.stop = notify_stop,
+ .plugin.connect = notify_connect,
+ .plugin.disconnect = notify_disconnect,
.plugin.configdialog = settings_dlg,
};