Code

lyrics: added callback
authorMax Kellermann <max@duempel.org>
Tue, 23 Sep 2008 10:08:53 +0000 (12:08 +0200)
committerMax Kellermann <max@duempel.org>
Tue, 23 Sep 2008 10:08:53 +0000 (12:08 +0200)
Instead of letting our caller poll lyrics_result(), call it back as
soon as we have the result.

src/lyrics.c
src/lyrics.h
src/screen_lyrics.c

index 917344701cf0d338af7d4526e155f4070004a61c..7a6124b6908be941383a4338dac6934f862822fd 100644 (file)
@@ -32,7 +32,8 @@ static GPtrArray *plugins;
 struct lyrics_loader {
        char *artist, *title;
 
-       enum lyrics_loader_result result;
+       lyrics_callback_t callback;
+       void *callback_data;
 
        guint next_plugin;
 
@@ -99,7 +100,7 @@ lyrics_eof(struct lyrics_loader *loader)
 
                lyrics_next_plugin(loader);
        } else {
-               loader->result = LYRICS_SUCCESS;
+               loader->callback(loader->data, loader->callback_data);
        }
 }
 
@@ -112,7 +113,6 @@ lyrics_data(mpd_unused GIOChannel *source,
        ssize_t nbytes;
 
        assert(loader != NULL);
-       assert(loader->result = LYRICS_BUSY);
        assert(loader->fd >= 0);
        assert(loader->pid > 0);
        assert(source == loader->channel);
@@ -134,6 +134,28 @@ lyrics_data(mpd_unused GIOChannel *source,
        return TRUE;
 }
 
+/**
+ * This is a timer callback which calls the lyrics callback "some
+ * timer later".  This solves the problem that lyrics_load() may fail
+ * immediately, leaving its return value in an undefined state.
+ * Instead, install a timer which calls the lyrics callback in the
+ * moment after.
+ */
+static gboolean
+lyrics_delayed_fail(gpointer data)
+{
+       struct lyrics_loader *loader = data;
+
+       assert(loader != NULL);
+       assert(loader->fd < 0);
+       assert(loader->pid < 0);
+       assert(loader->data == NULL);
+
+       loader->callback(NULL, loader->callback_data);
+
+       return FALSE;
+}
+
 static int
 lyrics_start_plugin(struct lyrics_loader *loader, const char *plugin_path)
 {
@@ -141,7 +163,6 @@ lyrics_start_plugin(struct lyrics_loader *loader, const char *plugin_path)
        pid_t pid;
 
        assert(loader != NULL);
-       assert(loader->result == LYRICS_BUSY);
        assert(loader->pid < 0);
        assert(loader->fd < 0);
        assert(loader->data == NULL);
@@ -198,7 +219,7 @@ lyrics_next_plugin(struct lyrics_loader *loader)
 
        if (loader->next_plugin >= plugins->len) {
                /* no plugins left */
-               loader->result = LYRICS_FAILED;
+               g_timeout_add(0, lyrics_delayed_fail, loader);
                return;
        }
 
@@ -206,13 +227,14 @@ lyrics_next_plugin(struct lyrics_loader *loader)
        ret = lyrics_start_plugin(loader, plugin_path);
        if (ret < 0) {
                /* system error */
-               loader->result = LYRICS_FAILED;
+               g_timeout_add(0, lyrics_delayed_fail, loader);
                return;
        }
 }
 
 struct lyrics_loader *
-lyrics_load(const char *artist, const char *title)
+lyrics_load(const char *artist, const char *title,
+           lyrics_callback_t callback, void *data)
 {
        struct lyrics_loader *loader = g_new(struct lyrics_loader, 1);
 
@@ -224,7 +246,8 @@ lyrics_load(const char *artist, const char *title)
 
        loader->artist = g_strdup(artist);
        loader->title = g_strdup(title);
-       loader->result = LYRICS_BUSY;
+       loader->callback = callback;
+       loader->data = data;
        loader->next_plugin = 0;
        loader->pid = -1;
        loader->fd = -1;
@@ -254,19 +277,3 @@ lyrics_free(struct lyrics_loader *loader)
        if (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)
-{
-       assert(loader->result == LYRICS_SUCCESS);
-       assert(loader->pid < 0);
-       assert(loader->data != NULL);
-
-       return loader->data;
-}
index 34380c344b576b71b5e01bbe2850138389240554..613ccb338f289f2841acb8a615de6200b0a3aa19 100644 (file)
 
 #include <glib.h>
 
-enum lyrics_loader_result {
-       LYRICS_SUCCESS,
-       LYRICS_BUSY,
-       LYRICS_FAILED
-};
+typedef void (*lyrics_callback_t)(const GString *result, void *data);
 
 struct lyrics_loader;
 
@@ -34,15 +30,10 @@ void lyrics_init(void);
 void lyrics_deinit(void);
 
 struct lyrics_loader *
-lyrics_load(const char *artist, const char *title);
+lyrics_load(const char *artist, const char *title,
+           lyrics_callback_t callback, void *callback_data);
 
 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
index cfc65893981ac9c119f2c93e88f09684ec17f5dc..9b9ea03a2f505145dcb31b51dc818cdb96518854 100644 (file)
@@ -76,15 +76,15 @@ screen_lyrics_clear(void)
 {
        guint i;
 
-       assert(current.loader == NULL ||
-              lyrics_result(current.loader) == LYRICS_SUCCESS);
-
        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 const char *
+list_callback(unsigned idx, int *highlight, void *data);
+
 static void
 screen_lyrics_set(const GString *str)
 {
@@ -122,32 +122,30 @@ screen_lyrics_set(const GString *str)
 
        if (*p != 0)
                g_ptr_array_add(current.lines, g_strdup(p));
+
+       /* paint new data */
+
+       if (get_cur_mode_id() == 104) { /* XXX don't use the literal number */
+               lw->clear = 1;
+               list_window_paint(lw, list_callback, NULL);
+               wrefresh(lw->w);
+
+               /* XXX repaint the screen title */
+       }
 }
 
-static int
-screen_lyrics_poll(void)
+static void
+screen_lyrics_callback(const GString *result, mpd_unused void *data)
 {
        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;
+       if (result != NULL)
+               screen_lyrics_set(result);
+       else
                screen_status_message (_("No lyrics"));
-               return -1;
-       }
 
-       assert(0);
-       return -1;
+       lyrics_free(current.loader);
+       current.loader = NULL;
 }
 
 static void
@@ -168,7 +166,8 @@ screen_lyrics_load(struct mpd_song *song)
        strfsong(buffer, sizeof(buffer), "%title%", song);
        current.title = g_strdup(buffer);
 
-       current.loader = lyrics_load(current.artist, current.title);
+       current.loader = lyrics_load(current.artist, current.title,
+                                    screen_lyrics_callback, NULL);
 }
 
 static void lyrics_paint(screen_t *screen, mpdclient_t *c);
@@ -246,8 +245,6 @@ 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();
 }
 
 
@@ -292,14 +289,6 @@ lyrics_cmd(screen_t *screen, mpdclient_t *c, command_t cmd)
                return 1;
 
        switch(cmd) {
-       case CMD_SELECT:
-               /* XXX */
-               if (current.loader != NULL) {
-                       int ret = screen_lyrics_poll();
-                       if (ret != 0)
-                               lyrics_paint(NULL, NULL);
-               }
-               return 1;
        case CMD_INTERRUPT:
                if (current.loader != NULL) {
                        screen_lyrics_abort();