X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fscreen_lyrics.c;h=6de59d5ef073869bb109728e91d36cdd524f6987;hb=8ba6b8463c9b53bcd6b05574d639eb9ac099a37a;hp=99487da3396c03672643dd9a8d405d1b10d391a7;hpb=83adc590c89c657e36da23b828f45ed7a881ec7a;p=ncmpc.git diff --git a/src/screen_lyrics.c b/src/screen_lyrics.c index 99487da..6de59d5 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 - * Tue Aug 1 23:17:38 2006 +/* ncmpc (Ncurses MPD Client) + * (c) 2004-2010 The Music Player Daemon Project + * Project homepage: http://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 @@ -13,369 +11,418 @@ * 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 * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" -#ifndef DISABLE_LYRICS_SCREEN -#include -#include "ncmpc.h" +#include "screen_lyrics.h" +#include "screen_interface.h" +#include "screen_status.h" +#include "screen_file.h" +#include "screen_song.h" +#include "i18n.h" #include "options.h" #include "mpdclient.h" -#include "command.h" #include "screen.h" -#include "screen_utils.h" -#include "easy_download.h" -#include "strfsong.h" -#include "src_lyrics.h" -#include "gcc.h" +#include "lyrics.h" +#include "screen_text.h" -#define _GNU_SOURCE +#include +#include #include #include #include -#include -#include #include -#include #include -static list_window_t *lw = NULL; -static int lyrics_text_rows = -1; -static int src_selection; +static struct screen_text text; + +static struct mpd_song *next_song; +static bool follow = false; + +static struct { + struct mpd_song *song; + + char *artist, *title, *plugin_name; + + struct plugin_cycle *loader; + + guint loader_timeout; +} current; + +static void +screen_lyrics_abort(void) +{ + if (current.loader != NULL) { + plugin_stop(current.loader); + current.loader = NULL; + } + + if (current.loader_timeout != 0) { + g_source_remove(current.loader_timeout); + current.loader_timeout = 0; + } + + if (current.plugin_name != NULL) { + g_free(current.plugin_name); + current.plugin_name = NULL; + } + + if (current.artist != NULL) { + g_free(current.artist); + current.artist = NULL; + } + + if (current.title != NULL) { + g_free(current.title); + current.title = NULL; + } + + if (current.song != NULL) { + mpd_song_free(current.song); + current.song = NULL; + } +} + +/** + * Repaint and update the screen, if it is currently active. + */ +static void +lyrics_repaint_if_active(void) +{ + if (screen_is_visible(&screen_lyrics)) { + screen_text_repaint(&text); + + /* XXX repaint the screen title */ + } +} + +static void +path_lyr_file(char *path, size_t size, + const char *artist, const char *title) +{ + snprintf(path, size, "%s/.lyrics/%s - %s.txt", + getenv("HOME"), artist, title); +} + +static bool +exists_lyr_file(const char *artist, const char *title) +{ + char path[1024]; + struct stat result; + + path_lyr_file(path, 1024, artist, title); -static void lyrics_paint(screen_t *screen, mpdclient_t *c); + return (stat(path, &result) == 0); +} -static FILE *create_lyr_file(char *artist, char *title) +static FILE * +create_lyr_file(const char *artist, const char *title) { char path[1024]; snprintf(path, 1024, "%s/.lyrics", getenv("HOME")); - if(g_access(path, W_OK) != 0) if(mkdir(path, S_IRWXU) != 0) return NULL; - - snprintf(path, 1024, "%s/.lyrics/%s", - getenv("HOME"), artist); - if(g_access(path, W_OK) != 0) if(mkdir(path, S_IRWXU) != 0) return NULL; + mkdir(path, S_IRWXU); - snprintf(path, 1024, "%s/.lyrics/%s/%s.lyric", - getenv("HOME"), artist, title); + path_lyr_file(path, 1024, artist, title); return fopen(path, "w"); } - -static int store_lyr_hd(void) +static int +store_lyr_hd(void) { - char artist[512]; - char title[512]; - static char path[1024]; FILE *lyr_file; unsigned i; - char line_buf[1024]; - - 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'; - snprintf(path, 1024, "%s/.lyrics/%s/%s.lyric", - getenv("HOME"), artist, title); - lyr_file = create_lyr_file(artist, title); + lyr_file = create_lyr_file(current.artist, current.title); if (lyr_file == NULL) return -1; - 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); - } + for (i = 0; i < text.lines->len; ++i) + fprintf(lyr_file, "%s\n", + (const char*)g_ptr_array_index(text.lines, i)); fclose(lyr_file); return 0; } - -static void check_repaint(void) +static int +delete_lyr_hd(void) { - if(screen_get_id("lyrics") == get_cur_mode_id())lyrics_paint(NULL, NULL); -} + char path[1024]; + if (!exists_lyr_file(current.artist, current.title)) + return -1; -static gpointer get_lyr(void *c) -{ - 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]; + path_lyr_file(path, 1024, current.artist, current.title); + if (unlink(path) != 0) + return -2; - //mpdclient_update((mpdclient_t*)c); + return 0; +} - if(!(IS_PAUSED(status->state)||IS_PLAYING(status->state))) { - formed_text_init(&lyr_text); - return NULL; - } +static void +screen_lyrics_set(const GString *str) +{ + screen_text_set(&text, str); + /* paint new data */ - lock=2; - result = 0; + lyrics_repaint_if_active(); +} - formed_text_init(&lyr_text); +static void +screen_lyrics_callback(const GString *result, const bool success, + const char *plugin_name, G_GNUC_UNUSED void *data) +{ + assert(current.loader != NULL); - strfsong(artist, MAX_SONGNAME_LENGTH, "%artist%", cur); - strfsong(title, MAX_SONGNAME_LENGTH, "%title%", cur); + current.plugin_name = g_strdup(plugin_name); - //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); + /* Display result, which may be lyrics or error messages */ + if (result != NULL) + screen_lyrics_set(result); - 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; - } + if (success == true) { + if (options.lyrics_autosave && + !exists_lyr_file(current.artist, current.title)) + store_lyr_hd(); + } else { + /* translators: no lyrics were found for the song */ + screen_status_message (_("No lyrics")); + } + + if (current.loader_timeout != 0) { + g_source_remove(current.loader_timeout); + current.loader_timeout = 0; } - /*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; + + plugin_stop(current.loader); + current.loader = NULL; } -static const char * -list_callback(unsigned idx, int *highlight, mpd_unused void *data) +static gboolean +screen_lyrics_timeout_callback(gpointer G_GNUC_UNUSED 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; - return ""; - } + plugin_stop(current.loader); + current.loader = NULL; - 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 ""; - } + screen_status_printf(_("Lyrics timeout occurred after %d seconds"), + options.lyrics_timeout); - get_text_line(&lyr_text, idx, buf, 512); - return buf; + current.loader_timeout = 0; + return FALSE; } +static void +screen_lyrics_load(const struct mpd_song *song) +{ + const char *artist, *title; + + assert(song != NULL); + + screen_lyrics_abort(); + screen_text_clear(&text); + + artist = mpd_song_get_tag(song, MPD_TAG_ARTIST, 0); + title = mpd_song_get_tag(song, MPD_TAG_TITLE, 0); + + current.song = mpd_song_dup(song); + current.artist = g_strdup(artist); + current.title = g_strdup(title); + + current.loader = lyrics_load(current.artist, current.title, + screen_lyrics_callback, NULL); + + if (options.lyrics_timeout != 0) { + current.loader_timeout = + g_timeout_add_seconds(options.lyrics_timeout, + screen_lyrics_timeout_callback, + NULL); + } +} static void -lyrics_init(WINDOW *w, int cols, int rows) +lyrics_screen_init(WINDOW *w, int cols, int rows) { - 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); + screen_text_init(&text, w, cols, rows); } static void lyrics_resize(int cols, int rows) { - lw->cols = cols; - lw->rows = rows; + screen_text_resize(&text, cols, rows); } static void lyrics_exit(void) { - list_window_free(lw); -} + screen_lyrics_abort(); + screen_text_deinit(&text); +} -static const char * -lyrics_title(mpd_unused char *str, mpd_unused size_t size) +static void +lyrics_open(struct mpdclient *c) { - 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"); + const struct mpd_song *next_song_c = + next_song != NULL ? next_song : c->song; + + if (next_song_c != NULL && + (current.song == NULL || + strcmp(mpd_song_get_uri(next_song_c), + mpd_song_get_uri(current.song)) != 0)) + screen_lyrics_load(next_song_c); + + if (next_song != NULL) { + mpd_song_free(next_song); + next_song = 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")); - } - } - - g_string_append_c (msg, ']'); - - return msg->str; } static void -lyrics_paint(mpd_unused screen_t *screen, mpd_unused mpdclient_t *c) +lyrics_update(struct mpdclient *c) { - lw->clear = 1; - list_window_paint(lw, list_callback, NULL); - wrefresh(lw->w); + if (!follow) + return; + + if (c->song != NULL && + (current.song == NULL || + strcmp(mpd_song_get_uri(c->song), + mpd_song_get_uri(current.song)) != 0)) + screen_lyrics_load(c->song); } +static const char * +lyrics_title(char *str, size_t size) +{ + if (current.loader != NULL) { + snprintf(str, size, "%s (%s)", + _("Lyrics"), + /* translators: this message is displayed + while data is retrieved */ + _("loading...")); + return str; + } else if (current.artist != NULL && current.title != NULL && + !screen_text_is_empty(&text)) { + int n; + n = snprintf(str, size, "%s: %s - %s", + _("Lyrics"), + current.artist, current.title); + + if (options.lyrics_show_plugin && current.plugin_name != NULL && + (unsigned int) n < size - 1) + snprintf(str + n, size - n, " (%s)", + current.plugin_name); + + return str; + } else + return _("Lyrics"); +} static void -lyrics_update(mpd_unused screen_t *screen, mpd_unused mpdclient_t *c) +lyrics_paint(void) { - if( lw->repaint ) { - list_window_paint(lw, list_callback, NULL); - wrefresh(lw->w); - lw->repaint = 0; - } + screen_text_paint(&text); } - -static int -lyrics_cmd(screen_t *screen, mpdclient_t *c, command_t cmd) +static bool +lyrics_cmd(struct mpdclient *c, command_t cmd) { - static retrieval_spec spec; + if (screen_text_cmd(&text, c, cmd)) + return true; - lw->repaint=1; switch(cmd) { - case CMD_LIST_NEXT: - if( lw->start+lw->rows < lyr_text.lines->len+1 ) - lw->start++; - return 1; - case CMD_LIST_PREVIOUS: - if( lw->start >0 ) - lw->start--; - return 1; - case CMD_LIST_FIRST: - lw->start = 0; - return 1; - case CMD_LIST_LAST: - if ((unsigned)lyrics_text_rows > lw->rows) - lw->start = lyrics_text_rows - lw->rows; - else - lw->start = 0; - return 1; - case CMD_LIST_NEXT_PAGE: - lw->start = lw->start + lw->rows - 1; - if (lw->start + lw->rows >= (unsigned)lyrics_text_rows + 1) { - if ((unsigned)lyrics_text_rows + 1 > lw->rows) - lw->start = lyrics_text_rows + 1 - lw->rows; - else - lw->start = 0; - } - return 1; - case CMD_LIST_PREVIOUS_PAGE: - if (lw->start > lw->rows) - lw->start -= lw->rows; - else - lw->start = 0; - return 1; - case CMD_SELECT: - spec.client = c; - spec.way = 0; - g_thread_create(get_lyr, &spec, FALSE, NULL); - return 1; case CMD_INTERRUPT: - if(lock > 1) lock = 4; - return 1; - case CMD_ADD: - if(lock > 0 && lock != 4) { - if(store_lyr_hd() == 0) - screen_status_message (_("Lyrics saved!")); + if (current.loader != NULL) { + screen_lyrics_abort(); + screen_text_clear(&text); + } + return true; + case CMD_SAVE_PLAYLIST: + if (current.loader == NULL && current.artist != NULL && + current.title != NULL && store_lyr_hd() == 0) + /* lyrics for the song were saved on hard disk */ + screen_status_message (_("Lyrics saved")); + return true; + case CMD_DELETE: + if (current.loader == NULL && current.artist != NULL && + current.title != NULL) { + switch (delete_lyr_hd()) { + case 0: + screen_status_message (_("Lyrics deleted")); + break; + case -1: + screen_status_message (_("No saved lyrics")); + break; + } } - return 1; + return true; 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++; - return 1; - default: - break; - } + if (c->song != NULL) { + screen_lyrics_load(c->song); + screen_text_repaint(&text); + } + return true; + case CMD_SELECT: + if (current.loader == NULL && current.artist != NULL && + current.title != NULL) { + current.loader = lyrics_load(current.artist, current.title, + screen_lyrics_callback, NULL); + screen_text_repaint(&text); + } + return true; - lw->selected = lw->start+lw->rows; - if (screen_find(screen, - lw, lyrics_text_rows, - cmd, list_callback, NULL)) { - /* center the row */ - lw->start = lw->selected - (lw->rows / 2); - if (lw->start + lw->rows > (unsigned)lyrics_text_rows) { - if (lw->rows < (unsigned)lyrics_text_rows) - lw->start = lyrics_text_rows - lw->rows; - else - lw->start = 0; +#ifdef ENABLE_SONG_SCREEN + case CMD_SCREEN_SONG: + if (current.song != NULL) { + screen_song_switch(c, current.song); + return true; } - return 1; + + break; +#endif + case CMD_SCREEN_SWAP: + screen_swap(c, current.song); + return true; + + case CMD_LOCATE: + if (current.song != NULL) { + screen_file_goto_song(c, current.song); + return true; + } + + return false; + + default: + break; } - return 0; + return false; } -static list_window_t * -lyrics_lw(void) +const struct screen_functions screen_lyrics = { + .init = lyrics_screen_init, + .exit = lyrics_exit, + .open = lyrics_open, + .update = lyrics_update, + .close = NULL, + .resize = lyrics_resize, + .paint = lyrics_paint, + .cmd = lyrics_cmd, + .get_title = lyrics_title, +}; + +void +screen_lyrics_switch(struct mpdclient *c, const struct mpd_song *song, bool f) { - return lw; -} + assert(song != NULL); -screen_functions_t * -get_screen_lyrics(void) -{ - static screen_functions_t functions; - - memset(&functions, 0, sizeof(screen_functions_t)); - functions.init = lyrics_init; - functions.exit = lyrics_exit; - functions.open = NULL; - functions.close = NULL; - functions.resize = lyrics_resize; - functions.paint = lyrics_paint; - functions.update = lyrics_update; - functions.cmd = lyrics_cmd; - functions.get_lw = lyrics_lw; - functions.get_title = lyrics_title; - - return &functions; + follow = f; + next_song = mpd_song_dup(song); + screen_switch(&screen_lyrics, c); } -#endif /* ENABLE_LYRICS_SCREEN */