Code

lyrics: converted in-process plugins to external programs
authorMax Kellermann <max@duempel.org>
Tue, 16 Sep 2008 17:11:40 +0000 (19:11 +0200)
committerMax Kellermann <max@duempel.org>
Tue, 16 Sep 2008 17:11:40 +0000 (19:11 +0200)
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

20 files changed:
configure.ac
lyrics/hd.py [new file with mode: 0755]
lyrics/leoslyrics.py [new file with mode: 0755]
lyrics/lyricswiki.rb [new file with mode: 0755]
plugins/Makefile.am [deleted file]
plugins/hd/Makefile.am [deleted file]
plugins/hd/lyrics_hd.c [deleted file]
plugins/leoslyrics/Makefile.am [deleted file]
plugins/leoslyrics/easy_download.c [deleted file]
plugins/leoslyrics/easy_download.h [deleted file]
plugins/leoslyrics/lyrics_leoslyrics.c [deleted file]
src/Makefile.am
src/lyrics.c [new file with mode: 0644]
src/lyrics.h [new file with mode: 0644]
src/lyrics_hd.c [deleted file]
src/lyrics_leoslyrics.c [deleted file]
src/main.c
src/screen_lyrics.c
src/src_lyrics.c [deleted file]
src/src_lyrics.h [deleted file]

index 8382c32cb4764b6fe1320daf425c7d4665cb044e..9c0fd9dfa9b42e3eb5344c92ef6b74a296d59b2a 100644 (file)
@@ -134,35 +134,6 @@ PKG_CHECK_MODULES([GTHREAD],
 AC_SUBST(GTHREAD_LIBS)
 AC_SUBST(GTHREAD_CFLAGS)
                  
-dnl check for gmodule
-PKG_CHECK_MODULES([GMODULE], 
-                 [gmodule-2.0],
-                 [gmodule=yes],
-                 [AC_MSG_WARN([gmodule-2.0 >= 0.20 is required the plugin system])])
-AC_SUBST(GMODULE_LIBS)
-AC_SUBST(GMODULE_CFLAGS)
-
-dnl check for libcurl
-PKG_CHECK_MODULES([libcurl], 
-                 [libcurl],
-                 [libcurl=yes],
-                 #[libcurl=yes,LIBS="$LIBS -lcurl"], #doesn't work for me on arch
-                 [AC_MSG_WARN([libcurl is required for the lyrics screen])])
-
-if test "x$libcurl" = "xyes"; then
- LIBS="$LIBS -lcurl" 
-fi
-                 
-dnl check for expat
-expat=expat
-AC_CHECK_LIB([$expat], 
-            [XML_ParserCreate],
-            [have_expat=yes], 
-            [AC_MSG_WARN($expat library is required for lyrics screen)])
-if test "x$have_expat" = "xyes"; then
-LIBS="$LIBS -l$expat"
-fi
-                 
 #if test "x$gthread-2.0" != "xyes"; then
 #  PKG_CHECK_MODULES([GTHREAD], 
 #                   [glib-2.0 >= 2.2],
@@ -250,23 +221,6 @@ if test "x$getmouse" = "xyes" ; then
                [])
 fi
 
