X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fplaylist%2Fitem.c;h=28634fe85c32252daee5f4a6385b3cf314882d3e;hb=68456f6755c903d008e5efc0695e1f4957f9d3b8;hp=ff67441fb0d41a1b2ddb3a02b24631c196b56cc4;hpb=d9d0e354a39aaa714e871d6f9fd5c2984fccf579;p=vlc diff --git a/src/playlist/item.c b/src/playlist/item.c index ff67441fb0..28634fe85c 100644 --- a/src/playlist/item.c +++ b/src/playlist/item.c @@ -34,6 +34,93 @@ static void ChangeToNode( playlist_t *p_playlist, playlist_item_t *p_item ); static int DeleteInner( playlist_t * p_playlist, playlist_item_t *p_item, vlc_bool_t b_stop ); +/***************************************************************************** + * An input item has gained a subitem (Event Callback) + *****************************************************************************/ +static void input_item_subitem_added( const vlc_event_t * p_event, + void * user_data ) +{ + playlist_item_t *p_parent_playlist_item = user_data; + playlist_t * p_playlist = p_parent_playlist_item->p_playlist; + input_item_t * p_parent, * p_child; + playlist_item_t * p_child_in_category; + playlist_item_t * p_item_in_category; + vlc_bool_t b_play; + + p_parent = p_event->p_obj; + p_child = p_event->u.input_item_subitem_added.p_new_child; + + PL_LOCK; + b_play = var_CreateGetBool( p_playlist, "playlist-autostart" ); + + /* This part is really hakish, but this playlist system isn't simple */ + /* First check if we haven't already added the item as we are + * listening using the onelevel and the category representent + * (Because of the playlist design) */ + p_child_in_category = playlist_ItemFindFromInputAndRoot( + p_playlist, p_child->i_id, + p_playlist->p_root_category, + VLC_FALSE /* Only non-node */ ); + + if( !p_child_in_category ) + { + /* Then, transform to a node if needed */ + p_item_in_category = playlist_ItemFindFromInputAndRoot( + p_playlist, p_parent->i_id, + p_playlist->p_root_category, + VLC_FALSE /* Only non-node */ ); + if( !p_item_in_category ) + { + /* Item may have been removed */ + PL_UNLOCK; + return; + } + + b_play = b_play && p_item_in_category == p_playlist->status.p_item; + + /* If this item is already a node don't transform it */ + if( p_item_in_category->i_children == -1 ) + { + p_item_in_category = playlist_ItemToNode( p_playlist, + p_item_in_category, VLC_TRUE ); + p_item_in_category->p_input->i_type = ITEM_TYPE_PLAYLIST; + } + + playlist_BothAddInput( p_playlist, p_child, p_item_in_category, + PLAYLIST_APPEND | PLAYLIST_SPREPARSE , PLAYLIST_END, + NULL, NULL, VLC_TRUE ); + + if( b_play ) + { + playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, + VLC_TRUE, p_item_in_category, NULL ); + } + } + + PL_UNLOCK; + +} + +/***************************************************************************** + * Listen to vlc_InputItemAddSubItem event + *****************************************************************************/ +static void install_input_item_observer( playlist_item_t * p_item, + input_item_t * p_input ) +{ + vlc_event_attach( &p_input->event_manager, vlc_InputItemSubItemAdded, + input_item_subitem_added, + p_item ); +} + +static void uninstall_input_item_observer( playlist_item_t * p_item, + input_item_t * p_input ) +{ + vlc_event_detach( &p_input->event_manager, vlc_InputItemSubItemAdded, + input_item_subitem_added, + p_item ); + +} + /***************************************************************************** * Playlist item creation *****************************************************************************/ @@ -56,8 +143,7 @@ playlist_item_t *__playlist_ItemNewFromInput( vlc_object_t *p_obj, input_item_t *p_input ) { DECMALLOC_NULL( p_item, playlist_item_t ); - playlist_t *p_playlist = p_obj->p_libvlc->p_playlist; - vlc_object_yield( p_playlist ); + playlist_t *p_playlist = pl_Yield( p_obj ); p_item->p_input = p_input; vlc_gc_incref( p_item->p_input ); @@ -68,8 +154,11 @@ playlist_item_t *__playlist_ItemNewFromInput( vlc_object_t *p_obj, p_item->i_children = -1; p_item->pp_children = NULL; p_item->i_flags = 0; + p_item->p_playlist = p_playlist; + + install_input_item_observer( p_item, p_input ); - vlc_object_release( p_playlist ); + pl_Release( p_item->p_playlist ); return p_item; } @@ -81,6 +170,8 @@ playlist_item_t *__playlist_ItemNewFromInput( vlc_object_t *p_obj, /** Delete a playlist item and detach its input item */ int playlist_ItemDelete( playlist_item_t *p_item ) { + uninstall_input_item_observer( p_item, p_item->p_input ); + vlc_gc_decref( p_item->p_input ); free( p_item ); return VLC_SUCCESS; @@ -109,6 +200,18 @@ static int DeleteFromInput( playlist_t *p_playlist, int i_input_id, return VLC_EGENERIC; } +/** Remove an input item when it appears from a root playlist item */ +int playlist_DeleteInputInParent( playlist_t *p_playlist, int i_input_id, + playlist_item_t *p_root, vlc_bool_t b_locked ) +{ + int i_ret; + if( !b_locked ) PL_LOCK; + i_ret = DeleteFromInput( p_playlist, i_input_id, + p_root, VLC_TRUE ); + if( !b_locked ) PL_UNLOCK; + return i_ret; +} + /** Remove an input item from ONELEVEL and CATEGORY */ int playlist_DeleteFromInput( playlist_t *p_playlist, int i_input_id, vlc_bool_t b_locked ) @@ -350,7 +453,10 @@ playlist_item_t *playlist_ItemToNode( playlist_t *p_playlist, p_playlist->p_root_onelevel, VLC_TRUE ); assert( p_item_in_one ); + + /* We already have it, and there is nothing more to do */ ChangeToNode( p_playlist, p_item_in_category ); + /* Item in one is a root, change it to node */ if( p_item_in_one->p_parent == p_playlist->p_root_onelevel ) ChangeToNode( p_playlist, p_item_in_one ); @@ -511,8 +617,7 @@ int playlist_ItemSetName( playlist_item_t *p_item, const char *psz_name ) { if( psz_name && p_item ) { - if( p_item->p_input->psz_name ) free( p_item->p_input->psz_name ); - p_item->p_input->psz_name = strdup( psz_name ); + input_item_SetName( p_item->p_input, psz_name ); return VLC_SUCCESS; } return VLC_EGENERIC; @@ -553,21 +658,19 @@ static void GoAndPreparse( playlist_t *p_playlist, int i_mode, vlc_cond_signal( &p_playlist->object_wait ); } /* Preparse if PREPARSE or SPREPARSE & not enough meta */ + char *psz_artist = input_item_GetArtist( p_item_cat->p_input ); + char *psz_album = input_item_GetAlbum( p_item_cat->p_input ); if( p_playlist->b_auto_preparse && (i_mode & PLAYLIST_PREPARSE || ( i_mode & PLAYLIST_SPREPARSE && - ( !p_item_cat->p_input->p_meta || (p_item_cat->p_input->p_meta && - ( EMPTY_STR( p_item_cat->p_input->p_meta->psz_artist ) || - EMPTY_STR( p_item_cat->p_input->p_meta->psz_album ) ) - ) - ) + ( EMPTY_STR( psz_artist ) || ( EMPTY_STR( psz_album ) ) ) ) ) ) playlist_PreparseEnqueue( p_playlist, p_item_cat->p_input ); /* If we already have it, signal it */ - else if( p_item_cat->p_input->p_meta && - !EMPTY_STR( p_item_cat->p_input->p_meta->psz_artist ) && - !EMPTY_STR( p_item_cat->p_input->p_meta->psz_album ) ) - p_item_cat->p_input->p_meta->i_status = ITEM_PREPARSED; + else if( !EMPTY_STR( psz_artist ) && !EMPTY_STR( psz_album ) ) + input_item_SetPreparsed( p_item_cat->p_input, VLC_TRUE ); + free( psz_artist ); + free( psz_album ); } /* Add the playlist item to the requested node and fire a notification */