static void add_to_playlist(intf_thread_t *intf, const char *uri, bool play_now, int options_count, const char *const *options) { vlc_playlist_t *playlist = vlc_intf_GetMainPlaylist(intf); input_item_t *media = input_item_New(uri, NULL); if (!media) return; input_item_AddOptions(media, options_count, options, VLC_INPUT_OPTION_TRUSTED); vlc_playlist_Lock(playlist); vlc_playlist_AppendOne(playlist, media); if (play_now) vlc_playlist_Start(playlist); vlc_playlist_Unlock(playlist); input_item_Release(media); }
/** * Add a MRL into the playlist or the media library, duration and options given * * \param p_playlist the playlist to add into * \param psz_uri the mrl to add to the playlist * \param psz_name a text giving a name or description of this item * \param i_mode the mode used when adding * \param i_pos the position in the playlist where to add. If this is * PLAYLIST_END the item will be added at the end of the playlist * regardless of its size * \param i_duration length of the item in milliseconds. * \param i_options the number of options * \param ppsz_options an array of options * \param i_option_flags options flags * \param b_playlist TRUE for playlist, FALSE for media library * \param b_locked TRUE if the playlist is locked * \return VLC_SUCCESS or a VLC error code */ int playlist_AddExt( playlist_t *p_playlist, const char * psz_uri, const char *psz_name, int i_mode, int i_pos, mtime_t i_duration, int i_options, const char *const *ppsz_options, unsigned i_option_flags, bool b_playlist, bool b_locked ) { int i_ret; input_item_t *p_input; p_input = input_item_NewExt( psz_uri, psz_name, i_duration, ITEM_TYPE_UNKNOWN, ITEM_NET_UNKNOWN ); if( p_input == NULL ) return VLC_ENOMEM; input_item_AddOptions( p_input, i_options, ppsz_options, i_option_flags ); i_ret = playlist_AddInput( p_playlist, p_input, i_mode, i_pos, b_playlist, b_locked ); vlc_gc_decref( p_input ); 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 */ }
/** * 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 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 ); vlc_xml_decode( 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 ); vlc_xml_decode( 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_duration, ITEM_TYPE_UNKNOWN, ITEM_NET_UNKNOWN ); if( p_entry == NULL ) goto end; input_item_AddOptions( p_entry, i_options, (const char **)ppsz_options, VLC_INPUT_OPTION_TRUSTED ); input_item_CopyOptions( p_entry, p_current_input ); /* 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 ); input_item_Release( p_entry ); end: 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 ); }
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 ) ) { char *psz_oldurl = NULL; 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 */ if (p_parent) { psz_oldurl = input_item_GetURI( p_parent ); msg_Dbg( p_this, "old path: %s", psz_oldurl ); } 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." ); } /* 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( psz_path, psz_name, i_duration, ITEM_TYPE_UNKNOWN, ITEM_NET_UNKNOWN ); input_item_AddOptions( p_input, i_options, (const char **)ppsz_options, VLC_INPUT_OPTION_TRUSTED ); 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 ); /* copy the original URL to the meta data, if "URL" is still empty */ char* url = input_item_GetURL( p_input ); if( url == NULL && p_parent) { EnsureUTF8( psz_oldurl ); msg_Dbg( p_this, "meta-URL: %s", psz_oldurl ); input_item_SetURL ( p_input, psz_oldurl ); } free( psz_oldurl ); free( url ); /* copy the psz_name to the meta data, if "Title" is still empty */ char* title = input_item_GetTitle( p_input ); if( title == NULL ) input_item_SetTitle ( p_input, psz_name ); free( title ); /* 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_input, p_parent ); 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, ( b_play ? PLAYLIST_GO : 0 ), true ); 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; }