/** * \brief parse the root node of the playlist */ static bool parse_plist_node( demux_t *p_demux, input_item_node_t *p_input_node, track_elem_t *p_track, xml_reader_t *p_xml_reader, const char *psz_element, xml_elem_hnd_t *p_handlers ) { VLC_UNUSED(p_track); VLC_UNUSED(psz_element); const char *attr, *value; bool b_version_found = false; /* read all playlist attributes */ while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) != NULL ) { /* attribute: version */ if( !strcmp( attr, "version" ) ) { b_version_found = true; if( strcmp( value, "1.0" ) ) msg_Warn( p_demux, "unsupported iTunes Media Library version" ); } /* unknown attribute */ else msg_Warn( p_demux, "invalid <plist> attribute:\"%s\"", attr ); } /* attribute version is mandatory !!! */ if( !b_version_found ) msg_Warn( p_demux, "<plist> requires \"version\" attribute" ); return parse_dict( p_demux, p_input_node, NULL, p_xml_reader, "plist", p_handlers ); }
/* <genrelist> * <genre name="the name"></genre> * ... * </genrelist> **/ static int DemuxGenre( demux_t *p_demux, xml_reader_t *p_xml_reader, input_item_node_t *p_input_node ) { const char *node; char *psz_name = NULL; /* genre name */ int type; while( (type = xml_ReaderNextNode( p_xml_reader, &node )) > 0 ) { switch( type ) { case XML_READER_STARTELEM: { if( !strcmp( node, "genre" ) ) { // Read the attributes const char *name, *value; while( (name = xml_ReaderNextAttr( p_xml_reader, &value )) ) { if( !strcmp( name, "name" ) ) { free(psz_name); psz_name = strdup( value ); } else msg_Warn( p_demux, "unexpected attribute %s in <%s>", name, node ); } } break; } case XML_READER_ENDELEM: if( !strcmp( node, "genre" ) && psz_name != NULL ) { char* psz_mrl; if( asprintf( &psz_mrl, SHOUTCAST_BASE_URL "?genre=%s", psz_name ) != -1 ) { input_item_t *p_input; vlc_xml_decode( psz_mrl ); p_input = input_item_New( psz_mrl, psz_name ); input_item_CopyOptions( p_input_node->p_item, p_input ); free( psz_mrl ); input_item_node_AppendItem( p_input_node, p_input ); vlc_gc_decref( p_input ); } FREENULL( psz_name ); } break; } } free( psz_name ); return 0; }
tt_node_t * tt_node_New( xml_reader_t* reader, tt_node_t* p_parent, const char* psz_node_name ) { tt_node_t *p_node = calloc( 1, sizeof( *p_node ) ); if( !p_node ) return NULL; p_node->i_type = TT_NODE_TYPE_ELEMENT; p_node->psz_node_name = strdup( psz_node_name ); if( unlikely( p_node->psz_node_name == NULL ) ) { free( p_node ); return NULL; } vlc_dictionary_init( &p_node->attr_dict, 0 ); tt_time_Init( &p_node->timings.begin ); tt_time_Init( &p_node->timings.end ); tt_time_Init( &p_node->timings.dur ); p_node->p_parent = p_parent; if( p_parent ) tt_node_ParentAddChild( p_parent, (tt_basenode_t *) p_node ); const char* psz_value = NULL; for( const char* psz_key = xml_ReaderNextAttr( reader, &psz_value ); psz_key != NULL; psz_key = xml_ReaderNextAttr( reader, &psz_value ) ) { char *psz_val = strdup( psz_value ); if( psz_val ) { vlc_dictionary_insert( &p_node->attr_dict, psz_key, psz_val ); if( !strcasecmp( psz_key, "begin" ) ) p_node->timings.begin = tt_ParseTime( psz_val ); else if( ! strcasecmp( psz_key, "end" ) ) p_node->timings.end = tt_ParseTime( psz_val ); else if( ! strcasecmp( psz_key, "dur" ) ) p_node->timings.dur = tt_ParseTime( psz_val ); else if( ! strcasecmp( psz_key, "timeContainer" ) ) p_node->timings.i_type = strcmp( psz_val, "seq" ) ? TT_TIMINGS_PARALLEL : TT_TIMINGS_SEQUENTIAL; } } return p_node; }
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 void ParseTTMLStyle( decoder_t *p_dec, xml_reader_t* p_reader ) { decoder_sys_t* p_sys = p_dec->p_sys; ttml_style_t *p_ttml_style = NULL; ttml_style_t *p_base_style = NULL; p_ttml_style = calloc( 1, sizeof(ttml_style_t) ); if ( unlikely( !p_ttml_style ) ) return ; p_ttml_style->font_style = text_style_Create( STYLE_NO_DEFAULTS ); if( unlikely( !p_ttml_style->font_style ) ) { free( p_ttml_style ); return ; } const char *attr, *val; while( (attr = xml_ReaderNextAttr( p_reader, &val ) ) ) { if ( !strcasecmp( attr, "style" ) ) { for( size_t i = 0; i < p_sys->i_styles; i++ ) { if( !strcasecmp( p_sys->pp_styles[i]->psz_styleid, val ) ) { p_base_style = p_sys->pp_styles[i]; break; } } } else if ( !strcasecmp( "xml:id", attr ) ) { free( p_ttml_style->psz_styleid ); p_ttml_style->psz_styleid = strdup( val ); } else if ( !strcasecmp ( "tts:fontFamily", attr ) ) { free( p_ttml_style->font_style->psz_fontname ); p_ttml_style->font_style->psz_fontname = strdup( val ); } else if ( !strcasecmp( "tts:fontSize", attr ) ) { p_ttml_style->font_style->i_font_size = atoi( val ); } else if ( !strcasecmp( "tts:color", attr ) ) { unsigned int i_color = vlc_html_color( val, NULL ); p_ttml_style->font_style->i_font_color = (i_color & 0xffffff); p_ttml_style->font_style->i_font_alpha = (i_color & 0xFF000000) >> 24; p_ttml_style->font_style->i_features |= STYLE_HAS_FONT_COLOR | STYLE_HAS_FONT_ALPHA; } else if ( !strcasecmp( "tts:backgroundColor", attr ) )
static int vlclua_xml_reader_next_attr( lua_State *L ) { xml_reader_t *p_reader = *(xml_reader_t**)luaL_checkudata( L, 1, "xml_reader" ); const char *psz_value; const char *psz_name = xml_ReaderNextAttr( p_reader, &psz_value ); if( !psz_name ) return 0; lua_pushstring( L, psz_name ); lua_pushstring( L, psz_value ); return 2; }
static void read_head( demux_t* p_demux, input_item_t* p_input ) { demux_sys_t* p_sys = p_demux->p_sys; const char* psz_name; int i_type; do { i_type = xml_ReaderNextNode( p_sys->p_reader, &psz_name ); if ( !strcasecmp( psz_name, "meta" ) ) { char* psz_attribute_name = NULL; char* psz_attribute_value = NULL; while (!psz_attribute_name || !psz_attribute_value) { const char* psz_attr = NULL; const char* psz_val = NULL; psz_attr = xml_ReaderNextAttr( p_sys->p_reader, &psz_val ); if ( !psz_attr || !psz_val ) break; if ( !strcasecmp( psz_attr, "name" ) ) psz_attribute_name = strdup( psz_val ); else if ( !strcasecmp( psz_attr, "content" ) ) psz_attribute_value = strdup( psz_val ); } if ( psz_attribute_name && psz_attribute_value ) { if ( !strcasecmp( psz_attribute_name, "TotalDuration" ) ) input_item_SetDuration( p_input, atoll( psz_attribute_value ) ); else if ( !strcasecmp( psz_attribute_name, "Author" ) ) input_item_SetPublisher( p_input, psz_attribute_value ); else if ( !strcasecmp( psz_attribute_name, "Rating" ) ) input_item_SetRating( p_input, psz_attribute_value ); else if ( !strcasecmp( psz_attribute_name, "Genre" ) ) input_item_SetGenre( p_input, psz_attribute_value ); } free( psz_attribute_name ); free( psz_attribute_value ); } else if ( !strcasecmp( psz_name, "title" ) ) { const char* psz_title; int i_type = xml_ReaderNextNode( p_sys->p_reader, &psz_title ); if ( i_type == XML_READER_TEXT && psz_title != NULL ) input_item_SetTitle( p_input, psz_title ); } } while ( i_type != XML_READER_ENDELEM || strcasecmp( psz_name, "head" ) ); }
bool XMLParser::parse() { const char *node; int type; if( !m_pReader ) return false; m_errors = false; while( (type = xml_ReaderNextNode( m_pReader, &node )) > 0 ) { if( m_errors ) return false; switch( type ) { case XML_READER_STARTELEM: { // Read the attributes AttrList_t attributes; const char *name, *value; while( (name = xml_ReaderNextAttr( m_pReader, &value )) != NULL ) attributes[strdup(name)] = strdup(value); handleBeginElement( node, attributes ); map<const char*, const char*, ltstr> ::iterator it = attributes.begin(); while( it != attributes.end() ) { free( (char *)it->first ); free( (char *)it->second ); ++it; } break; } // End element case XML_READER_ENDELEM: { handleEndElement( node ); break; } } } return (type == 0 && !m_errors ); }
static void read_body( demux_t* p_demux, input_item_node_t* p_node ) { demux_sys_t* p_sys = p_demux->p_sys; const char* psz_name; int i_type; i_type = xml_ReaderNextNode( p_sys->p_reader, &psz_name ); if ( i_type != XML_READER_STARTELEM || strcasecmp( psz_name, "seq" ) ) { msg_Err( p_demux, "Expected opening <seq> tag. Got <%s> with type %d", psz_name, i_type ); return; } do { i_type = xml_ReaderNextNode( p_sys->p_reader, &psz_name ); if ( !strcasecmp( psz_name, "media" ) ) { const char* psz_attr = NULL; const char* psz_val = NULL; while ((psz_attr = xml_ReaderNextAttr( p_sys->p_reader, &psz_val ))) { if ( !psz_val ) continue; if (!strcasecmp( psz_attr, "src" ) ) { char* mrl = ProcessMRL( psz_val, p_sys->psz_prefix ); if ( unlikely( !mrl ) ) return; input_item_t* p_item = input_item_NewExt( mrl, NULL, 0, NULL, 0, -1 ); if ( likely( p_item ) ) { input_item_node_AppendItem( p_node, p_item ); input_item_Release( p_item ); } free( mrl ); } } } } while ( i_type != XML_READER_ENDELEM || strcasecmp( psz_name, "seq" ) ); i_type = xml_ReaderNextNode( p_sys->p_reader, &psz_name ); if ( i_type != XML_READER_ENDELEM || strcasecmp( psz_name, "body" ) ) msg_Err( p_demux, "Expected closing <body> tag. Got: <%s> with type %d", psz_name, i_type ); }
/* "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; } } }
/**************************************************************************** * Parse the rss feed ***************************************************************************/ static bool ParseFeed( filter_t *p_filter, xml_reader_t *p_xml_reader, rss_feed_t *p_feed ) { VLC_UNUSED(p_filter); char *psz_eltname = NULL; bool b_is_item = false; bool b_is_image = false; int i_item = 0; while( xml_ReaderRead( p_xml_reader ) == 1 ) { switch( xml_ReaderNodeType( p_xml_reader ) ) { // Error case -1: goto end; case XML_READER_STARTELEM: free( psz_eltname ); psz_eltname = xml_ReaderName( p_xml_reader ); if( !psz_eltname ) goto end; #ifdef RSS_DEBUG msg_Dbg( p_filter, "element name: %s", psz_eltname ); #endif /* rss or atom */ if( !strcmp( psz_eltname, "item" ) || !strcmp( psz_eltname, "entry" ) ) { b_is_item = true; p_feed->i_items++; p_feed->p_items = xrealloc( p_feed->p_items, p_feed->i_items * sizeof( rss_item_t ) ); p_feed->p_items[p_feed->i_items-1].psz_title = NULL; p_feed->p_items[p_feed->i_items-1].psz_description = NULL; p_feed->p_items[p_feed->i_items-1].psz_link = NULL; } /* rss */ else if( !strcmp( psz_eltname, "image" ) ) { b_is_image = true; } /* atom */ else if( !strcmp( psz_eltname, "link" ) ) { char *psz_href = NULL; char *psz_rel = NULL; 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( !strcmp( psz_name, "rel" ) ) { free( psz_rel ); psz_rel = psz_value; } else if( !strcmp( psz_name, "href" ) ) { free( psz_href ); psz_href = psz_value; } else { free( psz_value ); } free( psz_name ); } /* "rel" and "href" must be defined */ if( psz_rel && psz_href ) { if( !strcmp( psz_rel, "alternate" ) && !b_is_item && !b_is_image && !p_feed->psz_link ) { p_feed->psz_link = psz_href; } /* this isn't in the rfc but i found some ... */ else if( ( !strcmp( psz_rel, "logo" ) || !strcmp( psz_rel, "icon" ) ) && !b_is_item && !b_is_image && !p_feed->psz_image ) { p_feed->psz_image = psz_href; } else { free( psz_href ); } } else { free( psz_href ); } free( psz_rel ); } break; case XML_READER_ENDELEM: free( psz_eltname ); psz_eltname = xml_ReaderName( p_xml_reader ); if( !psz_eltname ) goto end; #ifdef RSS_DEBUG msg_Dbg( p_filter, "element end : %s", psz_eltname ); #endif /* rss or atom */ if( !strcmp( psz_eltname, "item" ) || !strcmp( psz_eltname, "entry" ) ) { b_is_item = false; i_item++; } /* rss */ else if( !strcmp( psz_eltname, "image" ) ) { b_is_image = false; } FREENULL( psz_eltname ); break; case XML_READER_TEXT: { if( !psz_eltname ) break; char *psz_eltvalue = xml_ReaderValue( p_xml_reader ); if( !psz_eltvalue ) goto end; char *psz_clean = removeWhiteChars( psz_eltvalue ); free( psz_eltvalue ); psz_eltvalue = psz_clean; #ifdef RSS_DEBUG msg_Dbg( p_filter, " text : <%s>", psz_eltvalue ); #endif /* Is it an item ? */ if( b_is_item ) { rss_item_t *p_item = p_feed->p_items+i_item; /* rss/atom */ if( !strcmp( psz_eltname, "title" ) && !p_item->psz_title ) { p_item->psz_title = psz_eltvalue; } else if( !strcmp( psz_eltname, "link" ) /* rss */ && !p_item->psz_link ) { p_item->psz_link = psz_eltvalue; } /* rss/atom */ else if( ( !strcmp( psz_eltname, "description" ) || !strcmp( psz_eltname, "summary" ) ) && !p_item->psz_description ) { p_item->psz_description = psz_eltvalue; } else { free( psz_eltvalue ); } } /* Is it an image ? */ else if( b_is_image ) { if( !strcmp( psz_eltname, "url" ) && !p_feed->psz_image ) p_feed->psz_image = psz_eltvalue; else free( psz_eltvalue ); } else { /* rss/atom */ if( !strcmp( psz_eltname, "title" ) && !p_feed->psz_title ) { p_feed->psz_title = psz_eltvalue; } /* rss */ else if( !strcmp( psz_eltname, "link" ) && !p_feed->psz_link ) { p_feed->psz_link = psz_eltvalue; } /* rss ad atom */ else if( ( !strcmp( psz_eltname, "description" ) || !strcmp( psz_eltname, "subtitle" ) ) && !p_feed->psz_description ) { p_feed->psz_description = psz_eltvalue; } /* rss */ else if( ( !strcmp( psz_eltname, "logo" ) || !strcmp( psz_eltname, "icon" ) ) && !p_feed->psz_image ) { p_feed->psz_image = psz_eltvalue; } else { free( psz_eltvalue ); } } break; } } } free( psz_eltname ); return true; end: free( psz_eltname ); return false; }
static void ProcessEntry( int *pi_n_entry, xml_reader_t *p_xml_reader, input_item_node_t *p_subitems, input_item_t *p_current_input, char *psz_prefix ) { const char *psz_node = NULL; const char *psz_txt = NULL; int i_type; char *psz_title = NULL; char *psz_artist = NULL; char *psz_copyright = NULL; char *psz_moreinfo = NULL; char *psz_description = NULL; char *psz_name = NULL; char *psz_mrl = NULL; char *psz_href = NULL; input_item_t *p_entry = NULL; int i_options; mtime_t i_start = 0; mtime_t i_duration = 0; char *ppsz_options[2]; do { i_type = xml_ReaderNextNode( p_xml_reader, &psz_node ); if( i_type == XML_READER_STARTELEM ) { /* Metadata Node */ if( !strncasecmp( psz_node, "TITLE", 5 ) ) ReadElement( p_xml_reader, &psz_title ); else if( !strncasecmp( psz_node, "AUTHOR", 6 ) ) ReadElement( p_xml_reader, &psz_artist ); else if( !strncasecmp( psz_node, "COPYRIGHT", 9 ) ) ReadElement( p_xml_reader, &psz_copyright ); else if( !strncasecmp( psz_node,"MOREINFO", 8 ) ) { do { psz_txt = xml_ReaderNextAttr( p_xml_reader, &psz_node ); } while(psz_txt && strncasecmp( psz_txt, "HREF", 4 ) ); if( !psz_txt ) ReadElement( p_xml_reader, &psz_moreinfo ); else psz_moreinfo = strdup( psz_node ); resolve_xml_special_chars( psz_moreinfo ); } else if( !strncasecmp( psz_node, "ABSTRACT", 8 ) ) ReadElement( p_xml_reader, &psz_description ); else if( !strncasecmp( psz_node, "DURATION", 8 ) ) i_duration = ParseTime( p_xml_reader ); else if( !strncasecmp( psz_node, "STARTTIME", 9 ) ) i_start = ParseTime( p_xml_reader ); else /* Reference Node */ /* All ref node will be converted into an entry */ if( !strncasecmp( psz_node, "REF", 3 ) ) { *pi_n_entry = *pi_n_entry + 1; if( !psz_title ) psz_title = input_item_GetTitle( p_current_input ); if( !psz_artist ) psz_artist = input_item_GetArtist( p_current_input ); if( !psz_copyright ) psz_copyright = input_item_GetCopyright( p_current_input ); if( !psz_description ) psz_description = input_item_GetDescription( p_current_input ); do { psz_txt = xml_ReaderNextAttr( p_xml_reader, &psz_node ); } while( strncasecmp( psz_txt, "HREF", 4) ); psz_href = strdup( psz_node ); if( asprintf( &psz_name, "%d. %s", *pi_n_entry, psz_title ) == -1) psz_name = strdup( psz_title ); resolve_xml_special_chars( psz_href ); psz_mrl = ProcessMRL( psz_href, psz_prefix ); /* Add Time information */ i_options = 0; if( i_start ) { if( asprintf( ppsz_options, ":start-time=%d" ,(int) i_start/1000000 ) != -1) i_options++; } if( i_duration) { if( asprintf( ppsz_options + i_options, ":stop-time=%d", (int) (i_start+i_duration)/1000000 ) != -1) i_options++; } /* Create the input item */ p_entry = input_item_NewExt( psz_mrl, psz_name, i_options, (const char* const*) ppsz_options, VLC_INPUT_OPTION_TRUSTED, i_duration ); input_item_CopyOptions( p_current_input, p_entry ); /* Add the metadata */ if( psz_name ) input_item_SetTitle( p_entry, psz_name ); if( psz_artist ) input_item_SetArtist( p_entry, psz_artist ); if( psz_copyright ) input_item_SetCopyright( p_entry, psz_copyright ); if( psz_moreinfo ) input_item_SetURL( p_entry, psz_moreinfo ); if( psz_description ) input_item_SetDescription( p_entry, psz_description ); if( i_duration > 0) input_item_SetDuration( p_entry, i_duration ); input_item_node_AppendItem( p_subitems, p_entry ); while( i_options ) free( ppsz_options[--i_options] ); free( psz_name ); free( psz_mrl ); } } } while( i_type != XML_READER_ENDELEM || strncasecmp( psz_node, "ENTRY", 5 ) ); free( psz_href ); free( psz_title ); free( psz_artist ); free( psz_copyright ); free( psz_moreinfo ); free( psz_description ); }
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; }
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 ) { 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 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; }
/* <genrelist> * <genre name="the name"></genre> * ... * </genrelist> **/ static int DemuxGenre( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; char *psz_name = NULL; /* genre name */ char *psz_eltname = NULL; /* tag name */ input_item_t *p_input; while( xml_ReaderRead( p_sys->p_xml_reader ) == 1 ) { int i_type; // Get the node type i_type = xml_ReaderNodeType( p_sys->p_xml_reader ); switch( i_type ) { // Error case -1: return -1; break; case XML_READER_STARTELEM: // Read the element name psz_eltname = xml_ReaderName( p_sys->p_xml_reader ); if( !psz_eltname ) return -1; if( !strcmp( psz_eltname, "genre" ) ) { // Read the attributes while( xml_ReaderNextAttr( p_sys->p_xml_reader ) == VLC_SUCCESS ) { char *psz_attrname = xml_ReaderName( p_sys->p_xml_reader ); char *psz_attrvalue = xml_ReaderValue( p_sys->p_xml_reader ); if( !psz_attrname || !psz_attrvalue ) { FREENULL(psz_attrname); FREENULL(psz_attrvalue); free(psz_eltname); /*FIXME: isn't return a bit too much. what about break*/ return -1; } GET_VALUE( name ) else { msg_Warn( p_demux, "unexpected attribure %s in element %s", psz_attrname,psz_eltname ); } free( psz_attrname ); free( psz_attrvalue ); } } free( psz_eltname ); psz_eltname = NULL; break; case XML_READER_TEXT: break; // End element case XML_READER_ENDELEM: // Read the element name psz_eltname = xml_ReaderName( p_sys->p_xml_reader ); if( !psz_eltname ) return -1; if( !strcmp( psz_eltname, "genre" ) ) { char* psz_mrl; if( asprintf( &psz_mrl, SHOUTCAST_BASE_URL "?genre=%s", psz_name ) != -1 ) { p_input = input_item_New( p_demux, psz_mrl, psz_name ); input_item_CopyOptions( p_sys->p_current_input, p_input ); free( psz_mrl ); input_item_AddSubItem( p_sys->p_current_input, p_input ); vlc_gc_decref( p_input ); } FREENULL( psz_name ); } FREENULL( psz_eltname ); break; } } return 0; }
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 void ParseUSFHeaderTags( decoder_t *p_dec, xml_reader_t *p_xml_reader ) { decoder_sys_t *p_sys = p_dec->p_sys; char *psz_node; ssa_style_t *p_ssa_style = NULL; int i_style_level = 0; int i_metadata_level = 0; while ( xml_ReaderRead( p_xml_reader ) == 1 ) { switch ( xml_ReaderNodeType( p_xml_reader ) ) { case XML_READER_TEXT: case XML_READER_NONE: break; case XML_READER_ENDELEM: psz_node = xml_ReaderName( p_xml_reader ); if( !psz_node ) break; switch (i_style_level) { case 0: if( !strcasecmp( "metadata", psz_node ) && (i_metadata_level == 1) ) { i_metadata_level--; } break; case 1: if( !strcasecmp( "styles", psz_node ) ) { i_style_level--; } break; case 2: if( !strcasecmp( "style", psz_node ) ) { TAB_APPEND( p_sys->i_ssa_styles, p_sys->pp_ssa_styles, p_ssa_style ); p_ssa_style = NULL; i_style_level--; } break; } free( psz_node ); break; case XML_READER_STARTELEM: psz_node = xml_ReaderName( p_xml_reader ); if( !psz_node ) break; if( !strcasecmp( "metadata", psz_node ) && (i_style_level == 0) ) { i_metadata_level++; } else if( !strcasecmp( "resolution", psz_node ) && ( i_metadata_level == 1) ) { 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 ) { if( !strcasecmp( "x", psz_name ) ) p_sys->i_original_width = atoi( psz_value ); else if( !strcasecmp( "y", psz_name ) ) p_sys->i_original_height = atoi( psz_value ); } free( psz_name ); free( psz_value ); } } else if( !strcasecmp( "styles", psz_node ) && (i_style_level == 0) ) { i_style_level++; } else if( !strcasecmp( "style", psz_node ) && (i_style_level == 1) ) { i_style_level++; p_ssa_style = calloc( 1, sizeof(ssa_style_t) ); if( !p_ssa_style ) { free( psz_node ); return; } /* All styles are supposed to default to Default, and then * one or more settings are over-ridden. * At the moment this only effects styles defined AFTER * Default in the XML */ int i; for( i = 0; i < p_sys->i_ssa_styles; i++ ) { if( !strcasecmp( p_sys->pp_ssa_styles[i]->psz_stylename, "Default" ) ) { ssa_style_t *p_default_style = p_sys->pp_ssa_styles[i]; memcpy( p_ssa_style, p_default_style, sizeof( ssa_style_t ) ); //FIXME: Make font_style a pointer. Actually we double copy some data here, // we use text_style_Copy to avoid copying psz_fontname, though . text_style_Copy( &p_ssa_style->font_style, &p_default_style->font_style ); p_ssa_style->psz_stylename = NULL; } } 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 ) { if( !strcasecmp( "name", psz_name ) ) p_ssa_style->psz_stylename = strdup( psz_value ); } free( psz_name ); free( psz_value ); } } else if( !strcasecmp( "fontstyle", psz_node ) && (i_style_level == 2) ) { 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 ) { if( !strcasecmp( "face", psz_name ) ) { free( p_ssa_style->font_style.psz_fontname ); p_ssa_style->font_style.psz_fontname = strdup( psz_value ); } else if( !strcasecmp( "size", psz_name ) ) { if( ( *psz_value == '+' ) || ( *psz_value == '-' ) ) { int i_value = atoi( psz_value ); if( ( i_value >= -5 ) && ( i_value <= 5 ) ) p_ssa_style->font_style.i_font_size += ( i_value * p_ssa_style->font_style.i_font_size ) / 10; else if( i_value < -5 ) p_ssa_style->font_style.i_font_size = - i_value; else if( i_value > 5 ) p_ssa_style->font_style.i_font_size = i_value; } else p_ssa_style->font_style.i_font_size = atoi( psz_value ); } else if( !strcasecmp( "italic", psz_name ) ) { if( !strcasecmp( "yes", psz_value )) p_ssa_style->font_style.i_style_flags |= STYLE_ITALIC; else p_ssa_style->font_style.i_style_flags &= ~STYLE_ITALIC; } else if( !strcasecmp( "weight", psz_name ) ) { if( !strcasecmp( "bold", psz_value )) p_ssa_style->font_style.i_style_flags |= STYLE_BOLD; else p_ssa_style->font_style.i_style_flags &= ~STYLE_BOLD; } else if( !strcasecmp( "underline", psz_name ) ) { if( !strcasecmp( "yes", psz_value )) p_ssa_style->font_style.i_style_flags |= STYLE_UNDERLINE; else p_ssa_style->font_style.i_style_flags &= ~STYLE_UNDERLINE; } else if( !strcasecmp( "color", psz_name ) ) { if( *psz_value == '#' ) { unsigned long col = strtol(psz_value+1, NULL, 16); p_ssa_style->font_style.i_font_color = (col & 0x00ffffff); p_ssa_style->font_style.i_font_alpha = (col >> 24) & 0xff; } } else if( !strcasecmp( "outline-color", psz_name ) ) { if( *psz_value == '#' ) { unsigned long col = strtol(psz_value+1, NULL, 16); p_ssa_style->font_style.i_outline_color = (col & 0x00ffffff); p_ssa_style->font_style.i_outline_alpha = (col >> 24) & 0xff; } } else if( !strcasecmp( "outline-level", psz_name ) ) { p_ssa_style->font_style.i_outline_width = atoi( psz_value ); } else if( !strcasecmp( "shadow-color", psz_name ) ) { if( *psz_value == '#' ) { unsigned long col = strtol(psz_value+1, NULL, 16); p_ssa_style->font_style.i_shadow_color = (col & 0x00ffffff); p_ssa_style->font_style.i_shadow_alpha = (col >> 24) & 0xff; } } else if( !strcasecmp( "shadow-level", psz_name ) )
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; }
/* radio stations: * <stationlist> * <tunein base="/sbin/tunein-station.pls"></tunein> * <station name="the name" * mt="mime type" * id="the id" * br="bit rate" * genre="A big genre string" * ct="current track name/author/..." * lc="listener count"></station> * </stationlist> * * TV stations: * <stationlist> * <tunein base="/sbin/tunein-station.pls"></tunein> * <station name="the name" * id="the id" * br="bit rate" * rt="rating" * load="server load ?" * ct="current track name/author/..." * genre="A big genre string" * lc="listener count"></station> * </stationlist> **/ static int DemuxStation( demux_t *p_demux, xml_reader_t *p_xml_reader, input_item_node_t *p_input_node, bool b_adult ) { char *psz_base = NULL; /* */ char *psz_name = NULL; /* genre name */ char *psz_mt = NULL; /* mime type */ char *psz_id = NULL; /* id */ char *psz_br = NULL; /* bit rate */ char *psz_genre = NULL; /* genre */ char *psz_ct = NULL; /* current track */ char *psz_lc = NULL; /* listener count */ /* If these are set then it's *not* a radio but a TV */ char *psz_rt = NULL; /* rating for shoutcast TV */ char *psz_load = NULL; /* load for shoutcast TV */ const char *node; /* tag name */ int i_type; while( (i_type = xml_ReaderNextNode( p_xml_reader, &node )) > 0 ) { switch( i_type ) { case XML_READER_STARTELEM: // Read the attributes if( !strcmp( node, "tunein" ) ) { const char *name, *value; while( (name = xml_ReaderNextAttr( p_xml_reader, &value )) ) { if( !strcmp( name, "base" ) ) { free( psz_base ); psz_base = strdup( value ); } else msg_Warn( p_demux, "unexpected attribute %s in <%s>", name, node ); } } else if( !strcmp( node, "station" ) ) { const char *name, *value; while( (name = xml_ReaderNextAttr( p_xml_reader, &value )) ) { char **p = NULL; if( !strcmp( name, "name" ) ) p = &psz_name; else if ( !strcmp( name, "mt" ) ) p = &psz_mt; else if ( !strcmp( name, "id" ) ) p = &psz_id; else if ( !strcmp( name, "br" ) ) p = &psz_br; else if ( !strcmp( name, "genre" ) ) p = &psz_genre; else if ( !strcmp( name, "ct" ) ) p = &psz_ct; else if ( !strcmp( name, "lc" ) ) p = &psz_lc; else if ( !strcmp( name, "rt" ) ) p = &psz_rt; else if ( !strcmp( name, "load" ) ) p = &psz_load; if( p != NULL ) { free( *p ); *p = strdup( value ); } else msg_Warn( p_demux, "unexpected attribute %s in <%s>", name, node ); } } break; // End element case XML_READER_ENDELEM: if( !strcmp( node, "station" ) && ( psz_base || ( psz_rt && psz_load && ( b_adult || strcmp( psz_rt, "NC17" ) ) ) ) ) { char *psz_mrl = NULL; if( psz_rt || psz_load ) { /* tv */ if( asprintf( &psz_mrl, SHOUTCAST_TV_TUNEIN_URL "%s", psz_id ) == -1) psz_mrl = NULL; } else { /* radio */ if( asprintf( &psz_mrl, SHOUTCAST_TUNEIN_BASE_URL "%s?id=%s", psz_base, psz_id ) == -1 ) psz_mrl = NULL; } /* Create the item */ input_item_t *p_input; p_input = input_item_New( psz_mrl, psz_name ); input_item_CopyOptions( p_input_node->p_item, p_input ); free( psz_mrl ); #define SADD_INFO( type, field ) \ if( field ) \ input_item_AddInfo( p_input, _("Shoutcast"), \ vlc_gettext(type), "%s", field ) SADD_INFO( N_("Mime"), psz_mt ); SADD_INFO( N_("Bitrate"), psz_br ); SADD_INFO( N_("Listeners"), psz_lc ); SADD_INFO( N_("Load"), psz_load ); if( psz_genre ) input_item_SetGenre( p_input, psz_genre ); if( psz_ct ) input_item_SetNowPlaying( p_input, psz_ct ); if( psz_rt ) input_item_SetRating( p_input, psz_rt ); input_item_node_AppendItem( p_input_node, p_input ); vlc_gc_decref( p_input ); FREENULL( psz_base ); FREENULL( psz_name ); FREENULL( psz_mt ); FREENULL( psz_id ); FREENULL( psz_br ); FREENULL( psz_genre ); FREENULL( psz_ct ); FREENULL( psz_lc ); FREENULL( psz_rt ); FREENULL( psz_load ); } break; } } /* FIXME: leaks on missing ENDELEMENT? */ return 0; }
static void ParseUSFHeaderTags( decoder_t *p_dec, xml_reader_t *p_xml_reader ) { decoder_sys_t *p_sys = p_dec->p_sys; const char *node; ssa_style_t *p_ssa_style = NULL; int i_style_level = 0; int i_metadata_level = 0; int type; while( (type = xml_ReaderNextNode( p_xml_reader, &node )) > 0 ) { switch( type ) { case XML_READER_ENDELEM: switch (i_style_level) { case 0: if( !strcasecmp( "metadata", node ) && (i_metadata_level == 1) ) i_metadata_level--; break; case 1: if( !strcasecmp( "styles", node ) ) i_style_level--; break; case 2: if( !strcasecmp( "style", node ) ) { TAB_APPEND( p_sys->i_ssa_styles, p_sys->pp_ssa_styles, p_ssa_style ); p_ssa_style = NULL; i_style_level--; } break; } break; case XML_READER_STARTELEM: if( !strcasecmp( "metadata", node ) && (i_style_level == 0) ) i_metadata_level++; else if( !strcasecmp( "resolution", node ) && ( i_metadata_level == 1) ) { const char *attr, *val; while( (attr = xml_ReaderNextAttr( p_xml_reader, &val )) ) { if( !strcasecmp( "x", attr ) ) p_sys->i_original_width = atoi( val ); else if( !strcasecmp( "y", attr ) ) p_sys->i_original_height = atoi( val ); } } else if( !strcasecmp( "styles", node ) && (i_style_level == 0) ) { i_style_level++; } else if( !strcasecmp( "style", node ) && (i_style_level == 1) ) { i_style_level++; p_ssa_style = calloc( 1, sizeof(ssa_style_t) ); if( unlikely(!p_ssa_style) ) return; p_ssa_style->p_style = text_style_Create( STYLE_NO_DEFAULTS ); if( unlikely(!p_ssa_style->p_style) ) { free(p_ssa_style); return; } /* All styles are supposed to default to Default, and then * one or more settings are over-ridden. * At the moment this only effects styles defined AFTER * Default in the XML */ for( int i = 0; i < p_sys->i_ssa_styles; i++ ) { if( !strcasecmp( p_sys->pp_ssa_styles[i]->psz_stylename, "Default" ) ) { ssa_style_t *p_default_style = p_sys->pp_ssa_styles[i]; memcpy( p_ssa_style, p_default_style, sizeof( ssa_style_t ) ); //FIXME: Make font_style a pointer. Actually we double copy some data here, // we use text_style_Copy to avoid copying psz_fontname, though . text_style_Copy( p_ssa_style->p_style, p_default_style->p_style ); p_ssa_style->psz_stylename = NULL; } } const char *attr, *val; while( (attr = xml_ReaderNextAttr( p_xml_reader, &val )) ) { if( !strcasecmp( "name", attr ) ) { free( p_ssa_style->psz_stylename ); p_ssa_style->psz_stylename = strdup( val ); } } } else if( !strcasecmp( "fontstyle", node ) && (i_style_level == 2) ) { const char *attr, *val; while( (attr = xml_ReaderNextAttr( p_xml_reader, &val )) ) { if( !strcasecmp( "face", attr ) ) { free( p_ssa_style->p_style->psz_fontname ); p_ssa_style->p_style->psz_fontname = strdup( val ); } else if( !strcasecmp( "size", attr ) ) { if( ( *val == '+' ) || ( *val == '-' ) ) { int i_value = atoi( val ); if( ( i_value >= -5 ) && ( i_value <= 5 ) ) p_ssa_style->p_style->i_font_size += ( i_value * p_ssa_style->p_style->i_font_size ) / 10; else if( i_value < -5 ) p_ssa_style->p_style->i_font_size = - i_value; else if( i_value > 5 ) p_ssa_style->p_style->i_font_size = i_value; } else p_ssa_style->p_style->i_font_size = atoi( val ); } else if( !strcasecmp( "italic", attr ) ) { if( !strcasecmp( "yes", val )) p_ssa_style->p_style->i_style_flags |= STYLE_ITALIC; else p_ssa_style->p_style->i_style_flags &= ~STYLE_ITALIC; p_ssa_style->p_style->i_features |= STYLE_HAS_FLAGS; } else if( !strcasecmp( "weight", attr ) ) { if( !strcasecmp( "bold", val )) p_ssa_style->p_style->i_style_flags |= STYLE_BOLD; else p_ssa_style->p_style->i_style_flags &= ~STYLE_BOLD; p_ssa_style->p_style->i_features |= STYLE_HAS_FLAGS; } else if( !strcasecmp( "underline", attr ) ) { if( !strcasecmp( "yes", val )) p_ssa_style->p_style->i_style_flags |= STYLE_UNDERLINE; else p_ssa_style->p_style->i_style_flags &= ~STYLE_UNDERLINE; p_ssa_style->p_style->i_features |= STYLE_HAS_FLAGS; } else if( !strcasecmp( "color", attr ) ) { if( *val == '#' ) { unsigned long col = strtol(val+1, NULL, 16); p_ssa_style->p_style->i_font_color = (col & 0x00ffffff); p_ssa_style->p_style->i_font_alpha = (col >> 24) & 0xff; p_ssa_style->p_style->i_features |= STYLE_HAS_FONT_COLOR | STYLE_HAS_FONT_ALPHA; } } else if( !strcasecmp( "outline-color", attr ) ) { if( *val == '#' ) { unsigned long col = strtol(val+1, NULL, 16); p_ssa_style->p_style->i_outline_color = (col & 0x00ffffff); p_ssa_style->p_style->i_outline_alpha = (col >> 24) & 0xff; p_ssa_style->p_style->i_features |= STYLE_HAS_OUTLINE_COLOR | STYLE_HAS_OUTLINE_ALPHA; } } else if( !strcasecmp( "outline-level", attr ) ) { p_ssa_style->p_style->i_outline_width = atoi( val ); } else if( !strcasecmp( "shadow-color", attr ) ) { if( *val == '#' ) { unsigned long col = strtol(val+1, NULL, 16); p_ssa_style->p_style->i_shadow_color = (col & 0x00ffffff); p_ssa_style->p_style->i_shadow_alpha = (col >> 24) & 0xff; p_ssa_style->p_style->i_features |= STYLE_HAS_SHADOW_COLOR | STYLE_HAS_SHADOW_ALPHA; } }
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; }
/* radio stations: * <stationlist> * <tunein base="/sbin/tunein-station.pls"></tunein> * <station name="the name" * mt="mime type" * id="the id" * br="bit rate" * genre="A big genre string" * ct="current track name/author/..." * lc="listener count"></station> * </stationlist> * * TV stations: * <stationlist> * <tunein base="/sbin/tunein-station.pls"></tunein> * <station name="the name" * id="the id" * br="bit rate" * rt="rating" * load="server load ?" * ct="current track name/author/..." * genre="A big genre string" * lc="listener count"></station> * </stationlist> **/ static int DemuxStation( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; input_item_t *p_input; char *psz_base = NULL; /* */ char *psz_name = NULL; /* genre name */ char *psz_mt = NULL; /* mime type */ char *psz_id = NULL; /* id */ char *psz_br = NULL; /* bit rate */ char *psz_genre = NULL; /* genre */ char *psz_ct = NULL; /* current track */ char *psz_lc = NULL; /* listener count */ /* If these are set then it's *not* a radio but a TV */ char *psz_rt = NULL; /* rating for shoutcast TV */ char *psz_load = NULL; /* load for shoutcast TV */ char *psz_eltname = NULL; /* tag name */ while( xml_ReaderRead( p_sys->p_xml_reader ) == 1 ) { int i_type; // Get the node type i_type = xml_ReaderNodeType( p_sys->p_xml_reader ); switch( i_type ) { // Error case -1: return -1; break; case XML_READER_STARTELEM: // Read the element name psz_eltname = xml_ReaderName( p_sys->p_xml_reader ); if( !psz_eltname ) return -1; // Read the attributes if( !strcmp( psz_eltname, "tunein" ) ) { while( xml_ReaderNextAttr( p_sys->p_xml_reader ) == VLC_SUCCESS ) { char *psz_attrname = xml_ReaderName( p_sys->p_xml_reader ); char *psz_attrvalue = xml_ReaderValue( p_sys->p_xml_reader ); if( !psz_attrname || !psz_attrvalue ) { free( psz_eltname ); free( psz_attrname ); free( psz_attrvalue ); return -1; } GET_VALUE( base ) else { msg_Warn( p_demux, "unexpected attribure %s in element %s", psz_attrname, psz_eltname ); } free( psz_attrname ); free( psz_attrvalue ); } } else if( !strcmp( psz_eltname, "station" ) ) { while( xml_ReaderNextAttr( p_sys->p_xml_reader ) == VLC_SUCCESS ) { char *psz_attrname = xml_ReaderName( p_sys->p_xml_reader ); char *psz_attrvalue = xml_ReaderValue( p_sys->p_xml_reader ); if( !psz_attrname || !psz_attrvalue ) { free( psz_eltname ); free( psz_attrname ); free( psz_attrvalue ); return -1; } GET_VALUE( name ) else GET_VALUE( mt ) else GET_VALUE( id ) else GET_VALUE( br ) else GET_VALUE( genre ) else GET_VALUE( ct ) else GET_VALUE( lc ) else GET_VALUE( rt ) else GET_VALUE( load ) else { msg_Warn( p_demux, "unexpected attribute %s in element %s", psz_attrname, psz_eltname ); } free( psz_attrname ); free( psz_attrvalue ); } } free( psz_eltname ); break; case XML_READER_TEXT: break; // End element case XML_READER_ENDELEM: // Read the element name psz_eltname = xml_ReaderName( p_sys->p_xml_reader ); if( !psz_eltname ) return -1; if( !strcmp( psz_eltname, "station" ) && ( psz_base || ( psz_rt && psz_load && ( p_sys->b_adult || strcmp( psz_rt, "NC17" ) ) ) ) ) { char *psz_mrl = NULL; if( psz_rt || psz_load ) { /* tv */ if( asprintf( &psz_mrl, SHOUTCAST_TV_TUNEIN_URL "%s", psz_id ) == -1) psz_mrl = NULL; } else { /* radio */ if( asprintf( &psz_mrl, SHOUTCAST_TUNEIN_BASE_URL "%s?id=%s", psz_base, psz_id ) == -1 ) psz_mrl = NULL; } p_input = input_item_New( p_demux, psz_mrl, psz_name ); input_item_CopyOptions( p_sys->p_current_input, p_input ); free( psz_mrl ); #define SADD_INFO( type, field ) \ if( field ) \ input_item_AddInfo( p_input, _("Shoutcast"), \ vlc_gettext(type), "%s", field ) SADD_INFO( N_("Mime"), psz_mt ); SADD_INFO( N_("Bitrate"), psz_br ); SADD_INFO( N_("Listeners"), psz_lc ); SADD_INFO( N_("Load"), psz_load ); if( psz_genre ) input_item_SetGenre( p_input, psz_genre ); if( psz_ct ) input_item_SetNowPlaying( p_input, psz_ct ); if( psz_rt ) input_item_SetRating( p_input, psz_rt ); input_item_AddSubItem( p_sys->p_current_input, p_input ); vlc_gc_decref( p_input ); FREENULL( psz_name ); FREENULL( psz_mt ); FREENULL( psz_id ); FREENULL( psz_br ); FREENULL( psz_genre ); FREENULL( psz_ct ); FREENULL( psz_lc ); FREENULL( psz_rt ); } free( psz_eltname ); break; } }
/**************************************************************************** * Parse the rss feed ***************************************************************************/ static bool ParseFeed( filter_t *p_filter, xml_reader_t *p_xml_reader, rss_feed_t *p_feed ) { VLC_UNUSED(p_filter); const char *node; char *psz_eltname = NULL; bool b_is_item = false; bool b_is_image = false; int i_item = 0; int type; while( (type = xml_ReaderNextNode( p_xml_reader, &node )) > 0 ) { switch( type ) { case XML_READER_STARTELEM: #ifdef RSS_DEBUG msg_Dbg( p_filter, "element <%s>", node ); #endif psz_eltname = strdup( node ); if( unlikely(!psz_eltname) ) goto end; /* rss or atom */ if( !strcmp( node, "item" ) || !strcmp( node, "entry" ) ) { b_is_item = true; p_feed->i_items++; p_feed->p_items = (rss_item_t *)xrealloc( p_feed->p_items, p_feed->i_items * sizeof( rss_item_t ) ); // sunqueen modify p_feed->p_items[p_feed->i_items-1].psz_title = NULL; p_feed->p_items[p_feed->i_items-1].psz_description = NULL; p_feed->p_items[p_feed->i_items-1].psz_link = NULL; } /* rss */ else if( !strcmp( node, "image" ) ) { b_is_image = true; } /* atom */ else if( !strcmp( node, "link" ) ) { const char *name, *value; char *psz_href = NULL; char *psz_rel = NULL; while( (name = xml_ReaderNextAttr( p_xml_reader, &value )) != NULL ) { if( !strcmp( name, "rel" ) ) { free( psz_rel ); psz_rel = strdup( value ); } else if( !strcmp( name, "href" ) ) { free( psz_href ); psz_href = strdup( value ); } } /* "rel" and "href" must be defined */ if( psz_rel && psz_href ) { if( !strcmp( psz_rel, "alternate" ) && !b_is_item && !b_is_image && !p_feed->psz_link ) { p_feed->psz_link = psz_href; } /* this isn't in the rfc but i found some ... */ else if( ( !strcmp( psz_rel, "logo" ) || !strcmp( psz_rel, "icon" ) ) && !b_is_item && !b_is_image && !p_feed->psz_image ) { p_feed->psz_image = psz_href; } else { free( psz_href ); } } else { free( psz_href ); } free( psz_rel ); } break; case XML_READER_ENDELEM: FREENULL( psz_eltname ); #ifdef RSS_DEBUG msg_Dbg( p_filter, "element end </%s>", node ); #endif /* rss or atom */ if( !strcmp( node, "item" ) || !strcmp( node, "entry" ) ) { b_is_item = false; i_item++; } /* rss */ else if( !strcmp( node, "image" ) ) { b_is_image = false; } break; case XML_READER_TEXT: { if( !psz_eltname ) break; char *psz_eltvalue = removeWhiteChars( node ); #ifdef RSS_DEBUG msg_Dbg( p_filter, " text : \"%s\"", psz_eltvalue ); #endif /* Is it an item ? */ if( b_is_item ) { rss_item_t *p_item = p_feed->p_items+i_item; /* rss/atom */ if( !strcmp( psz_eltname, "title" ) && !p_item->psz_title ) { p_item->psz_title = psz_eltvalue; } else if( !strcmp( psz_eltname, "link" ) /* rss */ && !p_item->psz_link ) { p_item->psz_link = psz_eltvalue; } /* rss/atom */ else if( ( !strcmp( psz_eltname, "description" ) || !strcmp( psz_eltname, "summary" ) ) && !p_item->psz_description ) { p_item->psz_description = psz_eltvalue; } else { free( psz_eltvalue ); } } /* Is it an image ? */ else if( b_is_image ) { if( !strcmp( psz_eltname, "url" ) && !p_feed->psz_image ) p_feed->psz_image = psz_eltvalue; else free( psz_eltvalue ); } else { /* rss/atom */ if( !strcmp( psz_eltname, "title" ) && !p_feed->psz_title ) { p_feed->psz_title = psz_eltvalue; } /* rss */ else if( !strcmp( psz_eltname, "link" ) && !p_feed->psz_link ) { p_feed->psz_link = psz_eltvalue; } /* rss ad atom */ else if( ( !strcmp( psz_eltname, "description" ) || !strcmp( psz_eltname, "subtitle" ) ) && !p_feed->psz_description ) { p_feed->psz_description = psz_eltvalue; } /* rss */ else if( ( !strcmp( psz_eltname, "logo" ) || !strcmp( psz_eltname, "icon" ) ) && !p_feed->psz_image ) { p_feed->psz_image = psz_eltvalue; } else { free( psz_eltvalue ); } } break; } } } free( psz_eltname ); return true; end: free( psz_eltname ); return false; }
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 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 mtime_t ParseTime(xml_reader_t *p_xml_reader) { char *psz_value = NULL; char *psz_start = NULL; const char *psz_node = NULL; const char *psz_txt = NULL; int i_subfractions = -1; int i_subresult = 0; mtime_t i_result = 0; do { psz_txt = xml_ReaderNextAttr( p_xml_reader, &psz_node ); } while( psz_txt && strncasecmp( psz_txt, "VALUE", 5 ) ); psz_value = strdup( psz_node ); psz_start = psz_value; while( *psz_value ) { if( isdigit( *psz_value ) ) { i_subresult = i_subresult * 10; i_subresult += *psz_value - '0'; if( i_subfractions != -1 ) i_subfractions++; } else if( *psz_value == ':' ) { i_result += i_subresult; i_result = i_result * 60; i_subresult = 0; } else if( *psz_value == '.' ) { i_subfractions = 0; i_result += i_subresult; i_subresult = 0; } psz_value++; } if( i_subfractions == -1) i_result += i_subresult; /* Convert to microseconds */ if( i_subfractions == -1) i_subfractions = 0; while( i_subfractions < 6 ) { i_subresult = i_subresult * 10; i_subfractions++; } i_result = i_result * 1000000; if( i_subfractions != -1) i_result += i_subresult; free( psz_start ); return i_result; }