From fa4841b725e4d984d559490d42c81bcda34fed12 Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Fri, 21 Dec 2012 21:43:29 +0000 Subject: [PATCH] timeshift: reworked the configuration general config stuff has now been removed and a new timeshift tab has been created --- src/config2.c | 45 +-------- src/config2.h | 12 --- src/htsp_server.c | 3 +- src/timeshift.c | 60 ++++++++++++ src/timeshift.h | 9 ++ src/timeshift/private.h | 1 + src/timeshift/timeshift_filemgr.c | 6 +- src/webui/extjs.c | 80 ++++++++++++++++ src/webui/static/app/config.js | 51 ---------- src/webui/static/app/timeshift.js | 152 ++++++++++++++++++++++++++++++ src/webui/static/app/tvheadend.js | 3 + 11 files changed, 313 insertions(+), 109 deletions(-) create mode 100644 src/webui/static/app/timeshift.js diff --git a/src/config2.c b/src/config2.c index 05bb7a34..cfeeb127 100644 --- a/src/config2.c +++ b/src/config2.c @@ -26,24 +26,11 @@ static htsmsg_t *config; void config_init ( void ) { - int save = 0; - uint32_t u32; - config = hts_settings_load("config"); if (!config) { tvhlog(LOG_DEBUG, "config", "no configuration, loading defaults"); config = htsmsg_create_map(); } - - /* Defaults */ - if (htsmsg_get_u32(config, "timeshiftperiod", &u32)) - save |= config_set_timeshift_period(0); - if (htsmsg_get_u32(config, "timeshiftsize", &u32)) - save |= config_set_timeshift_size(0); - - /* Save defaults */ - if (save) - config_save(); } void config_save ( void ) @@ -67,6 +54,7 @@ static int _config_set_str ( const char *fld, const char *val ) return 0; } +#if 0 static int _config_set_u32 ( const char *fld, uint32_t val ) { uint32_t u32; @@ -78,6 +66,7 @@ static int _config_set_u32 ( const char *fld, uint32_t val ) } return 0; } +#endif const char *config_get_language ( void ) { @@ -98,33 +87,3 @@ int config_set_muxconfpath ( const char *path ) { return _config_set_str("muxconfpath", path); } - -const char *config_get_timeshift_path ( void ) -{ - return htsmsg_get_str(config, "timeshiftpath"); -} - -int config_set_timeshift_path ( const char *path ) -{ - return _config_set_str("timeshiftpath", path); -} - -uint32_t config_get_timeshift_period ( void ) -{ - return htsmsg_get_u32_or_default(config, "timeshiftperiod", 0); -} - -int config_set_timeshift_period ( uint32_t period ) -{ - return _config_set_u32("timeshiftperiod", period); -} - -uint32_t config_get_timeshift_size ( void ) -{ - return htsmsg_get_u32_or_default(config, "timeshiftsize", 0); -} - -int config_set_timeshift_size ( uint32_t size ) -{ - return _config_set_u32("timeshiftsize", size); -} diff --git a/src/config2.h b/src/config2.h index 7ba28e0a..cd68e306 100644 --- a/src/config2.h +++ b/src/config2.h @@ -36,16 +36,4 @@ const char *config_get_language ( void ); int config_set_language ( const char *str ) __attribute__((warn_unused_result)); -const char *config_get_timeshift_path ( void ); -int config_set_timeshift_path ( const char *str ) - __attribute__((warn_unused_result)); - -uint32_t config_get_timeshift_period ( void ); -int config_set_timeshift_period ( uint32_t val ) - __attribute__((warn_unused_result)); - -uint32_t config_get_timeshift_size ( void ); -int config_set_timeshift_size ( uint32_t val ) - __attribute__((warn_unused_result)); - #endif /* __TVH_CONFIG__H__ */ diff --git a/src/htsp_server.c b/src/htsp_server.c index 0c1db9b1..77556d6e 100644 --- a/src/htsp_server.c +++ b/src/htsp_server.c @@ -1264,7 +1264,8 @@ htsp_method_subscribe(htsp_connection_t *htsp, htsmsg_t *in) #if ENABLE_TIMESHIFT timeshiftPeriod = htsmsg_get_u32_or_default(in, "timeshiftPeriod", 0); - timeshiftPeriod = MIN(timeshiftPeriod, config_get_timeshift_period()); + if (!timeshift_unlimited_period) + timeshiftPeriod = MIN(timeshiftPeriod, timeshift_max_period); #endif /* diff --git a/src/timeshift.c b/src/timeshift.c index 2114442e..14cee0d1 100644 --- a/src/timeshift.c +++ b/src/timeshift.c @@ -34,12 +34,51 @@ static int timeshift_index = 0; +int timeshift_enabled; +int timeshift_ondemand; +char *timeshift_path; +int timeshift_unlimited_period; +uint32_t timeshift_max_period; +int timeshift_unlimited_size; +size_t timeshift_max_size; + /* * Intialise global file manager */ void timeshift_init ( void ) { + htsmsg_t *m; + const char *str; + uint32_t u32; + timeshift_filemgr_init(); + + /* Defaults */ + timeshift_enabled = 0; // Disabled + timeshift_ondemand = 0; // Permanent + timeshift_path = NULL; // setting dir + timeshift_unlimited_period = 0; + timeshift_max_period = 3600; // 1Hr + timeshift_unlimited_size = 0; + timeshift_max_size = 10000 * (size_t)1048576; // 10G + + /* Load settings */ + if ((m = hts_settings_load("timeshift/config"))) { + if (!htsmsg_get_u32(m, "enabled", &u32)) + timeshift_enabled = u32 ? 1 : 0; + if (!htsmsg_get_u32(m, "ondemand", &u32)) + timeshift_ondemand = u32 ? 1 : 0; + if ((str = htsmsg_get_str(m, "path"))) + timeshift_path = strdup(str); + if (!htsmsg_get_u32(m, "unlimited_period", &u32)) + timeshift_unlimited_period = u32 ? 1 : 0; + htsmsg_get_u32(m, "max_period", ×hift_max_period); + if (!htsmsg_get_u32(m, "unlimited_size", &u32)) + timeshift_unlimited_size = u32 ? 1 : 0; + if (!htsmsg_get_u32(m, "max_size", &u32)) + timeshift_max_size = 1048576LL * u32; + htsmsg_destroy(m); + } } /* @@ -50,6 +89,26 @@ void timeshift_term ( void ) timeshift_filemgr_term(); } +/* + * Save settings + */ +void timeshift_save ( void ) +{ + htsmsg_t *m; + + m = htsmsg_create_map(); + htsmsg_add_u32(m, "enabled", timeshift_enabled); + htsmsg_add_u32(m, "ondemand", timeshift_ondemand); + if (timeshift_path) + htsmsg_add_str(m, "path", timeshift_path); + htsmsg_add_u32(m, "unlimited_period", timeshift_unlimited_period); + htsmsg_add_u32(m, "max_period", timeshift_max_period); + htsmsg_add_u32(m, "unlimited_size", timeshift_unlimited_size); + htsmsg_add_u32(m, "max_size", timeshift_max_size / 1048576); + + hts_settings_save(m, "timeshift/config"); +} + /* * Receive data */ @@ -169,6 +228,7 @@ streaming_target_t *timeshift_create ts->full = 0; ts->vididx = -1; ts->id = timeshift_index; + ts->ondemand = timeshift_ondemand; pthread_mutex_init(&ts->rdwr_mutex, NULL); pthread_mutex_init(&ts->state_mutex, NULL); diff --git a/src/timeshift.h b/src/timeshift.h index 69574bc5..eeb6baad 100644 --- a/src/timeshift.h +++ b/src/timeshift.h @@ -19,8 +19,17 @@ #ifndef __TVH_TIMESHIFT_H__ #define __TVH_TIMESHIFT_H__ +extern int timeshift_enabled; +extern int timeshift_ondemand; +extern char *timeshift_path; +extern int timeshift_unlimited_period; +extern uint32_t timeshift_max_period; +extern int timeshift_unlimited_size; +extern size_t timeshift_max_size; + void timeshift_init ( void ); void timeshift_term ( void ); +void timeshift_save ( void ); streaming_target_t *timeshift_create (streaming_target_t *out, time_t max_period); diff --git a/src/timeshift/private.h b/src/timeshift/private.h index 11b53bac..133eb695 100644 --- a/src/timeshift/private.h +++ b/src/timeshift/private.h @@ -80,6 +80,7 @@ typedef struct timeshift { int id; ///< Reference number char *path; ///< Directory containing buffer time_t max_time; ///< Maximum period to shift + int ondemand; ///< Whether this is an on-demand timeshift enum { TS_INIT, diff --git a/src/timeshift/timeshift_filemgr.c b/src/timeshift/timeshift_filemgr.c index 01c2dd15..3562393f 100644 --- a/src/timeshift/timeshift_filemgr.c +++ b/src/timeshift/timeshift_filemgr.c @@ -111,13 +111,15 @@ static void timeshift_reaper_remove ( timeshift_file_t *tsf ) /* * Get root directory + * + * TODO: should this be fixed on startup? */ static void timeshift_filemgr_get_root ( char *buf, size_t len ) { - const char *path = config_get_timeshift_path(); + const char *path = timeshift_path; if (!path || !*path) path = hts_settings_get_root(); - snprintf(buf, len, "%s/timeshift", path); + snprintf(buf, len, "%s/timeshift/temp", path); } /* diff --git a/src/webui/extjs.c b/src/webui/extjs.c index f68dff87..2b6fff45 100644 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -48,6 +48,7 @@ #include "lang_codes.h" #include "subscriptions.h" #include "imagecache.h" +#include "timeshift.h" /** * @@ -130,6 +131,9 @@ extjs_root(http_connection_t *hc, const char *remain, void *opaque) extjs_load(hq, "static/app/iptv.js"); #if ENABLE_V4L extjs_load(hq, "static/app/v4l.js"); +#endif +#if ENABLE_TIMESHIFT + extjs_load(hq, "static/app/timeshift.js"); #endif extjs_load(hq, "static/app/chconf.js"); extjs_load(hq, "static/app/epg.js"); @@ -2034,6 +2038,79 @@ extjs_capabilities(http_connection_t *hc, const char *remain, void *opaque) return 0; } +/** + * + */ +#if ENABLE_TIMESHIFT +static int +extjs_timeshift(http_connection_t *hc, const char *remain, void *opaque) +{ + htsbuf_queue_t *hq = &hc->hc_reply; + const char *op = http_arg_get(&hc->hc_req_args, "op"); + htsmsg_t *out, *m; + const char *str; + + if(op == NULL) + return 400; + + pthread_mutex_lock(&global_lock); + + if(http_access_verify(hc, ACCESS_ADMIN)) { + pthread_mutex_unlock(&global_lock); + return HTTP_STATUS_UNAUTHORIZED; + } + + pthread_mutex_unlock(&global_lock); + + /* Basic settings (not the advanced schedule) */ + if(!strcmp(op, "loadSettings")) { + pthread_mutex_lock(&global_lock); + m = htsmsg_create_map(); + htsmsg_add_u32(m, "timeshift_enabled", timeshift_enabled); + htsmsg_add_u32(m, "timeshift_ondemand", timeshift_ondemand); + if (timeshift_path) + htsmsg_add_str(m, "timeshift_path", timeshift_path); + htsmsg_add_u32(m, "timeshift_unlimited_period", timeshift_unlimited_period); + htsmsg_add_u32(m, "timeshift_max_period", timeshift_max_period); + htsmsg_add_u32(m, "timeshift_unlimited_size", timeshift_unlimited_size); + htsmsg_add_u32(m, "timeshift_max_size", timeshift_max_size / 1048576); + pthread_mutex_unlock(&global_lock); + out = json_single_record(m, "config"); + + /* Save settings */ + } else if (!strcmp(op, "saveSettings") ) { + pthread_mutex_lock(&global_lock); + timeshift_enabled = http_arg_get(&hc->hc_req_args, "timeshift_enabled") ? 1 : 0; + timeshift_ondemand = http_arg_get(&hc->hc_req_args, "timeshift_ondemand") ? 1 : 0; + if ((str = http_arg_get(&hc->hc_req_args, "timeshift_path"))) { + if (timeshift_path) + free(timeshift_path); + timeshift_path = strdup(str); + } + timeshift_unlimited_period = http_arg_get(&hc->hc_req_args, "timeshift_unlimited_period") ? 1 : 0; + if ((str = http_arg_get(&hc->hc_req_args, "timeshift_max_period"))) + timeshift_max_period = (uint32_t)atol(str); + timeshift_unlimited_size = http_arg_get(&hc->hc_req_args, "timeshift_unlimited_size") ? 1 : 0; + if ((str = http_arg_get(&hc->hc_req_args, "timeshift_max_size"))) + timeshift_max_size = atol(str) * 1048576LL; + timeshift_save(); + pthread_mutex_unlock(&global_lock); + + out = htsmsg_create_map(); + htsmsg_add_u32(out, "success", 1); + + } else { + return HTTP_STATUS_BAD_REQUEST; + } + + htsmsg_json_serialize(out, hq, 0); + htsmsg_destroy(out); + http_output_content(hc, "text/x-json; charset=UTF-8"); + + return 0; +} +#endif + /** * WEB user interface */ @@ -2064,6 +2141,9 @@ extjs_start(void) http_path_add("/iptv/services", NULL, extjs_iptvservices, ACCESS_ADMIN); http_path_add("/servicedetails", NULL, extjs_servicedetails, ACCESS_ADMIN); http_path_add("/tv/adapter", NULL, extjs_tvadapter, ACCESS_ADMIN); +#if ENABLE_TIMESHIFT + http_path_add("/timeshift", NULL, extjs_timeshift, ACCESS_ADMIN); +#endif #if ENABLE_LINUXDVB extjs_start_dvb(); diff --git a/src/webui/static/app/config.js b/src/webui/static/app/config.js index a7e4d968..b71a4a5d 100644 --- a/src/webui/static/app/config.js +++ b/src/webui/static/app/config.js @@ -103,49 +103,6 @@ tvheadend.miscconf = function() { if (tvheadend.capabilities.indexOf('imagecache') == -1) imagecachePanel.hide(); - /* **************************************************************** - * Timeshift - * ***************************************************************/ - - var timeshiftPath = new Ext.form.TextField({ - fieldLabel : 'Temp. storage path', - name : 'timeshiftpath', - allowBlank : true, - width : 400 - }); - - var timeshiftPeriod = new Ext.form.NumberField({ - fieldLabel : 'Max period (minutes, per stream)', - name : 'timeshiftperiod', - allowBlank : false, - width : 400 - }); - - var timeshiftPeriodU = new Ext.form.Checkbox({ - fieldLabel : '(unlimited)', - name : 'timeshiftperiod_unlimited', - allowBlank : false, - width : 400 - }); - timeshiftPeriodU.on('check', function(e, c) { - timeshiftPeriod.setDisabled(c); - }); - - var timeshiftSize = new Ext.form.NumberField({ - fieldLabel : 'Max size (MB, global)', - name : 'timeshiftsize', - allowBlank : false, - width : 400 - }); - - var timeshiftFields = new Ext.form.FieldSet({ - title : 'Timeshift', - width : 700, - autoHeight : true, - collapsible : true, - items : [ timeshiftPath, timeshiftPeriod, timeshiftPeriodU ]//, timeshiftSize ] - }); - /* **************************************************************** * Form * ***************************************************************/ @@ -192,14 +149,6 @@ tvheadend.miscconf = function() { op : 'loadSettings' }, success : function(form, action) { - v = parseInt(timeshiftPeriod.getValue()); - if (v == 4294967295) { - timeshiftPeriodU.setValue(true); - timeshiftPeriod.setValue(""); - timeshiftPeriod.setDisabled(true); // TODO: this isn't working - } else { - timeshiftPeriod.setValue(v / 60); - } confpanel.enable(); } }); diff --git a/src/webui/static/app/timeshift.js b/src/webui/static/app/timeshift.js new file mode 100644 index 00000000..7f27ba4f --- /dev/null +++ b/src/webui/static/app/timeshift.js @@ -0,0 +1,152 @@ +tvheadend.timeshift = function() { + + /* **************************************************************** + * Data + * ***************************************************************/ + + var confreader = new Ext.data.JsonReader( + { + root: 'config' + }, + [ + 'timeshift_enabled', 'timeshift_ondemand', + 'timeshift_path', + 'timeshift_unlimited_period', 'timeshift_max_period', + 'timeshift_unlimited_size', 'timeshift_max_size' + ] + ); + + /* **************************************************************** + * Fields + * ***************************************************************/ + + var timeshiftEnabled = new Ext.form.Checkbox({ + fieldLabel: 'Enabled', + name: 'timeshift_enabled', + width: 300 + }); + + var timeshiftOndemand = new Ext.form.Checkbox({ + fieldLabel: 'On-Demand', + name: 'timeshift_ondemand', + width: 300 + }); + + var timeshiftPath = new Ext.form.TextField({ + fieldLabel: 'Storage Path', + name: 'timeshift_path', + allowBlank: true, + width: 300 + }); + + var timeshiftMaxPeriod = new Ext.form.NumberField({ + fieldLabel: 'Max. Period (mins)', + name: 'timeshift_max_period', + allowBlank: false, + width: 300 + }); + + var timeshiftUnlPeriod = new Ext.form.Checkbox({ + fieldLabel: ' unlimited', + name: 'timeshift_unlimited_period', + Width: 300 + }); + + var timeshiftMaxSize = new Ext.form.NumberField({ + fieldLabel: 'Max. Size (MB)', + name: 'timeshift_max_size', + allowBlank: false, + width: 300 + }); + + var timeshiftUnlSize = new Ext.form.Checkbox({ + fieldLabel: ' unlimited', + name: 'timeshift_unlimited_size', + Width: 300 + }); + + /* **************************************************************** + * Events + * ***************************************************************/ + + timeshiftUnlPeriod.on('check', function(e, c){ + timeshiftMaxPeriod.setDisabled(c); + }); + timeshiftUnlSize.on('check', function(e, c){ + timeshiftMaxSize.setDisabled(c); + }); + + /* **************************************************************** + * Form + * ***************************************************************/ + + var saveButton = new Ext.Button({ + text : "Save configuration", + tooltip : 'Save changes made to configuration below', + iconCls : 'save', + handler : saveChanges + }); + + var helpButton = new Ext.Button({ + text : 'Help', + handler : function() { + new tvheadend.help('Timeshift Configuration', 'config_timeshift.html'); + } + }); + + var confpanel = new Ext.FormPanel({ + title : 'Timeshift', + iconCls : 'clock', + border : false, + bodyStyle : 'padding:15px', + labelAlign : 'left', + labelWidth : 150, + waitMsgTarget : true, + reader : confreader, + layout : 'form', + defaultType : 'textfield', + autoHeight : true, + items : [ + timeshiftEnabled, timeshiftOndemand, + timeshiftPath, + timeshiftMaxPeriod, timeshiftUnlPeriod, + timeshiftMaxSize, timeshiftUnlSize + ], + tbar : [ saveButton, '->', helpButton ] + }); + + /* **************************************************************** + * Load/Save + * ***************************************************************/ + + confpanel.on('render', function() { + confpanel.getForm().load({ + url: 'timeshift', + params: { + 'op': 'loadSettings' + }, + success: function() { + confpanel.enable(); + timeshiftMaxPeriod.setDisabled(timeshiftUnlPeriod.getValue()); + timeshiftMaxSize.setDisabled(timeshiftUnlSize.getValue()); + } + }); + }); + + function saveChanges() { + confpanel.getForm().submit({ + url : 'timeshift', + params : { + op : 'saveSettings', + }, + waitMsg : 'Saving Data...', + success : function(form, action) { + }, + failure : function(form, action) { + Ext.Msg.alert('Save failed', action.result.errormsg); + } + }); + } + + return confpanel; +} diff --git a/src/webui/static/app/tvheadend.js b/src/webui/static/app/tvheadend.js index d1754f49..96bb66a3 100644 --- a/src/webui/static/app/tvheadend.js +++ b/src/webui/static/app/tvheadend.js @@ -270,6 +270,9 @@ function accessUpdate(o) { tvheadend.confpanel.add(new tvheadend.cwceditor); tvheadend.confpanel.add(new tvheadend.capmteditor); } + if (tvheadend.capabilities.indexOf('timeshift') != -1) { + tvheadend.confpanel.add(new tvheadend.timeshift); + } tvheadend.confpanel.doLayout(); }