Index: apps/plugins/m3u_cleaner.c =================================================================== --- apps/plugins/m3u_cleaner.c (revision 0) +++ apps/plugins/m3u_cleaner.c (revision 0) @@ -0,0 +1,190 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: m3u_cleaner.c 12807 2007-11-11 $ + * + * 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. + * + ****************************************************************************/ +#include "plugin.h" +PLUGIN_HEADER + +static struct plugin_api* rb; +static int num_entries=0; + +#define PRINT(y,string) \ + FOR_NB_SCREENS(i){\ + rb->screens[i]->puts_scroll(0,y,string);\ + rb->screens[i]->update();\ + } + +/* Code copied from firmware_flash plugin. */ + +/* Tool function to calculate a CRC32 across some buffer */ +/* third argument is either 0xFFFFFFFF to start or value from last piece */ +unsigned crc_32(const void *src, unsigned len, unsigned crc32) +{ + const unsigned char *buf = (const unsigned char *)src; + + /* CCITT standard polynomial 0x04C11DB7 */ + static const unsigned crc32_lookup[16] = + { /* lookup table for 4 bits at a time is affordable */ + 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, + 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, + 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, + 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD + }; + + unsigned char byte; + unsigned t; + + while (len--) + { + byte = *buf++; /* get one byte of data */ + + /* upper nibble of our data */ + t = crc32 >> 28; /* extract the 4 most significant bits */ + t ^= byte >> 4; /* XOR in 4 bits of data into the extracted bits */ + crc32 <<= 4; /* shift the CRC register left 4 bits */ + crc32 ^= crc32_lookup[t]; /* do the table lookup and XOR the result */ + + /* lower nibble of our data */ + t = crc32 >> 28; /* extract the 4 most significant bits */ + t ^= byte & 0x0F; /* XOR in 4 bits of data into the extracted bits */ + crc32 <<= 4; /* shift the CRC register left 4 bits */ + crc32 ^= crc32_lookup[t]; /* do the table lookup and XOR the result */ + } + + return crc32; +} + +bool is_duplicate(const char* entry, int len){ + #define MAX_PLAYLIST_ENTRIES 500 + static unsigned entries_crc[MAX_PLAYLIST_ENTRIES]; + int i=0; + unsigned entry_crc=crc_32(entry, len, 0xffffffff); + while(i add to list */ + entries_crc[num_entries]=entry_crc; + num_entries=(num_entries+1)%MAX_PLAYLIST_ENTRIES; + return false; + } + return true; +} + +int clean_playlist(const unsigned char* playlist_name){ + int i; + static int line=0; + static char string[MAX_PATH]; + int height; + rb->lcd_getstringsize("A", NULL, &height); + const int max_lines = LCD_HEIGHT/height; + + rb->snprintf(string,MAX_PATH,"Cleaning '%s' ...",playlist_name); + PRINT(line,string); + size_t size; + int entries_size=0; + bool have_bad_entries=false; + char* entry=rb->plugin_get_buffer(&size); + char* first=entry; + char* str; + int fd=rb->open(playlist_name, O_RDWR); + if(fd>=0){ + num_entries=0; + /* check playlist entries */ + while(rb->read_line(fd, entry, MAX_PATH)>0){ + if(entry[1]==':') /* skip drive letter */ + rb->strcpy(entry,entry+2); + str=entry; + while (*str!=0){ /* replace \ with / */ + if ( *str == '\\' ) *str = '/'; + str++; + } + string[0]=0; + if(rb->file_exists(entry)){ /* entry o.k. */ + if(!is_duplicate(entry, str-entry)){ + /* cannot use length returned by read_line, because of \r\n */ + entries_size+=str-entry+1; + entry=str+1; /* next entry points to the end of the current entry */ + *str='\n'; /* replace 0 with \n */ + } + else + rb->snprintf(string,MAX_PATH,"Duplicate: '%s'",entry); + } + else + rb->snprintf(string,MAX_PATH,"Invalid: '%s'",entry); + if(string[0]!=0){ + line=(line+1)%max_lines; + PRINT(line,string); + have_bad_entries=true; + } + if(rb->button_get(false)!=BUTTON_NONE){ /* press any button to abort */ + have_bad_entries=false; + break; + } + } + if(have_bad_entries){ /* only modify file if it has invalid entries */ + rb->ftruncate(fd,entries_size); + rb->lseek(fd, 0, SEEK_SET); + rb->write(fd,first,entries_size); + line=(line+1)%max_lines; + } + else{ + PRINT(line," "); /* m3u o.k. */ + } + rb->close(fd); + if(entries_size==0){ + rb->remove(playlist_name); + line=(line+1)%max_lines; + rb->snprintf(string,MAX_PATH,"Removed: '%s'",playlist_name); + PRINT(line,string); + } + } + return line; +} +void clean_playlist_dir(const unsigned char* playlist_dir){ + struct dirent *entry; + DIR* dir; + unsigned char* ext; + char fullpath[MAX_PATH]; + int i,line = 1; + dir = rb->opendir(playlist_dir); + if (dir) { + while((entry=rb->readdir(dir))!=0 && /* looking for playlists in dir */ + rb->button_get(false)==BUTTON_NONE){ /* press any button to abort */ + ext=rb->strrchr(entry->d_name,'.')+1; + if(rb->strncasecmp(ext,"m3u",3)==0){ /* check if it's a playlist */ + rb->snprintf(fullpath,MAX_PATH,"%s/%s",playlist_dir,entry->d_name); + line=clean_playlist(fullpath)+1; + } + } + rb->closedir(dir); + PRINT(line,"done"); + } + else + rb->splash(HZ,"Directory '%s' not found!",playlist_dir); +} + +/* this is the plugin entry point */ +enum plugin_status plugin_start(struct plugin_api* api, void* parameter) +{ + rb = api; + + parameter==NULL ? + clean_playlist_dir("/Playlists"): + clean_playlist((const unsigned char*) parameter); + + while(rb->button_get_w_tmo(HZ)==BUTTON_NONE){ /* wait for a button press */ + rb->yield(); + } + return PLUGIN_OK; +} Property changes on: apps/plugins/m3u_cleaner.c ___________________________________________________________________ Name: svn:executable + * Index: apps/plugins/SOURCES =================================================================== --- apps/plugins/SOURCES (revision 16685) +++ apps/plugins/SOURCES (working copy) @@ -21,6 +21,7 @@ stopwatch.c vbrfix.c viewer.c +m3u_cleaner.c #ifdef OLYMPUS_MROBE_500 /* remove these once the plugins before it are compileable */ Index: apps/plugins/CATEGORIES =================================================================== --- apps/plugins/CATEGORIES (revision 16685) +++ apps/plugins/CATEGORIES (working copy) @@ -95,3 +95,4 @@ wormlet,games xobox,games zxbox,viewers +m3u_cleaner,apps \ No newline at end of file Index: apps/plugins/viewers.config =================================================================== --- apps/plugins/viewers.config (revision 16685) +++ apps/plugins/viewers.config (working copy) @@ -41,3 +41,5 @@ ssg,games/superdom,- link,viewers/shortcuts_view,- *,viewers/shortcuts_append,- +m3u,apps/m3u_cleaner,1 +m3u8,apps/m3u_cleaner,1