📄 xspf.c
字号:
return false; } FREE_NAME(); } return false;}/** * \brief parses the tracklist node which only may contain <track>s */static bool parse_tracklist_node COMPLEX_INTERFACE{ VLC_UNUSED(psz_element); char *psz_name=NULL; int i_node; int i_ntracks = 0; /* now parse the <track>s */ while( xml_ReaderRead( p_xml_reader ) == 1 ) { i_node = xml_ReaderNodeType( p_xml_reader ); if( i_node == XML_READER_STARTELEM ) { psz_name = xml_ReaderName( p_xml_reader ); if( !psz_name ) { msg_Err( p_demux, "unexpected end of xml data" ); FREE_NAME(); return false; } if( strcmp( psz_name, "track") ) { msg_Err( p_demux, "unexpected child of <trackList>: <%s>", psz_name ); FREE_NAME(); return false; } FREE_NAME(); /* parse the track data in a separate function */ if( parse_track_node( p_demux, p_input_item, p_xml_reader,"track" ) == true ) i_ntracks++; } else if( i_node == XML_READER_ENDELEM ) break; } /* the <trackList> has to be terminated */ if( xml_ReaderNodeType( p_xml_reader ) != XML_READER_ENDELEM ) { msg_Err( p_demux, "there's a missing </trackList>" ); FREE_NAME(); return false; } psz_name = xml_ReaderName( p_xml_reader ); if( !psz_name || strcmp( psz_name, "trackList" ) ) { msg_Err( p_demux, "expected: </trackList>, found: </%s>", psz_name ); FREE_NAME(); return false; } FREE_NAME(); msg_Dbg( p_demux, "parsed %i tracks successfully", i_ntracks ); return true;}/** * \brief parse one track element * \param COMPLEX_INTERFACE */static bool parse_track_node COMPLEX_INTERFACE{ input_item_t *p_new_input = NULL; int i_node; char *psz_name=NULL; char *psz_value=NULL; xml_elem_hnd_t *p_handler=NULL; xml_elem_hnd_t track_elements[] = { {"location", SIMPLE_CONTENT, {NULL} }, {"identifier", SIMPLE_CONTENT, {NULL} }, {"title", SIMPLE_CONTENT, {.smpl = set_item_info} }, {"creator", SIMPLE_CONTENT, {.smpl = set_item_info} }, {"annotation", SIMPLE_CONTENT, {.smpl = set_item_info} }, {"info", SIMPLE_CONTENT, {NULL} }, {"image", SIMPLE_CONTENT, {.smpl = set_item_info} }, {"album", SIMPLE_CONTENT, {.smpl = set_item_info} }, {"trackNum", SIMPLE_CONTENT, {.smpl = set_item_info} }, {"duration", SIMPLE_CONTENT, {.smpl = set_item_info} }, {"link", SIMPLE_CONTENT, {NULL} }, {"meta", SIMPLE_CONTENT, {NULL} }, {"extension", COMPLEX_CONTENT, {.cmplx = parse_extension_node} }, {NULL, UNKNOWN_CONTENT, {NULL} } }; while( xml_ReaderRead( p_xml_reader ) == 1 ) { i_node = xml_ReaderNodeType( p_xml_reader ); switch( i_node ) { case XML_READER_NONE: break; case XML_READER_STARTELEM: /* element start tag */ psz_name = xml_ReaderName( p_xml_reader ); if( !psz_name || !*psz_name ) { msg_Err( p_demux, "invalid xml stream" ); FREE_ATT(); return false; } /* choose handler */ for( p_handler = track_elements; p_handler->name && strcmp( psz_name, p_handler->name ); p_handler++ ); if( !p_handler->name ) { msg_Err( p_demux, "unexpected element <%s>", psz_name ); FREE_ATT(); return false; } FREE_NAME(); /* complex content is parsed in a separate function */ if( p_handler->type == COMPLEX_CONTENT ) { if( !p_new_input ) { msg_Err( p_demux, "at <%s> level no new item has been allocated", p_handler->name ); FREE_ATT(); return false; } if( p_handler->pf_handler.cmplx( p_demux, p_new_input, p_xml_reader, p_handler->name ) ) { p_handler = NULL; FREE_ATT(); } else { FREE_ATT(); return false; } } break; case XML_READER_TEXT: /* simple element content */ FREE_ATT(); psz_value = xml_ReaderValue( p_xml_reader ); if( !psz_value ) { msg_Err( p_demux, "invalid xml stream" ); FREE_ATT(); return false; } break; case XML_READER_ENDELEM: /* element end tag */ psz_name = xml_ReaderName( p_xml_reader ); if( !psz_name ) { msg_Err( p_demux, "invalid xml stream" ); FREE_ATT(); return false; } /* leave if the current parent node <track> is terminated */ if( !strcmp( psz_name, psz_element ) ) { FREE_ATT(); if( p_demux->p_sys->i_identifier < p_demux->p_sys->i_tracklist_entries ) { p_demux->p_sys->pp_tracklist[ p_demux->p_sys->i_identifier ] = p_new_input; } else { if( p_demux->p_sys->i_identifier > p_demux->p_sys->i_tracklist_entries ) { p_demux->p_sys->i_tracklist_entries = p_demux->p_sys->i_identifier; } INSERT_ELEM( p_demux->p_sys->pp_tracklist, p_demux->p_sys->i_tracklist_entries, p_demux->p_sys->i_tracklist_entries, p_new_input ); } return true; } /* there MUST have been a start tag for that element name */ if( !p_handler || !p_handler->name || strcmp( p_handler->name, psz_name )) { msg_Err( p_demux, "there's no open element left for <%s>", psz_name ); FREE_ATT(); return false; } /* special case: location */ if( !strcmp( p_handler->name, "location" ) ) { char *psz_uri=NULL; /* there MUST NOT be an item */ if( p_new_input ) { msg_Err( p_demux, "item <%s> already created", psz_name ); FREE_ATT(); return false; } psz_uri = decode_URI_duplicate( psz_value ); if( psz_uri ) { if( p_demux->p_sys->psz_base && !strstr( psz_uri, "://" ) ) { char* psz_tmp = malloc( strlen(p_demux->p_sys->psz_base) + strlen(psz_uri) +1 ); if( !psz_tmp ) return false; sprintf( psz_tmp, "%s%s", p_demux->p_sys->psz_base, psz_uri ); free( psz_uri ); psz_uri = psz_tmp; } p_new_input = input_item_NewExt( p_demux, psz_uri, NULL, 0, NULL, -1 ); free( psz_uri ); input_item_CopyOptions( p_input_item, p_new_input ); psz_uri = NULL; FREE_ATT(); p_handler = NULL; } else { FREE_ATT(); return false; } } else if( !strcmp( p_handler->name, "identifier" ) ) { p_demux->p_sys->i_identifier = atoi( psz_value ); } else { /* there MUST be an item */ if( !p_new_input ) { msg_Err( p_demux, "item not yet created at <%s>", psz_name ); FREE_ATT(); return false; } if( p_handler->pf_handler.smpl ) { p_handler->pf_handler.smpl( p_new_input, p_handler->name, psz_value ); FREE_ATT(); } } FREE_ATT(); p_handler = NULL; break; default: /* unknown/unexpected xml node */ msg_Err( p_demux, "unexpected xml node %i", i_node ); FREE_ATT(); return false; } FREE_NAME(); } msg_Err( p_demux, "unexpected end of xml data" ); FREE_ATT(); return false;}/** * \brief handles the supported <track> sub-elements */static bool set_item_info SIMPLE_INTERFACE{ /* exit if setting is impossible */ if( !psz_name || !psz_value || !p_input ) return false; /* re-convert xml special characters inside psz_value */ resolve_xml_special_chars( psz_value ); /* handle each info element in a separate "if" clause */ if( !strcmp( psz_name, "title" ) ) { input_item_SetTitle( p_input, psz_value ); } else if( !strcmp( psz_name, "creator" ) ) { input_item_SetArtist( p_input, psz_value ); } else if( !strcmp( psz_name, "album" ) ) { input_item_SetAlbum( p_input, psz_value ); } else if( !strcmp( psz_name, "trackNum" ) ) { input_item_SetTrackNum( p_input, psz_value ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -