timeshift: Added on-demand buffer mode.

In this mode data will only be written to disk when paused and anything
in the buffer prior to the current play point will immediately be removed.

This implies that rewinding is never possible in this mode (though FF is)
and trying to do so will result in the buffer playback being paused.
This commit is contained in:
Adam Sutton 2012-12-23 21:33:17 +00:00
parent fa4841b725
commit acebb13f15
4 changed files with 36 additions and 7 deletions

View file

@ -147,7 +147,7 @@ static void timeshift_input
exit = 1;
/* Buffer to disk */
if (ts->state >= TS_LIVE) {
if ((ts->state > TS_LIVE) || (!ts->ondemand && (ts->state == TS_LIVE))) {
sm->sm_time = getmonoclock();
streaming_target_deliver2(&ts->wr_queue.sq_st, sm);
} else
@ -170,7 +170,6 @@ void
timeshift_destroy(streaming_target_t *pad)
{
timeshift_t *ts = (timeshift_t*)pad;
timeshift_file_t *tsf;
streaming_message_t *sm;
/* Must hold global lock */
@ -193,8 +192,7 @@ timeshift_destroy(streaming_target_t *pad)
close(ts->rd_pipe.wr);
/* Flush files */
while ((tsf = TAILQ_FIRST(&ts->files)))
timeshift_filemgr_remove(ts, tsf, 1);
timeshift_filemgr_flush(ts, NULL);
free(ts->path);
free(ts);

View file

@ -141,6 +141,7 @@ timeshift_file_t *timeshift_filemgr_next
( timeshift_file_t *ts, int *end, int keep );
void timeshift_filemgr_remove
( timeshift_t *ts, timeshift_file_t *tsf, int force );
void timeshift_filemgr_flush ( timeshift_t *ts, timeshift_file_t *end );
void timeshift_filemgr_close ( timeshift_file_t *tsf );
#endif /* __TVH_TIMESHIFT_PRIVATE_H__ */

View file

@ -117,9 +117,12 @@ static void timeshift_reaper_remove ( timeshift_file_t *tsf )
static void timeshift_filemgr_get_root ( char *buf, size_t len )
{
const char *path = timeshift_path;
if (!path || !*path)
if (!path || !*path) {
path = hts_settings_get_root();
snprintf(buf, len, "%s/timeshift/temp", path);
snprintf(buf, len, "%s/timeshift/buffer", path);
} else {
snprintf(buf, len, "%s/buffer", path);
}
}
/*
@ -156,6 +159,18 @@ void timeshift_filemgr_remove
timeshift_reaper_remove(tsf);
}
/*
* Flush all files
*/
void timeshift_filemgr_flush ( timeshift_t *ts, timeshift_file_t *end )
{
timeshift_file_t *tsf;
while ((tsf = TAILQ_FIRST(&ts->files))) {
if (tsf == end) break;
timeshift_filemgr_remove(ts, tsf, 1);
}
}
/*
* Get current / new file
*/
@ -216,6 +231,7 @@ timeshift_file_t *timeshift_filemgr_get ( timeshift_t *ts, int create )
tsf_tmp->fd = fd;
tsf_tmp->path = strdup(path);
tsf_tmp->refcount = 0;
tsf_tmp->last = getmonoclock();
TAILQ_INIT(&tsf_tmp->iframes);
TAILQ_INIT(&tsf_tmp->sstart);
TAILQ_INSERT_TAIL(&ts->files, tsf_tmp, link);

View file

@ -29,6 +29,8 @@
#include <string.h>
#include <assert.h>
//#define TSHFT_TRACE
/* **************************************************************************
* File Reading
* *************************************************************************/
@ -223,6 +225,10 @@ void *timeshift_reader ( void *p )
if (speed > 3200) speed = 3200;
if (speed < -3200) speed = -3200;
/* Ignore negative */
if (ts->ondemand && (speed < 0))
speed = 0;
/* Process */
if (cur_speed != speed) {
@ -241,7 +247,7 @@ void *timeshift_reader ( void *p )
ts->id);
timeshift_writer_flush(ts);
pthread_mutex_lock(&ts->rdwr_mutex);
if ((cur_file = timeshift_filemgr_get(ts, 0))) {
if ((cur_file = timeshift_filemgr_get(ts, ts->ondemand))) {
cur_off = cur_file->size;
pause_time = cur_file->last;
last_time = pause_time;
@ -467,6 +473,10 @@ void *timeshift_reader ( void *p )
ctrl = streaming_msg_create_code(SMT_SPEED, cur_speed);
streaming_target_deliver2(ts->output, ctrl);
/* Flush ALL files */
if (ts->ondemand)
timeshift_filemgr_flush(ts, NULL);
/* Pause */
} else if (cur_speed < 0) {
tvhlog(LOG_DEBUG, "timeshift", "ts %d sob pause stream", ts->id);
@ -475,6 +485,10 @@ void *timeshift_reader ( void *p )
ctrl = streaming_msg_create_code(SMT_SPEED, cur_speed);
streaming_target_deliver2(ts->output, ctrl);
}
/* Flush unwanted */
} else if (ts->ondemand && cur_file) {
timeshift_filemgr_flush(ts, cur_file);
}
pthread_mutex_unlock(&ts->rdwr_mutex);