/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * lyric_viewer.c (c) 2008 smoking gnu * * Copyright (C) 2002 Björn Stenberg * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * This plugin is my first rockbox project, so please don't expect it to be perfect ;) * I guess the "lyric-finding" part of this plugin could be handled by the rockbox core metadata parser, but this works too... *Update: *Now it checks how long the ID3 tag is before it searches for the lyric tag - therefore it doesn't have to search the *whole file if there's no lyric tag at all. * This plugin will NOT work when some other ID3-tag (e.g. Artist, Title etc) contains the string "USLT". ****************************************************************************/ #include "plugin.h" #define BUF_SIZE 5000 /*Size of the lyrics buffer - 5k should be way enough*/ static struct plugin_api* rb; static int line_count, fd; static struct gui_synclist gui_lyrics; static unsigned char lyr_buffer[BUF_SIZE]; PLUGIN_HEADER char* get_lyric_line(int selected_line, void *data, char *buffer, size_t buf_len) { int i=0, start=0, stop; (void) data; rb->strcpy(buffer,"Couldn't read line!"); /*Just in case something goes wrong*/ for (i=0; isnprintf(buffer, stop-start, "%s", &lyr_buffer[start]); return buffer; } int show_lyrics(void) { /*a standard gui_list*/ rb->gui_synclist_init(&gui_lyrics, &get_lyric_line, NULL, false, 1, NULL); rb->gui_synclist_set_nb_items(&gui_lyrics, line_count+1); rb->gui_synclist_limit_scroll(&gui_lyrics, false); rb->gui_synclist_select_item(&gui_lyrics, 0); rb->gui_synclist_draw(&gui_lyrics); int button; while (true) { rb->gui_syncstatusbar_draw(rb->statusbars, true); button = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK); if (rb->gui_synclist_do_button(&gui_lyrics, &button, LIST_WRAP_UNLESS_HELD)) { continue; } if (button==ACTION_STD_CANCEL) return 0; } } int find_lyr_tag(void) { int pos=0, eof_check, tag_pos=0, i, id3_length=0; char lyr_tag[5], temp; rb->strcpy(lyr_tag, "USLT"); eof_check=rb->read(fd, lyr_buffer, 6); if (eof_check==0) return 0; if (lyr_buffer[0]!='I' || lyr_buffer[1]!='D' || lyr_buffer[2]!='3') return 0; /*check whether there's an ID3 tag*/ for (i=0; i<4; i++) /*get its length*/ { id3_length<<=8; eof_check=rb->read(fd, &temp, 1); if (eof_check==0) return 0; id3_length+=temp; } for (i=0; i< id3_length; i++) /*... and finally search for the tag*/ { eof_check=rb->read(fd, &temp, 1); if (eof_check==0) return 0; pos++; if (temp==lyr_tag[tag_pos]) { if ((unsigned int)tag_pos < (rb->strlen(lyr_tag)-1)) { tag_pos++; } else { return pos; } } else tag_pos=0; } return 0; } int get_lyr_len(void) { int eof_check, pos=0, lyr_len=0, i; unsigned char temp; /*get the length of the lyrics*/ for (i=0; i<4; i++) { lyr_len<<=8; eof_check=rb->read(fd, &temp, 1); if (eof_check==0) return 0; lyr_len+=temp; } /*go to the beginning of the lyrics*/ temp=0; while(temp==0) { eof_check=rb->read(fd, &temp, 1); if (eof_check==0) return 0; pos++; } while(temp!=0) { eof_check=rb->read(fd, &temp, 1); if (eof_check==0) return 0; pos++; } return lyr_len-pos+2; } int save_lyrics(int len) { int eof_check, pos; unsigned char temp; /*just copy the whole lyric block to lyr_buffer[] */ for (pos=0; posread(fd, &temp, 1); if (eof_check==0) return 0; if (pos==BUF_SIZE) return -1; lyr_buffer[pos]=temp; if (temp=='\n') line_count++; } lyr_buffer[pos+1]=0; return 1; } enum plugin_status plugin_start(struct plugin_api* api, void* parameter) { int lyr_len=0; rb = api; fd=rb->open((char*)parameter, O_RDONLY); line_count=0; if (fd>=0) { if (find_lyr_tag()) /*check whether there is a USLT lyric tag */ { lyr_len=get_lyr_len(); /*get length of the lyrics */ save_lyrics(lyr_len); /*read lyrics and save them to the buffer */ show_lyrics(); /*show us those lyrics! */ } else rb->splash(HZ*2, "No Lyric tag found!"); rb->close(fd); } else rb->splash(HZ*2, "Could not open file '%s'!", (char*) parameter); return PLUGIN_OK; }