-dnl Plugin loading for lyrics sources
-AC_MSG_CHECKING([whether to include the plugin infrastructure])
-AC_ARG_ENABLE([plugin-support],
-            AC_HELP_STRING([--enable-plugin-support],
-                           [Enable loading lyrics plugins @<:@default=yes@:>@]),
-            [plugin_support="$enableval"],
-            [plugin_support=yes])
-if test "x$plugin_support" != "xyes" ; then
-    AC_DEFINE(DISABLE_PLUGIN_SYSTEM, 1, [Disable plugin system])
-fi
-
-if test "x$gmodule" != "xyes" ; then
-    AC_DEFINE(DISABLE_PLUGIN_SYSTEM, 1, [Disable plugin system])
-    plugin_support=no
-fi
-AC_MSG_RESULT([$plugin_support])
-
 dnl Optional screen - artist
 AC_MSG_CHECKING([whether to include the artist screen])
 AC_ARG_ENABLE([artist-screen], 
@@ -343,78 +297,6 @@ fi
 
 AC_MSG_RESULT([$lyrics_screen])
 
-dnl hd
-AC_MSG_CHECKING([whether to build with .lyrics support])
-AC_ARG_WITH([lyrics-hd],
-           AC_HELP_STRING([[--with-lyrics-leoslyrics[=plugin/fixed/no]]],
-                      [enable leoslyrics lyrics source @<:@default=plugin@:>@]),
-       [hd=$withval],
-       [hd=plugin])
-
-if test "x$plugin_support" != "xyes" ; then
-    if test "x$hd" == "xplugin" ; then
-       hd=fixed
-       AC_MSG_NOTICE([Enable lyrics plugin support to compile as a plugin!])
-   fi
-fi     
-AC_MSG_RESULT([$hd])
-if test "x$hd" == "xfixed"; then
-    AC_DEFINE_UNQUOTED([ENABLE_LYRSRC_HD], 1,
-                  [~/.lyrics inclusion])
-fi
-if test "x$hd" == "xplugin" ; then
-    src_lyr_plugins="${src_lyr_plugins}hd "
-fi
-AM_CONDITIONAL(HD_FIXED, test x$hd = xfixed)
-
-dnl leoslyrics
-AC_MSG_CHECKING([whether to build with leoslyrics])
-AC_ARG_WITH([lyrics-leoslyrics],
-           AC_HELP_STRING([[--with-lyrics-leoslyrics[=plugin/fixed/no]]],
-                      [enable leoslyrics lyrics source @<:@default=plugin@:>@]),
-       [leoslyrics=$withval],
-       [leoslyrics=plugin])
-
-if test "x$plugin_support" != "xyes" ; then
-    if test "x$leoslyrics" == "xplugin" ; then
-       leoslyrics=fixed
-       AC_MSG_NOTICE([Enable lyrics plugin support to compile as a plugin!])
-   fi
-fi     
-
-if test "x$have_expat" != "xyes" ; then
-    leoslyrics=no
-fi
-if test "x$libcurl" != "xyes" ; then
-    leoslyrics=no
-fi
-
-if test "x$leoslyrics" == "xplugin" ; then
-    src_lyr_plugins="${src_lyr_plugins}leoslyrics "
-fi
-AC_MSG_RESULT([$leoslyrics])
-
-if test "x$leoslyrics" == "xfixed" ; then 
-    AC_DEFINE_UNQUOTED([ENABLE_LYRSRC_LEOSLYRICS], 1,
-                  [Leoslyrics inclusion])
-fi
-
-#if test "x$leoslyrics" == "xfixed" ; then
- #   src_lyr_fixed="${src_lyr_fixed}../plugins/leoslyrics/lyrics_leoslyrics.c "
- #   leoslyrics_fixed=yes
-#fi
-AM_CONDITIONAL(LEOSLYRICS_FIXED, test x$leoslyrics = xfixed)
-
-dnl plugins directory
-AC_ARG_WITH([plugin-dir],
-           AC_HELP_STRING([[--with-plugin-dir[=DIRECTORY]]],
-                      [Directory where plugins are stored @<:@default=/usr/share/ncmpc/modules@:>@]),
-       [plugindir=$withval],
-       [plugindir="/usr/share/ncmpc/modules"])
-AC_DEFINE_UNQUOTED([PLUGIN_DIR_SYSTEM], ["$plugindir"],
-                  [Directory to search for plugins])
-
-AC_SUBST(plugindir)
 dnl Default host
 AC_MSG_CHECKING([for default MPD host])
 AC_ARG_WITH([default-host],
@@ -445,10 +327,5 @@ AC_ARG_WITH([default-timedisplay_type],
             [DEFAULT_TIMEDISPLAY_TYPE="elapsed"])
 AC_MSG_RESULT([$DEFAULT_TIMEDISPLAY_TYPE])
 AC_DEFINE_UNQUOTED([DEFAULT_TIMEDISPLAY_TYPE], ["$DEFAULT_TIMEDISPLAY_TYPE"], [Default way to display time, either 'elapsed' or 'remaining'])
-AC_SUBST(src_lyr_plugins)
-AC_SUBST(src_lyr_fixed)
-AC_CONFIG_FILES([Makefile src/Makefile plugins/Makefile doc/Makefile po/Makefile 
-               plugins/hd/Makefile 
-               plugins/leoslyrics/Makefile])
+AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile po/Makefile])
 AC_OUTPUT
