From: Max Kellermann Date: Tue, 23 Sep 2008 10:08:53 +0000 (+0200) Subject: lyrics: added callback X-Git-Tag: v0.12_alpha1~177 X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=a03216c4dd0d06da63a5040bbb1dce9212fc0271;p=ncmpc.git lyrics: added callback Instead of letting our caller poll lyrics_result(), call it back as soon as we have the result. --- diff --git a/src/lyrics.c b/src/lyrics.c index 9173447..7a6124b 100644 --- a/src/lyrics.c +++ b/src/lyrics.c @@ -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; -} diff --git a/src/lyrics.h b/src/lyrics.h index 34380c3..613ccb3 100644 --- a/src/lyrics.h +++ b/src/lyrics.h @@ -21,11 +21,7 @@ #include -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 diff --git a/src/screen_lyrics.c b/src/screen_lyrics.c index cfc6589..9b9ea03 100644 --- a/src/screen_lyrics.c +++ b/src/screen_lyrics.c @@ -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();