X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fplaylist%2Fplaylist.c;h=23b67811573d433e056f6bcf59a7321afc7c0ce7;hb=82f53048eacbf2c96f23f944707676ea7796b699;hp=a6b1e843359b972e8dbcaebe5811ba6304e58eaa;hpb=382926a8c14406854dae7eb79de693ffe1284ed0;p=vlc diff --git a/src/playlist/playlist.c b/src/playlist/playlist.c index a6b1e84335..23b6781157 100644 --- a/src/playlist/playlist.c +++ b/src/playlist/playlist.c @@ -37,13 +37,15 @@ #define TITLE_ALL N_( "All items, unsorted" ) #define PLAYLIST_PROFILE 1 +#undef PLAYLIST_DEBUG /***************************************************************************** * Local prototypes *****************************************************************************/ static void RunThread ( playlist_t * ); +static void RunPreparse( playlist_preparse_t * ); static playlist_item_t * NextItem ( playlist_t * ); -static void PlayItem ( playlist_t *, playlist_item_t * ); +static int PlayItem ( playlist_t *, playlist_item_t * ); static int ItemChange( vlc_object_t *, const char *, vlc_value_t, vlc_value_t, void * ); @@ -60,7 +62,6 @@ int playlist_vaControl( playlist_t * p_playlist, int i_query, va_list args ); */ playlist_t * __playlist_Create ( vlc_object_t *p_parent ) { - int i_index; playlist_t *p_playlist; playlist_view_t *p_view; vlc_value_t val; @@ -82,6 +83,12 @@ playlist_t * __playlist_Create ( vlc_object_t *p_parent ) val.i_int = -1; var_Set( p_playlist, "item-change", val ); + var_Create( p_playlist, "item-deleted", VLC_VAR_INTEGER ); + val.i_int = -1; + var_Set( p_playlist, "item-deleted", val ); + + var_Create( p_playlist, "item-append", VLC_VAR_ADDRESS ); + var_Create( p_playlist, "playlist-current", VLC_VAR_INTEGER ); val.i_int = -1; var_Set( p_playlist, "playlist-current", val ); @@ -120,6 +127,7 @@ playlist_t * __playlist_Create ( vlc_object_t *p_parent ) p_playlist->p_general = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, _( "General" ), p_view->p_root ); + p_playlist->p_general->i_flags |= PLAYLIST_RO_FLAG; /* Set startup status * We set to simple view on startup for interfaces that don't do @@ -145,6 +153,29 @@ playlist_t * __playlist_Create ( vlc_object_t *p_parent ) return NULL; } + /* Preparsing stuff */ + p_playlist->p_preparse = vlc_object_create( p_playlist, + sizeof( playlist_preparse_t ) ); + if( !p_playlist->p_preparse ) + { + msg_Err( p_playlist, "unable to create preparser" ); + vlc_object_destroy( p_playlist ); + return NULL; + } + + p_playlist->p_preparse->i_waiting = 0; + p_playlist->p_preparse->pp_waiting = NULL; + + vlc_object_attach( p_playlist->p_preparse, p_playlist ); + if( vlc_thread_create( p_playlist->p_preparse, "preparser", + RunPreparse, VLC_THREAD_PRIORITY_LOW, VLC_TRUE ) ) + { + msg_Err( p_playlist, "cannot spawn preparse thread" ); + vlc_object_detach( p_playlist->p_preparse ); + vlc_object_destroy( p_playlist->p_preparse ); + return NULL; + } + /* The object has been initialized, now attach it */ vlc_object_attach( p_playlist, p_parent ); @@ -156,8 +187,9 @@ playlist_t * __playlist_Create ( vlc_object_t *p_parent ) * * Delete all items in the playlist and free the playlist structure. * \param p_playlist the playlist structure to destroy + * \return VLC_SUCCESS or an error */ -void playlist_Destroy( playlist_t * p_playlist ) +int playlist_Destroy( playlist_t * p_playlist ) { int i; p_playlist->b_die = 1; @@ -168,8 +200,11 @@ void playlist_Destroy( playlist_t * p_playlist ) p_playlist->pp_sds[i]->psz_module ); } + vlc_thread_join( p_playlist->p_preparse ); vlc_thread_join( p_playlist ); + vlc_object_detach( p_playlist->p_preparse ); + var_Destroy( p_playlist, "intf-change" ); var_Destroy( p_playlist, "item-change" ); var_Destroy( p_playlist, "playlist-current" ); @@ -192,7 +227,10 @@ void playlist_Destroy( playlist_t * p_playlist ) free( p_view ); } + vlc_object_destroy( p_playlist->p_preparse ); vlc_object_destroy( p_playlist ); + + return VLC_SUCCESS; } @@ -221,11 +259,11 @@ int playlist_Control( playlist_t * p_playlist, int i_query, ... ) int playlist_vaControl( playlist_t * p_playlist, int i_query, va_list args ) { - vlc_mutex_lock( &p_playlist->object_lock ); - playlist_view_t *p_view; vlc_value_t val; + vlc_mutex_lock( &p_playlist->object_lock ); + #ifdef PLAYLIST_PROFILE p_playlist->request_date = mdate(); #endif @@ -251,7 +289,14 @@ int playlist_vaControl( playlist_t * p_playlist, int i_query, va_list args ) playlist_item_t *); p_playlist->request.i_view = p_playlist->status.i_view; p_view = playlist_ViewFind( p_playlist, p_playlist->status.i_view ); - p_playlist->request.p_node = p_view->p_root; + if( p_view ) + { + p_playlist->request.p_node = p_view->p_root; + } + else + { + p_playlist->request.p_node = NULL; + } break; case PLAYLIST_VIEWPLAY: @@ -296,6 +341,12 @@ int playlist_vaControl( playlist_t * p_playlist, int i_query, va_list args ) p_playlist->request.i_goto = -1; break; + case PLAYLIST_AUTOPLAY: + p_playlist->status.i_status = PLAYLIST_RUNNING; + + p_playlist->request.b_request = VLC_FALSE; + break; + case PLAYLIST_PAUSE: val.i_int = 0; if( p_playlist->p_input ) @@ -350,6 +401,18 @@ int playlist_vaControl( playlist_t * p_playlist, int i_query, va_list args ) return VLC_SUCCESS; } +int playlist_PreparseEnqueue( playlist_t *p_playlist, + input_item_t *p_item ) +{ + vlc_mutex_lock( &p_playlist->p_preparse->object_lock ); + INSERT_ELEM( p_playlist->p_preparse->pp_waiting, + p_playlist->p_preparse->i_waiting, + p_playlist->p_preparse->i_waiting, + p_item ); + vlc_mutex_unlock( &p_playlist->p_preparse->object_lock ); + return VLC_SUCCESS; +} + /* Destroy remaining objects */ static mtime_t ObjectGarbageCollector( playlist_t *p_playlist, int i_type, @@ -506,10 +569,8 @@ static void RunThread ( playlist_t *p_playlist ) { if( p_autodelete_item ) { - vlc_mutex_unlock( &p_playlist->object_lock ); playlist_Delete( p_playlist, p_autodelete_item->input.i_id ); - vlc_mutex_lock( &p_playlist->object_lock ); p_autodelete_item = NULL; } p_playlist->status.i_status = PLAYLIST_STOPPED; @@ -521,9 +582,7 @@ static void RunThread ( playlist_t *p_playlist ) if( p_autodelete_item ) { - vlc_mutex_unlock( &p_playlist->object_lock ); playlist_Delete( p_playlist, p_autodelete_item->input.i_id ); - vlc_mutex_lock( &p_playlist->object_lock ); p_autodelete_item = NULL; } } @@ -623,6 +682,39 @@ static void RunThread ( playlist_t *p_playlist ) } } +/* Queue for items to preparse */ +static void RunPreparse ( playlist_preparse_t *p_obj ) +{ + playlist_t *p_playlist = (playlist_t *)p_obj->p_parent; + vlc_bool_t b_sleep; + + /* Tell above that we're ready */ + vlc_thread_ready( p_obj ); + + while( !p_playlist->b_die ) + { + vlc_mutex_lock( &p_obj->object_lock ); + + if( p_obj->i_waiting > 0 ) + { + input_item_t *p_current = p_obj->pp_waiting[0]; + REMOVE_ELEM( p_obj->pp_waiting, p_obj->i_waiting, 0 ); + vlc_mutex_unlock( &p_obj->object_lock ); + input_Preparse( p_playlist, p_current ); + var_SetInteger( p_playlist, "item-change", p_current->i_id ); + vlc_mutex_lock( &p_obj->object_lock ); + } + b_sleep = ( p_obj->i_waiting == 0 ); + + vlc_mutex_unlock( &p_obj->object_lock ); + + if( p_obj->i_waiting == 0 ) + { + msleep( INTF_IDLE_SLEEP ); + } + } +} + /***************************************************************************** * NextItem ***************************************************************************** @@ -657,8 +749,7 @@ static playlist_item_t * NextItem( playlist_t *p_playlist ) /* Nothing requested */ if( !p_playlist->request.b_request && p_playlist->status.p_item == NULL ) { - msg_Warn( p_playlist,"nothing requested" ); - return NULL; + msg_Dbg( p_playlist,"nothing requested, starting" ); } /* Repeat and play/stop */ @@ -674,7 +765,7 @@ static playlist_item_t * NextItem( playlist_t *p_playlist ) return NULL; } - if( !p_playlist->request.b_request && + if( !p_playlist->request.b_request && p_playlist->status.p_item && !(p_playlist->status.p_item->i_flags & PLAYLIST_SKIP_FLAG) ) { msg_Dbg( p_playlist, "no-skip mode, stopping") ; @@ -722,6 +813,9 @@ static playlist_item_t * NextItem( playlist_t *p_playlist ) /* We are not playing from a view */ if( p_playlist->request.i_view == -1 ) { +#ifdef PLAYLIST_DEBUG + msg_Dbg( p_playlist, "non-view mode request"); +#endif /* Directly select the item, just like now */ i_skip = p_playlist->request.i_skip; i_goto = p_playlist->request.i_goto; @@ -748,6 +842,9 @@ static playlist_item_t * NextItem( playlist_t *p_playlist ) } else { +#ifdef PLAYLIST_DEBUG + msg_Dbg( p_playlist, "view mode request" ); +#endif p_new = p_playlist->request.p_item; i_skip = p_playlist->request.i_skip; @@ -760,7 +857,11 @@ static playlist_item_t * NextItem( playlist_t *p_playlist ) p_view = playlist_ViewFind( p_playlist,p_playlist->request.i_view ); p_playlist->status.p_node = p_playlist->request.p_node; p_playlist->status.i_view = p_playlist->request.i_view; - if( i_skip > 0 ) + if( !p_view ) + { + msg_Err( p_playlist, "p_view is NULL and should not! (FIXME)" ); + } + else if( i_skip > 0 ) { for( i = i_skip; i > 0 ; i-- ) { @@ -769,7 +870,22 @@ static playlist_item_t * NextItem( playlist_t *p_playlist ) p_view->p_root, p_playlist->request.p_node, p_new ); - if( p_new == NULL ) break; + if( p_new == NULL ) + { + if( b_loop ) + { + p_new = playlist_FindNextFromParent( p_playlist, + p_playlist->request.i_view, + p_view->p_root, + p_playlist->request.p_node, + NULL ); + if( p_new == NULL ) break; + } + else + { + break; + } + } } } else if( i_skip < 0 ) @@ -794,18 +910,27 @@ static playlist_item_t * NextItem( playlist_t *p_playlist ) { p_playlist->request_date = 0; - if( p_playlist->status.i_view == -1 ) { if( p_playlist->i_index + 1 < p_playlist->i_size ) { p_playlist->i_index++; p_new = p_playlist->pp_items[p_playlist->i_index]; + if( !(p_new->i_flags & PLAYLIST_SKIP_FLAG) ) + { + return NULL; + } } else { msg_Dbg( p_playlist,"finished" ); - p_new = NULL; + if( b_loop && p_playlist->i_size > 0) + { + p_playlist->i_index = 0; + p_new = p_playlist->pp_items[0]; + } + else + p_new = NULL; } } /* We are playing with a view */ @@ -814,11 +939,26 @@ static playlist_item_t * NextItem( playlist_t *p_playlist ) playlist_view_t *p_view = playlist_ViewFind( p_playlist, p_playlist->status.i_view ); - p_new = playlist_FindNextFromParent( p_playlist, + if( !p_view ) + { + msg_Err( p_playlist, "p_view is NULL and should not! (FIXME)" ); + } + else + { + p_new = playlist_FindNextFromParent( p_playlist, p_playlist->status.i_view, p_view->p_root, p_playlist->status.p_node, p_playlist->status.p_item ); + if( p_new == NULL && b_loop ) + { + p_new = playlist_FindNextFromParent( p_playlist, + p_playlist->status.i_view, + p_view->p_root, + p_playlist->status.p_node, + NULL ); + } + } } } @@ -831,11 +971,13 @@ static playlist_item_t * NextItem( playlist_t *p_playlist ) } #ifdef PLAYLIST_PROFILE - msg_Dbg(p_playlist,"next item found in "I64Fi " us\n",mdate()-start ); + msg_Dbg(p_playlist,"next item found in "I64Fi " us", mdate()-start ); #endif - if( p_new == NULL ) { msg_Info( p_playlist, "Nothing to play" ); } - + if( p_new == NULL ) + { + msg_Info( p_playlist, "Nothing to play" ); + } return p_new; } @@ -889,16 +1031,18 @@ static void SkipItem( playlist_t *p_playlist, int i_arg ) /***************************************************************************** * PlayItem: start the input thread for an item ****************************************************************************/ -static void PlayItem( playlist_t *p_playlist, playlist_item_t *p_item ) +static int PlayItem( playlist_t *p_playlist, playlist_item_t *p_item ) { vlc_value_t val; - int i; msg_Dbg( p_playlist, "creating new input thread" ); p_item->i_nb_played++; p_playlist->status.p_item = p_item; + p_playlist->i_index = playlist_GetPositionById( p_playlist, + p_item->input.i_id ); + #ifdef PLAYLIST_PROFILE if( p_playlist->request_date != 0 ) { @@ -918,6 +1062,8 @@ static void PlayItem( playlist_t *p_playlist, playlist_item_t *p_item ) var_Set( p_playlist, "playlist-current", val); vlc_mutex_lock( &p_playlist->object_lock); + return VLC_SUCCESS; + } /* Forward item change from input */ @@ -925,14 +1071,13 @@ static int ItemChange( vlc_object_t *p_obj, const char *psz_var, vlc_value_t oldval, vlc_value_t newval, void *param ) { playlist_t *p_playlist = (playlist_t *)param; - int i_index; //p_playlist->b_need_update = VLC_TRUE; var_SetInteger( p_playlist, "item-change", newval.i_int ); /* Update view */ /* FIXME: Make that automatic */ - playlist_ViewUpdate( p_playlist, VIEW_S_AUTHOR ); +// playlist_ViewUpdate( p_playlist, VIEW_S_AUTHOR ); return VLC_SUCCESS; }