Mercurial > mplayer.hg
changeset 4782:4b728967bd77
Playtree parser switch to a by line mode.
Winamp (pls) playlist support.
author | albeu |
---|---|
date | Thu, 21 Feb 2002 13:12:53 +0000 |
parents | e370779ac77f |
children | 17f29765ea77 |
files | playtreeparser.c playtreeparser.h |
diffstat | 2 files changed, 302 insertions(+), 186 deletions(-) [+] |
line wrap: on
line diff
--- a/playtreeparser.c Thu Feb 21 13:11:31 2002 +0000 +++ b/playtreeparser.c Thu Feb 21 13:12:53 2002 +0000 @@ -19,211 +19,320 @@ extern play_tree_t* asx_parser_build_tree(char* buffer, int ref); +#define BUF_STEP 1024 + +#define WHITES " \n\r\t" + +static void +strstrip(char* str) { + char* i; + + for(i = str ; i[0] != '\0' && strchr(WHITES,i[0]) != NULL; i++) + /* NOTHING */; + if(i[0] != '\0') { + memmove(str,i,strlen(i)); + for(i = str + strlen(str) ; strchr(WHITES,i[0]) != NULL; i--) + /* NOTHING */; + i[1] = '\0'; + } else + str[0] = '\0'; +} + +static char* +play_tree_parser_get_line(play_tree_parser_t* p) { + char *end,*line_end; + int r,resize = 0; + + if(p->buffer == NULL) { + p->buffer = (char*)malloc(BUF_STEP); + p->buffer_size = BUF_STEP; + p->iter = p->buffer; + } + + if(p->stream->eof && p->buffer_end == 0) + return NULL; + + while(1) { + + if(resize) { + r = p->iter - p->buffer; + p->buffer = (char*)realloc(p->buffer,p->buffer_size+BUF_STEP); + p->iter = p->buffer + r; + p->buffer_size += BUF_STEP; + resize = 0; + } + + if(p->buffer_size - p->buffer_end > 1 && ! p->stream->eof) { + r = stream_read(p->stream,p->buffer + p->buffer_end,p->buffer_size - p->buffer_end - 1); + if(r > 0) { + p->buffer_end += r; + p->buffer[p->buffer_end] = '\0'; + } + } + + end = strchr(p->iter,'\n'); + if(!end) { + if(p->stream->eof) { + end = p->buffer + p->buffer_end + 1; + break; + } + resize = 1; + continue; + } + break; + } + + line_end = ((*(end-1)) == '\r') ? end-1 : end; + p->line = (char*)realloc(p->line,line_end - p->iter+1); + if(!p->line) + return NULL; + strncpy(p->line,p->iter,line_end - p->iter); + p->line[line_end - p->iter] = '\0'; + end++; + + if(!p->keep) { + if(end[1] != '\0') { + p->buffer_end = strlen(end); + memmove(p->buffer,end,p->buffer_end); + p->buffer[p->buffer_end] = '\0'; + } else + p->buffer_end = 0; + p->iter = p->buffer; + } else + p->iter = end; + + return p->line; +} + +static void +play_tree_parser_reset(play_tree_parser_t* p) { + p->iter = p->buffer; +} + +static void +play_tree_parser_stop_keeping(play_tree_parser_t* p) { + p->keep = 0; + if(p->iter && p->iter != p->buffer) { + p->buffer_end -= p->iter -p->buffer; + if(p->buffer_end) + memmove(p->buffer,p->iter,p->buffer_end); + p->iter = p->buffer; + } +} + play_tree_t* parse_asx(play_tree_parser_t* p) { - int r; - int comments = 0,read = 1,eof = 0; + int comments = 0,get_line = 1; + char* line = NULL; mp_msg(MSGT_PLAYTREE,MSGL_V,"Trying asx...\n"); while(1) { - if(read && eof) // Eof reached before anything useful - return NULL; - if(read) { - if(p->buffer_size - p->buffer_end < 50) p->buffer_size += 255; - p->buffer = (char*)realloc(p->buffer,p->buffer_size*sizeof(char)); - if(p->buffer == NULL) { - mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",p->buffer_size*sizeof(char)); - p->buffer_size = p->buffer_end = 0; + if(get_line) { + line = play_tree_parser_get_line(p); + if(!line) return NULL; - } - - r = stream_read(p->stream,p->buffer+p->buffer_end,p->buffer_size-p->buffer_end-1); - if(r < 0) { - mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't read from stream r=%d\n",r); - return NULL; - } else if(r == 0) - eof = 1; - p->buffer_end += r; - p->buffer[p->buffer_end] = '\0'; + strstrip(line); + if(line[0] == '\0') + continue; } - - if(comments) { // Jump comments - int e; - char* end = strstr(p->buffer,"-->"); - if(!end) { - if(p->buffer[p->buffer_end-1] != '-') - p->buffer_end = 0; // Drop buffer content if last char isn't '-' - continue; - } - comments = 0; - e = end - p->buffer + 3; - if(e >= p->buffer_end) { // > seems impossible - p->buffer_end = 0; // Drop buffer content - read = 1; - continue; - } - p->buffer_end -= e; - memmove(p->buffer,end+3,p->buffer_end); // Drop comments - continue; - } - - for(r= 0 ; r < p->buffer_end ; r++) { - if(strchr(" \n\r\t",p->buffer[r]) != NULL) // Jump space - continue; - if(p->buffer[r] != '<') { - mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"First char isn't '<' but '%c'\n",p->buffer[r]); + if(!comments) { + if(line[0] != '<') { + mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"First char isn't '<' but '%c'\n",line[0]); mp_msg(MSGT_PLAYTREE,MSGL_DBG3,"Buffer = [%s]\n",p->buffer); return NULL; - } - break; // Stop on first '<' - } - if(r > p->buffer_end-4) { // We need more - if(r > 0) { // Drop unuseful beggining - p->buffer_end -= r; - memmove(p->buffer,&p->buffer[r],p->buffer_end); - } - read = 1; - continue; - } + } else if(strncmp(line,"<!--",4) == 0) { // Comments + comments = 1; + line += 4; + if(line[0] != '\0' && strlen(line) > 0) + get_line = 0; + } else if(strncasecmp(line,"<ASX",4) == 0) // We got an asx element + break; + else // We don't get an asx + return NULL; + } else { // Comments + char* c; + c = strchr(line,'-'); + if(c) { + if (strncmp(c,"--!>",4) == 0) { // End of comments + comments = 0; + line = c+4; + if(line[0] != '\0') // There is some more data on this line : keep it + get_line = 0; - if(strncmp(&p->buffer[r],"<!--",4) == 0) { // Comments - read = 0; - comments = 1; - continue; + } else { + line = c+1; // Jump the - + if(line[0] != '\0') // Some more data + get_line = 0; + else // End of line + get_line = 1; + } + } else // No - on this line (or rest of line) : get next one + get_line = 1; } + } + + mp_msg(MSGT_PLAYTREE,MSGL_V,"Detected asx format\n"); - if(strncasecmp(&p->buffer[r],"<ASX",4) != 0) // First element is not a comment nor an asx : end - return NULL; - - - mp_msg(MSGT_PLAYTREE,MSGL_V,"Detected asx format\n"); - break; - } // We have an asx : load it in memory and parse - while(!eof) { - if(p->buffer_size - p->buffer_end < 50) p->buffer_size += 255; - p->buffer = (char*)realloc(p->buffer,p->buffer_size*sizeof(char)); - if(p->buffer == NULL) { - mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",p->buffer_size*sizeof(char)); - p->buffer_size = p->buffer_end = 0; - return NULL; - } - r = stream_read(p->stream,p->buffer+p->buffer_end,p->buffer_size-p->buffer_end-1); - if(r > 0) - p->buffer_end += r; - if(r <= 0) - break; - p->buffer[p->buffer_end] = '\0'; - } + while((line = play_tree_parser_get_line(p)) != NULL) + /* NOTHING */; mp_msg(MSGT_PLAYTREE,MSGL_DBG3,"Parsing asx file : [%s]\n",p->buffer); return asx_parser_build_tree(p->buffer,p->deep); } +static char* +pls_entry_get_value(char* line) { + char* i; + + i = strchr(line,'='); + if(!i || i[1] == '\0') + return NULL; + else + return i+1; +} + +typedef struct pls_entry { + char* file; + char* title; + char* length; +} pls_entry_t; + +static int +pls_read_entry(char* line,pls_entry_t** _e,int* _max_entry,char** val) { + int num,max_entry = (*_max_entry); + pls_entry_t* e = (*_e); + char* v; + + v = pls_entry_get_value(line); + if(!v) { + mp_msg(MSGT_PLAYTREE,MSGL_ERR,"No value in entry %s\n",line); + return 0; + } + + num = atoi(line); + if(num < 0) { + num = max_entry+1; + mp_msg(MSGT_PLAYTREE,MSGL_WARN,"No entry index in entry %s\nAssuming %d\n",line,num); + } + if(num > max_entry) { + e = (pls_entry_t*)realloc(e,num*sizeof(pls_entry_t)); + memset(&e[max_entry],0,(num-max_entry)*sizeof(pls_entry_t)); + max_entry = num; + } + (*_e) = e; + (*_max_entry) = max_entry; + (*val) = v; + + return num; +} + + +play_tree_t* +parse_pls(play_tree_parser_t* p) { + char *line,*v; + pls_entry_t* entries = NULL; + int n_entries = 0,max_entry=0,num; + play_tree_t *list = NULL, *entry = NULL; + + mp_msg(MSGT_PLAYTREE,MSGL_V,"Trying winamp playlist...\n"); + line = play_tree_parser_get_line(p); + strstrip(line); + if(strcasecmp(line,"[playlist]")) + return NULL; + mp_msg(MSGT_PLAYTREE,MSGL_V,"Detected winamp playlist format\n"); + play_tree_parser_stop_keeping(p); + line = play_tree_parser_get_line(p); + if(!line) + return NULL; + strstrip(line); + if(strncasecmp(line,"NumberOfEntries",15) == 0) { + v = pls_entry_get_value(line); + n_entries = atoi(v); + if(n_entries < 0) + mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"Invalid number of entries : very funny !!!\n"); + else + mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"Playlist claim to have %d entries. Let's see.\n",n_entries); + line = play_tree_parser_get_line(p); + } + + while(line) { + strstrip(line); + if(line[0] == '\0') { + line = play_tree_parser_get_line(p); + continue; + } + if(strncasecmp(line,"File",4) == 0) { + num = pls_read_entry(line+4,&entries,&max_entry,&v); + if(num < 0) + mp_msg(MSGT_PLAYTREE,MSGL_ERR,"No value in entry %s\n",line); + else + entries[num-1].file = strdup(v); + } else if(strncasecmp(line,"Title",5) == 0) { + num = pls_read_entry(line+5,&entries,&max_entry,&v); + if(num < 0) + mp_msg(MSGT_PLAYTREE,MSGL_ERR,"No value in entry %s\n",line); + else + entries[num-1].title = strdup(v); + } else if(strncasecmp(line,"Length",6) == 0) { + num = pls_read_entry(line+6,&entries,&max_entry,&v); + if(num < 0) + mp_msg(MSGT_PLAYTREE,MSGL_ERR,"No value in entry %s\n",line); + else + entries[num-1].length = strdup(v); + } else + mp_msg(MSGT_PLAYTREE,MSGL_WARN,"Unknow entry type %s\n",line); + line = play_tree_parser_get_line(p); + } + + for(num = 0; num < max_entry ; num++) { + if(entries[num].file == NULL) + mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Entry %d don't have a file !!!!\n",num+1); + else { + entry = play_tree_new(); + play_tree_add_file(entry,entries[num].file); + free(entries[num].file); + if(list) + play_tree_append_entry(list,entry); + else + list = entry; + } + if(entries[num].title) { + // When we have info in playtree we add this info + free(entries[num].title); + } + if(entries[num].length) { + // When we have info in playtree we add this info + free(entries[num].length); + } + } + + free(entries); + + return list; +} + play_tree_t* parse_textplain(play_tree_parser_t* p) { - char* end; - char* file; - int eof = 0,r,p_end=-1,resize = 0; + char* line; play_tree_t *list = NULL, *entry = NULL; mp_msg(MSGT_PLAYTREE,MSGL_V,"Trying plaintext...\n"); - - if(p->buffer_size < 255 && ! p->stream->eof) { - p->buffer_size = 255; - p->buffer = (char*)realloc(p->buffer,p->buffer_size*sizeof(char)); - if(p->buffer == NULL) { - mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",p->buffer_size*sizeof(char)); - p->buffer_size = p->buffer_end = 0; - return NULL; - } - } - + play_tree_parser_stop_keeping(p); - while(!eof) { - if(resize) { - p->buffer_size += 255; - p->buffer = (char*)realloc(p->buffer,p->buffer_size*sizeof(char)); - resize = 0; - if(p->buffer == NULL) { - mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",p->buffer_size*sizeof(char)); - p->buffer_size = p->buffer_end = 0; - if(list) play_tree_free_list(list,1); - return NULL; - } - } - if(!p->stream->eof) { - r = stream_read(p->stream,p->buffer+p->buffer_end,p->buffer_size-p->buffer_end-1); - if(r < 0) { - mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't read from stream r=%d\n",r); - return NULL; - } - p->buffer_end += r; - p->buffer[p->buffer_end] = '\0'; - } else eof = 1; - r = 0; - while(1) { - p_end = r; - for( ; p->buffer[r] != '\0' ; r++) { - if(strchr(" \n\r\t",p->buffer[r]) != NULL) - continue; - break; - } - if(p->buffer[r] == '\0') { - p_end = r; - if(!eof) - resize = 1; - break; - } - end = strchr(&p->buffer[r],'\n'); - if(!end) { - if(!eof) { - p_end = r; - if(p_end == 0) { - resize = 1; - } - break; - } - entry = play_tree_new(); - play_tree_add_file(entry,&p->buffer[r]); - r = p->buffer_end; - - } - else { - if(*(end-1) == '\r') end--; - file = (char*)malloc((end-(&p->buffer[r])+1)*sizeof(char)); - if(file == NULL) { - mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",p->buffer_size*sizeof(char)); - p->buffer_size = p->buffer_end = 0; - if(list) play_tree_free_list(list,1); - return NULL; - } - // TODO : Check if the given file exist and is readable (or it'a an url) - strncpy(file,&p->buffer[r],end-(&p->buffer[r])); - file[end-(&p->buffer[r])] = '\0'; - entry = play_tree_new(); - play_tree_add_file(entry,file); - free(file); - r += end-(&p->buffer[r]); - p_end = r; - } - if(entry) { - mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"Adding file %s to playlist\n",entry->files[0]); - if(list) play_tree_append_entry(list,entry); - else list = entry; - entry = NULL; - } - } - if(!eof && p_end > 0 && p_end < p->buffer_end) { - memmove(p->buffer,&p->buffer[p_end],p->buffer_end-p_end); - p->buffer_end -= p_end; - } else if(!eof && !resize && p_end == p->buffer_end) { - p->buffer_end = 0; - p->buffer[0] = '\0'; - } + while((line = play_tree_parser_get_line(p)) != NULL) { + strstrip(line); + if(line[0] == '\0') + continue; + entry = play_tree_new(); + play_tree_add_file(entry,line); + if(!list) + list = entry; + else + play_tree_append_entry(list,entry); } if(!list) return NULL; @@ -290,6 +399,7 @@ return NULL; p->stream = stream; p->deep = deep; + p->keep = 1; return p; @@ -303,7 +413,8 @@ #endif if(p->buffer) free(p->buffer); - free(p->buffer); + if(p->line) free(p->line); + free(p); } play_tree_t* @@ -314,9 +425,18 @@ assert(p != NULL); #endif - while(1) { + + while(play_tree_parser_get_line(p) != NULL) { + play_tree_parser_reset(p); + tree = parse_asx(p); if(tree) break; + play_tree_parser_reset(p); + + tree = parse_pls(p); + if(tree) break; + play_tree_parser_reset(p); + // Here come the others formats ( textplain must stay the last one ) tree = parse_textplain(p); if(tree) break; @@ -332,9 +452,5 @@ if(!tree) mp_msg(MSGT_PLAYTREE,MSGL_WARN,"Warning empty playlist\n"); - if(p->buffer) free(p->buffer); - p->buffer = NULL; - p->buffer_end = p->buffer_size = 0; - return tree; }
--- a/playtreeparser.h Thu Feb 21 13:11:31 2002 +0000 +++ b/playtreeparser.h Thu Feb 21 13:12:53 2002 +0000 @@ -7,9 +7,9 @@ typedef struct play_tree_parser { stream_t* stream; - char* buffer; + char *buffer,*iter,*line; int buffer_size , buffer_end; - int deep; + int deep,keep; } play_tree_parser_t;