/** * \brief demuxer function for iTML parsing */ int Demux( demux_t *p_demux ) { xml_reader_t *p_xml_reader; char *psz_name = NULL; input_item_t *p_current_input = GetCurrentItem(p_demux); p_demux->p_sys->i_ntracks = 0; /* create new xml parser from stream */ p_xml_reader = xml_ReaderCreate( p_demux, p_demux->s ); if( !p_xml_reader ) goto end; /* locating the root node */ do { if( xml_ReaderRead( p_xml_reader ) != 1 ) { msg_Err( p_demux, "can't read xml stream" ); goto end; } } while( xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM ); /* checking root node name */ psz_name = xml_ReaderName( p_xml_reader ); if( !psz_name || strcmp( psz_name, "plist" ) ) { msg_Err( p_demux, "invalid root node name: %s", psz_name ); goto end; } input_item_node_t *p_subitems = input_item_node_Create( p_current_input ); xml_elem_hnd_t pl_elements[] = { {"dict", COMPLEX_CONTENT, {.cmplx = parse_plist_dict} } };
static int Android_ParseSystemFonts( filter_t *p_filter, const char *psz_path ) { int i_ret = VLC_SUCCESS; stream_t *p_stream = stream_UrlNew( p_filter, psz_path ); if( !p_stream ) return VLC_EGENERIC; xml_reader_t *p_xml = xml_ReaderCreate( p_filter, p_stream ); if( !p_xml ) { stream_Delete( p_stream ); return VLC_EGENERIC; } const char *p_node; int i_type; while( ( i_type = xml_ReaderNextNode( p_xml, &p_node ) ) > 0 ) { if( i_type == XML_READER_STARTELEM && !strcasecmp( "family", p_node ) ) { if( ( i_ret = Android_ParseFamily( p_filter, p_xml ) ) ) break; } } xml_ReaderDelete( p_xml ); stream_Delete( p_stream ); return i_ret; }
XMLParser::XMLParser( intf_thread_t *pIntf, const string &rFileName ) : SkinObject( pIntf ), m_pXML( NULL ), m_pReader( NULL ), m_pStream( NULL ) { m_pXML = xml_Create( pIntf ); if( !m_pXML ) { msg_Err( getIntf(), "cannot initialize xml" ); return; } LoadCatalog(); char *psz_uri = vlc_path2uri( rFileName.c_str(), NULL ); m_pStream = stream_UrlNew( pIntf, psz_uri ); free( psz_uri ); if( !m_pStream ) { msg_Err( getIntf(), "failed to open %s for reading", rFileName.c_str() ); return; } m_pReader = xml_ReaderCreate( m_pXML, m_pStream ); if( !m_pReader ) { msg_Err( getIntf(), "failed to open %s for parsing", rFileName.c_str() ); return; } xml_ReaderUseDTD( m_pReader ); }
int Import_WPL( vlc_object_t* p_this ) { demux_t* p_demux = (demux_t*)p_this; CHECK_FILE(); if( !demux_IsPathExtension( p_demux, ".wpl" ) && !demux_IsPathExtension( p_demux, ".zpl" ) ) return VLC_EGENERIC; DEMUX_INIT_COMMON(); demux_sys_t* p_sys = p_demux->p_sys; uint8_t *p_peek; ssize_t i_peek = stream_Peek( p_demux->s, (const uint8_t **) &p_peek, 2048 ); if( unlikely( i_peek <= 0 ) ) { Close_WPL( p_this ); return VLC_EGENERIC; } stream_t *p_probestream = stream_MemoryNew( p_demux->s, p_peek, i_peek, true ); if( unlikely( !p_probestream ) ) { Close_WPL( p_this ); return VLC_EGENERIC; } p_sys->p_reader = xml_ReaderCreate( p_this, p_probestream ); if ( !p_sys->p_reader ) { msg_Err( p_demux, "Failed to create an XML reader" ); Close_WPL( p_this ); stream_Delete( p_probestream ); return VLC_EGENERIC; } const int i_flags = p_sys->p_reader->i_flags; p_sys->p_reader->i_flags |= OBJECT_FLAGS_QUIET; const char* psz_name; int type = xml_ReaderNextNode( p_sys->p_reader, &psz_name ); p_sys->p_reader->i_flags = i_flags; if ( type != XML_READER_STARTELEM || strcasecmp( psz_name, "smil" ) ) { msg_Err( p_demux, "Invalid WPL playlist. Root element should have been <smil>" ); Close_WPL( p_this ); stream_Delete( p_probestream ); return VLC_EGENERIC; } p_sys->p_reader = xml_ReaderReset( p_sys->p_reader, p_demux->s ); stream_Delete( p_probestream ); msg_Dbg( p_demux, "Found valid WPL playlist" ); return VLC_SUCCESS; }
static int ParseSkins2Info( addons_finder_t *p_finder, stream_t *p_stream, char **ppsz_title, char **ppsz_source ) { const char *p_node; int i_current_node_type; bool b_done = false; xml_reader_t *p_xml_reader = xml_ReaderCreate( p_finder, p_stream ); if( !p_xml_reader ) return VLC_EGENERIC; if( xml_ReaderNextNode( p_xml_reader, &p_node ) != XML_READER_STARTELEM ) { msg_Err( p_finder, "invalid xml file" ); goto error; } if ( strcmp( p_node, "Theme") ) { msg_Err( p_finder, "unsupported XML data format" ); goto error; } while( !b_done && (i_current_node_type = xml_ReaderNextNode( p_xml_reader, &p_node )) > 0 ) { switch( i_current_node_type ) { case XML_READER_STARTELEM: { if ( !strcmp( p_node, "ThemeInfo" ) ) { const char *attr, *value; while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) ) { if ( !strcmp( attr, "name" ) ) *ppsz_title = strdup( value ); else if ( !strcmp( attr, "webpage" ) ) *ppsz_source = strdup( value ); } b_done = true; } break; } default: break; } } xml_ReaderDelete( p_xml_reader ); return ( b_done ) ? VLC_SUCCESS : VLC_EGENERIC; error: xml_ReaderDelete( p_xml_reader ); return VLC_EGENERIC; }
static int Demux( demux_t *p_demux ) { xml_reader_t *p_xml_reader = NULL; const char *node; int i_ret = -1; input_item_t *p_current_input = GetCurrentItem(p_demux); input_item_node_t *p_input_node = NULL; p_xml_reader = xml_ReaderCreate( p_demux, p_demux->s ); if( !p_xml_reader ) goto error; /* check root node */ if( xml_ReaderNextNode( p_xml_reader, &node ) != XML_READER_STARTELEM ) { msg_Err( p_demux, "invalid file (no root node)" ); goto error; } if( strcmp( node, "genrelist" ) && strcmp( node, "stationlist" ) ) { msg_Err( p_demux, "invalid root node <%s>", node ); goto error; } p_input_node = input_item_node_Create( p_current_input ); if( !strcmp( node, "genrelist" ) ) { /* we're reading a genre list */ if( DemuxGenre( p_demux, p_xml_reader, p_input_node ) ) goto error; } else { /* we're reading a station list */ if( DemuxStation( p_demux, p_xml_reader, p_input_node, var_InheritBool( p_demux, "shoutcast-show-adult" ) ) ) goto error; } input_item_node_PostAndDelete( p_input_node ); p_input_node = NULL; i_ret = 0; /* Needed for correct operation of go back */ error: if( p_xml_reader ) xml_ReaderDelete( p_xml_reader ); if( p_input_node ) input_item_node_Delete( p_input_node ); vlc_gc_decref(p_current_input); return i_ret; }
/** * \brief demuxer function for XSPF parsing */ int Demux( demux_t *p_demux ) { int i_ret = -1; xml_reader_t *p_xml_reader = NULL; const char *name = NULL; input_item_t *p_current_input = GetCurrentItem(p_demux); p_demux->p_sys->pp_tracklist = NULL; p_demux->p_sys->i_tracklist_entries = 0; p_demux->p_sys->i_track_id = -1; p_demux->p_sys->psz_base = NULL; /* create new xml parser from stream */ p_xml_reader = xml_ReaderCreate( p_demux, p_demux->s ); if( !p_xml_reader ) goto end; /* locating the root node */ if( xml_ReaderNextNode( p_xml_reader, &name ) != XML_READER_STARTELEM ) { msg_Err( p_demux, "can't read xml stream" ); goto end; } /* checking root node name */ if( strcmp( name, "playlist" ) ) { msg_Err( p_demux, "invalid root node name <%s>", name ); goto end; } input_item_node_t *p_subitems = input_item_node_Create( p_current_input ); i_ret = parse_playlist_node( p_demux, p_subitems, p_xml_reader, "playlist" ) ? 0 : -1; for( int i = 0 ; i < p_demux->p_sys->i_tracklist_entries ; i++ ) { input_item_t *p_new_input = p_demux->p_sys->pp_tracklist[i]; if( p_new_input ) { input_item_node_AppendItem( p_subitems, p_new_input ); } } input_item_node_PostAndDelete( p_subitems ); end: vlc_gc_decref(p_current_input); if( p_xml_reader ) xml_ReaderDelete( p_xml_reader ); return i_ret; /* Needed for correct operation of go back */ }
/***************************************************************************** * Import_podcast: main import function *****************************************************************************/ int Import_podcast( vlc_object_t *p_this ) { stream_t *p_demux = (stream_t *)p_this; CHECK_FILE(p_demux); if( stream_IsMimeType( p_demux->s, "text/xml" ) || stream_IsMimeType( p_demux->s, "application/xml" ) ) { /* XML: check if the root node is "rss". Use a specific peeked * probestream in order to not modify the source state while probing. * */ const uint8_t *p_peek; ssize_t i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 2048 ); if( unlikely( i_peek <= 0 ) ) return VLC_EGENERIC; stream_t *p_probestream = vlc_stream_MemoryNew( p_demux, (uint8_t *)p_peek, i_peek, true ); if( unlikely( !p_probestream ) ) return VLC_EGENERIC; xml_reader_t *p_xml_reader = xml_ReaderCreate( p_demux, p_probestream ); if( !p_xml_reader ) { vlc_stream_Delete( p_probestream ); return VLC_EGENERIC; } const char *node; int ret; if( ( ret = xml_ReaderNextNode( p_xml_reader, &node ) ) != XML_READER_STARTELEM || strcmp( node, "rss" ) ) { vlc_stream_Delete( p_probestream ); xml_ReaderDelete( p_xml_reader ); return VLC_EGENERIC; } xml_ReaderDelete( p_xml_reader ); vlc_stream_Delete( p_probestream ); /* SUCCESS: this text/xml is a rss file */ } else if( !stream_IsMimeType( p_demux->s, "application/rss+xml" ) ) return VLC_EGENERIC; p_demux->pf_readdir = ReadDir; p_demux->pf_control = access_vaDirectoryControlHelper; msg_Dbg( p_demux, "using podcast reader" ); return VLC_SUCCESS; }
/** * \brief demuxer function for iTML parsing */ int Demux( demux_t *p_demux ) { xml_reader_t *p_xml_reader; const char *node; input_item_t *p_current_input = GetCurrentItem(p_demux); p_demux->p_sys->i_ntracks = 0; /* create new xml parser from stream */ p_xml_reader = xml_ReaderCreate( p_demux, p_demux->s ); if( !p_xml_reader ) goto end; /* locating the root node */ int type; do { type = xml_ReaderNextNode( p_xml_reader, &node ); if( type <= 0 ) { msg_Err( p_demux, "can't read xml stream" ); goto end; } } while( type != XML_READER_STARTELEM ); /* checking root node name */ if( strcmp( node, "plist" ) ) { msg_Err( p_demux, "invalid root node <%s>", node ); goto end; } input_item_node_t *p_subitems = input_item_node_Create( p_current_input ); xml_elem_hnd_t pl_elements[] = // { {"dict", COMPLEX_CONTENT, {.cmplx = parse_plist_dict} } }; { {"dict", COMPLEX_CONTENT, {(bool (__cdecl *)(track_elem_t *,const char *,char *))parse_plist_dict} } }; // sunqueen modify parse_plist_node( p_demux, p_subitems, NULL, p_xml_reader, "plist", pl_elements ); input_item_node_PostAndDelete( p_subitems ); vlc_gc_decref(p_current_input); end: if( p_xml_reader ) xml_ReaderDelete( p_xml_reader ); /* Needed for correct operation of go back */ return 0; }
static int Demux( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; xml_t *p_xml; xml_reader_t *p_xml_reader; char *psz_eltname = NULL; INIT_PLAYLIST_STUFF; p_sys->p_current_input = p_current_input; p_xml = p_sys->p_xml = xml_Create( p_demux ); if( !p_xml ) return -1; p_xml_reader = xml_ReaderCreate( p_xml, p_demux->s ); if( !p_xml_reader ) return -1; p_sys->p_xml_reader = p_xml_reader; /* check root node */ if( xml_ReaderRead( p_xml_reader ) != 1 ) { msg_Err( p_demux, "invalid file (no root node)" ); return -1; } if( xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM || ( psz_eltname = xml_ReaderName( p_xml_reader ) ) == NULL || ( strcmp( psz_eltname, "genrelist" ) && strcmp( psz_eltname, "stationlist" ) ) ) { msg_Err( p_demux, "invalid root node %i, %s", xml_ReaderNodeType( p_xml_reader ), psz_eltname ); free( psz_eltname ); return -1; } if( !strcmp( psz_eltname, "genrelist" ) ) { /* we're reading a genre list */ free( psz_eltname ); if( DemuxGenre( p_demux ) ) return -1; } else { /* we're reading a station list */ free( psz_eltname ); if( DemuxStation( p_demux ) ) return -1; } HANDLE_PLAY_AND_RELEASE; return 0; /* Needed for correct operation of go back */ }
static int vlclua_xml_create_reader( lua_State *L ) { vlc_object_t *obj = vlclua_get_this( L ); stream_t *p_stream = *(stream_t **)luaL_checkudata( L, 2, "stream" ); xml_reader_t *p_reader = xml_ReaderCreate( obj, p_stream ); if( !p_reader ) return luaL_error( L, "XML reader creation failed." ); xml_reader_t **pp_reader = lua_newuserdata( L, sizeof( xml_reader_t * ) ); *pp_reader = p_reader; if( luaL_newmetatable( L, "xml_reader" ) ) { lua_newtable( L ); luaL_register( L, NULL, vlclua_xml_reader_reg ); lua_setfield( L, -2, "__index" ); lua_pushcfunction( L, vlclua_xml_reader_delete ); lua_setfield( L, -2, "__gc" ); } lua_setmetatable( L, -2 ); return 1; }
/** * \brief demuxer function for iTML parsing */ int Demux( demux_t *p_demux ) { xml_reader_t *p_xml_reader; const char *node; input_item_t *p_current_input = GetCurrentItem(p_demux); p_demux->p_sys->i_ntracks = 0; /* create new xml parser from stream */ p_xml_reader = xml_ReaderCreate( p_demux, p_demux->s ); if( !p_xml_reader ) goto end; /* locating the root node */ int type; do { type = xml_ReaderNextNode( p_xml_reader, &node ); if( type <= 0 ) { msg_Err( p_demux, "can't read xml stream" ); goto end; } } while( type != XML_READER_STARTELEM ); /* checking root node name */ if( strcmp( node, "plist" ) ) { msg_Err( p_demux, "invalid root node <%s>", node ); goto end; } input_item_node_t *p_subitems = input_item_node_Create( p_current_input ); xml_elem_hnd_t pl_elements[] = { {"dict", COMPLEX_CONTENT, {.cmplx = parse_plist_dict} } };
int OpenDemux( vlc_object_t* p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; const uint8_t *p_peek; ssize_t i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 2048 ); if( unlikely( i_peek <= 32 ) ) return VLC_EGENERIC; const char *psz_xml = (const char *) p_peek; size_t i_xml = i_peek; /* Try to probe without xml module/loading the full document */ char *psz_alloc = NULL; switch( GetQWBE(p_peek) ) { /* See RFC 3023 Part 4 */ case UINT64_C(0xFFFE3C003F007800): /* UTF16 BOM<? */ case UINT64_C(0xFFFE3C003F007400): /* UTF16 BOM<t */ case UINT64_C(0xFEFF003C003F0078): /* UTF16 BOM<? */ case UINT64_C(0xFEFF003C003F0074): /* UTF16 BOM<t */ psz_alloc = FromCharset( "UTF-16", p_peek, i_peek ); break; case UINT64_C(0x3C003F0078006D00): /* UTF16-LE <?xm */ case UINT64_C(0x3C003F0074007400): /* UTF16-LE <tt */ psz_alloc = FromCharset( "UTF-16LE", p_peek, i_peek ); break; case UINT64_C(0x003C003F0078006D): /* UTF16-BE <?xm */ case UINT64_C(0x003C003F00740074): /* UTF16-BE <tt */ psz_alloc = FromCharset( "UTF-16BE", p_peek, i_peek ); break; case UINT64_C(0xEFBBBF3C3F786D6C): /* UTF8 BOM<?xml */ case UINT64_C(0x3C3F786D6C207665): /* UTF8 <?xml ve */ case UINT64_C(0xEFBBBF3C74742078): /* UTF8 BOM<tt x*/ break; default: if(GetDWBE(p_peek) != UINT32_C(0x3C747420)) /* tt node without xml document marker */ return VLC_EGENERIC; } if( psz_alloc ) { psz_xml = psz_alloc; i_xml = strlen( psz_alloc ); } /* Simplified probing. Valid TTML must have a namespace declaration */ const char *psz_tt = strnstr( psz_xml, "tt ", i_xml ); if( !psz_tt || psz_tt == psz_xml || (psz_tt[-1] != ':' && psz_tt[-1] != '<') ) { free( psz_alloc ); return VLC_EGENERIC; } else { const char * const rgsz[] = { "=\"http://www.w3.org/ns/ttml\"", "=\"http://www.w3.org/2004/11/ttaf1\"", "=\"http://www.w3.org/2006/04/ttaf1\"", "=\"http://www.w3.org/2006/10/ttaf1\"", }; const char *psz_ns = NULL; for( size_t i=0; i<ARRAY_SIZE(rgsz) && !psz_ns; i++ ) { psz_ns = strnstr( psz_xml, rgsz[i], i_xml - (psz_tt - psz_xml) ); } free( psz_alloc ); if( !psz_ns ) return VLC_EGENERIC; } p_demux->p_sys = p_sys = calloc( 1, sizeof( *p_sys ) ); if( unlikely( p_sys == NULL ) ) return VLC_ENOMEM; p_sys->b_first_time = true; p_sys->temporal_extent.i_type = TT_TIMINGS_PARALLEL; tt_time_Init( &p_sys->temporal_extent.begin ); tt_time_Init( &p_sys->temporal_extent.end ); tt_time_Init( &p_sys->temporal_extent.dur ); p_sys->temporal_extent.begin.base = 0; p_sys->p_xml = xml_Create( p_demux ); if( !p_sys->p_xml ) goto error; p_sys->p_reader = xml_ReaderCreate( p_sys->p_xml, p_demux->s ); if( !p_sys->p_reader ) goto error; #ifndef TTML_DEMUX_DEBUG p_sys->p_reader->obj.flags |= OBJECT_FLAGS_QUIET; #endif if( ReadTTML( p_demux ) != VLC_SUCCESS ) goto error; tt_timings_Resolve( (tt_basenode_t *) p_sys->p_rootnode, &p_sys->temporal_extent, &p_sys->times.p_array, &p_sys->times.i_count ); #ifdef TTML_DEMUX_DEBUG { struct vlc_memstream stream; if( vlc_memstream_open( &stream ) ) goto error; tt_time_t t; tt_time_Init( &t ); tt_node_ToText( &stream, (tt_basenode_t*)p_sys->p_rootnode, &t /* invalid */ ); vlc_memstream_putc( &stream, '\0' ); if( vlc_memstream_close( &stream ) == VLC_SUCCESS ) { msg_Dbg( p_demux, "%s", stream.ptr ); free( stream.ptr ); } } #endif p_demux->pf_demux = Demux; p_demux->pf_control = Control; es_format_t fmt; es_format_Init( &fmt, SPU_ES, VLC_CODEC_TTML ); p_sys->p_es = es_out_Add( p_demux->out, &fmt ); if( !p_sys->p_es ) goto error; es_format_Clean( &fmt ); return VLC_SUCCESS; error: CloseDemux( p_demux ); return VLC_EGENERIC; }
/**************************************************************************** * FetchRSS (or Atom) feeds ***************************************************************************/ static rss_feed_t* FetchRSS( filter_t *p_filter ) { filter_sys_t *p_sys = p_filter->p_sys; stream_t *p_stream; xml_t *p_xml; xml_reader_t *p_xml_reader; int i_feed; /* These data are not modified after the creation of the module so we don't need to hold the lock */ int i_feeds = p_sys->i_feeds; bool b_images = p_sys->b_images; /* Allocate a new structure */ rss_feed_t *p_feeds = (rss_feed_t *)malloc( i_feeds * sizeof( rss_feed_t ) ); // sunqueen modify if( !p_feeds ) return NULL; p_xml = xml_Create( p_filter ); if( !p_xml ) { msg_Err( p_filter, "Failed to open XML parser" ); free( p_feeds ); return NULL; } /* Fetch all feeds and parse them */ for( i_feed = 0; i_feed < i_feeds; i_feed++ ) { rss_feed_t *p_feed = p_feeds + i_feed; rss_feed_t *p_old_feed = p_sys->p_feeds + i_feed; /* Initialize the structure */ p_feed->psz_title = NULL; p_feed->psz_description = NULL; p_feed->psz_link = NULL; p_feed->psz_image = NULL; p_feed->p_pic = NULL; p_feed->i_items = 0; p_feed->p_items = NULL; p_feed->psz_url = strdup( p_old_feed->psz_url ); /* Fetch the feed */ msg_Dbg( p_filter, "opening %s RSS/Atom feed ...", p_feed->psz_url ); p_stream = stream_UrlNew( p_filter, p_feed->psz_url ); if( !p_stream ) { msg_Err( p_filter, "Failed to open %s for reading", p_feed->psz_url ); p_xml_reader = NULL; goto error; } p_xml_reader = xml_ReaderCreate( p_xml, p_stream ); if( !p_xml_reader ) { msg_Err( p_filter, "Failed to open %s for parsing", p_feed->psz_url ); goto error; } /* Parse the feed */ if( !ParseFeed( p_filter, p_xml_reader, p_feed ) ) goto error; /* If we have a image: load it if requiere */ if( b_images && p_feed->psz_image && !p_feed->p_pic ) { p_feed->p_pic = LoadImage( p_filter, p_feed->psz_image ); } msg_Dbg( p_filter, "done with %s RSS/Atom feed", p_feed->psz_url ); xml_ReaderDelete( p_xml_reader ); stream_Delete( p_stream ); } xml_Delete( p_xml ); return p_feeds; error: FreeRSS( p_feeds, i_feed + 1 ); if( p_xml_reader ) xml_ReaderDelete( p_xml_reader ); if( p_stream ) stream_Delete( p_stream ); if( p_xml ) xml_Delete( p_xml ); return NULL; }
static int Demux( demux_t *p_demux ) { int i_ret = -1; xml_reader_t *p_xml_reader = NULL; char *psz_elname = NULL; input_item_t *p_input; char *psz_mrl = NULL, *psz_title = NULL, *psz_genre = NULL; char *psz_now = NULL, *psz_listeners = NULL, *psz_bitrate = NULL; input_item_node_t *p_subitems = NULL; input_item_t *p_current_input = GetCurrentItem(p_demux); psz_elname = stream_ReadLine( p_demux->s ); free( psz_elname ); psz_elname = NULL; p_xml_reader = xml_ReaderCreate( p_demux, p_demux->s ); if( !p_xml_reader ) goto end; /* xml */ /* check root node */ if( xml_ReaderRead( p_xml_reader ) != 1 ) { msg_Err( p_demux, "invalid file (no root node)" ); goto end; } if( xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM || ( psz_elname = xml_ReaderName( p_xml_reader ) ) == NULL || strcmp( psz_elname, "WinampXML" ) ) { msg_Err( p_demux, "invalid root node %i, %s", xml_ReaderNodeType( p_xml_reader ), psz_elname ); goto end; } FREENULL( psz_elname ); /* root node should not have any attributes, and should only * contain the "playlist node */ /* Skip until 1st child node */ while( (i_ret = xml_ReaderRead( p_xml_reader )) == 1 && xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM ); if( i_ret != 1 ) { msg_Err( p_demux, "invalid file (no child node)" ); goto end; } if( ( psz_elname = xml_ReaderName( p_xml_reader ) ) == NULL || strcmp( psz_elname, "playlist" ) ) { msg_Err( p_demux, "invalid child node %s", psz_elname ); goto end; } FREENULL( psz_elname ); // Read the attributes while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS ) { char *psz_name = xml_ReaderName( p_xml_reader ); char *psz_value = xml_ReaderValue( p_xml_reader ); if( !psz_name || !psz_value ) { free( psz_name ); free( psz_value ); goto end; } if( !strcmp( psz_name, "num_entries" ) ) { msg_Dbg( p_demux, "playlist has %d entries", atoi(psz_value) ); } else if( !strcmp( psz_name, "label" ) ) { input_item_SetName( p_current_input, psz_value ); } else { msg_Warn( p_demux, "stray attribute %s with value %s in element" " 'playlist'", psz_name, psz_value ); } free( psz_name ); free( psz_value ); } p_subitems = input_item_node_Create( p_current_input ); while( (i_ret = xml_ReaderRead( p_xml_reader )) == 1 ) { // Get the node type switch( xml_ReaderNodeType( p_xml_reader ) ) { // Error case -1: goto end; case XML_READER_STARTELEM: { // Read the element name free( psz_elname ); psz_elname = xml_ReaderName( p_xml_reader ); if( !psz_elname ) goto end; // Read the attributes while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS ) { char *psz_name = xml_ReaderName( p_xml_reader ); char *psz_value = xml_ReaderValue( p_xml_reader ); if( !psz_name || !psz_value ) { free( psz_name ); free( psz_value ); goto end; } if( !strcmp( psz_elname, "entry" ) && !strcmp( psz_name, "Playstring" ) ) { psz_mrl = psz_value; } else { msg_Warn( p_demux, "unexpected attribute %s in element %s", psz_name, psz_elname ); free( psz_value ); } free( psz_name ); } break; } case XML_READER_TEXT: { char *psz_text = xml_ReaderValue( p_xml_reader ); if( IsWhitespace( psz_text ) ) { free( psz_text ); break; } if( !strcmp( psz_elname, "Name" ) ) { psz_title = psz_text; } else if( !strcmp( psz_elname, "Genre" ) ) { psz_genre = psz_text; } else if( !strcmp( psz_elname, "Nowplaying" ) ) { psz_now = psz_text; } else if( !strcmp( psz_elname, "Listeners" ) ) { psz_listeners = psz_text; } else if( !strcmp( psz_elname, "Bitrate" ) ) { psz_bitrate = psz_text; } else if( !strcmp( psz_elname, "" ) ) { free( psz_text ); } else { msg_Warn( p_demux, "unexpected text in element '%s'", psz_elname ); free( psz_text ); } break; } // End element case XML_READER_ENDELEM: { // Read the element name free( psz_elname ); psz_elname = xml_ReaderName( p_xml_reader ); if( !psz_elname ) goto end; if( !strcmp( psz_elname, "entry" ) ) { p_input = input_item_New( p_demux, psz_mrl, psz_title ); if( psz_now ) input_item_SetNowPlaying( p_input, psz_now ); if( psz_genre ) input_item_SetGenre( p_input, psz_genre ); if( psz_listeners ) msg_Err( p_demux, "Unsupported meta listeners" ); if( psz_bitrate ) msg_Err( p_demux, "Unsupported meta bitrate" ); input_item_node_AppendItem( p_subitems, p_input ); vlc_gc_decref( p_input ); FREENULL( psz_title ); FREENULL( psz_mrl ); FREENULL( psz_genre ); FREENULL( psz_bitrate ); FREENULL( psz_listeners ); FREENULL( psz_now ); } free( psz_elname ); psz_elname = strdup( "" ); break; } } } if( i_ret != 0 ) { msg_Warn( p_demux, "error while parsing data" ); i_ret = 0; /* Needed for correct operation of go back */ } end: free( psz_elname ); if( p_subitems ) input_item_node_PostAndDelete( p_subitems ); vlc_gc_decref( p_current_input ); if( p_xml_reader ) xml_ReaderDelete( p_xml_reader ); return i_ret; }
/* "specs" : http://phobos.apple.com/static/iTunesRSS.html */ static int ReadDir( stream_t *p_demux, input_item_node_t *p_subitems ) { bool b_item = false; bool b_image = false; xml_reader_t *p_xml_reader; char *psz_elname = NULL; char *psz_item_mrl = NULL; char *psz_item_size = NULL; char *psz_item_type = NULL; char *psz_item_name = NULL; char *psz_item_date = NULL; char *psz_item_author = NULL; char *psz_item_category = NULL; char *psz_item_duration = NULL; char *psz_item_keywords = NULL; char *psz_item_subtitle = NULL; char *psz_item_summary = NULL; char *psz_art_url = NULL; const char *node; int i_type; input_item_t *p_input; input_item_t *p_current_input = GetCurrentItem(p_demux); p_xml_reader = xml_ReaderCreate( p_demux, p_demux->s ); if( !p_xml_reader ) goto error; /* xml */ /* check root node */ if( xml_ReaderNextNode( p_xml_reader, &node ) != XML_READER_STARTELEM ) { msg_Err( p_demux, "invalid file (no root node)" ); goto error; } if( strcmp( node, "rss" ) ) { msg_Err( p_demux, "invalid root node <%s>", node ); goto error; } while( (i_type = xml_ReaderNextNode( p_xml_reader, &node )) > 0 ) { switch( i_type ) { case XML_READER_STARTELEM: { free( psz_elname ); psz_elname = strdup( node ); if( unlikely(!psz_elname) ) goto error; if( !strcmp( node, "item" ) ) b_item = true; else if( !strcmp( node, "image" ) ) b_image = true; // Read the attributes const char *attr, *value; while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) ) { if( !strcmp( node, "enclosure" ) ) { char **p = NULL; if( !strcmp( attr, "url" ) ) p = &psz_item_mrl; else if( !strcmp( attr, "length" ) ) p = &psz_item_size; else if( !strcmp( attr, "type" ) ) p = &psz_item_type; if( p != NULL ) { free( *p ); *p = strdup( value ); } else msg_Dbg( p_demux,"unhandled attribute %s in <%s>", attr, node ); } else msg_Dbg( p_demux,"unhandled attribute %s in <%s>", attr, node ); } break; } case XML_READER_TEXT: { if(!psz_elname) break; /* item specific meta data */ if( b_item ) { char **p; if( !strcmp( psz_elname, "title" ) ) p = &psz_item_name; else if( !strcmp( psz_elname, "itunes:author" ) || !strcmp( psz_elname, "author" ) ) /* <author> isn't standard iTunes podcast stuff */ p = &psz_item_author; else if( !strcmp( psz_elname, "itunes:summary" ) || !strcmp( psz_elname, "description" ) ) /* <description> isn't standard iTunes podcast stuff */ p = &psz_item_summary; else if( !strcmp( psz_elname, "pubDate" ) ) p = &psz_item_date; else if( !strcmp( psz_elname, "itunes:category" ) ) p = &psz_item_category; else if( !strcmp( psz_elname, "itunes:duration" ) ) p = &psz_item_duration; else if( !strcmp( psz_elname, "itunes:keywords" ) ) p = &psz_item_keywords; else if( !strcmp( psz_elname, "itunes:subtitle" ) ) p = &psz_item_subtitle; else break; free( *p ); *p = strdup( node ); } /* toplevel meta data */ else if( !b_image ) { if( !strcmp( psz_elname, "title" ) ) input_item_SetName( p_current_input, node ); #define ADD_GINFO( info, name ) \ else if( !strcmp( psz_elname, name ) ) \ input_item_AddInfo( p_current_input, _("Podcast Info"), \ info, "%s", node ); ADD_GINFO( _("Podcast Link"), "link" ) ADD_GINFO( _("Podcast Copyright"), "copyright" ) ADD_GINFO( _("Podcast Category"), "itunes:category" ) ADD_GINFO( _("Podcast Keywords"), "itunes:keywords" ) ADD_GINFO( _("Podcast Subtitle"), "itunes:subtitle" ) #undef ADD_GINFO else if( !strcmp( psz_elname, "itunes:summary" ) || !strcmp( psz_elname, "description" ) ) { /* <description> isn't standard iTunes podcast stuff */ input_item_AddInfo( p_current_input, _( "Podcast Info" ), _( "Podcast Summary" ), "%s", node ); } } else { if( !strcmp( psz_elname, "url" ) && *node ) { free( psz_art_url ); psz_art_url = strdup( node ); } else msg_Dbg( p_demux, "unhandled text in element <%s>", psz_elname ); } break; } // End element case XML_READER_ENDELEM: { FREENULL( psz_elname ); if( !strcmp( node, "item" ) ) { if( psz_item_mrl == NULL ) { if (psz_item_name) msg_Warn( p_demux, "invalid XML item, skipping %s", psz_item_name ); else msg_Warn( p_demux, "invalid XML item, skipped" ); FREENULL( psz_item_name ); FREENULL( psz_item_size ); FREENULL( psz_item_type ); FREENULL( psz_item_date ); FREENULL( psz_item_author ); FREENULL( psz_item_category ); FREENULL( psz_item_duration ); FREENULL( psz_item_keywords ); FREENULL( psz_item_subtitle ); FREENULL( psz_item_summary ); FREENULL( psz_art_url ); FREENULL( psz_elname ); continue; } vlc_xml_decode( psz_item_mrl ); vlc_xml_decode( psz_item_name ); p_input = input_item_New( psz_item_mrl, psz_item_name ); FREENULL( psz_item_mrl ); FREENULL( psz_item_name ); if( p_input == NULL ) break; /* FIXME: meta data memory leaks? */ /* Set the duration if available */ if( psz_item_duration ) p_input->i_duration = strTimeToMTime( psz_item_duration ); #define ADD_INFO( info, field ) \ if( field ) { \ input_item_AddInfo( p_input, _( "Podcast Info" ), (info), "%s", \ (field) ); \ FREENULL( field ); } ADD_INFO( _("Podcast Publication Date"), psz_item_date ); ADD_INFO( _("Podcast Author"), psz_item_author ); ADD_INFO( _("Podcast Subcategory"), psz_item_category ); ADD_INFO( _("Podcast Duration"), psz_item_duration ); ADD_INFO( _("Podcast Keywords"), psz_item_keywords ); ADD_INFO( _("Podcast Subtitle"), psz_item_subtitle ); ADD_INFO( _("Podcast Summary"), psz_item_summary ); ADD_INFO( _("Podcast Type"), psz_item_type ); #undef ADD_INFO /* Add the global art url to this item, if any */ if( psz_art_url ) { vlc_xml_decode( psz_art_url ); input_item_SetArtURL( p_input, psz_art_url ); } if( psz_item_size ) { input_item_AddInfo( p_input, _( "Podcast Info" ), _( "Podcast Size" ), _("%s bytes"), psz_item_size ); FREENULL( psz_item_size ); } input_item_node_AppendItem( p_subitems, p_input ); input_item_Release( p_input ); b_item = false; } else if( !strcmp( node, "image" ) ) { b_image = false; } break; } } }
/** * \brief demuxer function for XSPF parsing */ int Demux( demux_t *p_demux ) { int i_ret = -1; xml_t *p_xml = NULL; xml_reader_t *p_xml_reader = NULL; char *psz_name = NULL; input_item_t *p_current_input = GetCurrentItem(p_demux); p_demux->p_sys->pp_tracklist = NULL; p_demux->p_sys->i_tracklist_entries = 0; p_demux->p_sys->i_track_id = -1; p_demux->p_sys->psz_base = NULL; /* create new xml parser from stream */ p_xml = xml_Create( p_demux ); if( !p_xml ) goto end; p_xml_reader = xml_ReaderCreate( p_xml, p_demux->s ); if( !p_xml_reader ) goto end; /* locating the root node */ do { if( xml_ReaderRead( p_xml_reader ) != 1 ) { msg_Err( p_demux, "can't read xml stream" ); goto end; } } while( xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM ); /* checking root node name */ psz_name = xml_ReaderName( p_xml_reader ); if( !psz_name || strcmp( psz_name, "playlist" ) ) { msg_Err( p_demux, "invalid root node name: %s", psz_name ); free( psz_name ); goto end; } free( psz_name ); i_ret = parse_playlist_node( p_demux, p_current_input, p_xml_reader, "playlist" ) ? 0 : -1; for( int i = 0 ; i < p_demux->p_sys->i_tracklist_entries ; i++ ) { input_item_t *p_new_input = p_demux->p_sys->pp_tracklist[i]; if( p_new_input ) { input_item_AddSubItem( p_current_input, p_new_input ); } } end: vlc_gc_decref(p_current_input); if( p_xml_reader ) xml_ReaderDelete( p_xml, p_xml_reader ); if( p_xml ) xml_Delete( p_xml ); return i_ret; /* Needed for correct operation of go back */ }
static int Demux( demux_t *p_demux ) { const char *psz_node = NULL; char *psz_txt = NULL; char *psz_base = FindPrefix( p_demux ); char *psz_title_asx = NULL; char *psz_entryref = NULL; xml_reader_t *p_xml_reader = NULL; input_item_t *p_current_input = GetCurrentItem( p_demux ); input_item_node_t *p_subitems = NULL; bool b_first_node = false; int i_type; int i_n_entry = 0; p_xml_reader = xml_ReaderCreate( p_demux, p_demux->s ); if( !p_xml_reader ) { msg_Err( p_demux, "Cannot parse ASX input file as XML"); goto error; } p_subitems = input_item_node_Create( p_current_input ); do { i_type = xml_ReaderNextNode( p_xml_reader, &psz_node ); if( i_type == XML_READER_STARTELEM ) { if( !b_first_node ) { if(!strncasecmp( psz_node, "ASX", 3 ) ) b_first_node = true; else { msg_Err( p_demux, "invalid root node" ); goto error; } } /* Metadata Node Handler */ if( !strncasecmp( psz_node, "TITLE", 5 ) ) { ReadElement( p_xml_reader, &psz_title_asx ); input_item_SetTitle( p_current_input, psz_title_asx ); } else if( !strncasecmp( psz_node, "AUTHOR", 6 ) ) { ReadElement( p_xml_reader, &psz_txt ); input_item_SetArtist( p_current_input, psz_txt ); } else if( !strncasecmp( psz_node, "COPYRIGHT", 9 ) ) { ReadElement( p_xml_reader, &psz_txt ); input_item_SetCopyright( p_current_input, psz_txt ); } else if( !strncasecmp( psz_node, "MOREINFO", 8 ) ) { const char *psz_tmp; do { psz_tmp = xml_ReaderNextAttr( p_xml_reader, &psz_node ); } while( psz_tmp && strncasecmp( psz_tmp, "HREF", 4 ) ); if( !psz_tmp ) // If HREF attribute doesn't exist ReadElement( p_xml_reader, &psz_txt ); else psz_txt = strdup( psz_node ); resolve_xml_special_chars( psz_txt ); input_item_SetURL( p_current_input, psz_txt ); } else if( !strncasecmp( psz_node, "ABSTRACT", 8 ) ) { ReadElement( p_xml_reader, &psz_txt ); input_item_SetDescription( p_current_input, psz_txt ); } else /* Base Node handler */ if( !strncasecmp( psz_node, "BASE", 4 ) ) ReadElement( p_xml_reader, &psz_base ); else /* Entry Ref Handler */ if( !strncasecmp( psz_node, "ENTRYREF", 7 ) ) { const char *psz_tmp; do { psz_tmp = xml_ReaderNextAttr( p_xml_reader, &psz_node ); } while( psz_tmp && !strncasecmp( psz_tmp, "HREF", 4 ) ); /* Create new input item */ input_item_t *p_input; psz_txt = strdup( psz_node ); resolve_xml_special_chars( psz_txt ); p_input = input_item_New( psz_txt, psz_title_asx ); input_item_CopyOptions( p_current_input, p_input ); input_item_node_AppendItem( p_subitems, p_input ); vlc_gc_decref( p_input ); } else /* Entry Handler */ if( !strncasecmp( psz_node, "ENTRY", 5 ) ) { ProcessEntry( &i_n_entry, p_xml_reader, p_subitems, p_current_input, psz_base); } /* FIXME Unsupported elements PARAM EVENT REPEAT ENDMARK STARTMARK */ } } while( i_type != XML_READER_ENDELEM || strncasecmp( psz_node, "ASX", 3 ) ); input_item_node_PostAndDelete( p_subitems ); p_subitems = NULL; error: free( psz_base ); free( psz_title_asx ); free( psz_entryref ); free( psz_txt ); if( p_xml_reader) xml_ReaderDelete( p_xml_reader ); if( p_subitems ) input_item_node_Delete( p_subitems ); vlc_gc_decref( p_current_input ); return 0; }
static int LoadCatalog( addons_finder_t *p_finder ) { char *psz_path; char * psz_userdir = config_GetUserDir( VLC_DATA_DIR ); if ( !psz_userdir ) return VLC_ENOMEM; if ( asprintf( &psz_path, "%s%s", psz_userdir, ADDONS_CATALOG ) < 1 ) { free( psz_userdir ); return VLC_ENOMEM; } free( psz_userdir ); addon_entry_t *p_entry = NULL; const char *p_node; int i_current_node_type; int i_ret = VLC_SUCCESS; /* attr */ const char *attr, *value; /* temp reading */ char *psz_filename = NULL; int i_filetype = -1; struct stat stat_; if ( vlc_stat( psz_path, &stat_ ) ) { free( psz_path ); return VLC_EGENERIC; } char *psz_catalog_uri = vlc_path2uri( psz_path, "file" ); free( psz_path ); if ( !psz_catalog_uri ) return VLC_EGENERIC; stream_t *p_stream = stream_UrlNew( p_finder, psz_catalog_uri ); free( psz_catalog_uri ); if (! p_stream ) return VLC_EGENERIC; xml_reader_t *p_xml_reader = xml_ReaderCreate( p_finder, p_stream ); if( !p_xml_reader ) { stream_Delete( p_stream ); return VLC_EGENERIC; } if( xml_ReaderNextNode( p_xml_reader, &p_node ) != XML_READER_STARTELEM ) { msg_Err( p_finder, "invalid catalog" ); i_ret = VLC_EGENERIC; goto end; } if ( strcmp( p_node, "videolan") ) { msg_Err( p_finder, "unsupported catalog data format" ); i_ret = VLC_EGENERIC; goto end; } while( (i_current_node_type = xml_ReaderNextNode( p_xml_reader, &p_node )) > 0 ) { switch( i_current_node_type ) { case XML_READER_STARTELEM: { if ( ! strcmp( p_node, "addon" ) ) { if ( p_entry ) /* ?!? Unclosed tag */ addon_entry_Release( p_entry ); p_entry = addon_entry_New(); //p_entry->psz_source_module = strdup( ADDONS_MODULE_SHORTCUT ); p_entry->e_flags = ADDON_MANAGEABLE; p_entry->e_state = ADDON_INSTALLED; while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) ) { if ( !strcmp( attr, "type" ) ) { p_entry->e_type = ReadType( value ); } else if ( !strcmp( attr, "id" ) ) { addons_uuid_read( value, & p_entry->uuid ); } else if ( !strcmp( attr, "downloads" ) ) { p_entry->i_downloads = atoi( value ); if ( p_entry->i_downloads < 0 ) p_entry->i_downloads = 0; } else if ( !strcmp( attr, "score" ) ) { p_entry->i_score = atoi( value ); if ( p_entry->i_score < 0 ) p_entry->i_score = 0; else if ( p_entry->i_score > ADDON_MAX_SCORE ) p_entry->i_score = ADDON_MAX_SCORE; } else if ( !strcmp( attr, "source" ) ) { p_entry->psz_source_module = strdup( value ); } else if ( !strcmp( attr, "version" ) ) { p_entry->psz_version = strdup( value ); } } break; } if ( !p_entry ) break; BINDNODE("name", p_entry->psz_name, TYPE_STRING) BINDNODE("archive", p_entry->psz_archive_uri, TYPE_STRING) BINDNODE("summary", p_entry->psz_summary, TYPE_STRING) BINDNODE("description", p_entry->psz_description, TYPE_STRING) BINDNODE("image", p_entry->psz_image_data, TYPE_STRING) BINDNODE("resource", psz_filename, TYPE_STRING) BINDNODE("creator", p_entry->psz_author, TYPE_STRING) BINDNODE("sourceurl", p_entry->psz_source_uri, TYPE_STRING) data_pointer.e_type = TYPE_NONE; if ( ! strcmp( p_node, "resource" ) ) { while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) ) { if ( !strcmp( attr, "type" ) ) { i_filetype = ReadType( value ); } } } break; } case XML_READER_TEXT: if ( data_pointer.e_type == TYPE_NONE || !p_entry ) break; if ( data_pointer.e_type == TYPE_STRING ) *data_pointer.u_data.ppsz = strdup( p_node ); else if ( data_pointer.e_type == TYPE_LONG ) *data_pointer.u_data.pl = atol( p_node ); else if ( data_pointer.e_type == TYPE_INTEGER ) *data_pointer.u_data.pi = atoi( p_node ); break; case XML_READER_ENDELEM: if ( !p_entry ) break; if ( ! strcmp( p_node, "addon" ) ) { /* then append entry */ ARRAY_APPEND( p_finder->entries, p_entry ); p_entry = NULL; } if ( ! strcmp( p_node, "resource" ) ) { if ( p_entry && psz_filename && i_filetype >= 0 ) { addon_file_t *p_file = malloc( sizeof(addon_file_t) ); p_file->e_filetype = i_filetype; p_file->psz_filename = psz_filename; p_file->psz_download_uri = NULL; ARRAY_APPEND( p_entry->files, p_file ); } /* reset temp */ psz_filename = NULL; i_filetype = -1; } data_pointer.e_type = TYPE_NONE; break; default: break; } } end: if ( p_entry ) /* ?!? Unclosed tag */ addon_entry_Release( p_entry ); xml_ReaderDelete( p_xml_reader ); stream_Delete( p_stream ); return i_ret; }
/** * \brief demuxer function for XSPF parsing */ int Demux( demux_t *p_demux ) { int i_ret = 1; xml_t *p_xml = NULL; xml_reader_t *p_xml_reader = NULL; char *psz_name = NULL; INIT_PLAYLIST_STUFF; p_demux->p_sys->pp_tracklist = NULL; p_demux->p_sys->i_tracklist_entries = 0; p_demux->p_sys->i_track_id = -1; p_demux->p_sys->psz_base = NULL; /* create new xml parser from stream */ p_xml = xml_Create( p_demux ); if( !p_xml ) i_ret = -1; else { p_xml_reader = xml_ReaderCreate( p_xml, p_demux->s ); if( !p_xml_reader ) i_ret = -1; } /* locating the root node */ if( i_ret == 1 ) { do { if( xml_ReaderRead( p_xml_reader ) != 1 ) { msg_Err( p_demux, "can't read xml stream" ); i_ret = -1; } } while( i_ret == VLC_SUCCESS && xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM ); } /* checking root node name */ if( i_ret == 1 ) { psz_name = xml_ReaderName( p_xml_reader ); if( !psz_name || strcmp( psz_name, "playlist" ) ) { msg_Err( p_demux, "invalid root node name: %s", psz_name ); i_ret = -1; } FREE_NAME(); } if( i_ret == 1 ) i_ret = parse_playlist_node( p_demux, p_current_input, p_xml_reader, "playlist" ) ? 0 : -1; int i; for( i = 0 ; i < p_demux->p_sys->i_tracklist_entries ; i++ ) { input_item_t *p_new_input = p_demux->p_sys->pp_tracklist[i]; if( p_new_input ) { input_item_AddSubItem( p_current_input, p_new_input ); } } HANDLE_PLAY_AND_RELEASE; if( p_xml_reader ) xml_ReaderDelete( p_xml, p_xml_reader ); if( p_xml ) xml_Delete( p_xml ); return i_ret; /* Needed for correct operation of go back */ }
static int ReadDir( stream_t *p_demux, input_item_node_t *p_subitems ) { xml_reader_t *p_xml_reader; input_item_t *p_input; int i_ret = -1; /* List of all possible attributes. The only required one is "src" */ bool b_autoplay = false; bool b_controller = true; qtl_fullscreen_t fullscreen = false; char *psz_href = NULL; bool b_kioskmode = false; qtl_loop_t loop = LOOP_FALSE; int i_movieid = -1; char *psz_moviename = NULL; bool b_playeveryframe = false; char *psz_qtnext = NULL; bool b_quitwhendone = false; char *psz_src = NULL; char *psz_mimetype = NULL; int i_volume = 100; p_xml_reader = xml_ReaderCreate( p_demux, p_demux->p_source ); if( !p_xml_reader ) goto error; for( int i = 0;; ++i ) /* locate root node */ { const char *node; if( i == ROOT_NODE_MAX_DEPTH || xml_ReaderNextNode( p_xml_reader, &node ) != XML_READER_STARTELEM ) { msg_Err( p_demux, "unable to locate root-node" ); goto error; } if( strcmp( node, "embed" ) == 0 ) break; /* found it */ msg_Dbg( p_demux, "invalid root node <%s>, trying next (%d / %d)", node, i + 1, ROOT_NODE_MAX_DEPTH ); } const char *attrname, *value; while( (attrname = xml_ReaderNextAttr( p_xml_reader, &value )) != NULL ) { if( !strcmp( attrname, "autoplay" ) ) b_autoplay = !strcmp( value, "true" ); else if( !strcmp( attrname, "controller" ) ) b_controller = !strcmp( attrname, "false" ); else if( !strcmp( attrname, "fullscreen" ) ) { if( !strcmp( value, "double" ) ) fullscreen = FULLSCREEN_DOUBLE; else if( !strcmp( value, "half" ) ) fullscreen = FULLSCREEN_HALF; else if( !strcmp( value, "current" ) ) fullscreen = FULLSCREEN_CURRENT; else if( !strcmp( value, "full" ) ) fullscreen = FULLSCREEN_FULL; else fullscreen = FULLSCREEN_NORMAL; } else if( !strcmp( attrname, "href" ) ) { free( psz_href ); psz_href = strdup( value ); } else if( !strcmp( attrname, "kioskmode" ) ) b_kioskmode = !strcmp( value, "true" ); else if( !strcmp( attrname, "loop" ) ) { if( !strcmp( value, "true" ) ) loop = LOOP_TRUE; else if( !strcmp( value, "palindrome" ) ) loop = LOOP_PALINDROME; else loop = LOOP_FALSE; } else if( !strcmp( attrname, "movieid" ) ) i_movieid = atoi( value ); else if( !strcmp( attrname, "moviename" ) ) { free( psz_moviename ); psz_moviename = strdup( value ); } else if( !strcmp( attrname, "playeveryframe" ) ) b_playeveryframe = !strcmp( value, "true" ); else if( !strcmp( attrname, "qtnext" ) ) { free( psz_qtnext ); psz_qtnext = strdup( value ); } else if( !strcmp( attrname, "quitwhendone" ) ) b_quitwhendone = !strcmp( value, "true" ); else if( !strcmp( attrname, "src" ) ) { free( psz_src ); psz_src = strdup( value ); } else if( !strcmp( attrname, "mimetype" ) ) { free( psz_mimetype ); psz_mimetype = strdup( value ); } else if( !strcmp( attrname, "volume" ) ) i_volume = atoi( value ); else msg_Dbg( p_demux, "Attribute %s with value %s isn't valid", attrname, value ); } msg_Dbg( p_demux, "autoplay: %s (unused by VLC)", b_autoplay ? "true": "false" ); msg_Dbg( p_demux, "controller: %s (unused by VLC)", b_controller ? "true": "false" ); msg_Dbg( p_demux, "fullscreen: %s (unused by VLC)", ppsz_fullscreen[fullscreen] ); msg_Dbg( p_demux, "href: %s", psz_href ); msg_Dbg( p_demux, "kioskmode: %s (unused by VLC)", b_kioskmode ? "true":"false" ); msg_Dbg( p_demux, "loop: %s (unused by VLC)", ppsz_loop[loop] ); msg_Dbg( p_demux, "movieid: %d (unused by VLC)", i_movieid ); msg_Dbg( p_demux, "moviename: %s", psz_moviename ); msg_Dbg( p_demux, "playeverframe: %s (unused by VLC)", b_playeveryframe ? "true":"false" ); msg_Dbg( p_demux, "qtnext: %s", psz_qtnext ); msg_Dbg( p_demux, "quitwhendone: %s (unused by VLC)", b_quitwhendone ? "true":"false" ); msg_Dbg( p_demux, "src: %s", psz_src ); msg_Dbg( p_demux, "mimetype: %s", psz_mimetype ); msg_Dbg( p_demux, "volume: %d (unused by VLC)", i_volume ); if( !psz_src ) { msg_Err( p_demux, "Mandatory attribute 'src' not found" ); } else { p_input = input_item_New( psz_src, psz_moviename ); #define SADD_INFO( type, field ) if( field ) { input_item_AddInfo( \ p_input, "QuickTime Media Link", type, "%s", field ) ; } SADD_INFO( "href", psz_href ); SADD_INFO( _("Mime"), psz_mimetype ); input_item_node_AppendItem( p_subitems, p_input ); input_item_Release( p_input ); if( psz_qtnext ) { vlc_xml_decode( psz_qtnext ); p_input = input_item_New( psz_qtnext, NULL ); input_item_node_AppendItem( p_subitems, p_input ); input_item_Release( p_input ); } } i_ret = 0; /* Needed for correct operation of go back */ error: if( p_xml_reader ) xml_ReaderDelete( p_xml_reader ); free( psz_href ); free( psz_moviename ); free( psz_qtnext ); free( psz_src ); free( psz_mimetype ); return i_ret; }
static int ParseCategoriesInfo( addons_finder_t *p_finder, stream_t *p_stream ) { int i_num_entries_created = 0; const char *p_node; const char *attr, *value; int i_current_node_type; addon_entry_t *p_entry = NULL; xml_reader_t *p_xml_reader = xml_ReaderCreate( p_finder, p_stream ); if( !p_xml_reader ) return 0; if( xml_ReaderNextNode( p_xml_reader, &p_node ) != XML_READER_STARTELEM ) { msg_Err( p_finder, "invalid xml file" ); goto end; } if ( strcmp( p_node, "videolan") ) { msg_Err( p_finder, "unsupported XML data format" ); goto end; } while( (i_current_node_type = xml_ReaderNextNode( p_xml_reader, &p_node )) > 0 ) { switch( i_current_node_type ) { case XML_READER_STARTELEM: { if ( ! strcmp( p_node, "addon" ) ) { if ( p_entry ) /* Unclosed tag */ addon_entry_Release( p_entry ); p_entry = addon_entry_New(); p_entry->psz_source_module = strdup( ADDONS_MODULE_SHORTCUT ); p_entry->e_flags = ADDON_MANAGEABLE; p_entry->e_state = ADDON_NOTINSTALLED; while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) ) { if ( !strcmp( attr, "type" ) ) { p_entry->e_type = ReadType( value ); } else if ( !strcmp( attr, "id" ) ) { addons_uuid_read( value, & p_entry->uuid ); } else if ( !strcmp( attr, "downloads" ) ) { p_entry->i_downloads = atoi( value ); } else if ( !strcmp( attr, "score" ) ) { p_entry->i_score = atol( value ); } else if ( !strcmp( attr, "version" ) ) { p_entry->psz_version = strdup( value ); } } break; } if ( !p_entry ) break; BINDNODE("name", p_entry->psz_name, TYPE_STRING) BINDNODE("archive", p_entry->psz_archive_uri, TYPE_STRING) BINDNODE("summary", p_entry->psz_summary, TYPE_STRING) BINDNODE("description", p_entry->psz_description, TYPE_STRING) BINDNODE("image", p_entry->psz_image_data, TYPE_STRING) BINDNODE("creator", p_entry->psz_author, TYPE_STRING) BINDNODE("sourceurl", p_entry->psz_source_uri, TYPE_STRING) data_pointer.e_type = TYPE_NONE; break; } case XML_READER_TEXT: if ( data_pointer.e_type == TYPE_NONE || !p_entry ) break; if ( data_pointer.e_type == TYPE_STRING ) *data_pointer.u_data.ppsz = strdup( p_node ); else if ( data_pointer.e_type == TYPE_LONG ) *data_pointer.u_data.pl = atol( p_node ); else if ( data_pointer.e_type == TYPE_INTEGER ) *data_pointer.u_data.pi = atoi( p_node ); break; case XML_READER_ENDELEM: if ( !p_entry ) break; if ( ! strcmp( p_node, "addon" ) ) { /* then append entry */ ARRAY_APPEND( p_finder->entries, p_entry ); p_entry = NULL; i_num_entries_created++; } data_pointer.e_type = TYPE_NONE; break; default: break; } } end: if ( p_entry ) /* Unclosed tag */ addon_entry_Release( p_entry ); xml_ReaderDelete( p_xml_reader ); return i_num_entries_created; }
static int Demux( demux_t *p_demux ) { int i_ret = -1; xml_reader_t *p_xml_reader = NULL; char *psz_elname = NULL; const char *node; input_item_t *p_input; char *psz_mrl = NULL, *psz_title = NULL, *psz_genre = NULL; char *psz_now = NULL, *psz_listeners = NULL, *psz_bitrate = NULL; input_item_node_t *p_subitems = NULL; input_item_t *p_current_input = GetCurrentItem(p_demux); free( stream_ReadLine( p_demux->s ) ); p_xml_reader = xml_ReaderCreate( p_demux, p_demux->s ); if( !p_xml_reader ) return -1; /* xml */ /* check root node */ if( xml_ReaderNextNode( p_xml_reader, &node ) != XML_READER_STARTELEM ) { msg_Err( p_demux, "invalid file (no root node)" ); goto end; } if( strcmp( node, "WinampXML" ) ) { msg_Err( p_demux, "invalid root node: %s", node ); goto end; } /* root node should not have any attributes, and should only * contain the "playlist node */ /* Skip until 1st child node */ while( (i_ret = xml_ReaderNextNode( p_xml_reader, &node )) != XML_READER_STARTELEM ) if( i_ret <= 0 ) { msg_Err( p_demux, "invalid file (no child node)" ); goto end; } if( strcmp( node, "playlist" ) ) { msg_Err( p_demux, "invalid child node %s", node ); goto end; } // Read the attributes const char *attr, *value; while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) != NULL ) { if( !strcmp( attr, "num_entries" ) ) msg_Dbg( p_demux, "playlist has %d entries", atoi(value) ); else if( !strcmp( attr, "label" ) ) input_item_SetName( p_current_input, value ); else msg_Warn( p_demux, "stray attribute %s with value %s in element" " <playlist>", attr, value ); } p_subitems = input_item_node_Create( p_current_input ); while( (i_ret = xml_ReaderNextNode( p_xml_reader, &node )) > 0 ) { // Get the node type switch( i_ret ) { case XML_READER_STARTELEM: { // Read the element name free( psz_elname ); psz_elname = strdup( node ); if( unlikely(!psz_elname) ) goto end; // Read the attributes while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) ) { if( !strcmp( psz_elname, "entry" ) && !strcmp( attr, "Playstring" ) ) { free( psz_mrl ); psz_mrl = strdup( value ); } else { msg_Warn( p_demux, "unexpected attribute %s in <%s>", attr, psz_elname ); } } break; } case XML_READER_TEXT: { char **p; if( psz_elname == NULL ) break; if( IsWhitespace( node ) ) break; if( !strcmp( psz_elname, "Name" ) ) p = &psz_title; else if( !strcmp( psz_elname, "Genre" ) ) p = &psz_genre; else if( !strcmp( psz_elname, "Nowplaying" ) ) p = &psz_now; else if( !strcmp( psz_elname, "Listeners" ) ) p = &psz_listeners; else if( !strcmp( psz_elname, "Bitrate" ) ) p = &psz_bitrate; else { msg_Warn( p_demux, "unexpected text in element <%s>", psz_elname ); break; } free( *p ); *p = strdup( node ); break; } // End element case XML_READER_ENDELEM: { // Read the element name if( !strcmp( node, "entry" ) ) { p_input = input_item_New( p_demux, psz_mrl, psz_title ); if( psz_now ) input_item_SetNowPlaying( p_input, psz_now ); if( psz_genre ) input_item_SetGenre( p_input, psz_genre ); if( psz_listeners ) msg_Err( p_demux, "Unsupported meta listeners" ); if( psz_bitrate ) msg_Err( p_demux, "Unsupported meta bitrate" ); input_item_node_AppendItem( p_subitems, p_input ); vlc_gc_decref( p_input ); FREENULL( psz_title ); FREENULL( psz_mrl ); FREENULL( psz_genre ); FREENULL( psz_bitrate ); FREENULL( psz_listeners ); FREENULL( psz_now ); } FREENULL( psz_elname ); break; } } } if( i_ret < 0 ) { msg_Warn( p_demux, "error while parsing data" ); i_ret = 0; /* Needed for correct operation of go back */ } end: free( psz_elname ); if( p_subitems ) input_item_node_PostAndDelete( p_subitems ); vlc_gc_decref( p_current_input ); if( p_xml_reader ) xml_ReaderDelete( p_xml_reader ); return i_ret; }
static int Demux( demux_t *p_demux ) { xml_reader_t *p_xml_reader; const char *node; input_item_t *p_input; int i_ret = -1; /* List of all possible attributes. The only required one is "src" */ bool b_autoplay = false; bool b_controler = true; qtl_fullscreen_t fullscreen = false; char *psz_href = NULL; bool b_kioskmode = false; qtl_loop_t loop = LOOP_FALSE; int i_movieid = -1; char *psz_moviename = NULL; bool b_playeveryframe = false; char *psz_qtnext = NULL; bool b_quitwhendone = false; char *psz_src = NULL; char *psz_mimetype = NULL; int i_volume = 100; input_item_t *p_current_input = GetCurrentItem(p_demux); p_xml_reader = xml_ReaderCreate( p_demux, p_demux->s ); if( !p_xml_reader ) goto error; /* check root node */ if( xml_ReaderNextNode( p_xml_reader, &node ) != XML_READER_STARTELEM || strcmp( node, "embed" ) ) { msg_Err( p_demux, "invalid root node <%s>", node ); /* second line has <?quicktime tag ... so we try to skip it */ msg_Dbg( p_demux, "trying to read one more node" ); if( xml_ReaderNextNode( p_xml_reader, &node ) != XML_READER_STARTELEM || strcmp( node, "embed" ) ) { msg_Err( p_demux, "invalid root node <%s>", node ); goto error; } } const char *attrname, *value; while( (attrname = xml_ReaderNextAttr( p_xml_reader, &value )) != NULL ) { if( !strcmp( attrname, "autoplay" ) ) b_autoplay = !strcmp( value, "true" ); else if( !strcmp( attrname, "controler" ) ) b_controler = !strcmp( attrname, "false" ); else if( !strcmp( attrname, "fullscreen" ) ) { if( !strcmp( value, "double" ) ) fullscreen = FULLSCREEN_DOUBLE; else if( !strcmp( value, "half" ) ) fullscreen = FULLSCREEN_HALF; else if( !strcmp( value, "current" ) ) fullscreen = FULLSCREEN_CURRENT; else if( !strcmp( value, "full" ) ) fullscreen = FULLSCREEN_FULL; else fullscreen = FULLSCREEN_NORMAL; } else if( !strcmp( attrname, "href" ) ) { free( psz_href ); psz_href = strdup( value ); } else if( !strcmp( attrname, "kioskmode" ) ) b_kioskmode = !strcmp( value, "true" ); else if( !strcmp( attrname, "loop" ) ) { if( !strcmp( value, "true" ) ) loop = LOOP_TRUE; else if( !strcmp( value, "palindrome" ) ) loop = LOOP_PALINDROME; else loop = LOOP_FALSE; } else if( !strcmp( attrname, "movieid" ) ) i_movieid = atoi( value ); else if( !strcmp( attrname, "moviename" ) ) { free( psz_moviename ); psz_moviename = strdup( value ); } else if( !strcmp( attrname, "playeveryframe" ) ) b_playeveryframe = !strcmp( value, "true" ); else if( !strcmp( attrname, "qtnext" ) ) { free( psz_qtnext ); psz_qtnext = strdup( value ); } else if( !strcmp( attrname, "quitwhendone" ) ) b_quitwhendone = !strcmp( value, "true" ); else if( !strcmp( attrname, "src" ) ) { free( psz_src ); psz_src = strdup( value ); } else if( !strcmp( attrname, "mimetype" ) ) { free( psz_mimetype ); psz_mimetype = strdup( value ); } else if( !strcmp( attrname, "volume" ) ) i_volume = atoi( value ); else msg_Dbg( p_demux, "Attribute %s with value %s isn't valid", attrname, value ); } msg_Dbg( p_demux, "autoplay: %s (unused by VLC)", b_autoplay ? "true": "false" ); msg_Dbg( p_demux, "controler: %s (unused by VLC)", b_controler ? "true": "false" ); msg_Dbg( p_demux, "fullscreen: %s (unused by VLC)", ppsz_fullscreen[fullscreen] ); msg_Dbg( p_demux, "href: %s", psz_href ); msg_Dbg( p_demux, "kioskmode: %s (unused by VLC)", b_kioskmode ? "true":"false" ); msg_Dbg( p_demux, "loop: %s (unused by VLC)", ppsz_loop[loop] ); msg_Dbg( p_demux, "movieid: %d (unused by VLC)", i_movieid ); msg_Dbg( p_demux, "moviename: %s", psz_moviename ); msg_Dbg( p_demux, "playeverframe: %s (unused by VLC)", b_playeveryframe ? "true":"false" ); msg_Dbg( p_demux, "qtnext: %s", psz_qtnext ); msg_Dbg( p_demux, "quitwhendone: %s (unused by VLC)", b_quitwhendone ? "true":"false" ); msg_Dbg( p_demux, "src: %s", psz_src ); msg_Dbg( p_demux, "mimetype: %s", psz_mimetype ); msg_Dbg( p_demux, "volume: %d (unused by VLC)", i_volume ); if( !psz_src ) { msg_Err( p_demux, "Mandatory attribute 'src' not found" ); } else { input_item_node_t *p_subitems = input_item_node_Create( p_current_input ); p_input = input_item_New( psz_src, psz_moviename ); #define SADD_INFO( type, field ) if( field ) { input_item_AddInfo( \ p_input, "QuickTime Media Link", type, "%s", field ) ; } SADD_INFO( "href", psz_href ); SADD_INFO( _("Mime"), psz_mimetype ); input_item_node_AppendItem( p_subitems, p_input ); vlc_gc_decref( p_input ); if( psz_qtnext ) { p_input = input_item_New( psz_qtnext, NULL ); input_item_node_AppendItem( p_subitems, p_input ); vlc_gc_decref( p_input ); } input_item_node_PostAndDelete( p_subitems ); } i_ret = 0; /* Needed for correct operation of go back */ error: if( p_xml_reader ) xml_ReaderDelete( p_xml_reader ); vlc_gc_decref(p_current_input); free( psz_href ); free( psz_moviename ); free( psz_qtnext ); free( psz_src ); free( psz_mimetype ); return i_ret; }
static int ParseManifest( addons_finder_t *p_finder, addon_entry_t *p_entry, const char *psz_tempfile, stream_t *p_stream ) { int i_num_entries_created = 0; const char *p_node; int i_current_node_type; /* attr */ const char *attr, *value; /* temp reading */ const char *psz_filename = NULL; int i_filetype = -1; xml_reader_t *p_xml_reader = xml_ReaderCreate( p_finder, p_stream ); if( !p_xml_reader ) return 0; if( xml_ReaderNextNode( p_xml_reader, &p_node ) != XML_READER_STARTELEM ) { msg_Err( p_finder, "invalid xml file" ); goto end; } if ( strcmp( p_node, "videolan") ) { msg_Err( p_finder, "unsupported XML data format" ); goto end; } while( (i_current_node_type = xml_ReaderNextNode( p_xml_reader, &p_node )) > 0 ) { switch( i_current_node_type ) { case XML_READER_STARTELEM: { BINDNODE("resource", psz_filename, TYPE_STRING) data_pointer.e_type = TYPE_NONE; /* * Manifests are not allowed to update addons properties * such as uuid, score, downloads, ... * On the other hand, repo API must not set files directly. */ if ( ! strcmp( p_node, "resource" ) ) { while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) ) { if ( !strcmp( attr, "type" ) ) { i_filetype = ReadType( value ); } } } else if ( ! strcmp( p_node, "addon" ) ) { while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) ) { if ( !strcmp( attr, "type" ) ) { p_entry->e_type = ReadType( value ); } } } break; } case XML_READER_TEXT: if ( data_pointer.e_type == TYPE_NONE || !p_entry ) break; if ( data_pointer.e_type == TYPE_STRING ) *data_pointer.u_data.ppsz = strdup( p_node ); else if ( data_pointer.e_type == TYPE_LONG ) *data_pointer.u_data.pl = atol( p_node ); else if ( data_pointer.e_type == TYPE_INTEGER ) *data_pointer.u_data.pi = atoi( p_node ); break; case XML_READER_ENDELEM: if ( ! strcmp( p_node, "resource" ) ) { if ( psz_filename && i_filetype >= 0 ) { addon_file_t *p_file = malloc( sizeof(addon_file_t) ); p_file->e_filetype = i_filetype; p_file->psz_filename = strdup( psz_filename ); if ( asprintf( & p_file->psz_download_uri, "unzip://%s!/%s", psz_tempfile, psz_filename ) > 0 ) { ARRAY_APPEND( p_entry->files, p_file ); msg_Dbg( p_finder, "manifest lists file %s extractable from %s", psz_filename, p_file->psz_download_uri ); i_num_entries_created++; } else { free( p_file->psz_filename ); free( p_file ); } } /* reset temp */ psz_filename = NULL; i_filetype = -1; } data_pointer.e_type = TYPE_NONE; break; default: break; } } end: xml_ReaderDelete( p_xml_reader ); return i_num_entries_created; }
static int parse_Manifest( stream_t *s ) { stream_sys_t *p_sys = s->p_sys; xml_reader_t *vlc_reader = NULL; int type = UNKNOWN_ES; const char *name, *value; stream_t *st = s->p_source; msg_Dbg( s, "Manifest parsing\n" ); vlc_reader = xml_ReaderCreate( st, st ); if( !vlc_reader ) { msg_Err( s, "Failed to open source for parsing" ); return VLC_EGENERIC; } const char *node; uint8_t *WaveFormatEx; sms_stream_t *sms = NULL; quality_level_t *ql = NULL; custom_attrs_t *cp = NULL; int64_t start_time = 0, duration = 0; int64_t computed_start_time = 0, computed_duration = 0; unsigned next_track_id = 1; int loop_count = 0; bool b_weird = false; int ret = VLC_SUCCESS; #define TIMESCALE 10000000 while( (type = xml_ReaderNextNode( vlc_reader, &node )) > 0 ) { switch( type ) { case XML_READER_STARTELEM: if( !strcmp( node, "SmoothStreamingMedia" ) ) { while( (name = xml_ReaderNextAttr( vlc_reader, &value )) ) { if( !strcmp( name, "Duration" ) ) p_sys->vod_duration = strtoull( value, NULL, 10 ); else if( !strcmp( name, "TimeScale" ) ) p_sys->timescale = strtoul( value, NULL, 10 ); else if ( !strcmp( name, "LookAheadFragmentCount" ) ) p_sys->download.lookahead_count = strtoul( value, NULL, 10 ); } if( !p_sys->timescale ) p_sys->timescale = TIMESCALE; } else if( !strcmp( node, "StreamIndex" ) ) { sms_Free( sms ); sms = sms_New(); if( unlikely( !sms ) ) { ret = VLC_ENOMEM; goto cleanup; } sms->id = next_track_id; next_track_id++; while( (name = xml_ReaderNextAttr( vlc_reader, &value )) ) { if( !strcmp( name, "Type" ) ) { if( !strcmp( value, "video" ) ) sms->type = VIDEO_ES; else if( !strcmp( value, "audio" ) ) sms->type = AUDIO_ES; else if( !strcmp( value, "text" ) ) sms->type = SPU_ES; } else if( !strcmp( name, "Name" ) ) sms->name = strdup( value ); else if( !strcmp( name, "TimeScale" ) ) sms->timescale = strtoull( value, NULL, 10 ); else if( !strcmp( name, "FourCC" ) ) sms->default_FourCC = VLC_FOURCC( value[0], value[1], value[2], value[3] ); else if( !strcmp( name, "Chunks" ) ) { sms->vod_chunks_nb = strtoul( value, NULL, 10 ); if( sms->vod_chunks_nb == 0 ) /* live */ sms->vod_chunks_nb = UINT32_MAX; } else if( !strcmp( name, "QualityLevels" ) ) sms->qlevel_nb = strtoul( value, NULL, 10 ); else if( !strcmp( name, "Url" ) ) sms->url_template = strdup(value); } if( !sms->timescale ) sms->timescale = TIMESCALE; if( !sms->name ) { if( sms->type == VIDEO_ES ) sms->name = strdup( "video" ); else if( sms->type == AUDIO_ES ) sms->name = strdup( "audio" ); else if( sms->type == SPU_ES ) sms->name = strdup( "text" ); } } else if ( !strcmp( node, "CustomAttributes" ) ) { if (!sms || !ql || cp) break; cp = (custom_attrs_t *) calloc( 1, sizeof(*cp) ); if( unlikely( !cp ) ) { ret = VLC_ENOMEM; goto cleanup; } } else if ( !strcmp( node, "Attribute" ) ) { if (!sms || !ql || !cp) break; while( (name = xml_ReaderNextAttr( vlc_reader, &value )) ) { if( !strcmp( name, "Name" ) && !cp->psz_key ) cp->psz_key = strdup( value ); else if( !strcmp( name, "Value" ) && !cp->psz_value ) cp->psz_value = strdup( value ); } } else if( !strcmp( node, "QualityLevel" ) ) { if ( !sms ) break; ql = ql_New(); if( !ql ) { ret = VLC_ENOMEM; goto cleanup; } while( (name = xml_ReaderNextAttr( vlc_reader, &value )) ) { if( !strcmp( name, "Index" ) ) ql->Index = strtol( value, NULL, 10 ); else if( !strcmp( name, "Bitrate" ) ) ql->Bitrate = strtoul( value, NULL, 10 ); else if( !strcmp( name, "PacketSize" ) ) ql->nBlockAlign = strtoul( value, NULL, 10 ); else if( !strcmp( name, "FourCC" ) ) ql->FourCC = VLC_FOURCC( value[0], value[1], value[2], value[3] ); else if( !strcmp( name, "CodecPrivateData" ) ) ql->CodecPrivateData = strdup( value ); else if( !strcmp( name, "WaveFormatEx" ) ) { WaveFormatEx = decode_string_hex_to_binary( value ); uint16_t data_len = ((uint16_t *)WaveFormatEx)[8]; ql->CodecPrivateData = strndup( value + 36, data_len * 2 ); uint16_t wf_tag = ((uint16_t *)WaveFormatEx)[0]; wf_tag_to_fourcc( wf_tag, &ql->FourCC, NULL ); ql->Channels = ((uint16_t *)WaveFormatEx)[1]; ql->SamplingRate = ((uint32_t *)WaveFormatEx)[1]; ql->nBlockAlign = ((uint16_t *)WaveFormatEx)[6]; ql->BitsPerSample = ((uint16_t *)WaveFormatEx)[7]; free( WaveFormatEx ); } else if( !strcmp( name, "MaxWidth" ) || !strcmp( name, "Width" ) ) ql->MaxWidth = strtoul( value, NULL, 10 ); else if( !strcmp( name, "MaxHeight" ) || !strcmp( name, "Height" ) ) ql->MaxHeight = strtoul( value, NULL, 10 ); else if( !strcmp( name, "Channels" ) ) ql->Channels = strtoul( value, NULL, 10 ); else if( !strcmp( name, "SamplingRate" ) ) ql->SamplingRate = strtoul( value, NULL, 10 ); else if( !strcmp( name, "BitsPerSample" ) ) ql->BitsPerSample = strtoul( value, NULL, 10 ); } ARRAY_APPEND( sms->qlevels, ql ); } else if ( !strcmp( node, "Content" ) && sms && !sms->url_template ) { /* empty(@Url) && ./Content == manifest embedded content */ sms_Free( sms ); sms = NULL; } else if( !strcmp( node, "c" ) ) { if ( !sms ) break; loop_count++; start_time = duration = -1; while( (name = xml_ReaderNextAttr( vlc_reader, &value )) ) { if( !strcmp( name, "t" ) ) start_time = strtoll( value, NULL, 10 ); if( !strcmp( name, "d" ) ) duration = strtoll( value, NULL, 10 ); } if( start_time == -1 ) { assert( duration != -1 ); computed_start_time += computed_duration; computed_duration = duration; } else if( duration == -1 ) { assert( start_time != -1 ); /* Handle weird Manifests which give only the start time * of the first segment. In those cases, we have to look * at the start time of the second segment to compute * the duration of the first one. */ if( loop_count == 1 ) { b_weird = true; computed_start_time = start_time; continue; } computed_duration = start_time - computed_start_time; if( !b_weird ) computed_start_time = start_time; } else { if( b_weird ) computed_duration = start_time - computed_start_time; else { computed_start_time = start_time; computed_duration = duration; } } if( unlikely( chunk_AppendNew( sms, computed_duration, computed_start_time ) == NULL ) ) { ret = VLC_ENOMEM; goto cleanup; } if( b_weird && start_time != -1 ) computed_start_time = start_time; } break; case XML_READER_ENDELEM: if ( !strcmp( node, "CustomAttributes" ) ) { if ( cp ) { ARRAY_APPEND(ql->custom_attrs, cp); cp = NULL; } } else if ( !strcmp( node, "Attribute" ) ) { if( !cp->psz_key || !cp->psz_value ) { cleanup_attributes( &cp ); } } else if( strcmp( node, "StreamIndex" ) ) break; else if ( sms ) { ARRAY_APPEND( p_sys->sms, sms ); computed_start_time = 0; computed_duration = 0; loop_count = 0; if( b_weird && !chunk_AppendNew( sms, computed_duration, computed_start_time ) ) { ret = VLC_ENOMEM; goto cleanup; } b_weird = false; if( sms->qlevel_nb == 0 ) sms->qlevel_nb = sms->qlevels.i_size; sms = NULL; } break; case XML_READER_TEXT: break; default: ret = VLC_EGENERIC; goto cleanup; } } #undef TIMESCALE cleanup: cleanup_attributes( &cp ); sms_Free( sms ); xml_ReaderDelete( vlc_reader ); return ret; }