static int vlclua_node_add_subitem( lua_State *L ) { services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L ); input_item_t **pp_node = (input_item_t **)luaL_checkudata( L, 1, "node" ); if( *pp_node ) { if( lua_istable( L, -1 ) ) { lua_getfield( L, -1, "path" ); if( lua_isstring( L, -1 ) ) { char **ppsz_options = NULL; int i_options = 0; const char *psz_path = lua_tostring( L, -1 ); vlclua_read_options( p_sd, L, &i_options, &ppsz_options ); input_item_node_t *p_input_node = input_item_node_Create( *pp_node ); input_item_t *p_input = input_item_NewExt( p_sd, psz_path, psz_path, i_options, (const char **)ppsz_options, VLC_INPUT_OPTION_TRUSTED, -1 ); lua_pop( L, 1 ); if( p_input ) { vlclua_read_meta_data( p_sd, L, p_input ); /* This one is to be tested... */ vlclua_read_custom_meta_data( p_sd, L, p_input ); lua_getfield( L, -1, "duration" ); if( lua_isnumber( L, -1 ) ) input_item_SetDuration( p_input, (lua_tonumber( L, -1 )*1e6) ); else if( !lua_isnil( L, -1 ) ) msg_Warn( p_sd, "Item duration should be a number (in seconds)." ); lua_pop( L, 1 ); input_item_node_AppendItem( p_input_node, p_input ); input_item_node_PostAndDelete( p_input_node ); input_item_t **udata = (input_item_t **) lua_newuserdata( L, sizeof( input_item_t * ) ); *udata = p_input; if( luaL_newmetatable( L, "input_item_t" ) ) { lua_pushliteral( L, "none of your business" ); lua_setfield( L, -2, "__metatable" ); } lua_setmetatable( L, -2 ); vlc_gc_decref( p_input ); } while( i_options > 0 ) free( ppsz_options[--i_options] ); free( ppsz_options ); } else msg_Err( p_sd, "node:add_subitem: the \"path\" parameter can't be empty" ); } else msg_Err( p_sd, "Error parsing add_subitem arguments" ); } return 1; }
/** * \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 */ }
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; }
static int vlclua_node_add_node( lua_State *L ) { services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L ); input_item_t **pp_node = (input_item_t **)luaL_checkudata( L, 1, "node" ); if( *pp_node ) { if( lua_istable( L, -1 ) ) { lua_getfield( L, -1, "title" ); if( lua_isstring( L, -1 ) ) { const char *psz_name = lua_tostring( L, -1 ); input_item_node_t *p_input_node = input_item_node_Create( *pp_node ); input_item_t *p_input = input_item_NewWithType( VLC_OBJECT( p_sd ), "vlc://nop", psz_name, 0, NULL, 0, -1, ITEM_TYPE_NODE ); lua_pop( L, 1 ); if( p_input ) { lua_getfield( L, -1, "arturl" ); if( lua_isstring( L, -1 ) && strcmp( lua_tostring( L, -1 ), "" ) ) { char *psz_value = strdup( lua_tostring( L, -1 ) ); EnsureUTF8( psz_value ); msg_Dbg( p_sd, "ArtURL: %s", psz_value ); input_item_SetArtURL( p_input, psz_value ); free( psz_value ); } input_item_node_AppendItem( p_input_node, p_input ); input_item_node_PostAndDelete( p_input_node ); input_item_t **udata = (input_item_t **) lua_newuserdata( L, sizeof( input_item_t * ) ); *udata = p_input; if( luaL_newmetatable( L, "node" ) ) { lua_newtable( L ); luaL_register( L, NULL, vlclua_node_reg ); lua_setfield( L, -2, "__index" ); } lua_setmetatable( L, -2 ); } } else msg_Err( p_sd, "node:add_node: the \"title\" parameter can't be empty" ); } else msg_Err( p_sd, "Error parsing add_node arguments" ); } return 1; }
static int Demux( demux_t *p_demux ) { char *psz_line; input_item_t *p_current_input = GetCurrentItem(p_demux); input_item_node_t *p_subitems = input_item_node_Create( p_current_input ); while( (psz_line = stream_ReadLine( p_demux->s )) ) { char *psz_parse = psz_line; /* Skip leading tabs and spaces */ while( *psz_parse == ' ' || *psz_parse == '\t' || *psz_parse == '\n' || *psz_parse == '\r' ) psz_parse++; /* if the line is the uri of the media item */ if( !strncasecmp( psz_parse, "<media src=\"", strlen( "<media src=\"" ) ) ) { char *psz_uri = psz_parse + strlen( "<media src=\"" ); psz_parse = strchr( psz_uri, '"' ); if( psz_parse != NULL ) { *psz_parse = '\0'; resolve_xml_special_chars( psz_uri ); psz_uri = ProcessMRL( psz_uri, p_demux->p_sys->psz_prefix ); if( psz_uri != NULL ) { input_item_t *p_input; p_input = input_item_NewExt( psz_uri, psz_uri, 0, NULL, 0, -1 ); input_item_node_AppendItem( p_subitems, p_input ); vlc_gc_decref( p_input ); free( psz_uri ); } } } /* Fetch another line */ free( psz_line ); } input_item_node_PostAndDelete( p_subitems ); vlc_gc_decref(p_current_input); var_Destroy( p_demux, "wpl-extvlcopt" ); return 0; /* Needed for correct operation of go back */ }
/** * \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; }
/***************************************************************************** * Demux: The important stuff *****************************************************************************/ static int Demux( demux_t *p_demux ) { char *psz_line; input_item_t *p_input; input_item_t *p_current_input = GetCurrentItem(p_demux); input_item_node_t *p_subitems = input_item_node_Create( p_current_input ); while( (psz_line = stream_ReadLine( p_demux->s )) ) { char **ppsz_options = NULL; int i_options = 0; char *psz_name = NULL; if( !ParseLine( psz_line, &psz_name, &ppsz_options, &i_options ) ) { free( psz_line ); continue; } EnsureUTF8( psz_name ); for( int i = 0; i< i_options; i++ ) EnsureUTF8( ppsz_options[i] ); p_input = input_item_NewExt( "dvb://", psz_name, i_options, (const char**)ppsz_options, VLC_INPUT_OPTION_TRUSTED, -1 ); input_item_node_AppendItem( p_subitems, p_input ); vlc_gc_decref( p_input ); while( i_options-- ) free( ppsz_options[i_options] ); free( ppsz_options ); free( psz_line ); } input_item_node_PostAndDelete( p_subitems ); vlc_gc_decref(p_current_input); return 0; /* Needed for correct operation of go back */ }
/** Parses the whole channels.conf file */ static int Demux(demux_t *demux) { input_item_t *input = GetCurrentItem(demux); input_item_node_t *subitems = input_item_node_Create(input); char *line; while ((line = stream_ReadLine(demux->s)) != NULL) { input_item_t *item = ParseLine(line); if (item == NULL) continue; input_item_node_AppendItem(subitems, item); vlc_gc_decref(item); } input_item_node_PostAndDelete(subitems); vlc_gc_decref(input); return 0; /* Needed for correct operation of go back */ }
/* * Builds playlist based on available input items. */ void MediaServer::_buildPlaylist( Container* p_parent, input_item_node_t *p_input_node ) { bool b_send = p_input_node == NULL; if( b_send ) p_input_node = input_item_node_Create( p_parent->getInputItem() ); for ( unsigned int i = 0; i < p_parent->getNumContainers(); i++ ) { Container* p_container = p_parent->getContainer( i ); input_item_t* p_input_item = input_item_New( "vlc://nop", p_container->getTitle() ); input_item_node_t *p_new_node = input_item_node_AppendItem( p_input_node, p_input_item ); p_container->setInputItem( p_input_item ); _buildPlaylist( p_container, p_new_node ); } for ( unsigned int i = 0; i < p_parent->getNumItems(); i++ ) { Item* p_item = p_parent->getItem( i ); input_item_t* p_input_item = input_item_NewExt( p_item->getResource(), p_item->getTitle(), 0, NULL, 0, p_item->getDuration() ); assert( p_input_item ); input_item_node_AppendItem( p_input_node, p_input_item ); p_item->setInputItem( p_input_item ); } if( b_send ) input_item_node_PostAndDelete( p_input_node ); }
static int Demux( demux_t* p_demux ) { const char* psz_name; int i_type; demux_sys_t* p_sys = p_demux->p_sys; input_item_t* p_input = GetCurrentItem( p_demux ); input_item_node_t* p_node = input_item_node_Create( p_input ); p_sys->psz_prefix = FindPrefix( p_demux ); do { i_type = xml_ReaderNextNode( p_sys->p_reader, &psz_name ); if ( i_type == XML_READER_STARTELEM && !strcasecmp( psz_name, "head" ) ) read_head( p_demux, p_input ); else if ( i_type == XML_READER_STARTELEM && !strcasecmp( psz_name, "body" ) ) read_body( p_demux, p_node ); } while (i_type != XML_READER_ENDELEM || strcasecmp( psz_name, "smil" ) ); input_item_node_PostAndDelete( p_node ); input_item_Release( p_input ); return 0; }
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; }
/* This won't hold the item, but can tell to interested third parties * Like the playlist, that there is a new sub item. With this design * It is not the input item's responsability to keep all the ref of * the input item children. */ void input_item_PostSubItem( input_item_t *p_parent, input_item_t *p_child ) { input_item_node_t *p_node = input_item_node_Create( p_parent ); input_item_node_AppendItem( p_node, p_child ); input_item_node_PostAndDelete( p_node ); }
/** * Main demux callback function * @param p_demux: this demux object */ static int Demux( demux_t *p_demux ) { char *psz_line; char *psz_artist = NULL, *psz_album = NULL, *psz_genre = NULL, *psz_year = NULL; char *psz_author = NULL, *psz_title = NULL, *psz_copyright = NULL, *psz_cdnum = NULL, *psz_comments = NULL; mtime_t i_duration = -1; const char **ppsz_options = NULL; int i_options = 0, i_start = 0, i_stop = 0; bool b_cleanup = false; input_item_t *p_input; input_item_t *p_current_input = GetCurrentItem(p_demux); input_item_node_t *p_subitems = input_item_node_Create( p_current_input ); psz_line = vlc_stream_ReadLine( p_demux->s ); while( psz_line ) { char *psz_parse = psz_line; /* Skip leading tabs and spaces */ while( *psz_parse == ' ' || *psz_parse == '\t' || *psz_parse == '\n' || *psz_parse == '\r' ) psz_parse++; if( *psz_parse == '#' ) { /* Ignore comments */ } else if( *psz_parse ) { char *psz_mrl, *psz_option_next, *psz_option; char *psz_param, *psz_value; /* Get the MRL from the file. Note that this might contain parameters of form ?param1=value1¶m2=value2 in a RAM file */ psz_mrl = ProcessMRL( psz_parse, p_demux->p_sys->psz_prefix ); b_cleanup = true; if ( !psz_mrl ) goto error; /* We have the MRL, now we have to check for options and parse them from MRL */ psz_option = strchr( psz_mrl, '?' ); /* Look for start of options */ if( psz_option ) { /* Remove options from MRL because VLC can't get the file otherwise */ *psz_option = '\0'; psz_option++; psz_option_next = psz_option; while( 1 ) /* Process each option */ { /* Look for end of first option which maybe a & or \0 */ psz_option = psz_option_next; psz_option_next = strchr( psz_option, '&' ); if( psz_option_next ) { *psz_option_next = '\0'; psz_option_next++; } else psz_option_next = strchr( psz_option, '\0' ); /* Quit if options are over */ if( psz_option_next == psz_option ) break; /* Parse out param and value */ psz_param = psz_option; psz_value = strchr( psz_option, '=' ); if( psz_value == NULL ) break; *psz_value = '\0'; psz_value++; /* Take action based on parameter value in the below if else structure */ /* TODO: Remove any quotes surrounding values if required */ if( !strcmp( psz_param, "clipinfo" ) ) { ParseClipInfo( psz_value, &psz_artist, &psz_title, &psz_album, &psz_genre, &psz_year, &psz_cdnum, &psz_comments ); /* clipinfo has various sub parameters, which is parsed by this function */ } else if( !strcmp( psz_param, "author" ) ) { psz_author = vlc_uri_decode_duplicate(psz_value); EnsureUTF8( psz_author ); } else if( !strcmp( psz_param, "start" ) && strncmp( psz_mrl, "rtsp", 4 ) /* Our rtsp-real or our real demuxer is wrong */ ) { i_start = ParseTime( psz_value, strlen( psz_value ) ); char *temp; if( i_start ) { if( asprintf( &temp, ":start-time=%d", i_start ) != -1 ) INSERT_ELEM( ppsz_options, i_options, i_options, temp ); } } else if( !strcmp( psz_param, "end" ) ) { i_stop = ParseTime( psz_value, strlen( psz_value ) ); char *temp; if( i_stop ) { if( asprintf( &temp, ":stop-time=%d", i_stop ) != -1 ) INSERT_ELEM( ppsz_options, i_options, i_options, temp ); } } else if( !strcmp( psz_param, "title" ) ) { free( psz_title ); psz_title = vlc_uri_decode_duplicate(psz_value); EnsureUTF8( psz_title ); } else if( !strcmp( psz_param, "copyright" ) ) { psz_copyright = vlc_uri_decode_duplicate(psz_value); EnsureUTF8( psz_copyright ); } else { /* TODO: insert option anyway? Currently ignores*/ /* INSERT_ELEM( ppsz_options, i_options, i_options, psz_option ); */ } } } /* Create the input item and pump in all the options into playlist item */ p_input = input_item_NewExt( psz_mrl, psz_title, i_duration, ITEM_TYPE_UNKNOWN, ITEM_NET_UNKNOWN ); if( !p_input ) { free( psz_mrl ); goto error; } input_item_AddOptions( p_input, i_options, ppsz_options, 0 ); if( !EMPTY_STR( psz_artist ) ) input_item_SetArtist( p_input, psz_artist ); if( !EMPTY_STR( psz_author ) ) input_item_SetPublisher( p_input, psz_author ); if( !EMPTY_STR( psz_title ) ) input_item_SetTitle( p_input, psz_title ); if( !EMPTY_STR( psz_copyright ) ) input_item_SetCopyright( p_input, psz_copyright ); if( !EMPTY_STR( psz_album ) ) input_item_SetAlbum( p_input, psz_album ); if( !EMPTY_STR( psz_genre ) ) input_item_SetGenre( p_input, psz_genre ); if( !EMPTY_STR( psz_year ) ) input_item_SetDate( p_input, psz_year ); if( !EMPTY_STR( psz_cdnum ) ) input_item_SetTrackNum( p_input, psz_cdnum ); if( !EMPTY_STR( psz_comments ) ) input_item_SetDescription( p_input, psz_comments ); input_item_node_AppendItem( p_subitems, p_input ); vlc_gc_decref( p_input ); free( psz_mrl ); } error: /* Fetch another line */ free( psz_line ); psz_line = vlc_stream_ReadLine( p_demux->s ); if( !psz_line ) b_cleanup = true; if( b_cleanup ) { /* Cleanup state */ while( i_options-- ) free( (char*)ppsz_options[i_options] ); FREENULL( ppsz_options ); FREENULL( psz_artist ); FREENULL( psz_title ); FREENULL( psz_author ); FREENULL( psz_copyright ); FREENULL( psz_album ); FREENULL( psz_genre ); FREENULL( psz_year ); FREENULL( psz_cdnum ); FREENULL( psz_comments ); i_options = 0; i_duration = -1; i_start = 0; i_stop = 0; b_cleanup = false; } } input_item_node_PostAndDelete( p_subitems ); vlc_gc_decref(p_current_input); var_Destroy( p_demux, "m3u-extvlcopt" ); return 0; /* Needed for correct operation of go back */ }
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 ) { char *psz_line; mtime_t i_duration = -1; char *psz_title = NULL, *psz_genre = NULL, *psz_tracknum = NULL, *psz_language = NULL, *psz_artist = NULL, *psz_album = NULL, *psz_date = NULL, *psz_publisher = NULL, *psz_encodedby = NULL, *psz_description = NULL, *psz_url = NULL, *psz_copyright = NULL, *psz_mrl = NULL; input_item_t *p_current_input = GetCurrentItem(p_demux); psz_line = stream_ReadLine( p_demux->s ); char *psz_parse = psz_line; /* Skip leading tabs and spaces */ while( *psz_parse == ' ' || *psz_parse == '\t' || *psz_parse == '\n' || *psz_parse == '\r' ) psz_parse++; /* if the 1st line is "AC", skip it */ /* TODO: using this information ? */ if( !strncasecmp( psz_parse, "AC", strlen( "AC" ) ) ) { free( psz_line ); psz_line = stream_ReadLine( p_demux->s ); } input_item_node_t *p_subitems = input_item_node_Create( p_current_input ); /* Loop on all lines */ while( psz_line ) { psz_parse = psz_line; /* Skip leading tabs and spaces */ while( *psz_parse == ' ' || *psz_parse == '\t' || *psz_parse == '\n' || *psz_parse == '\r' ) psz_parse++; /* filename */ if( !strncasecmp( psz_parse, "NM", strlen( "NM" ) ) ) { char *psz_tabvalue = ParseTabValue( psz_parse ); if( !EMPTY_STR(psz_tabvalue) ) { psz_mrl = ProcessMRL( psz_tabvalue, p_demux->p_sys->psz_prefix ); } free( psz_tabvalue ); } /* duration */ else if( !strncasecmp( psz_parse, "DR", strlen( "DR" ) ) ) { char *psz_tabvalue = ParseTabValue( psz_parse ); if( !EMPTY_STR(psz_tabvalue) ) { int i_parsed_duration = atoi( psz_tabvalue ); if( i_parsed_duration >= 0 ) i_duration = i_parsed_duration * INT64_C(1000); } free( psz_tabvalue ); } #define PARSE(tag,variable) \ else if( !strncasecmp( psz_parse, tag, strlen( tag ) ) ) \ variable = ParseTabValue( psz_parse ); PARSE( "TT", psz_title ) PARSE( "TG", psz_genre ) PARSE( "TR", psz_tracknum ) PARSE( "TL", psz_language ) PARSE( "TA", psz_artist ) PARSE( "TB", psz_album ) PARSE( "TY", psz_date ) PARSE( "TH", psz_publisher ) PARSE( "TE", psz_encodedby ) PARSE( "TC", psz_description ) PARSE( "TU", psz_url ) PARSE( "TO", psz_copyright ) #undef PARSE /* force a duration ? */ else if( !strncasecmp( psz_parse, "FD", strlen( "FD" ) ) ) {} /* end of file entry */ else if( !strncasecmp( psz_parse, "BR!", strlen( "BR!" ) ) ) { /* create the input item */ input_item_t *p_input = input_item_NewExt( p_demux, psz_mrl, psz_title, 0, NULL, 0, i_duration ); input_item_node_AppendItem( p_subitems, p_input ); FREENULL( psz_mrl ); FREENULL( psz_title ); i_duration = -1; #define SET(variable, type) \ if( !EMPTY_STR(variable) ) \ { \ input_item_Set##type( p_input, variable ); \ FREENULL( variable ); \ } /* set the meta */ SET( psz_genre, Genre ); SET( psz_tracknum, TrackNum ); SET( psz_language, Language ); SET( psz_artist, Artist ); SET( psz_album, Album ); SET( psz_date, Date ); SET( psz_encodedby, EncodedBy ); SET( psz_description, Description ); SET( psz_copyright, Copyright ); #undef SET vlc_gc_decref( p_input ); } else msg_Warn( p_demux, "invalid line '%s'", psz_parse ); /* Fetch another line */ free( psz_line ); psz_line = stream_ReadLine( p_demux->s ); } input_item_node_PostAndDelete( p_subitems ); vlc_gc_decref(p_current_input); var_Destroy( p_demux, "zpl-extvlcopt" ); return 0; /* Needed for correct operation of go back */ }
static int GetTracks( access_t *p_access, input_item_t *p_current ) { access_sys_t *p_sys = p_access->p_sys; const int i_titles = ioctl_GetTracksMap( VLC_OBJECT(p_access), p_sys->vcddev, &p_sys->p_sectors ); if( i_titles <= 0 ) { if( i_titles < 0 ) msg_Err( p_access, "unable to count tracks" ); else if( i_titles <= 0 ) msg_Err( p_access, "no audio tracks found" ); return VLC_EGENERIC;; } /* */ input_item_SetName( p_current, "Audio CD" ); const char *psz_album = NULL; const char *psz_year = NULL; const char *psz_genre = NULL; const char *psz_artist = NULL; const char *psz_description = NULL; /* Return true if the given string is not NULL and not empty */ #define NONEMPTY( psz ) ( (psz) && *(psz) ) /* If the given string is NULL or empty, fill it by the return value of 'code' */ #define ON_EMPTY( psz, code ) do { if( !NONEMPTY( psz) ) { (psz) = code; } } while(0) /* Retreive CDDB information */ #ifdef HAVE_LIBCDDB char psz_year_buffer[4+1]; msg_Dbg( p_access, "fetching infos with CDDB" ); cddb_disc_t *p_disc = GetCDDBInfo( p_access, i_titles, p_sys->p_sectors ); if( p_disc ) { psz_album = cddb_disc_get_title( p_disc ); psz_genre = cddb_disc_get_genre( p_disc ); /* */ const unsigned i_year = cddb_disc_get_year( p_disc ); if( i_year > 0 ) { psz_year = psz_year_buffer; snprintf( psz_year_buffer, sizeof(psz_year_buffer), "%u", i_year ); } /* Set artist only if unique */ for( int i = 0; i < i_titles; i++ ) { cddb_track_t *t = cddb_disc_get_track( p_disc, i ); if( !t ) continue; const char *psz_track_artist = cddb_track_get_artist( t ); if( psz_artist && psz_track_artist && strcmp( psz_artist, psz_track_artist ) ) { psz_artist = NULL; break; } psz_artist = psz_track_artist; } } #endif /* CD-Text */ vlc_meta_t **pp_cd_text; int i_cd_text; if( ioctl_GetCdText( VLC_OBJECT(p_access), p_sys->vcddev, &pp_cd_text, &i_cd_text ) ) { msg_Dbg( p_access, "CD-TEXT information missing" ); i_cd_text = 0; pp_cd_text = NULL; } /* Retrieve CD-TEXT information but prefer CDDB */ if( i_cd_text > 0 && pp_cd_text[0] ) { const vlc_meta_t *p_disc = pp_cd_text[0]; ON_EMPTY( psz_album, vlc_meta_Get( p_disc, vlc_meta_Album ) ); ON_EMPTY( psz_genre, vlc_meta_Get( p_disc, vlc_meta_Genre ) ); ON_EMPTY( psz_artist, vlc_meta_Get( p_disc, vlc_meta_Artist ) ); ON_EMPTY( psz_description, vlc_meta_Get( p_disc, vlc_meta_Description ) ); } if( NONEMPTY( psz_album ) ) { input_item_SetName( p_current, psz_album ); input_item_SetAlbum( p_current, psz_album ); } if( NONEMPTY( psz_genre ) ) input_item_SetGenre( p_current, psz_genre ); if( NONEMPTY( psz_artist ) ) input_item_SetArtist( p_current, psz_artist ); if( NONEMPTY( psz_year ) ) input_item_SetDate( p_current, psz_year ); if( NONEMPTY( psz_description ) ) input_item_SetDescription( p_current, psz_description ); const mtime_t i_duration = (int64_t)( p_sys->p_sectors[i_titles] - p_sys->p_sectors[0] ) * CDDA_DATA_SIZE * 1000000 / 44100 / 2 / 2; input_item_SetDuration( p_current, i_duration ); input_item_node_t *p_root = input_item_node_Create( p_current ); /* Build title table */ for( int i = 0; i < i_titles; i++ ) { input_item_t *p_input_item; char *psz_uri, *psz_opt, *psz_first, *psz_last; char *psz_name; msg_Dbg( p_access, "track[%d] start=%d", i, p_sys->p_sectors[i] ); /* */ if( asprintf( &psz_uri, "cdda://%s", p_access->psz_location ) == -1 ) psz_uri = NULL; if( asprintf( &psz_opt, "cdda-track=%i", i+1 ) == -1 ) psz_opt = NULL; if( asprintf( &psz_first, "cdda-first-sector=%i",p_sys->p_sectors[i] ) == -1 ) psz_first = NULL; if( asprintf( &psz_last, "cdda-last-sector=%i", p_sys->p_sectors[i+1] ) == -1 ) psz_last = NULL; /* Define a "default name" */ if( asprintf( &psz_name, _("Audio CD - Track %02i"), (i+1) ) == -1 ) psz_name = NULL; /* Create playlist items */ const mtime_t i_duration = (int64_t)( p_sys->p_sectors[i+1] - p_sys->p_sectors[i] ) * CDDA_DATA_SIZE * 1000000 / 44100 / 2 / 2; p_input_item = input_item_NewWithType( psz_uri, psz_name, 0, NULL, 0, i_duration, ITEM_TYPE_DISC ); input_item_CopyOptions( p_current, p_input_item ); input_item_AddOption( p_input_item, psz_first, VLC_INPUT_OPTION_TRUSTED ); input_item_AddOption( p_input_item, psz_last, VLC_INPUT_OPTION_TRUSTED ); input_item_AddOption( p_input_item, psz_opt, VLC_INPUT_OPTION_TRUSTED ); const char *psz_track_title = NULL; const char *psz_track_artist = NULL; const char *psz_track_genre = NULL; const char *psz_track_description = NULL; #ifdef HAVE_LIBCDDB /* Retreive CDDB information */ if( p_disc ) { cddb_track_t *t = cddb_disc_get_track( p_disc, i ); if( t != NULL ) { psz_track_title = cddb_track_get_title( t ); psz_track_artist = cddb_track_get_artist( t ); } } #endif /* Retreive CD-TEXT information but prefer CDDB */ if( i+1 < i_cd_text && pp_cd_text[i+1] ) { const vlc_meta_t *t = pp_cd_text[i+1]; ON_EMPTY( psz_track_title, vlc_meta_Get( t, vlc_meta_Title ) ); ON_EMPTY( psz_track_artist, vlc_meta_Get( t, vlc_meta_Artist ) ); ON_EMPTY( psz_track_genre, vlc_meta_Get( t, vlc_meta_Genre ) ); ON_EMPTY( psz_track_description, vlc_meta_Get( t, vlc_meta_Description ) ); } /* */ ON_EMPTY( psz_track_artist, psz_artist ); ON_EMPTY( psz_track_genre, psz_genre ); ON_EMPTY( psz_track_description, psz_description ); /* */ if( NONEMPTY( psz_track_title ) ) { input_item_SetName( p_input_item, psz_track_title ); input_item_SetTitle( p_input_item, psz_track_title ); } if( NONEMPTY( psz_track_artist ) ) input_item_SetArtist( p_input_item, psz_track_artist ); if( NONEMPTY( psz_track_genre ) ) input_item_SetGenre( p_input_item, psz_track_genre ); if( NONEMPTY( psz_track_description ) ) input_item_SetDescription( p_input_item, psz_track_description ); if( NONEMPTY( psz_album ) ) input_item_SetAlbum( p_input_item, psz_album ); if( NONEMPTY( psz_year ) ) input_item_SetDate( p_input_item, psz_year ); char psz_num[3+1]; snprintf( psz_num, sizeof(psz_num), "%d", 1+i ); input_item_SetTrackNum( p_input_item, psz_num ); input_item_node_AppendItem( p_root, p_input_item ); vlc_gc_decref( p_input_item ); free( psz_uri ); free( psz_opt ); free( psz_name ); free( psz_first ); free( psz_last ); } #undef ON_EMPTY #undef NONEMPTY input_item_node_PostAndDelete( p_root ); /* */ for( int i = 0; i < i_cd_text; i++ ) { vlc_meta_t *p_meta = pp_cd_text[i]; if( !p_meta ) continue; vlc_meta_Delete( p_meta ); } free( pp_cd_text ); #ifdef HAVE_LIBCDDB if( p_disc ) cddb_disc_destroy( p_disc ); #endif return VLC_SUCCESS; }
static int Demux( demux_t *p_demux ) { char *psz_name = NULL; char *psz_line; char *psz_mrl = NULL; char *psz_mrl_orig = NULL; char *psz_key; char *psz_value; int i_item = -1; input_item_t *p_input; input_item_t *p_current_input = GetCurrentItem(p_demux); input_item_node_t *p_subitems = input_item_node_Create( p_current_input ); while( ( psz_line = stream_ReadLine( p_demux->s ) ) ) { if( !strncasecmp( psz_line, "[playlist]", sizeof("[playlist]")-1 ) || !strncasecmp( psz_line, "[Reference]", sizeof("[Reference]")-1 ) ) { free( psz_line ); continue; } psz_key = psz_line; psz_value = strchr( psz_line, '=' ); if( psz_value ) { *psz_value='\0'; psz_value++; } else { free( psz_line ); continue; } if( !strcasecmp( psz_key, "version" ) ) { msg_Dbg( p_demux, "pls file version: %s", psz_value ); free( psz_line ); continue; } if( !strcasecmp( psz_key, "numberofentries" ) ) { msg_Dbg( p_demux, "pls should have %d entries", atoi(psz_value) ); free( psz_line); continue; } /* find the number part of of file1, title1 or length1 etc */ int i_new_item; if( sscanf( psz_key, "%*[^0-9]%d", &i_new_item ) != 1 ) { msg_Warn( p_demux, "couldn't find number of items" ); free( psz_line ); continue; } if( i_item == -1 ) i_item = i_new_item; else if( i_item != i_new_item ) { /* we found a new item, insert the previous */ if( psz_mrl ) { p_input = input_item_New( psz_mrl, psz_name ); input_item_CopyOptions( p_current_input, p_input ); input_item_node_AppendItem( p_subitems, p_input ); vlc_gc_decref( p_input ); free( psz_mrl_orig ); psz_mrl_orig = psz_mrl = NULL; } else { msg_Warn( p_demux, "no file= part found for item %d", i_item ); } free( psz_name ); psz_name = NULL; i_item = i_new_item; } if( !strncasecmp( psz_key, "file", sizeof("file") -1 ) || !strncasecmp( psz_key, "Ref", sizeof("Ref") -1 ) ) { free( psz_mrl_orig ); psz_mrl_orig = psz_mrl = ProcessMRL( psz_value, p_demux->p_sys->psz_prefix ); if( !strncasecmp( psz_key, "Ref", sizeof("Ref") -1 ) ) { if( !strncasecmp( psz_mrl, "http://", sizeof("http://") -1 ) ) memcpy( psz_mrl, "mmsh", 4 ); } } else if( !strncasecmp( psz_key, "title", sizeof("title") -1 ) ) { free( psz_name ); psz_name = strdup( psz_value ); } else if( !strncasecmp( psz_key, "length", sizeof("length") -1 ) ) /* duration in seconds */; else { msg_Warn( p_demux, "unknown key found in pls file: %s", psz_key ); } free( psz_line ); } /* Add last object */ if( psz_mrl ) { p_input = input_item_New( psz_mrl, psz_name ); input_item_CopyOptions( p_current_input, p_input ); input_item_node_AppendItem( p_subitems, p_input ); vlc_gc_decref( p_input ); free( psz_mrl_orig ); } else { msg_Warn( p_demux, "no file= part found for item %d", i_item ); } free( psz_name ); psz_name = NULL; input_item_node_PostAndDelete( p_subitems ); vlc_gc_decref(p_current_input); return 0; /* Needed for correct operation of go back */ }
static int Demux( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; char *psz_line; char *psz_attrvalue; char *psz_version = NULL; char *psz_url = NULL; char *psz_docid = NULL; int i_duration = -1; char *psz_title = NULL; char *psz_description = NULL; input_item_t *p_input; input_item_t *p_current_input = GetCurrentItem(p_demux); input_item_node_t *p_subitems = input_item_node_Create( p_current_input ); p_sys->p_current_input = p_current_input; while( ( psz_line = stream_ReadLine( p_demux->s ) ) ) { if( *psz_line == '#' ) { /* This is a comment */ free( psz_line ); continue; } psz_attrvalue = strchr( psz_line, ':' ); if( !psz_attrvalue ) { msg_Dbg( p_demux, "Unable to parse line (%s)", psz_line ); free( psz_line ); continue; } *psz_attrvalue = '\0'; psz_attrvalue++; if( !strcmp( psz_line, "gvp_version" ) ) { psz_version = strdup( psz_attrvalue ); } else if( !strcmp( psz_line, "url" ) ) { psz_url = strdup( psz_attrvalue ); } else if( !strcmp( psz_line, "docid" ) ) { psz_docid = strdup( psz_attrvalue ); } else if( !strcmp( psz_line, "duration" ) ) { i_duration = atoi( psz_attrvalue ); } else if( !strcmp( psz_line, "title" ) ) { psz_title = strdup( psz_attrvalue ); } else if( !strcmp( psz_line, "description" ) ) { char *buf; if( !psz_description ) { psz_description = strdup( psz_attrvalue ); } else { /* handle multi-line descriptions */ if( asprintf( &buf, "%s\n%s", psz_description, psz_attrvalue ) == -1 ) buf = NULL; free( psz_description ); psz_description = buf; } /* remove ^M char at the end of the line (if any) */ buf = psz_description + strlen( psz_description ); if( buf != psz_description ) { buf--; if( *buf == '\r' ) *buf = '\0'; } } free( psz_line ); } if( !psz_url ) { msg_Err( p_demux, "URL not found" ); } else { p_input = input_item_New( psz_url, psz_title ); #define SADD_INFO( type, field ) if( field ) { input_item_AddInfo( \ p_input, _("Google Video"), type, "%s", field ) ; } SADD_INFO( "gvp_version", psz_version ); SADD_INFO( "docid", psz_docid ); SADD_INFO( "description", psz_description ); input_item_node_AppendItem( p_subitems, p_input ); vlc_gc_decref( p_input ); } input_item_node_PostAndDelete( p_subitems ); vlc_gc_decref(p_current_input); free( psz_version ); free( psz_url ); free( psz_docid ); free( psz_title ); free( psz_description ); return 0; /* 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 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; }
static int Demux( demux_t *p_demux ) { char *psz_line; char *psz_name = NULL; char *psz_artist = NULL; char *psz_album_art = NULL; int i_parsed_duration = 0; mtime_t i_duration = -1; const char**ppsz_options = NULL; char * (*pf_dup) (const char *) = p_demux->p_sys->pf_dup; int i_options = 0; bool b_cleanup = false; input_item_t *p_input; input_item_t *p_current_input = GetCurrentItem(p_demux); input_item_node_t *p_subitems = input_item_node_Create( p_current_input ); psz_line = vlc_stream_ReadLine( p_demux->s ); while( psz_line ) { char *psz_parse = psz_line; /* Skip leading tabs and spaces */ while( *psz_parse == ' ' || *psz_parse == '\t' || *psz_parse == '\n' || *psz_parse == '\r' ) psz_parse++; if( *psz_parse == '#' ) { /* Parse extra info */ /* Skip leading tabs and spaces */ while( *psz_parse == ' ' || *psz_parse == '\t' || *psz_parse == '\n' || *psz_parse == '\r' || *psz_parse == '#' ) psz_parse++; if( !*psz_parse ) goto error; if( !strncasecmp( psz_parse, "EXTINF:", sizeof("EXTINF:") -1 ) ) { /* Extended info */ psz_parse += sizeof("EXTINF:") - 1; FREENULL( psz_name ); FREENULL( psz_artist ); parseEXTINF( psz_parse, &psz_artist, &psz_name, &i_parsed_duration ); if( i_parsed_duration >= 0 ) i_duration = i_parsed_duration * INT64_C(1000000); if( psz_name ) psz_name = pf_dup( psz_name ); if( psz_artist ) psz_artist = pf_dup( psz_artist ); } else if( !strncasecmp( psz_parse, "EXTVLCOPT:", sizeof("EXTVLCOPT:") -1 ) ) { /* VLC Option */ char *psz_option; psz_parse += sizeof("EXTVLCOPT:") -1; if( !*psz_parse ) goto error; psz_option = pf_dup( psz_parse ); if( psz_option ) INSERT_ELEM( ppsz_options, i_options, i_options, psz_option ); } /* Special case for jamendo which provide the albumart */ else if( !strncasecmp( psz_parse, "EXTALBUMARTURL:", sizeof( "EXTALBUMARTURL:" ) -1 ) ) { psz_parse += sizeof( "EXTALBUMARTURL:" ) - 1; free( psz_album_art ); psz_album_art = pf_dup( psz_parse ); } } else if( !strncasecmp( psz_parse, "RTSPtext", sizeof("RTSPtext") -1 ) ) { ;/* special case to handle QuickTime RTSPtext redirect files */ } else if( *psz_parse ) { char *psz_mrl; psz_parse = pf_dup( psz_parse ); if( !psz_name && psz_parse ) /* Use filename as name for relative entries */ psz_name = strdup( psz_parse ); psz_mrl = ProcessMRL( psz_parse, p_demux->p_sys->psz_prefix ); b_cleanup = true; if( !psz_mrl ) { free( psz_parse ); goto error; } p_input = input_item_NewExt( psz_mrl, psz_name, i_duration, ITEM_TYPE_UNKNOWN, ITEM_NET_UNKNOWN ); free( psz_parse ); free( psz_mrl ); if( !p_input ) goto error; input_item_AddOptions( p_input, i_options, ppsz_options, 0 ); input_item_CopyOptions( p_input, p_current_input ); if( !EMPTY_STR(psz_artist) ) input_item_SetArtist( p_input, psz_artist ); if( psz_name ) input_item_SetTitle( p_input, psz_name ); if( !EMPTY_STR(psz_album_art) ) input_item_SetArtURL( p_input, psz_album_art ); input_item_node_AppendItem( p_subitems, p_input ); vlc_gc_decref( p_input ); } error: /* Fetch another line */ free( psz_line ); psz_line = vlc_stream_ReadLine( p_demux->s ); if( !psz_line ) b_cleanup = true; if( b_cleanup ) { /* Cleanup state */ while( i_options-- ) free( (char*)ppsz_options[i_options] ); FREENULL( ppsz_options ); i_options = 0; FREENULL( psz_name ); FREENULL( psz_artist ); FREENULL( psz_album_art ); i_parsed_duration = 0; i_duration = -1; b_cleanup = false; } } input_item_node_PostAndDelete( p_subitems ); vlc_gc_decref(p_current_input); var_Destroy( p_demux, "m3u-extvlcopt" ); return 0; /* Needed for correct operation of go back */ }
int __vlclua_playlist_add_internal( vlc_object_t *p_this, lua_State *L, playlist_t *p_playlist, input_item_t *p_parent, bool b_play ) { int i_count = 0; input_item_node_t *p_parent_node = NULL; assert( p_parent || p_playlist ); /* playlist */ if( lua_istable( L, -1 ) ) { if( p_parent ) p_parent_node = input_item_node_Create( p_parent ); lua_pushnil( L ); /* playlist nil */ while( lua_next( L, -2 ) ) { /* playlist key item */ /* <Parse playlist item> */ if( lua_istable( L, -1 ) ) { lua_getfield( L, -1, "path" ); /* playlist key item path */ if( lua_isstring( L, -1 ) ) { const char *psz_path = NULL; const char *psz_name = NULL; char **ppsz_options = NULL; int i_options = 0; mtime_t i_duration = -1; input_item_t *p_input; /* Read path and name */ psz_path = lua_tostring( L, -1 ); msg_Dbg( p_this, "Path: %s", psz_path ); lua_getfield( L, -2, "name" ); /* playlist key item path name */ if( lua_isstring( L, -1 ) ) { psz_name = lua_tostring( L, -1 ); msg_Dbg( p_this, "Name: %s", psz_name ); } else { if( !lua_isnil( L, -1 ) ) msg_Warn( p_this, "Playlist item name should be a string." ); psz_name = psz_path; } /* Read duration */ lua_getfield( L, -3, "duration" ); /* playlist key item path name duration */ if( lua_isnumber( L, -1 ) ) { i_duration = (mtime_t)(lua_tonumber( L, -1 )*1e6); } else if( !lua_isnil( L, -1 ) ) { msg_Warn( p_this, "Playlist item duration should be a number (in seconds)." ); } lua_pop( L, 1 ); /* pop "duration" */ /* playlist key item path name */ /* Read options: item must be on top of stack */ lua_pushvalue( L, -3 ); /* playlist key item path name item */ vlclua_read_options( p_this, L, &i_options, &ppsz_options ); /* Create input item */ p_input = input_item_NewExt( p_playlist, psz_path, psz_name, i_options, (const char **)ppsz_options, VLC_INPUT_OPTION_TRUSTED, i_duration ); lua_pop( L, 3 ); /* pop "path name item" */ /* playlist key item */ /* Read meta data: item must be on top of stack */ vlclua_read_meta_data( p_this, L, p_input ); /* Read custom meta data: item must be on top of stack*/ vlclua_read_custom_meta_data( p_this, L, p_input ); /* Append item to playlist */ if( p_parent ) /* Add to node */ { input_item_CopyOptions( p_parent, p_input ); input_item_node_AppendItem( p_parent_node, p_input ); } else /* Play or Enqueue (preparse) */ /* FIXME: playlist_AddInput() can fail */ playlist_AddInput( p_playlist, p_input, PLAYLIST_APPEND | ( b_play ? PLAYLIST_GO : PLAYLIST_PREPARSE ), PLAYLIST_END, true, false ); i_count ++; /* increment counter */ vlc_gc_decref( p_input ); while( i_options > 0 ) free( ppsz_options[--i_options] ); free( ppsz_options ); } else { lua_pop( L, 1 ); /* pop "path" */ msg_Warn( p_this, "Playlist item's path should be a string" ); } /* playlist key item */ } else { msg_Warn( p_this, "Playlist item should be a table" ); } /* <Parse playlist item> */ lua_pop( L, 1 ); /* pop the value, keep the key for * the next lua_next() call */ /* playlist key */ } /* playlist */ if( p_parent ) { if( i_count ) input_item_node_PostAndDelete( p_parent_node ); else input_item_node_Delete( p_parent_node ); } } else { msg_Warn( p_this, "Playlist should be a table." ); } return i_count; }