📄 xspf.c
字号:
else if( !strcmp( psz_name, "duration" ) ) { long i_num = atol( psz_value ); input_item_SetDuration( p_input, (mtime_t) i_num*1000 ); } else if( !strcmp( psz_name, "annotation" ) ) { input_item_SetDescription( p_input, psz_value ); } else if( !strcmp( psz_name, "image" ) ) { char *psz_uri = decode_URI_duplicate( psz_value ); input_item_SetArtURL( p_input, psz_uri ); free( psz_uri ); } return true;}/** * \brief handles the <option> elements */static bool set_option 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 ); input_item_AddOpt( p_input, psz_value, 0 ); return true;}/** * \brief parse the extension node of a XSPF playlist */static bool parse_extension_node COMPLEX_INTERFACE{ char *psz_name = NULL; char *psz_value = NULL; char *psz_title = NULL; char *psz_application = NULL; int i_node; bool b_release_input_item = false; xml_elem_hnd_t *p_handler = NULL; input_item_t *p_new_input = NULL; xml_elem_hnd_t pl_elements[] = { {"node", COMPLEX_CONTENT, {.cmplx = parse_extension_node} }, {"item", COMPLEX_CONTENT, {.cmplx = parse_extitem_node} }, {"option", SIMPLE_CONTENT, {.smpl = set_option} }, {NULL, UNKNOWN_CONTENT, {NULL} } }; /* read all extension node attributes */ while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS ) { psz_name = xml_ReaderName( p_xml_reader ); psz_value = xml_ReaderValue( p_xml_reader ); if( !psz_name || !psz_value ) { msg_Err( p_demux, "invalid xml stream @ <node>" ); FREE_ATT(); return false; } /* attribute: title */ if( !strcmp( psz_name, "title" ) ) { resolve_xml_special_chars( psz_value ); psz_title = strdup( psz_value ); } /* extension attribute: application */ else if( !strcmp( psz_name, "application" ) ) { psz_application = strdup( psz_value ); } /* unknown attribute */ else msg_Warn( p_demux, "invalid <%s> attribute:\"%s\"", psz_element, psz_name ); FREE_ATT(); } /* attribute title is mandatory except for <extension> */ if( !strcmp( psz_element, "node" ) ) { if( !psz_title ) { msg_Warn( p_demux, "<node> requires \"title\" attribute" ); return false; } p_new_input = input_item_NewWithType( VLC_OBJECT( p_demux ), "vlc://nop", psz_title, 0, NULL, -1, ITEM_TYPE_DIRECTORY ); if( p_new_input ) { input_item_AddSubItem( p_input_item, p_new_input ); p_input_item = p_new_input; b_release_input_item = true; } free( psz_title ); } else if( !strcmp( psz_element, "extension" ) ) { if( !psz_application ) { msg_Warn( p_demux, "<extension> requires \"application\" attribute" ); return false; } else if( strcmp( psz_application, "http://www.videolan.org/vlc/playlist/0" ) ) { msg_Dbg( p_demux, "Skipping \"%s\" extension tag", psz_application ); free( psz_application ); return false; } } free( psz_application ); /* parse the child elements */ 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(); if(b_release_input_item) vlc_gc_decref( p_new_input ); return false; } /* choose handler */ for( p_handler = pl_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(); if(b_release_input_item) vlc_gc_decref( p_new_input ); return false; } FREE_NAME(); /* complex content is parsed in a separate function */ if( p_handler->type == COMPLEX_CONTENT ) { if( p_handler->pf_handler.cmplx( p_demux, p_input_item, p_xml_reader, p_handler->name ) ) { p_handler = NULL; FREE_ATT(); } else { FREE_ATT(); if(b_release_input_item) vlc_gc_decref( p_new_input ); 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(); if(b_release_input_item) vlc_gc_decref( p_new_input ); 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(); if(b_release_input_item) vlc_gc_decref( p_new_input ); return false; } /* leave if the current parent node is terminated */ if( !strcmp( psz_name, psz_element ) ) { FREE_ATT(); if(b_release_input_item) vlc_gc_decref( 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(); if(b_release_input_item) vlc_gc_decref( p_new_input ); return false; } if( p_handler->pf_handler.smpl ) { p_handler->pf_handler.smpl( p_input_item, p_handler->name, psz_value ); } FREE_ATT(); p_handler = NULL; break; default: /* unknown/unexpected xml node */ msg_Err( p_demux, "unexpected xml node %i", i_node ); FREE_ATT(); if(b_release_input_item) vlc_gc_decref( p_new_input ); return false; } FREE_NAME(); } if(b_release_input_item) vlc_gc_decref( p_new_input ); return false;}/** * \brief parse the extension item node of a XSPF playlist */static bool parse_extitem_node COMPLEX_INTERFACE{ VLC_UNUSED(psz_element); input_item_t *p_new_input = NULL; char *psz_name = NULL; char *psz_value = NULL; int i_href = -1; /* read all extension item attributes */ while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS ) { psz_name = xml_ReaderName( p_xml_reader ); psz_value = xml_ReaderValue( p_xml_reader ); if( !psz_name || !psz_value ) { msg_Err( p_demux, "invalid xml stream @ <item>" ); FREE_ATT(); return false; } /* attribute: href */ if( !strcmp( psz_name, "href" ) ) { i_href = atoi( psz_value ); } /* unknown attribute */ else msg_Warn( p_demux, "invalid <item> attribute:\"%s\"", psz_name); FREE_ATT(); } /* attribute href is mandatory */ if( i_href < 0 ) { msg_Warn( p_demux, "<item> requires \"href\" attribute" ); return false; } if( i_href >= p_demux->p_sys->i_tracklist_entries ) { msg_Warn( p_demux, "invalid \"href\" attribute" ); return false; } p_new_input = p_demux->p_sys->pp_tracklist[ i_href ]; if( p_new_input ) { input_item_AddSubItem( p_input_item, p_new_input ); vlc_gc_decref( p_new_input ); p_demux->p_sys->pp_tracklist[i_href] = NULL; } /* kludge for #1293 - XTAG sends ENDELEM for self closing tag */ /* (libxml sends NONE) */ xml_ReaderRead( p_xml_reader ); return true;}/** * \brief skips complex element content that we can't manage */static bool skip_element COMPLEX_INTERFACE{ VLC_UNUSED(p_demux); VLC_UNUSED(p_input_item); char *psz_endname; while( xml_ReaderRead( p_xml_reader ) == 1 ) { if( xml_ReaderNodeType( p_xml_reader ) == XML_READER_ENDELEM ) { psz_endname = xml_ReaderName( p_xml_reader ); if( !psz_endname ) return false; if( !strcmp( psz_element, psz_endname ) ) { free( psz_endname ); return true; } else free( psz_endname ); } } return false;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -