X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Finput%2Fitem.c;h=58cfc46851a3b78a0b23a01841d69b099818750e;hb=7f71d43e9424959a0514b952bd9c29d08a65e0b0;hp=e8e087df59b73454429610e59fff57857f69146b;hpb=b14d7afaffb17b5aac49207b2ca12e9367f4aaf5;p=vlc diff --git a/src/input/item.c b/src/input/item.c index e8e087df59..58cfc46851 100644 --- a/src/input/item.c +++ b/src/input/item.c @@ -25,50 +25,20 @@ # include "config.h" #endif #include +#include #include #include #include "vlc_playlist.h" #include "vlc_interface.h" +#include +#include #include "item.h" #include "info.h" static int GuessType( const input_item_t *p_item ); -/** Stuff moved out of vlc_input.h -- FIXME: should probably not be inline - * anyway. */ -static inline void input_item_Init( vlc_object_t *p_o, input_item_t *p_i ) -{ - memset( p_i, 0, sizeof(input_item_t) ); - - p_i->psz_name = NULL; - p_i->psz_uri = NULL; - TAB_INIT( p_i->i_es, p_i->es ); - TAB_INIT( p_i->i_options, p_i->ppsz_options ); - p_i->optflagv = NULL, p_i->optflagc = 0; - TAB_INIT( p_i->i_categories, p_i->pp_categories ); - TAB_INIT( p_i->i_epg, p_i->pp_epg ); - - p_i->i_type = ITEM_TYPE_UNKNOWN; - p_i->b_fixed_name = true; - - p_i->p_stats = NULL; - p_i->p_meta = NULL; - - vlc_mutex_init( &p_i->lock ); - vlc_event_manager_t * p_em = &p_i->event_manager; - vlc_event_manager_init( p_em, p_i, p_o ); - vlc_event_manager_register_event_type( p_em, vlc_InputItemMetaChanged ); - vlc_event_manager_register_event_type( p_em, vlc_InputItemSubItemAdded ); - vlc_event_manager_register_event_type( p_em, vlc_InputItemSubItemTreeAdded ); - vlc_event_manager_register_event_type( p_em, vlc_InputItemDurationChanged ); - vlc_event_manager_register_event_type( p_em, vlc_InputItemPreparsedChanged ); - vlc_event_manager_register_event_type( p_em, vlc_InputItemNameChanged ); - vlc_event_manager_register_event_type( p_em, vlc_InputItemInfoChanged ); - vlc_event_manager_register_event_type( p_em, vlc_InputItemErrorWhenReadingChanged ); -} - static inline void input_item_Clean( input_item_t *p_i ) { int i; @@ -215,7 +185,7 @@ void input_item_SetMeta( input_item_t *p_i, vlc_meta_type_t meta_type, const cha } /* FIXME GRRRRRRRRRR args should be in the reverse order to be - * consistant with (nearly?) all or copy funcs */ + * consistent with (nearly?) all or copy funcs */ void input_item_CopyOptions( input_item_t *p_parent, input_item_t *p_child ) { @@ -234,13 +204,17 @@ void input_item_CopyOptions( input_item_t *p_parent, vlc_mutex_unlock( &p_parent->lock ); } -static void notify_subitem_added(input_item_t *p_parent, input_item_t *p_child) +static void post_subitems( input_item_node_t *p_node ) { - /* Notify interested third parties */ - vlc_event_t event; - event.type = vlc_InputItemSubItemAdded; - event.u.input_item_subitem_added.p_new_child = p_child; - vlc_event_send( &p_parent->event_manager, &event ); + for( int i = 0; i < p_node->i_children; i++ ) + { + vlc_event_t event; + event.type = vlc_InputItemSubItemAdded; + event.u.input_item_subitem_added.p_new_child = p_node->pp_children[i]->p_item; + vlc_event_send( &p_node->p_item->event_manager, &event ); + + post_subitems( p_node->pp_children[i] ); + } } /* This won't hold the item, but can tell to interested third parties @@ -249,10 +223,6 @@ static void notify_subitem_added(input_item_t *p_parent, input_item_t *p_child) * the input item children. */ void input_item_PostSubItem( input_item_t *p_parent, input_item_t *p_child ) { - vlc_mutex_lock( &p_parent->lock ); - p_parent->i_type = ITEM_TYPE_PLAYLIST; - vlc_mutex_unlock( &p_parent->lock ); - 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 ); @@ -356,14 +326,17 @@ char *input_item_GetURI( input_item_t *p_i ) vlc_mutex_unlock( &p_i->lock ); return psz_s; } + void input_item_SetURI( input_item_t *p_i, const char *psz_uri ) { - vlc_mutex_lock( &p_i->lock ); + assert( psz_uri ); #ifndef NDEBUG - if( !strstr( psz_uri, "://" ) || strstr( psz_uri, " " ) || strstr( psz_uri, "\"" ) ) - fprintf( stderr, "input_item_SetURI() was likely called with a path. FIXME\n" ); + if( !strstr( psz_uri, "://" ) + || strchr( psz_uri, ' ' ) || strchr( psz_uri, '"' ) ) + fprintf( stderr, "Warning: %s(\"%s\"): file path instead of URL.\n", + __func__, psz_uri ); #endif - + vlc_mutex_lock( &p_i->lock ); free( p_i->psz_uri ); p_i->psz_uri = strdup( psz_uri ); @@ -383,7 +356,10 @@ void input_item_SetURI( input_item_t *p_i, const char *psz_uri ) /* Make the name more readable */ if( p_i->psz_name ) + { decode_URI( p_i->psz_name ); + EnsureUTF8( p_i->psz_name ); + } } else { /* Strip login and password from title */ @@ -737,6 +713,9 @@ void input_item_SetEpg( input_item_t *p_item, const vlc_epg_t *p_update ) vlc_mutex_unlock( &p_item->lock ); + if( !p_epg ) + return; + #ifdef EPG_DEBUG char *psz_epg; if( asprintf( &psz_epg, "EPG %s", p_epg->psz_name ? p_epg->psz_name : "unknown" ) < 0 ) @@ -812,63 +791,106 @@ void input_item_SetEpgOffline( input_item_t *p_item ) vlc_event_send( &p_item->event_manager, &event ); } - -input_item_t *__input_item_NewExt( vlc_object_t *p_obj, const char *psz_uri, - const char *psz_name, - int i_options, - const char *const *ppsz_options, - unsigned i_option_flags, - mtime_t i_duration ) +input_item_t *input_item_NewExt( const char *psz_uri, + const char *psz_name, + int i_options, + const char *const *ppsz_options, + unsigned i_option_flags, + mtime_t i_duration ) { - return input_item_NewWithType( p_obj, psz_uri, psz_name, + return input_item_NewWithType( psz_uri, psz_name, i_options, ppsz_options, i_option_flags, i_duration, ITEM_TYPE_UNKNOWN ); } -input_item_t *input_item_NewWithType( vlc_object_t *p_obj, const char *psz_uri, - const char *psz_name, - int i_options, - const char *const *ppsz_options, - unsigned i_option_flags, - mtime_t i_duration, - int i_type ) +input_item_t * +input_item_NewWithType( const char *psz_uri, const char *psz_name, + int i_options, const char *const *ppsz_options, + unsigned flags, mtime_t duration, int type ) { - libvlc_priv_t *priv = libvlc_priv (p_obj->p_libvlc); - static vlc_mutex_t input_id_lock = VLC_STATIC_MUTEX; + static vlc_atomic_t last_input_id = VLC_ATOMIC_INIT(0); - input_item_t* p_input = malloc( sizeof(input_item_t ) ); + input_item_t* p_input = calloc( 1, sizeof( *p_input ) ); if( !p_input ) return NULL; + vlc_event_manager_t * p_em = &p_input->event_manager; - input_item_Init( p_obj, p_input ); + p_input->i_id = vlc_atomic_inc(&last_input_id); vlc_gc_init( p_input, input_item_Destroy ); + vlc_mutex_init( &p_input->lock ); - vlc_mutex_lock( &input_id_lock ); - p_input->i_id = ++priv->i_last_input_id; - vlc_mutex_unlock( &input_id_lock ); - - p_input->b_fixed_name = false; - - p_input->i_type = i_type; - p_input->b_prefers_tree = false; + p_input->psz_name = NULL; + if( psz_name ) + input_item_SetName( p_input, psz_name ); + p_input->psz_uri = NULL; if( psz_uri ) input_item_SetURI( p_input, psz_uri ); + else + p_input->i_type = ITEM_TYPE_UNKNOWN; - if( i_type != ITEM_TYPE_UNKNOWN ) - p_input->i_type = i_type; + TAB_INIT( p_input->i_options, p_input->ppsz_options ); + p_input->optflagc = 0; + p_input->optflagv = NULL; + for( int i = 0; i < i_options; i++ ) + input_item_AddOption( p_input, ppsz_options[i], flags ); - if( psz_name ) - input_item_SetName( p_input, psz_name ); + p_input->i_duration = duration; + TAB_INIT( p_input->i_categories, p_input->pp_categories ); + TAB_INIT( p_input->i_es, p_input->es ); + p_input->p_stats = NULL; + p_input->i_nb_played = 0; + p_input->p_meta = NULL; + TAB_INIT( p_input->i_epg, p_input->pp_epg ); - p_input->i_duration = i_duration; + vlc_event_manager_init( p_em, p_input ); + vlc_event_manager_register_event_type( p_em, vlc_InputItemMetaChanged ); + vlc_event_manager_register_event_type( p_em, vlc_InputItemSubItemAdded ); + vlc_event_manager_register_event_type( p_em, vlc_InputItemSubItemTreeAdded ); + vlc_event_manager_register_event_type( p_em, vlc_InputItemDurationChanged ); + vlc_event_manager_register_event_type( p_em, vlc_InputItemPreparsedChanged ); + vlc_event_manager_register_event_type( p_em, vlc_InputItemNameChanged ); + vlc_event_manager_register_event_type( p_em, vlc_InputItemInfoChanged ); + vlc_event_manager_register_event_type( p_em, vlc_InputItemErrorWhenReadingChanged ); - for( int i = 0; i < i_options; i++ ) - input_item_AddOption( p_input, ppsz_options[i], i_option_flags ); + if( type != ITEM_TYPE_UNKNOWN ) + p_input->i_type = type; + p_input->b_fixed_name = false; + p_input->b_error_when_reading = false; return p_input; } +input_item_t *input_item_Copy( input_item_t *p_input ) +{ + vlc_mutex_lock( &p_input->lock ); + + input_item_t *p_new_input = + input_item_NewWithType( p_input->psz_uri, p_input->psz_name, + 0, NULL, 0, p_input->i_duration, + p_input->i_type ); + + if( p_new_input ) + { + for( int i = 0 ; i< p_input->i_options; i++ ) + { + input_item_AddOption( p_new_input, + p_input->ppsz_options[i], + p_input->optflagv[i] ); + } + + if( p_input->p_meta ) + { + p_new_input->p_meta = vlc_meta_New(); + vlc_meta_Merge( p_new_input->p_meta, p_input->p_meta ); + } + } + + vlc_mutex_unlock( &p_input->lock ); + + return p_new_input; +} + struct item_type_entry { const char psz_scheme[7]; @@ -894,18 +916,25 @@ static int GuessType( const input_item_t *p_item ) { "bd", ITEM_TYPE_DISC }, { "cable", ITEM_TYPE_CARD }, { "cdda", ITEM_TYPE_CDDA }, + { "cqam", ITEM_TYPE_CARD }, { "dc1394", ITEM_TYPE_CARD }, { "dccp", ITEM_TYPE_NET }, + { "deckli", ITEM_TYPE_CARD }, /* decklink */ { "dir", ITEM_TYPE_DIRECTORY }, { "dshow", ITEM_TYPE_CARD }, { "dv", ITEM_TYPE_CARD }, { "dvb", ITEM_TYPE_CARD }, { "dvd", ITEM_TYPE_DISC }, + { "dtv", ITEM_TYPE_CARD }, + { "eyetv", ITEM_TYPE_CARD }, + { "fd", ITEM_TYPE_UNKNOWN }, { "ftp", ITEM_TYPE_NET }, { "http", ITEM_TYPE_NET }, { "icyx", ITEM_TYPE_NET }, + { "imem", ITEM_TYPE_UNKNOWN }, { "itpc", ITEM_TYPE_NET }, { "jack", ITEM_TYPE_CARD }, + { "linsys", ITEM_TYPE_CARD }, { "live", ITEM_TYPE_NET }, /* livedotcom */ { "mms", ITEM_TYPE_NET }, { "mtp", ITEM_TYPE_DISC }, @@ -921,6 +950,8 @@ static int GuessType( const input_item_t *p_item ) { "satell", ITEM_TYPE_CARD }, /* sattelite */ { "screen", ITEM_TYPE_CARD }, { "sdp", ITEM_TYPE_NET }, + { "sftp", ITEM_TYPE_NET }, + { "shm", ITEM_TYPE_CARD }, { "smb", ITEM_TYPE_NET }, { "svcd", ITEM_TYPE_DISC }, { "tcp", ITEM_TYPE_NET }, @@ -962,29 +993,27 @@ input_item_node_t *input_item_node_Create( input_item_t *p_input ) static void RecursiveNodeDelete( input_item_node_t *p_node ) { - for( int i = 0; i < p_node->i_children; i++ ) - RecursiveNodeDelete( p_node->pp_children[i] ); + for( int i = 0; i < p_node->i_children; i++ ) + RecursiveNodeDelete( p_node->pp_children[i] ); - vlc_gc_decref( p_node->p_item ); - free( p_node->pp_children ); - free( p_node ); + vlc_gc_decref( p_node->p_item ); + free( p_node->pp_children ); + free( p_node ); } void input_item_node_Delete( input_item_node_t *p_node ) { - if( p_node->p_parent ) - { - for( int i = 0; i < p_node->p_parent->i_children; i++ ) - if( p_node->p_parent->pp_children[i] == p_node ) - { - REMOVE_ELEM( p_node->p_parent->pp_children, - p_node->p_parent->i_children, - i ); - break; - } - } - - RecursiveNodeDelete( p_node ); + if( p_node->p_parent ) + for( int i = 0; i < p_node->p_parent->i_children; i++ ) + if( p_node->p_parent->pp_children[i] == p_node ) + { + REMOVE_ELEM( p_node->p_parent->pp_children, + p_node->p_parent->i_children, + i ); + break; + } + + RecursiveNodeDelete( p_node ); } input_item_node_t *input_item_node_AppendItem( input_item_node_t *p_node, input_item_t *p_item ) @@ -997,8 +1026,6 @@ input_item_node_t *input_item_node_AppendItem( input_item_node_t *p_node, input_ void input_item_node_AppendNode( input_item_node_t *p_parent, input_item_node_t *p_child ) { - notify_subitem_added(p_parent->p_item, p_child->p_item); - assert( p_parent && p_child && p_child->p_parent == NULL ); INSERT_ELEM( p_parent->pp_children, p_parent->i_children, @@ -1009,10 +1036,44 @@ void input_item_node_AppendNode( input_item_node_t *p_parent, input_item_node_t void input_item_node_PostAndDelete( input_item_node_t *p_root ) { - vlc_event_t event; - event.type = vlc_InputItemSubItemTreeAdded; - event.u.input_item_subitem_tree_added.p_root = p_root; - vlc_event_send( &p_root->p_item->event_manager, &event ); + post_subitems( p_root ); + + vlc_event_t event; + event.type = vlc_InputItemSubItemTreeAdded; + event.u.input_item_subitem_tree_added.p_root = p_root; + vlc_event_send( &p_root->p_item->event_manager, &event ); + + input_item_node_Delete( p_root ); +} + +/* Called by es_out when a new Elementary Stream is added or updated. */ +void input_item_UpdateTracksInfo(input_item_t *item, const es_format_t *fmt) +{ + int i; + es_format_t *fmt_copy = malloc(sizeof *fmt_copy); + if (!fmt_copy) + return; + + es_format_Copy(fmt_copy, fmt); + /* XXX: we could free p_extra to save memory, we will likely not need + * the decoder specific data */ + + vlc_mutex_lock( &item->lock ); + + for( i = 0; i < item->i_es; i++ ) + { + if (item->es[i]->i_id != fmt->i_id) + continue; + + /* We've found the right ES, replace it */ + es_format_Clean(item->es[i]); + free(item->es[i]); + item->es[i] = fmt_copy; + vlc_mutex_unlock( &item->lock ); + return; + } - input_item_node_Delete( p_root ); + /* ES not found, insert it */ + TAB_APPEND(item->i_es, item->es, fmt_copy); + vlc_mutex_unlock( &item->lock ); }