diff options
author | Andreas Obergrusberger <tradiaz@yahoo.de> | 2006-08-04 08:48:26 +0000 |
---|---|---|
committer | Andreas Obergrusberger <tradiaz@yahoo.de> | 2006-08-04 08:48:26 +0000 |
commit | e2a6f80bc6c71cfe6a68f419b2561d6d32252a88 (patch) | |
tree | efbfdabfda29a9f097e7324d44689129d60b7b89 /src/screen_lyrics.c | |
parent | 22f156f5f87705a9b8cda9958179939d8b3fbdc9 (diff) | |
download | mpd-e2a6f80bc6c71cfe6a68f419b2561d6d32252a88.tar.gz mpd-e2a6f80bc6c71cfe6a68f419b2561d6d32252a88.tar.xz mpd-e2a6f80bc6c71cfe6a68f419b2561d6d32252a88.zip |
the updated sources
git-svn-id: https://svn.musicpd.org/ncmpc/branches/tradiaz@4543 09075e82-0dd4-0310-85a5-a0d7c8717e4f
Diffstat (limited to 'src/screen_lyrics.c')
-rw-r--r-- | src/screen_lyrics.c | 542 |
1 files changed, 542 insertions, 0 deletions
diff --git a/src/screen_lyrics.c b/src/screen_lyrics.c new file mode 100644 index 000000000..6df0e5d9a --- /dev/null +++ b/src/screen_lyrics.c @@ -0,0 +1,542 @@ +/* + * $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 + * lyrics enhancement written by Andreas Obergrusberger <tradiaz@yahoo.de> + * using www.leoslyrics.com XML API + * + * 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 <stdlib.h> +#include <string.h> +#include <glib.h> +#include <ncurses.h> +#include <expat.h> +#include <unistd.h> + +#include "config.h" +#ifndef DISABLE_LYRICS_SCREEN +#include "ncmpc.h" +#include "options.h" +#include "mpdclient.h" +#include "command.h" +#include "screen.h" +#include "screen_utils.h" +#include "easy_download.h" + +#define LEOSLYRICS_SEARCH_URL "http://api.leoslyrics.com/api_search.php?auth=QuodLibet&artist=%s&songtitle=%s" + +#define LEOSLYRICS_CONTENT_URL "http://api.leoslyrics.com/api_lyrics.php?auth=QuodLibet&hid=%s" + +#define CREDITS "Lyrics provided by www.LeosLyrics.com" +typedef struct _formed_text +{ + GString *text; + GArray *lines; + int val; +} formed_text; + + +XML_Parser parser, contentp; +static int lyrics_text_rows = -1; +static list_window_t *lw = NULL; +guint8 result; +char *hid; +GTimer *dltime; +short int lock; +//GString *lyr_text; +//char *lyr_text; +//GArray *textline; +formed_text lyr_text; +/* result is a bitset in which the succes 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? +*/ +static void lyrics_paint(screen_t *screen, mpdclient_t *c); + +void get_text_line(formed_text *text, int num, char *dest, int len) +{ + memset(dest, '\0', len*sizeof(char)); + if(num >= text->lines->len-1) return; + int linelen; + 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'; +} + +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 == 1 && 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; +} +/* +char *check_lyr_hd(char *artist, char *title, int how) +{ //checking whether for lyrics file existence and proper access + 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; + + 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+1); + free(*line); + *line = NULL; n = 0; + } + + return 0; +} + +int store_lyr_hd() +{ + char artist[512]; + char title[512]; + static char path[1024]; + FILE *lyr_file; + + get_text_line(&lyr_text, 0, artist, 512); + get_text_line(&lyr_text, 1, title, 512); + artist[strlen(artist)-2] = '\0'; + title[strlen(title)-2] = '\0'; + + snprintf(path, 1024, "%s/.lyrics/%s/%s.lyric", + getenv("HOME"), artist, title); + + if (check_lyr_hd(artist, title, F_OK) == 0) lyr_file = fopen(path, "w"); + else lyr_file = fopen(path, "xw"); + if(lyr_file == NULL) return -1; + + int i; + char line_buf[1024]; + + for(i = 2; i <= lyr_text.text->len; i++) + { + get_text_line(&lyr_text, i, line_buf, 0); + fputs(line_buf, lyr_file); + } + fclose(lyr_file); + return 0; +} + +*/ +void check_repaint() +{ + if(screen_get_id("lyrics") == get_cur_mode_id())lyrics_paint(NULL, NULL); +} + +int check_dl_progress(void *clientp, double dltotal, double dlnow, + double ultotal, double ulnow) +{ + if(g_timer_elapsed(dltime, NULL) >= options.lyrics_timeout) + { + 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 = 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) + { + add_text_line(&lyr_text, s, len); + } +} + +gpointer get_lyr(void *c) +{ + mpd_Status *status = ((mpdclient_t*)c)->status; + mpd_Song *cur = ((mpdclient_t*)c)->song; + mpdclient_update((mpdclient_t*)c); + + if(!(IS_PAUSED(status->state)||IS_PLAYING(status->state))) + { + formed_text_init(&lyr_text); + return NULL; + } + + char url_avail[256]; + char url_hid[256]; + char artist[MAX_SONGNAME_LENGTH]; + char title[MAX_SONGNAME_LENGTH]; + lock = 2; + result = 0; + + if(dltime == NULL) dltime = g_timer_new(); + + strfsong(artist, MAX_SONGNAME_LENGTH, "%artist%", cur); + strfsong(title, MAX_SONGNAME_LENGTH, "%title%", cur); + + formed_text_init(&lyr_text); + add_text_line(&lyr_text, artist, 0); + add_text_line(&lyr_text, title, 0); + + //if(get_lyr_hd(artist, title) == 0) return &lyr_text; + + //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 NULL; + g_timer_stop(dltime); + + //we gotta parse that stuff with expat + parser = XML_ParserCreate(NULL); + XML_SetUserData(parser, NULL); + + int state; + + XML_SetElementHandler(parser, check_search_response, end_tag); + XML_SetCharacterDataHandler(parser, check_search_success); + XML_Parse(parser, lyr_avail.data, strlen(lyr_avail.data), state); + XML_ParserFree(parser); + + if(!(result & 4)) return NULL; //check whether lyrics found + easy_download_struct lyr_content = {NULL, 0,-1}; + snprintf(url_hid, 512, LEOSLYRICS_CONTENT_URL, hid); + + g_timer_continue(dltime); + if(!(easy_download(url_hid, &lyr_content, check_dl_progress))) return NULL; + 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), state); + XML_ParserFree(contentp); + + lw->start = 0; + check_repaint(); + + lock = 1; + return &lyr_text; +} + +static char * +list_callback(int index, int *highlight, void *data) +{ + static char buf[512]; + int linelen; + + //i think i'ts fine to write it into the 1st line... + if((index == lyr_text.lines->len && lyr_text.lines->len != 2)|| + ((lyr_text.lines->len == 0 + ||lyr_text.lines->len == 2) && index == 0)) + { + *highlight=3; + return CREDITS; + } + + if(index < 2 && lyr_text.lines->len > 2) *highlight=3; + else if(index >= lyr_text.lines->len || index == 2) + { + return ""; + } + if(index >1) index--; + get_text_line(&lyr_text, index, buf, 512); + return buf; +} + + +static void +lyrics_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); + +} + +static void +lyrics_resize(int cols, int rows) +{ + lw->cols = cols; + lw->rows = rows; +} + +static void +lyrics_exit(void) +{ + list_window_free(lw); +} + + +static char * +lyrics_title(char *str, size_t size) +{ + if(lyr_text.lines->len == 2){ + if(lock == 1 && !(result & 2)) return _("Lyrics [No connection]"); + if(lock == 1 && !(result & 4)) return _("Lyrics [Not found]"); + if(lock == 2) return _("Lyrics [retrieving]"); + } + /*if(lyr_text.lines->len > 2) + { + static char buf[512]; + char artist[512]; + char title[512]; + get_text_line(&lyr_text, 0, artist, 512); + get_text_line(&lyr_text, 1, artist, 512); + snprintf(buf, 512, "Lyrics %s - %s", artist, title); + return buf; + }*/ + return "Lyrics"; +} + +static void +lyrics_paint(screen_t *screen, mpdclient_t *c) +{ + lw->clear = 1; + list_window_paint(lw, list_callback, NULL); + wrefresh(lw->w); +} + +static void +lyrics_update(screen_t *screen, mpdclient_t *c) +{ + if( lw->repaint ) + { + list_window_paint(lw, list_callback, NULL); + wrefresh(lw->w); + lw->repaint = 0; + } +} + + +static int +lyrics_cmd(screen_t *screen, mpdclient_t *c, command_t cmd) +{ + 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: + lw->start = lyrics_text_rows-lw->rows; + if( lw->start<0 ) + lw->start = 0; + return 1; + case CMD_LIST_NEXT_PAGE: + lw->start = lw->start + lw->rows-1; + if( lw->start+lw->rows >= lyr_text.lines->len+1 ) + lw->start = lyr_text.lines->len-lw->rows+1; + if( lw->start<0 ) + lw->start = 0; + return 1; + case CMD_LIST_PREVIOUS_PAGE: + lw->start = lw->start - lw->rows; + if( lw->start<0 ) + lw->start = 0; + return 1; + case CMD_SELECT: + g_thread_create(get_lyr, c, FALSE, NULL); + return 1; + default: + break; + } + + lw->selected = lw->start+lw->rows; + if( screen_find(screen, c, + lw, lyrics_text_rows, + cmd, list_callback, NULL) ) + { + /* center the row */ + lw->start = lw->selected-(lw->rows/2); + if( lw->start+lw->rows > lyrics_text_rows ) + lw->start = lyrics_text_rows-lw->rows; + if( lw->start<0 ) + lw->start=0; + return 1; + } + + return 0; +} + +static list_window_t * +lyrics_lw(void) +{ + return lw; +} + +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; +} +#endif /* ENABLE_LYRICS_SCREEN */ |