/** * Run the main control thread itself */ static void *Thread ( void *data ) { playlist_t *p_playlist = data; playlist_private_t *p_sys = pl_priv(p_playlist); playlist_Lock( p_playlist ); while( vlc_object_alive( p_playlist ) || p_sys->p_input ) { /* FIXME: what's that ! */ if( p_sys->b_reset_currently_playing && mdate() - p_sys->last_rebuild_date > 30000 ) // 30 ms { ResetCurrentlyPlaying( p_playlist, get_current_status_item( p_playlist ) ); p_sys->last_rebuild_date = mdate(); } /* If there is an input, check that it doesn't need to die. */ while( !LoopInput( p_playlist ) ) vlc_cond_wait( &p_sys->signal, &p_sys->lock ); LoopRequest( p_playlist ); } playlist_Unlock( p_playlist ); return NULL; }
static int RandomCallback( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *a ) { (void)psz_cmd; (void)oldval; (void)newval; (void)a; playlist_t *p_playlist = (playlist_t*)p_this; bool random = newval.b_bool; PL_LOCK; if( !random ) { pl_priv(p_playlist)->b_reset_currently_playing = true; vlc_cond_signal( &pl_priv(p_playlist)->signal ); } else { /* Shuffle and sync the playlist on activation of random mode. * This preserves the current playing item, so that the user * can return to it if needed. (See #4472) */ playlist_private_t *p_sys = pl_priv(p_playlist); playlist_item_t *p_new = p_sys->status.p_item; ResetCurrentlyPlaying( p_playlist, NULL ); if( p_new ) ResyncCurrentIndex( p_playlist, p_new ); } PL_UNLOCK; return VLC_SUCCESS; }
/** * Compute the next playlist item depending on * the playlist course mode (forward, backward, random, view,...). * * \param p_playlist the playlist object * \return nothing */ static playlist_item_t *NextItem( playlist_t *p_playlist ) { playlist_private_t *p_sys = pl_priv(p_playlist); playlist_item_t *p_new = NULL; /* Handle quickly a few special cases */ /* No items to play */ if( p_playlist->items.i_size == 0 ) { msg_Info( p_playlist, "playlist is empty" ); return NULL; } /* Start the real work */ if( p_sys->request.b_request ) { p_new = p_sys->request.p_item; int i_skip = p_sys->request.i_skip; PL_DEBUG( "processing request item: %s, node: %s, skip: %i", PLI_NAME( p_sys->request.p_item ), PLI_NAME( p_sys->request.p_node ), i_skip ); if( p_sys->request.p_node && p_sys->request.p_node != get_current_status_node( p_playlist ) ) { set_current_status_node( p_playlist, p_sys->request.p_node ); p_sys->request.p_node = NULL; p_sys->b_reset_currently_playing = true; } /* If we are asked for a node, go to it's first child */ if( i_skip == 0 && ( p_new == NULL || p_new->i_children != -1 ) ) { i_skip++; if( p_new != NULL ) { p_new = playlist_GetNextLeaf( p_playlist, p_new, NULL, true, false ); for( int i = 0; i < p_playlist->current.i_size; i++ ) { if( p_new == ARRAY_VAL( p_playlist->current, i ) ) { p_playlist->i_current_index = i; i_skip = 0; } } } } if( p_sys->b_reset_currently_playing ) /* A bit too bad to reset twice ... */ ResetCurrentlyPlaying( p_playlist, p_new ); else if( p_new ) ResyncCurrentIndex( p_playlist, p_new ); else p_playlist->i_current_index = -1; if( p_playlist->current.i_size && (i_skip > 0) ) { if( p_playlist->i_current_index < -1 ) p_playlist->i_current_index = -1; for( int i = i_skip; i > 0 ; i-- ) { p_playlist->i_current_index++; if( p_playlist->i_current_index >= p_playlist->current.i_size ) { PL_DEBUG( "looping - restarting at beginning of node" ); p_playlist->i_current_index = 0; } } p_new = ARRAY_VAL( p_playlist->current, p_playlist->i_current_index ); } else if( p_playlist->current.i_size && (i_skip < 0) ) { for( int i = i_skip; i < 0 ; i++ ) { p_playlist->i_current_index--; if( p_playlist->i_current_index <= -1 ) { PL_DEBUG( "looping - restarting at end of node" ); p_playlist->i_current_index = p_playlist->current.i_size-1; } } p_new = ARRAY_VAL( p_playlist->current, p_playlist->i_current_index ); } /* Clear the request */ p_sys->request.b_request = false; } /* "Automatic" item change ( next ) */ else { bool b_loop = var_GetBool( p_playlist, "loop" ); bool b_repeat = var_GetBool( p_playlist, "repeat" ); bool b_playstop = var_GetBool( p_playlist, "play-and-stop" ); /* Repeat and play/stop */ if( b_repeat && get_current_status_item( p_playlist ) ) { msg_Dbg( p_playlist,"repeating item" ); return get_current_status_item( p_playlist ); } if( b_playstop ) { msg_Dbg( p_playlist,"stopping (play and stop)" ); return NULL; } /* */ if( get_current_status_item( p_playlist ) ) { playlist_item_t *p_parent = get_current_status_item( p_playlist ); while( p_parent ) { if( p_parent->i_flags & PLAYLIST_SKIP_FLAG ) { msg_Dbg( p_playlist, "blocking item, stopping") ; return NULL; } p_parent = p_parent->p_parent; } } PL_DEBUG( "changing item without a request (current %i/%i)", p_playlist->i_current_index, p_playlist->current.i_size ); /* Cant go to next from current item */ if( get_current_status_item( p_playlist ) && get_current_status_item( p_playlist )->i_flags & PLAYLIST_SKIP_FLAG ) return NULL; if( p_sys->b_reset_currently_playing ) ResetCurrentlyPlaying( p_playlist, get_current_status_item( p_playlist ) ); p_playlist->i_current_index++; assert( p_playlist->i_current_index <= p_playlist->current.i_size ); if( p_playlist->i_current_index == p_playlist->current.i_size ) { if( !b_loop || p_playlist->current.i_size == 0 ) return NULL; p_playlist->i_current_index = 0; } PL_DEBUG( "using item %i", p_playlist->i_current_index ); if ( p_playlist->current.i_size == 0 ) return NULL; p_new = ARRAY_VAL( p_playlist->current, p_playlist->i_current_index ); /* The new item can't be autoselected */ if( p_new != NULL && p_new->i_flags & PLAYLIST_SKIP_FLAG ) return NULL; } return p_new; }