-AC_MSG_WARN([TO BUILD AN INSTALL THE PLUGINS cd TO THE plugins DIRECTORY AND EXECUTE make && make install THERE])
diff --git a/lyrics/hd.py b/lyrics/hd.py
new file mode 100755 (executable)
index 0000000..173342c
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+#
+# Load lyrics from the user's home directory
+#
+# Author: Max Kellermann <max@duempel.org>
+#
+
+from sys import argv, exit, stdout
+from os import environ
+from os.path import expanduser
+
+path = expanduser("~/.lyrics/%s - %s.txt" % (argv[1], argv[2]))
+try:
+    f = file(path)
+except IOError:
+    exit(2)
+
+while True:
+    x = f.read(4096)
+    if not x:
+        break
+    stdout.write(x)
diff --git a/lyrics/leoslyrics.py b/lyrics/leoslyrics.py
new file mode 100755 (executable)
index 0000000..0cee65a
--- /dev/null
@@ -0,0 +1,68 @@
+#!/usr/bin/python
+#
+# Load lyrics from leoslyrics.com
+#
+# Author: Max Kellermann <max@duempel.org>
+#
+
+from sys import argv, exit
+from urllib import urlencode, urlopen
+from xml.sax import make_parser, SAXException
+from xml.sax.handler import ContentHandler
+
+class SearchContentHandler(ContentHandler):
+    def __init__(self):
+        self.code = None
+        self.hid = None
+
+    def startElement(self, name, attrs):
+        if name == 'response':
+            self.code = int(attrs['code'])
+        elif name == 'result':
+            if self.hid is None or attrs['exactMatch'] == 'true':
+                self.hid = attrs['hid']
+
+def search(artist, title):
+    query = urlencode({'auth': 'ncmpc',
+                       'artist': artist,
+                       'songtitle': title})
+    url = "http://api.leoslyrics.com/api_search.php?" + query
+    f = urlopen(url)
+    handler = SearchContentHandler()
+    parser = make_parser()
+    parser.setContentHandler(handler)
+    parser.parse(f)
+    return handler.hid
+
+class LyricsContentHandler(ContentHandler):
+    def __init__(self):
+        self.code = None
+        self.is_text = False
+        self.text = None
+
+    def startElement(self, name, attrs):
+        if name == 'text':
+            self.text = ''
+            self.is_text = True
+        else:
+            self.is_text = False
+
+    def characters(self, chars):
+        if self.is_text:
+            self.text += chars
+
+def lyrics(hid):
+    query = urlencode({'auth': 'ncmpc',
+                       'hid': hid})
+    url = "http://api.leoslyrics.com/api_lyrics.php?" + query
+    f = urlopen(url)
+    handler = LyricsContentHandler()
+    parser = make_parser()
+    parser.setContentHandler(handler)
+    parser.parse(f)
+    return handler.text
+
+hid = search(argv[1], argv[2])
+if hid is None:
+    exit(2)
+print lyrics(hid)
diff --git a/lyrics/lyricswiki.rb b/lyrics/lyricswiki.rb
new file mode 100755 (executable)
index 0000000..39aa4a5
--- /dev/null
@@ -0,0 +1,16 @@
+#!/usr/bin/env ruby
+#
+# Load lyrics from lyricswiki.org
+#
+# Author: Max Kellermann <max@duempel.org>
+#
+
+require 'uri'
+require 'net/http'
+
+url = "http://lyricwiki.org/api.php" + \
+    "?artist=#{URI.escape(ARGV[0])}&song=#{URI.escape(ARGV[1])}"
+response = Net::HTTP.get(URI.parse(url))
+
+exit(2) unless response =~ /<pre>\s*(.*?)\s*<\/pre>/im
+puts $1
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
deleted file mode 100644 (file)
index 9bb784f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-SUBDIRS = \
-         ${src_lyr_plugins}
-
-AUTOMAKE_OPTIONS =   foreign 1.6
-
-
diff --git a/plugins/hd/Makefile.am b/plugins/hd/Makefile.am
deleted file mode 100644 (file)
index f4d4608..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-AM_CPPFLAGS =\
-  $(GLIB_CFLAGS)\
-  $(GTHREAD_CFLAGS)\
-  $(libcurl_CFLAGS)\
-  -I../../src
-
-###----
-
-plugin_headers =\
-                ../src_lyrics.h\
-                ../screen_lyrics.h\
-                ../easy_download.h\
-                ../options.h
-
-###-----
-
-ncmpc_modulesdir = @plugindir@
-
-ncmpc_modules_LTLIBRARIES = libhd.la 
-
-### libhd
-
-libhd_la_LIBADD =\
-  $(GLIB_LIBS)\
-  $(libcurl_LIBS)
-
-libhd_la_headers =\
-                         $(plugins_headers)
-
-libhd_la_SOURCES =\
-                         lyrics_hd.c\
-                         $(libhd_la_headers)
-install:
-       @$(MAKE)
-       mkdir -p ${ncmpc_modulesdir}
-       if test -f .libs/libhd.so; then cp .libs/libhd.so ${ncmpc_modulesdir}/lyrics_hd.so; fi
-
-uninstall:
-       @$(MAKE)
-       rm -f ${ncmpc_modulesdir}/lyrics_hd.so
diff --git a/plugins/hd/lyrics_hd.c b/plugins/hd/lyrics_hd.c
deleted file mode 100644 (file)
index 7a3a8b7..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-#include <glib.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include "src_lyrics.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_me (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/plugins/leoslyrics/Makefile.am b/plugins/leoslyrics/Makefile.am
deleted file mode 100644 (file)
index 4eb76f3..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-AM_CPPFLAGS =\
-  $(GLIB_CFLAGS)\
-  $(GTHREAD_CFLAGS)\
-  $(libcurl_CFLAGS)\
-  -I../../src
-
-###----
-
-plugin_headers =\
-                ../src_lyrics.h\
-                ../screen_lyrics.h\
-                ../easy_download.h\
-                ../options.h
-
-###-----
-
-ncmpc_modulesdir = @plugindir@
-
-ncmpc_modules_LTLIBRARIES = libleoslyrics.la 
-
-### libleoslyrics
-
-libleoslyrics_la_LIBADD =\
-  $(GLIB_LIBS)\
-  $(libcurl_LIBS)
-
-libleoslyrics_la_headers =\
-                         easy_download.h\
-                         $(plugins_headers)
-
-libleoslyrics_la_SOURCES =\
-                         easy_download.c\
-                         lyrics_leoslyrics.c\
-                         $(libleoslyrics_la_headers)
-
-install:
-       @$(MAKE)
-       mkdir -p ${DESTDIR}${libdir}
-       if test -f .libs/libleoslyrics.so; then cp .libs/libleoslyrics.so ${ncmpc_modulesdir}/lyrics_leoslyrics.so; fi
-
-uninstall:
-       @$(MAKE)
-       rm -f ${ncmpc_modulesdir}/lyrics_leoslyrics.so
diff --git a/plugins/leoslyrics/easy_download.c b/plugins/leoslyrics/easy_download.c
deleted file mode 100644 (file)
index 83616cf..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*     by Qball
- *  
- *  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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-#include "ncmpc.h"
-
-#ifdef ENABLE_LYRICS_SCREEN
-
-#include <curl/curl.h>
-#include "easy_download.h"
-
-static size_t write_data(void *buffer, size_t size,
-       size_t nmemb, easy_download_struct *dld)
-{
-       if(dld->data == NULL)
-       {
-               dld->size = 0;
-       }
-       dld->data = g_realloc(dld->data,(gulong)(size*nmemb+dld->size));
-
-       memset(&(dld->data)[dld->size], '\0', (size*nmemb));
-       memcpy(&(dld->data)[dld->size], buffer, size*nmemb);
-
-       dld->size += size*nmemb;
-       if(dld->size >= dld->max_size && dld->max_size > 0)
-       {
-               return 0;
-       }
-       return size*nmemb;
-}
-
-int easy_download(char *url,easy_download_struct *dld,
-               curl_progress_callback cb)
-{
-       CURL *curl = NULL;
-       int res;
-       if(!dld) return 0;
-       easy_download_clean(dld);
-       /* initialize curl */
-       curl = curl_easy_init();
-       if(!curl) return 0;
-       /* set uri */
-       curl_easy_setopt(curl, CURLOPT_URL, url);
-       /* set callback data */
-       curl_easy_setopt(curl, CURLOPT_WRITEDATA, dld);
-       /* set callback function */
-       curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
-       curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
-       curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, cb);
-       /* run */
-       res = curl_easy_perform(curl);
-       /* cleanup */
-       curl_easy_cleanup(curl);
-       if(!res)
-       {
-               return 1;
-       }
-       if(dld->data) g_free(dld->data);
-       return 0;
-}
-
-void easy_download_clean(easy_download_struct *dld)
-{
-       if(dld->data)g_free(dld->data);
-       dld->data = NULL;
-       dld->size = 0;
-       dld->max_size = -1;
-}
-
-#endif
diff --git a/plugins/leoslyrics/easy_download.h b/plugins/leoslyrics/easy_download.h
deleted file mode 100644 (file)
index 92dc22e..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *  by Qball
- *
- *  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 <curl/curl.h>
-
-typedef struct _easy_download_struct{
-       char *data;
-       int size;
-       int max_size;
-
-}easy_download_struct;
-
-
-int easy_download(char *url,easy_download_struct *dld, 
-               curl_progress_callback cb);
-void easy_download_clean(easy_download_struct *dld);
diff --git a/plugins/leoslyrics/lyrics_leoslyrics.c b/plugins/leoslyrics/lyrics_leoslyrics.c
deleted file mode 100644 (file)
index 5bcb322..0000000
+++ /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];
-
-        //this replacess the whitespaces with '+'
-        g_strdelimit(artist, " ", '+');
-        g_strdelimit(title, " ", '+');
-        
-        //we insert the artist and the title into the url              
-        snprintf(url_avail, 512, LEOSLYRICS_SEARCH_URL, artist, 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
-
-       CURL *curl = curl_easy_init ();
-       char *esc_hid = curl_easy_escape (curl, hid, 0);
-       free (hid);
-
-        snprintf(url, 512, LEOSLYRICS_CONTENT_URL, 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_me (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";
-}
index 21bef4d20d4b09c913346802b385232003d8d74d..31cabfda0be43b21acde8836d2248176f49837e8 100644 (file)
@@ -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 (file)
index 0000000..10ba2a9
--- /dev/null
@@ -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 (file)
index 0000000..34380c3
--- /dev/null
@@ -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 (file)
index e7acfc2..0000000
+++ /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 (file)
index 99dac9d..0000000
+++ /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";
-}
index 52cbd4758317789ef712015b01a981100a7b7015..d54fd37179f813504e3e5a9c5439879ce8689b90 100644 (file)
@@ -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();
index 99487da3396c03672643dd9a8d405d1b10d391a7..2f63fb0ae62be5d5cd72cbffa117c8b5d07b9ffd 100644 (file)
@@ -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
 #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 (file)
index 21e6437..0000000
+++ /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 (file)
index 98c695d..0000000
+++ /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