aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2008-09-16 19:11:40 +0200
committerMax Kellermann <max@duempel.org>2008-09-16 19:11:40 +0200
commitf41b9942af7278ab67dc799ad6c17ad74dc0aa1b (patch)
tree69c7c715ff3abd78bb26a7a4d80dd1da5fd5c08b /src
parent4d01c183b4c1e4c51dff3d9aeec1c01ce13a4323 (diff)
downloadmpd-f41b9942af7278ab67dc799ad6c17ad74dc0aa1b.tar.gz
mpd-f41b9942af7278ab67dc799ad6c17ad74dc0aa1b.tar.xz
mpd-f41b9942af7278ab67dc799ad6c17ad74dc0aa1b.zip
lyrics: converted in-process plugins to external programs
In-process plugins are very problematic. It is much easier and flexible to move the lyrics plugins to external programs, with a trivial protocol. This is work in progress, among the things missing: - protocol specification, including exit codes - plugin installation - plugin search directory - run-time configuration (currently hard coded) - automatic polling (using glib's main loop?) - better and more robust error handling
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am20
-rw-r--r--src/lyrics.c243
-rw-r--r--src/lyrics.h48
-rw-r--r--src/lyrics_hd.c50
-rw-r--r--src/lyrics_leoslyrics.c162
-rw-r--r--src/main.c4
-rw-r--r--src/screen_lyrics.c355
-rw-r--r--src/src_lyrics.c202
-rw-r--r--src/src_lyrics.h75
9 files changed, 482 insertions, 677 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 21bef4d20..31cabfda0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,21 +3,18 @@
AM_CPPFLAGS = \
$(GLIB_CFLAGS)\
$(GTHREAD_CFLAGS)\
- $(GMODULE_CFLAGS)\
-DLOCALE_DIR=\""$(datadir)/locale"\"\
-DSYSCONFDIR=\""$(sysconfdir)"\"
ncmpc_LDADD = \
$(GLIB_LIBS)\
- $(GTHREAD_LIBS)\
- $(GMODULE_LIBS)
+ $(GTHREAD_LIBS)
ncmpc_headers = \
libmpdclient.h\
song.h \
mpdclient.h\
playlist.h \
- easy_download.h\
options.h\
conf.h\
command.h\
@@ -31,7 +28,7 @@ ncmpc_headers = \
utils.h\
ncmpc.h\
screen_browse.h\
- src_lyrics.h \
+ lyrics.h \
str_pool.h \
gcc.h
@@ -50,7 +47,6 @@ ncmpc_SOURCES = \
options.c\
conf.c\
command.c\
- easy_download.c\
screen.c\
screen_utils.c\
screen_play.c\
@@ -67,19 +63,9 @@ ncmpc_SOURCES = \
wreadln.c\
strfsong.c\
utils.c\
- src_lyrics.c \
+ lyrics.c \
str_pool.c
-if LEOSLYRICS_FIXED
-ncmpc_SOURCES+=lyrics_leoslyrics.c
-AM_CPPFLAGS+=${libcurl_CFLAGS}
-ncmpc_LDADD+=${libcurl_LIBS}
-endif
-
-if HD_FIXED
-ncmpc_SOURCES+=lyrics_hd.c
-endif
-
ncmpc_SOURCES+=${ncmpc_headers}
diff --git a/src/lyrics.c b/src/lyrics.c
new file mode 100644
index 000000000..10ba2a909
--- /dev/null
+++ b/src/lyrics.c
@@ -0,0 +1,243 @@
+/* ncmpc
+ * Copyright (C) 2008 Max Kellermann <max@duempel.org>
+ * This project's homepage is: http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "lyrics.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/signal.h>
+#include <sys/wait.h>
+#include <pthread.h>
+
+static GPtrArray *plugins;
+
+struct lyrics_loader {
+ char *artist, *title;
+
+ enum lyrics_loader_result result;
+
+ pthread_t thread;
+ pthread_mutex_t mutex;
+
+ pid_t pid;
+ int fd;
+
+ GString *data;
+};
+
+static int lyrics_register_plugin(const char *path0)
+{
+ int ret;
+ struct stat st;
+ char *path;
+
+ ret = stat(path0, &st);
+ if (ret < 0)
+ return -1;
+
+ path = g_strdup(path0);
+ g_ptr_array_add(plugins, path);
+ return 0;
+}
+
+void lyrics_init(void)
+{
+ plugins = g_ptr_array_new();
+
+ /* XXX configurable paths */
+ lyrics_register_plugin("./lyrics/hd.py");
+ lyrics_register_plugin("./lyrics/leoslyrics.py");
+ lyrics_register_plugin("./lyrics/lyricswiki.rb");
+}
+
+void lyrics_deinit(void)
+{
+ guint i;
+
+ for (i = 0; i < plugins->len; ++i)
+ free(g_ptr_array_index(plugins, i));
+ g_ptr_array_free(plugins, TRUE);
+}
+
+static int
+lyrics_start_plugin(struct lyrics_loader *loader, const char *plugin_path)
+{
+ int ret, fds[2];
+ pid_t pid;
+
+ assert(loader != NULL);
+ assert(loader->result == LYRICS_BUSY);
+ assert(loader->pid < 0);
+
+ ret = pipe(fds);
+ if (ret < 0)
+ return -1;
+
+ pid = fork();
+
+ if (pid < 0) {
+ close(fds[0]);
+ close(fds[1]);
+ return -1;
+ }
+
+ if (pid == 0) {
+ dup2(fds[1], 1);
+ dup2(fds[1], 1);
+ close(fds[0]);
+ close(fds[1]);
+ close(0);
+ /* XXX close other fds? */
+
+ execl(plugin_path, plugin_path,
+ loader->artist, loader->title, NULL);
+ _exit(1);
+ }
+
+ close(fds[1]);
+
+ loader->pid = pid;
+ loader->fd = fds[0];
+ loader->data = g_string_new(NULL);
+
+ /* XXX CLOEXEC? */
+
+ return 0;
+}
+
+static int
+lyrics_try_plugin(struct lyrics_loader *loader, const char *plugin_path)
+{
+ int ret, status;
+ char buffer[256];
+ ssize_t nbytes;
+
+ assert(loader != NULL);
+ assert(loader->fd >= 0);
+
+ ret = lyrics_start_plugin(loader, plugin_path);
+ if (ret != 0)
+ return ret;
+
+ assert(loader->pid > 0);
+
+ while ((nbytes = read(loader->fd, buffer, sizeof(buffer))) > 0)
+ g_string_append_len(loader->data, buffer, nbytes);
+
+ ret = waitpid(loader->pid, &status, 0);
+ loader->pid = -1;
+
+ if (ret < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ g_string_free(loader->data, TRUE);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void *
+lyrics_thread(void *arg)
+{
+ struct lyrics_loader *loader = arg;
+ guint next_plugin = 0;
+ int ret = -1;
+
+ while (next_plugin < plugins->len && ret != 0) {
+ const char *plugin_path = g_ptr_array_index(plugins,
+ next_plugin++);
+ ret = lyrics_try_plugin(loader, plugin_path);
+ assert(loader->pid < 0);
+ }
+
+ pthread_mutex_lock(&loader->mutex);
+ loader->result = ret == 0 ? LYRICS_SUCCESS : LYRICS_FAILED;
+ loader->thread = 0;
+ pthread_mutex_unlock(&loader->mutex);
+ return NULL;
+}
+
+struct lyrics_loader *
+lyrics_load(const char *artist, const char *title)
+{
+ struct lyrics_loader *loader = g_new(struct lyrics_loader, 1);
+ int ret;
+
+ assert(artist != NULL);
+ assert(title != NULL);
+
+ if (loader == NULL)
+ return NULL;
+
+ loader->artist = g_strdup(artist);
+ loader->title = g_strdup(title);
+ loader->result = LYRICS_BUSY;
+ loader->pid = -1;
+
+ pthread_mutex_init(&loader->mutex, NULL);
+
+ ret = pthread_create(&loader->thread, NULL, lyrics_thread, loader);
+ if (ret != 0) {
+ lyrics_free(loader);
+ return NULL;
+ }
+
+ return loader;
+}
+
+void
+lyrics_free(struct lyrics_loader *loader)
+{
+ pid_t pid = loader->pid;
+ pthread_t thread = loader->thread;
+
+ if (pid > 0)
+ kill(pid, SIGTERM);
+
+ if (loader->thread != 0)
+ pthread_join(thread, NULL);
+
+ assert(loader->pid < 0);
+ assert(loader->thread == 0);
+
+ if (loader->result == LYRICS_SUCCESS && loader->data != NULL)
+ g_string_free(loader->data, TRUE);
+}
+
+enum lyrics_loader_result
+lyrics_result(struct lyrics_loader *loader)
+{
+ return loader->result;
+}
+
+const GString *
+lyrics_get(struct lyrics_loader *loader)
+{
+ /* sync with thread */
+ pthread_mutex_lock(&loader->mutex);
+ pthread_mutex_unlock(&loader->mutex);
+
+ assert(loader->result == LYRICS_SUCCESS);
+ assert(loader->pid < 0);
+ assert(loader->thread == 0);
+ assert(loader->data != NULL);
+
+ return loader->data;
+}
diff --git a/src/lyrics.h b/src/lyrics.h
new file mode 100644
index 000000000..34380c344
--- /dev/null
+++ b/src/lyrics.h
@@ -0,0 +1,48 @@
+/* ncmpc
+ * Copyright (C) 2008 Max Kellermann <max@duempel.org>
+ * This project's homepage is: http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef LYRICS_H
+#define LYRICS_H
+
+#include <glib.h>
+
+enum lyrics_loader_result {
+ LYRICS_SUCCESS,
+ LYRICS_BUSY,
+ LYRICS_FAILED
+};
+
+struct lyrics_loader;
+
+void lyrics_init(void);
+
+void lyrics_deinit(void);
+
+struct lyrics_loader *
+lyrics_load(const char *artist, const char *title);
+
+void
+lyrics_free(struct lyrics_loader *loader);
+
+enum lyrics_loader_result
+lyrics_result(struct lyrics_loader *loader);
+
+const GString *
+lyrics_get(struct lyrics_loader *loader);
+
+#endif
diff --git a/src/lyrics_hd.c b/src/lyrics_hd.c
deleted file mode 100644
index e7acfc252..000000000
--- a/src/lyrics_hd.c
+++ /dev/null
@@ -1,50 +0,0 @@
-#include "src_lyrics.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-
-char *check_lyr_hd(char *artist, char *title, int how)
-{ //checking whether for lyrics file existence and proper access
- result |= 2;
- static char path[1024];
- snprintf(path, 1024, "%s/.lyrics/%s/%s.lyric",
- getenv("HOME"), artist, title);
-
- if(g_access(path, how) != 0) return NULL;
- return path;
-}
-
-
-int get_lyr_hd(char *artist, char *title)
-{
- char *path = check_lyr_hd(artist, title, R_OK);
- if(path == NULL) return -1;
-
- FILE *lyr_file;
- lyr_file = fopen(path, "r");
- if(lyr_file == NULL) return -1;
- result |= 4;
- char *buf = NULL;
- char **line = &buf;
- size_t n = 0;
-
- while(1)
- {
- n = getline(line, &n, lyr_file);
- if( n < 1 || *line == NULL || feof(lyr_file) != 0 ) return 0;
- add_text_line(&lyr_text, *line, n);
- free(*line);
- *line = NULL; n = 0;
- }
-
- return 0;
-}
-
-int register_lyr_hd (src_lyr *source_descriptor)
-{
- source_descriptor->check_lyr = check_lyr_hd;
- source_descriptor->get_lyr = get_lyr_hd;
-
- source_descriptor->name = "Harddisk";
- source_descriptor->description = "";
-}
diff --git a/src/lyrics_leoslyrics.c b/src/lyrics_leoslyrics.c
deleted file mode 100644
index 99dac9dde..000000000
--- a/src/lyrics_leoslyrics.c
+++ /dev/null
@@ -1,162 +0,0 @@
-#include "src_lyrics.h"
-#include "easy_download.h"
-#include <expat.h>
-#include <string.h>
-#include "options.h"
-
-#define LEOSLYRICS_SEARCH_URL "http://api.leoslyrics.com/api_search.php?auth=ncmpc&artist=%s&songtitle=%s"
-#define LEOSLYRICS_CONTENT_URL "http://api.leoslyrics.com/api_lyrics.php?auth=ncmpc&hid=%s"
-#define CREDITS "Lyrics provided by www.LeosLyrics.com"
-
-char *hid;
-XML_Parser parser, contentp;
-
-int check_dl_progress(void *clientp, double dltotal, double dlnow,
- double ultotal, double ulnow)
-{
- if(g_timer_elapsed(dltime, NULL) >= options.lyrics_timeout || lock == 4)
- {
- formed_text_init(&lyr_text);
- return -1;
- }
-
- return 0;
-}
-
-
-
-static void check_content(void *data, const char *name, const char **atts)
-{
- if(strstr(name, "text") != NULL)
- {
-
- result |= 16;
- }
-}
-
-
-static void check_search_response(void *data, const char *name,
- const char **atts)
-{
- if(strstr(name, "response") != NULL)
- {
- result |=2;
- return;
- }
-
- if(result & 4)
- {
- if(strstr(name, "result") != NULL)
- {
- if(strstr(atts[2], "hid") != NULL)
- {
- hid = strdup (atts[3]);
- }
-
- if(strstr(atts[2], "exactMatch") != NULL)
- {
- result |= 8;
- }
- }
- }
-
-}
-
-static void end_tag(void *data, const char *name)
-{
- //hmmmmmm
-}
-
- static void check_search_success(void *userData, const XML_Char *s, int len)
- {
- if(result & 2) //lets first check whether we're right
- { //we don't really want to search in the wrong string
- if(strstr((char*) s, "SUCCESS"))
- {
- result |=4;
- }
- }
- }
-
-static void fetch_text(void *userData, const XML_Char *s, int len)
-{
- if(result & 16)
- {
- if (s[0] == 13 ) return; //ignore any single carriage returns
- add_text_line(&lyr_text, s, len);
- }
-}
-
-/*int deregister_lyr_leoslyrics ()
-{
-
-}*/
-
-int check_lyr_leoslyrics(char *artist, char *title, char *url)
-{
- char url_avail[256];
- CURL *curl = curl_easy_init ();
-
-
- //this replacess the whitespaces with '+'
- char *esc_title = curl_easy_escape (curl, title, 0);
- char *esc_artist = curl_easy_escape (curl, artist, 0);
- //we insert the artist and the title into the url
- snprintf(url_avail, 512, LEOSLYRICS_SEARCH_URL, esc_artist, esc_title);
-
- //download that xml!
- easy_download_struct lyr_avail = {NULL, 0,-1};
-
- g_timer_start(dltime);
- if(!easy_download(url_avail, &lyr_avail, check_dl_progress)) return -1;
- g_timer_stop(dltime);
-
- //we gotta parse that stuff with expat
- parser = XML_ParserCreate(NULL);
- XML_SetUserData(parser, NULL);
-
- XML_SetElementHandler(parser, check_search_response, end_tag);
- XML_SetCharacterDataHandler(parser, check_search_success);
- XML_Parse(parser, lyr_avail.data, strlen(lyr_avail.data), 0);
- XML_ParserFree(parser);
-
- if(!(result & 4)) return -1; //check whether lyrics found
-
- char *esc_hid = curl_easy_escape (curl, hid, 0);
- free (hid);
-
- snprintf(url, 512, LEOSLYRICS_CONTENT_URL, esc_hid);
-
- return 0;
-}
-
-int get_lyr_leoslyrics(char *artist, char *title)
-{
- char url_hid[256];
- if(dltime == NULL) dltime = g_timer_new();
-
- if(check_lyr_leoslyrics(artist, title, url_hid) != 0) return -1;
-
- easy_download_struct lyr_content = {NULL, 0,-1};
- g_timer_continue(dltime);
- if(!(easy_download(url_hid, &lyr_content, check_dl_progress))) return -1;
- g_timer_stop(dltime);
-
- contentp = XML_ParserCreate(NULL);
- XML_SetUserData(contentp, NULL);
- XML_SetElementHandler(contentp, check_content, end_tag);
- XML_SetCharacterDataHandler(contentp, fetch_text);
- XML_Parse(contentp, lyr_content.data, strlen(lyr_content.data), 0);
- XML_ParserFree(contentp);
-
- return 0;
-
-}
-int register_lyr_leoslyrics (src_lyr *source_descriptor)
-{
- source_descriptor->check_lyr = check_lyr_leoslyrics;
- source_descriptor->get_lyr = get_lyr_leoslyrics;
-
- source_descriptor->name = "Leoslyrics";
- source_descriptor->description = "powered by http://www.leoslyrics.com";
-}
diff --git a/src/main.c b/src/main.c
index 52cbd4758..d54fd3717 100644
--- a/src/main.c
+++ b/src/main.c
@@ -25,7 +25,7 @@
#include "options.h"
#include "conf.h"
#include "command.h"
-#include "src_lyrics.h"
+#include "lyrics.h"
#include "screen.h"
#include "screen_utils.h"
#include "strfsong.h"
@@ -252,7 +252,7 @@ main(int argc, const char *argv[])
ncurses_init();
- src_lyr_init ();
+ lyrics_init();
/* connect to our music player daemon */
mpd = mpdclient_new();
diff --git a/src/screen_lyrics.c b/src/screen_lyrics.c
index 99487da33..2f63fb0ae 100644
--- a/src/screen_lyrics.c
+++ b/src/screen_lyrics.c
@@ -1,8 +1,6 @@
-/*
- * $Id: screen_lyrics.c 3355 2006-09-1 17:44:04Z tradiaz $
- *
+/*
* (c) 2006 by Kalle Wallin <kaw@linux.se>
- * Tue Aug 1 23:17:38 2006
+ * Copyright (C) 2008 Max Kellermann <max@duempel.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,9 +26,8 @@
#include "command.h"
#include "screen.h"
#include "screen_utils.h"
-#include "easy_download.h"
#include "strfsong.h"
-#include "src_lyrics.h"
+#include "lyrics.h"
#include "gcc.h"
#define _GNU_SOURCE
@@ -38,160 +35,192 @@
#include <string.h>
#include <glib.h>
#include <ncurses.h>
-#include <expat.h>
#include <unistd.h>
-#include <glib/gstdio.h>
#include <stdio.h>
static list_window_t *lw = NULL;
static int lyrics_text_rows = -1;
-static int src_selection;
-static void lyrics_paint(screen_t *screen, mpdclient_t *c);
+static struct {
+ const struct mpd_song *song;
-static FILE *create_lyr_file(char *artist, char *title)
-{
- char path[1024];
+ char *artist, *title;
- snprintf(path, 1024, "%s/.lyrics",
- getenv("HOME"));
- if(g_access(path, W_OK) != 0) if(mkdir(path, S_IRWXU) != 0) return NULL;
+ struct lyrics_loader *loader;
- snprintf(path, 1024, "%s/.lyrics/%s",
- getenv("HOME"), artist);
- if(g_access(path, W_OK) != 0) if(mkdir(path, S_IRWXU) != 0) return NULL;
+ GPtrArray *lines;
+} current;
- snprintf(path, 1024, "%s/.lyrics/%s/%s.lyric",
- getenv("HOME"), artist, title);
+static void
+screen_lyrics_abort(void)
+{
+ if (current.loader != NULL) {
+ lyrics_free(current.loader);
+ current.loader = NULL;
+ }
- return fopen(path, "w");
+ if (current.artist != NULL) {
+ g_free(current.artist);
+ current.artist = NULL;
+ }
+
+ if (current.title != NULL) {
+ g_free(current.title);
+ current.artist = NULL;
+ }
+
+ current.song = NULL;
}
+static void
+screen_lyrics_clear(void)
+{
+ guint i;
+
+ assert(current.loader == NULL ||
+ lyrics_result(current.loader) == LYRICS_SUCCESS);
-static int store_lyr_hd(void)
+ current.song = NULL;
+
+ for (i = 0; i < current.lines->len; ++i)
+ g_free(g_ptr_array_index(current.lines, i));
+
+ g_ptr_array_set_size(current.lines, 0);
+}
+
+static void
+screen_lyrics_set(const GString *str)
{
- char artist[512];
- char title[512];
- static char path[1024];
- FILE *lyr_file;
- unsigned i;
- char line_buf[1024];
+ const char *p, *eol, *next;
- get_text_line(&lyr_text, 0, artist, 512);
- get_text_line(&lyr_text, 1, title, 512);
- artist[strlen(artist)-1] = '\0';
- title[strlen(title)-1] = '\0';
+ screen_lyrics_clear();
- snprintf(path, 1024, "%s/.lyrics/%s/%s.lyric",
- getenv("HOME"), artist, title);
- lyr_file = create_lyr_file(artist, title);
- if (lyr_file == NULL)
- return -1;
+ p = str->str;
+ while ((eol = strchr(p, '\n')) != NULL) {
+ char *line;
+
+ next = eol + 1;
+
+ /* strip whitespace at end */
+
+ while (eol > p && (unsigned char)eol[-1] <= 0x20)
+ --eol;
- for (i = 3; i <= lyr_text.text->len; i++) {
- if (get_text_line(&lyr_text, i, line_buf, 1024) == -1)
- break;
- fputs(line_buf, lyr_file);
+ /* create copy and append it to current.lines*/
+
+ line = g_malloc(eol - p + 1);
+ memcpy(line, p, eol - p);
+ line[eol - p] = 0;
+
+ g_ptr_array_add(current.lines, line);
+
+ /* reset control characters */
+
+ for (eol = line + (eol - p); line < eol; ++line)
+ if ((unsigned char)*line < 0x20)
+ *line = ' ';
+
+ p = next;
}
- fclose(lyr_file);
- return 0;
+ if (*p != 0)
+ g_ptr_array_add(current.lines, g_strdup(p));
}
+static int
+screen_lyrics_poll(void)
+{
+ assert(current.loader != NULL);
+
+ switch (lyrics_result(current.loader)) {
+ case LYRICS_BUSY:
+ return 0;
+
+ case LYRICS_SUCCESS:
+ screen_lyrics_set(lyrics_get(current.loader));
+ lyrics_free(current.loader);
+ current.loader = NULL;
+ return 1;
+
+ case LYRICS_FAILED:
+ lyrics_free(current.loader);
+ current.loader = NULL;
+ screen_status_message (_("No lyrics"));
+ return -1;
+ }
+
+ assert(0);
+ return -1;
+}
-static void check_repaint(void)
+static void
+screen_lyrics_load(struct mpd_song *song)
{
- if(screen_get_id("lyrics") == get_cur_mode_id())lyrics_paint(NULL, NULL);
+ char buffer[MAX_SONGNAME_LENGTH];
+
+ assert(song != NULL);
+
+ screen_lyrics_abort();
+ screen_lyrics_clear();
+
+ strfsong(buffer, sizeof(buffer), "%artist%", song);
+ current.artist = g_strdup(buffer);
+
+ strfsong(buffer, sizeof(buffer), "%title%", song);
+ current.title = g_strdup(buffer);
+
+ current.loader = lyrics_load(current.artist, current.title);
}
+static void lyrics_paint(screen_t *screen, mpdclient_t *c);
-static gpointer get_lyr(void *c)
+static FILE *create_lyr_file(const char *artist, const char *title)
{
- mpd_Status *status = ((retrieval_spec*)c)->client->status;
- mpd_Song *cur = ((retrieval_spec*)c)->client->song;
- char artist[MAX_SONGNAME_LENGTH];
- char title[MAX_SONGNAME_LENGTH];
-
- //mpdclient_update((mpdclient_t*)c);
+ char path[1024];
- if(!(IS_PAUSED(status->state)||IS_PLAYING(status->state))) {
- formed_text_init(&lyr_text);
- return NULL;
- }
+ snprintf(path, 1024, "%s/.lyrics",
+ getenv("HOME"));
+ mkdir(path, S_IRWXU);
+ snprintf(path, 1024, "%s/.lyrics/%s - %s.txt",
+ getenv("HOME"), artist, title);
- lock=2;
- result = 0;
+ return fopen(path, "w");
+}
- formed_text_init(&lyr_text);
+static int store_lyr_hd(void)
+{
+ FILE *lyr_file;
+ unsigned i;
- strfsong(artist, MAX_SONGNAME_LENGTH, "%artist%", cur);
- strfsong(title, MAX_SONGNAME_LENGTH, "%title%", cur);
+ lyr_file = create_lyr_file(current.artist, current.title);
+ if (lyr_file == NULL)
+ return -1;
- //write header..
- formed_text_init(&lyr_text);
- add_text_line(&lyr_text, artist, 0);
- add_text_line(&lyr_text, title, 0);
- add_text_line(&lyr_text, "", 0);
- add_text_line(&lyr_text, "", 0);
+ for (i = 0; i < current.lines->len; ++i)
+ fprintf(lyr_file, "%s\n",
+ (const char*)g_ptr_array_index(current.lines, i));
- if (((retrieval_spec*)c)->way != -1) /*till it'S of use*/ {
- if(get_lyr_by_src (src_selection, artist, title) != 0) {
- lock=0;
- return NULL;
- }
- }
- /*else{
- if(get_lyr_hd(artist, title) != 0)
- {
- if(get_lyr_hd(artist, title) != 0) return NULL;
- }
- else result |= 1;
- }*/
- //return NULL;
- lw->start = 0;
- check_repaint();
- lock = 1;
- return &lyr_text;
+ fclose(lyr_file);
+ return 0;
}
static const char *
-list_callback(unsigned idx, int *highlight, mpd_unused void *data)
+list_callback(unsigned idx, mpd_unused int *highlight, mpd_unused void *data)
{
- static char buf[512];
-
- //i think i'ts fine to write it into the 1st line...
- if ((idx == lyr_text.lines->len && lyr_text.lines->len > 4) ||
- ((lyr_text.lines->len == 0 || lyr_text.lines->len == 4) &&
- idx == 0)) {
- src_lyr* selected = g_array_index(src_lyr_stack, src_lyr*, src_selection);
- *highlight=3;
- if (selected != NULL)
- return selected->description;
+ if (current.lines == NULL || idx >= current.lines->len)
return "";
- }
-
- if (idx < 2 && lyr_text.lines->len > 4)
- *highlight=3;
- else if(idx >= lyr_text.lines->len ||
- (idx < 4 && idx != 0 && lyr_text.lines->len < 5)) {
- return "";
- }
- get_text_line(&lyr_text, idx, buf, 512);
- return buf;
+ return g_ptr_array_index(current.lines, idx);
}
static void
-lyrics_init(WINDOW *w, int cols, int rows)
+lyrics_screen_init(WINDOW *w, int cols, int rows)
{
+ current.lines = g_ptr_array_new();
lw = list_window_init(w, cols, rows);
lw->flags = LW_HIDE_CURSOR;
- //lyr_text.lines = g_array_new(FALSE, TRUE, 4);
- formed_text_init(&lyr_text);
- if (!g_thread_supported())
- g_thread_init(NULL);
}
static void
@@ -205,46 +234,36 @@ static void
lyrics_exit(void)
{
list_window_free(lw);
-}
+ screen_lyrics_abort();
+ screen_lyrics_clear();
-static const char *
-lyrics_title(mpd_unused char *str, mpd_unused size_t size)
-{
- static GString *msg;
- if (msg == NULL)
- msg = g_string_new ("");
- else g_string_erase (msg, 0, -1);
-
- g_string_append (msg, "Lyrics [");
-
- if (src_selection > (int)src_lyr_stack->len - 1)
- g_string_append (msg, "No plugin available");
- else {
- src_lyr* selected = g_array_index (src_lyr_stack, src_lyr*, src_selection);
- if (selected != NULL)
- g_string_append (msg, selected->name);
- else
- g_string_append (msg, "NONE");
- }
+ g_ptr_array_free(current.lines, TRUE);
+ current.lines = NULL;
+}
- if(lyr_text.lines->len == 4) {
- if(lock == 1) {
- if(!(result & 1)) {
- g_string_append (msg, " - ");
- if(!(result & 2)) g_string_append (msg, _("No access"));
- else if(!(result & 4)||!(result & 16)) g_string_append (msg, _("Not found"));
- }
- }
- if(lock == 2) {
- g_string_append (msg, " - ");
- g_string_append (msg, _("retrieving"));
- }
- }
+static void
+lyrics_open(mpd_unused screen_t *screen, mpdclient_t *c)
+{
+ if (c->song != NULL && c->song != current.song)
+ screen_lyrics_load(c->song);
+ else if (current.loader != NULL)
+ screen_lyrics_poll();
+}
- g_string_append_c (msg, ']');
- return msg->str;
+static const char *
+lyrics_title(char *str, size_t size)
+{
+ if (current.loader != NULL)
+ return "Lyrics (loading)";
+ else if (current.artist != NULL && current.title != NULL &&
+ current.lines->len > 0) {
+ snprintf(str, size, "Lyrics: %s - %s",
+ current.artist, current.title);
+ return str;
+ } else
+ return "Lyrics";
}
static void
@@ -270,12 +289,10 @@ lyrics_update(mpd_unused screen_t *screen, mpd_unused mpdclient_t *c)
static int
lyrics_cmd(screen_t *screen, mpdclient_t *c, command_t cmd)
{
- static retrieval_spec spec;
-
lw->repaint=1;
switch(cmd) {
case CMD_LIST_NEXT:
- if( lw->start+lw->rows < lyr_text.lines->len+1 )
+ if (current.lines != NULL && lw->start+lw->rows < current.lines->len+1)
lw->start++;
return 1;
case CMD_LIST_PREVIOUS:
@@ -307,29 +324,29 @@ lyrics_cmd(screen_t *screen, mpdclient_t *c, command_t cmd)
lw->start = 0;
return 1;
case CMD_SELECT:
- spec.client = c;
- spec.way = 0;
- g_thread_create(get_lyr, &spec, FALSE, NULL);
+ /* XXX */
+ if (current.loader != NULL) {
+ int ret = screen_lyrics_poll();
+ if (ret != 0)
+ lyrics_paint(NULL, NULL);
+ }
return 1;
case CMD_INTERRUPT:
- if(lock > 1) lock = 4;
+ if (current.loader != NULL) {
+ screen_lyrics_abort();
+ screen_lyrics_clear();
+ }
return 1;
case CMD_ADD:
- if(lock > 0 && lock != 4) {
- if(store_lyr_hd() == 0)
- screen_status_message (_("Lyrics saved!"));
- }
+ if (current.loader == NULL && current.artist != NULL &&
+ current.title != NULL && store_lyr_hd() == 0)
+ screen_status_message (_("Lyrics saved!"));
return 1;
case CMD_LYRICS_UPDATE:
- spec.client = c;
- spec.way = 1;
- g_thread_create(get_lyr, &spec, FALSE, NULL);
- return 1;
- case CMD_SEARCH_MODE:
- //while (0==0) fprintf (stderr, "%i", src_lyr_stack->len);
- if (src_selection == (int)src_lyr_stack->len - 1)
- src_selection = -1;
- src_selection++;
+ if (c->song != NULL) {
+ screen_lyrics_load(c->song);
+ lyrics_paint(NULL, NULL);
+ }
return 1;
default:
break;
@@ -365,9 +382,9 @@ get_screen_lyrics(void)
static screen_functions_t functions;
memset(&functions, 0, sizeof(screen_functions_t));
- functions.init = lyrics_init;
+ functions.init = lyrics_screen_init;
functions.exit = lyrics_exit;
- functions.open = NULL;
+ functions.open = lyrics_open;
functions.close = NULL;
functions.resize = lyrics_resize;
functions.paint = lyrics_paint;
diff --git a/src/src_lyrics.c b/src/src_lyrics.c
deleted file mode 100644
index 21e6437be..000000000
--- a/src/src_lyrics.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- *
- * (c) 2006 by Kalle Wallin <kaw@linux.se>
- * Thu Dec 28 23:17:38 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include "src_lyrics.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-
-#define PLUGIN_DIR_USER "/.ncmpc/plugins"
-
-int get_text_line(formed_text *text, unsigned num, char *dest, size_t len)
-{
- int linelen;
-
- memset(dest, '\0', len*sizeof(char));
- if (num >= text->lines->len - 1)
- return -1;
-
- if (num == 0) {
- linelen = g_array_index(text->lines, int, num);
- memcpy(dest, text->text->str, linelen*sizeof(char));
- } else if (num == 1) { //dont ask me why, but this is needed....
- linelen = g_array_index(text->lines, int, num)
- - g_array_index(text->lines, int, num-1);
- memcpy(dest, &text->text->str[g_array_index(text->lines, int, num-1)],
- linelen*sizeof(char));
- } else {
- linelen = g_array_index(text->lines, int, num+1)
- - g_array_index(text->lines, int, num);
- memcpy(dest, &text->text->str[g_array_index(text->lines, int, num)],
- linelen*sizeof(char));
- }
-
- dest[linelen] = '\n';
- dest[linelen + 1] = '\0';
-
- return 0;
-}
-
-void add_text_line(formed_text *dest, const char *src, int len)
-{
-
- // need this because g_array_append_val doesnt work with literals
- // and expat sends "\n" as an extra line everytime
- if(len == 0) {
- dest->val = strlen(src);
- if(dest->lines->len > 0) dest->val += g_array_index(dest->lines, int,
- dest->lines->len-1);
- g_string_append(dest->text, src);
- g_array_append_val(dest->lines, dest->val);
- return;
- }
-
- if(len > 1 || dest->val == 0) {
- dest->val = len;
- if(dest->lines->len > 0) dest->val += g_array_index(dest->lines, int,
- dest->lines->len-1);
- } else if (len < 6 && dest->val != 0)
- dest->val = 0;
-
- if (dest->val > 0) {
- g_string_append_len(dest->text, src, len);
- g_array_append_val(dest->lines, dest->val);
- }
-}
-
-void formed_text_init(formed_text *text)
-{
- if (text->text != NULL)
- g_string_free(text->text, TRUE);
- text->text = g_string_new("");
-
- if (text->lines != NULL)
- g_array_free(text->lines, TRUE);
- text->lines = g_array_new(FALSE, TRUE, 4);
-
- text->val = 0;
-}
-
-#ifdef ENABLE_LYRSRC_LEOSLYRICS
-int deregister_lyr_leoslyrics ();
-int register_lyr_leoslyrics (src_lyr *source_descriptor);
-#endif
-
-#ifdef ENABLE_LYRSRC_HD
-int deregister_lyr_hd ();
-int register_lyr_hd (src_lyr *source_descriptor);
-#endif
-
-static int src_lyr_plugins_load(void);
-
-void src_lyr_stack_init(void)
-{
- src_lyr_stack = g_array_new (TRUE, FALSE, sizeof (src_lyr*));
-
-#ifdef ENABLE_LYRSRC_HD
- src_lyr *src_lyr_hd = malloc (sizeof (src_lyr));
- src_lyr_hd->register_src_lyr = register_lyr_hd;
- g_array_append_val (src_lyr_stack, src_lyr_hd);
-#endif
-#ifdef ENABLE_LYRSRC_LEOSLYRICS
- src_lyr *src_lyr_leoslyrics = malloc (sizeof (src_lyr));
- src_lyr_leoslyrics->register_src_lyr = register_lyr_leoslyrics;
- g_array_append_val (src_lyr_stack, src_lyr_leoslyrics);
-#endif
-
-#ifndef DISABLE_PLUGIN_SYSTEM
-
- src_lyr_plugins_load ();
-#endif
-}
-
-int src_lyr_init(void)
-{
- int i = 0;
-
- src_lyr_stack_init ();
-
- while (g_array_index (src_lyr_stack, src_lyr*, i) != NULL) {
- src_lyr *i_stack;
- i_stack = g_array_index (src_lyr_stack, src_lyr*, i);
- i_stack->register_src_lyr (i_stack);
- i++;
- }
- return 0;
-}
-
-int get_lyr_by_src (int priority, char *artist, char *title)
-{
- if(src_lyr_stack->len == 0) return -1;
- g_array_index (src_lyr_stack, src_lyr*, priority)->get_lyr (artist, title);
- return 0;
-}
-
-static int src_lyr_load_plugin_file(const char *file)
-{
- GString *path;
- src_lyr *new_src;
- src_lyr_plugin_register register_func;
-
- path = g_string_new (PLUGIN_DIR_SYSTEM);
- g_string_append (path, "/");
- g_string_append (path, file);
-
- new_src = malloc(sizeof(src_lyr));
- new_src->module = g_module_open (path->str, G_MODULE_BIND_LAZY);
- if (!g_module_symbol (new_src->module, "register_me", (gpointer*) &register_func))
- return -1;
- new_src->register_src_lyr = register_func;
- g_array_append_val (src_lyr_stack, new_src);
- return 0;
-}
-
-static void src_lyr_plugins_load_from_dir(GDir *plugin_dir)
-{
- const gchar *cur_file;
-
- for (;;) {
- cur_file = g_dir_read_name (plugin_dir);
- if (cur_file == NULL) break;
- src_lyr_load_plugin_file (cur_file);
- }
-}
-
-static int src_lyr_plugins_load(void)
-{
- GDir *plugin_dir;
- GString *user_dir_path;
-
- plugin_dir = g_dir_open (PLUGIN_DIR_SYSTEM, 0, NULL);
- if (plugin_dir == NULL)
- return -1;
- src_lyr_plugins_load_from_dir (plugin_dir);
-
- user_dir_path = g_string_new (g_get_home_dir());
- g_string_append (user_dir_path, PLUGIN_DIR_USER);
-
- plugin_dir = g_dir_open (user_dir_path->str, 0, NULL);
- if (plugin_dir == NULL)
- return -1;
- src_lyr_plugins_load_from_dir (plugin_dir);
-
- return 0;
-}
diff --git a/src/src_lyrics.h b/src/src_lyrics.h
deleted file mode 100644
index 98c695dac..000000000
--- a/src/src_lyrics.h
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef SOURCE_LYRICS
-#define SOURCE_LYRICS
-
-#include "config.h"
-#include "mpdclient.h"
-
-#include <sys/types.h>
-#include <glib.h>
-#include <gmodule.h>
-
-typedef struct _formed_text
-{
- GString *text;
- GArray *lines;
- int val;
-} formed_text;
-
-void formed_text_init(formed_text *text);
-void add_text_line(formed_text *dest, const char *src, int len);
-
-typedef struct _retrieval_spec
-{
- mpdclient_t *client;
- int way;
-} retrieval_spec;
-
-GTimer *dltime;
-short int lock;
-formed_text lyr_text;
-
-guint8 result;
-
-/* result is a bitset in which the success when searching 4 lyrics is logged
-countend by position - backwards
-0: lyrics in database
-1: proper access to the lyrics provider
-2: lyrics found
-3: exact match
-4: lyrics downloaded
-5: lyrics saved
-wasting 3 bits doesn't mean being a fat memory hog like kde.... does it?
-*/
-
-
-typedef struct src_lyr src_lyr;
-
-struct src_lyr
-{
- char *name;
- char *source_name;
- char *description;
-
- int (*register_src_lyr) (src_lyr *source_descriptor);
- int (*deregister_src_lyr)(void);
-
- int (*check_lyr) (char *artist, char *title, char *url);
- int (*get_lyr) (char *artist, char *title);
- int (*state_lyr)(void);
-
-#ifndef DISABLE_PLUGIN_SYSTEM
- GModule *module;
-#endif
-};
-
-typedef int (*src_lyr_plugin_register) (src_lyr *source_descriptor);
-
-GArray *src_lyr_stack;
-
-int get_text_line(formed_text *text, unsigned num, char *dest, size_t len);
-
-void src_lyr_stack_init(void);
-int src_lyr_init(void);
-int get_lyr_by_src (int priority, char *artist, char *title);
-
-#endif