+ vlc_mutex_lock( &p_ts->lock );
+
+ if( !p_ts->p_storage_w || TsStorageIsFull( p_ts->p_storage_w, p_cmd ) )
+ {
+ ts_storage_t *p_storage = TsStorageNew( p_ts->psz_tmp_path, p_ts->i_tmp_size_max );
+
+ if( !p_storage )
+ {
+ CmdClean( p_cmd );
+ vlc_mutex_unlock( &p_ts->lock );
+ /* TODO warn the user (but only once) */
+ return;
+ }
+
+ if( !p_ts->p_storage_w )
+ {
+ p_ts->p_storage_r = p_ts->p_storage_w = p_storage;
+ }
+ else
+ {
+ TsStoragePack( p_ts->p_storage_w );
+ p_ts->p_storage_w->p_next = p_storage;
+ p_ts->p_storage_w = p_storage;
+ }
+ }
+
+ /* TODO return error and warn the user (but only once) */
+ TsStoragePushCmd( p_ts->p_storage_w, p_cmd, p_ts->p_storage_r == p_ts->p_storage_w );
+
+ vlc_cond_signal( &p_ts->wait );
+
+ vlc_mutex_unlock( &p_ts->lock );
+}
+static int TsPopCmdLocked( ts_thread_t *p_ts, ts_cmd_t *p_cmd, bool b_flush )
+{
+ vlc_assert_locked( &p_ts->lock );
+
+ if( TsStorageIsEmpty( p_ts->p_storage_r ) )
+ return VLC_EGENERIC;
+
+ TsStoragePopCmd( p_ts->p_storage_r, p_cmd, b_flush );
+
+ while( p_ts->p_storage_r && TsStorageIsEmpty( p_ts->p_storage_r ) )
+ {
+ ts_storage_t *p_next = p_ts->p_storage_r->p_next;
+ if( !p_next )
+ break;
+
+ TsStorageDelete( p_ts->p_storage_r );
+ p_ts->p_storage_r = p_next;
+ }
+
+ return VLC_SUCCESS;
+}
+static bool TsHasCmd( ts_thread_t *p_ts )
+{
+ bool b_cmd;
+
+ vlc_mutex_lock( &p_ts->lock );
+ b_cmd = TsStorageIsEmpty( p_ts->p_storage_r );
+ vlc_mutex_unlock( &p_ts->lock );
+
+ return b_cmd;
+}
+static bool TsIsUnused( ts_thread_t *p_ts )
+{
+ bool b_unused;
+
+ vlc_mutex_lock( &p_ts->lock );
+ b_unused = !p_ts->b_paused &&
+ p_ts->i_rate == p_ts->i_rate_source &&
+ TsStorageIsEmpty( p_ts->p_storage_r );
+ vlc_mutex_unlock( &p_ts->lock );
+
+ return b_unused;
+}
+static int TsChangePause( ts_thread_t *p_ts, bool b_source_paused, bool b_paused, mtime_t i_date )
+{
+ vlc_mutex_lock( &p_ts->lock );
+
+ int i_ret;
+ if( b_paused )
+ {
+ assert( !b_source_paused );
+ i_ret = es_out_SetPauseState( p_ts->p_out, true, true, i_date );
+ }
+ else
+ {
+ i_ret = es_out_SetPauseState( p_ts->p_out, false, false, i_date );
+ }
+
+ if( !i_ret )
+ {
+ if( !b_paused )
+ {
+ assert( p_ts->i_pause_date > 0 );
+
+ p_ts->i_cmd_delay += i_date - p_ts->i_pause_date;
+ }
+
+ p_ts->b_paused = b_paused;
+ p_ts->i_pause_date = i_date;
+
+ vlc_cond_signal( &p_ts->wait );
+ }
+ vlc_mutex_unlock( &p_ts->lock );
+ return i_ret;
+}
+static int TsChangeRate( ts_thread_t *p_ts, int i_src_rate, int i_rate )
+{
+ int i_ret;
+
+ vlc_mutex_lock( &p_ts->lock );
+ p_ts->i_cmd_delay += p_ts->i_rate_delay;
+
+ p_ts->i_rate_date = -1;
+ p_ts->i_rate_delay = 0;
+ p_ts->i_rate = i_rate;
+ p_ts->i_rate_source = i_src_rate;
+
+ i_ret = es_out_SetRate( p_ts->p_out, i_rate, i_rate );
+ vlc_mutex_unlock( &p_ts->lock );
+
+ return i_ret;
+}
+
+static void *TsRun( void *p_data )
+{
+ ts_thread_t *p_ts = p_data;
+ mtime_t i_buffering_date = -1;