📄 playtreeparser.c
字号:
#include "config.h"#include <stdlib.h>#include <stdio.h>#include <string.h>#ifdef MP_DEBUG#include <assert.h>#endif#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <ctype.h>#include "m_config.h"#include "playtree.h"#include "playtreeparser.h"#include "libmpdemux/stream.h"#include "libmpdemux/demuxer.h"#include "mp_msg.h"extern play_tree_t*asx_parser_build_tree(char* buffer, int ref);#define BUF_STEP 1024#define WHITES " \n\r\t"static voidstrstrip(char* str) { char* i; if (str==NULL) return; for(i = str ; i[0] != '\0' && strchr(WHITES,i[0]) != NULL; i++) /* NOTHING */; if(i[0] != '\0') { memmove(str,i,strlen(i) + 1); for(i = str + strlen(str) - 1 ; 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 || p->iter[0] == '\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; break; } resize = 1; continue; } break; } line_end = ((*(end-1)) == '\r') ? end-1 : end; if(line_end - p->iter >= 0) p->line = (char*)realloc(p->line,line_end - p->iter+1); else return NULL; if(line_end - p->iter > 0) strncpy(p->line,p->iter,line_end - p->iter); p->line[line_end - p->iter] = '\0'; if(end[0] != '\0') end++; if(!p->keep) { if(end[0] != '\0') { p->buffer_end -= end-p->iter; 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 voidplay_tree_parser_reset(play_tree_parser_t* p) { p->iter = p->buffer;}static voidplay_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 comments = 0,get_line = 1; char* line = NULL; mp_msg(MSGT_PLAYTREE,MSGL_V,"Trying asx...\n"); while(1) { if(get_line) { line = play_tree_parser_get_line(p); if(!line) return NULL; strstrip(line); if(line[0] == '\0') continue; } 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; } 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; } 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"); // We have an asx : load it in memory and parse 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 intpls_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, *last_entry = NULL; mp_msg(MSGT_PLAYTREE,MSGL_V,"Trying Winamp playlist...\n"); if (!(line = play_tree_parser_get_line(p))) return NULL; 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 claims 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,"Unknown 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 { mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"Adding entry %s\n",entries[num].file); entry = play_tree_new(); play_tree_add_file(entry,entries[num].file); free(entries[num].file); if(list) play_tree_append_entry(last_entry,entry); else list = entry; last_entry = 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); entry = play_tree_new(); play_tree_set_child(entry,list); return entry;}/* Reference Ini-Format: Each entry is assumed a reference */play_tree_t*parse_ref_ini(play_tree_parser_t* p) { char *line,*v; play_tree_t *list = NULL, *entry = NULL, *last_entry = NULL; mp_msg(MSGT_PLAYTREE,MSGL_V,"Trying reference-ini playlist...\n"); if (!(line = play_tree_parser_get_line(p))) return NULL; strstrip(line); if(strcasecmp(line,"[Reference]")) return NULL; mp_msg(MSGT_PLAYTREE,MSGL_V,"Detected reference-ini playlist format\n"); play_tree_parser_stop_keeping(p); line = play_tree_parser_get_line(p); if(!line) return NULL; while(line) { strstrip(line); if(strncasecmp(line,"Ref",3) == 0) { v = pls_entry_get_value(line+3); if(!v) mp_msg(MSGT_PLAYTREE,MSGL_ERR,"No value in entry %s\n",line); else { mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"Adding entry %s\n",v); entry = play_tree_new(); play_tree_add_file(entry,v); if(list) play_tree_append_entry(last_entry,entry); else list = entry; last_entry = entry; } } line = play_tree_parser_get_line(p); } if(!list) return NULL; entry = play_tree_new(); play_tree_set_child(entry,list); return entry;}play_tree_t*parse_m3u(play_tree_parser_t* p) { char* line; play_tree_t *list = NULL, *entry = NULL, *last_entry = NULL; mp_msg(MSGT_PLAYTREE,MSGL_V,"Trying extended m3u playlist...\n"); if (!(line = play_tree_parser_get_line(p))) return NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -