diff --git a/debian/changelog b/debian/changelog
index febf59c3..b725af2b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -21,7 +21,10 @@ hts-tvheadend (2.6) hts; urgency=low
Ticket #99
* Increase logging and include various stats to XMLTV grab
-
+
+ * Add support for configuring a per-channel pre/post extra time for
+ scheduled recordings. Ticket #104
+
hts-tvheadend (2.5) hts; urgency=low
* If a previosly detected DVB adapter was not present during startup,
diff --git a/docs/html/config_channels.html b/docs/html/config_channels.html
index d2ed23ac..a95d3cee 100644
--- a/docs/html/config_channels.html
+++ b/docs/html/config_channels.html
@@ -40,6 +40,17 @@
in the EPG if you have many channels. The tags are also presented
in a Media player.
+
DVR Pre-Start
+ Allows the user to specify an amout of extra time that should
+ be prepended to a recording scheduled on this channel.
+ In other words, if you type 5 here for a recording that is scheduled
+ for 20:00 will start to record at 19:55.
+
+ DVR Post-End
+ Similar to DVR Pre-Start this allows the user to add an extra
+ amount of time that should be appended to a recording.
+ In other words, if you type 5 here for a recording that is scheduled
+ to end 20:30 will stop to record at 20:35.
diff --git a/src/channels.c b/src/channels.c
index 9163f8d7..45d19820 100644
--- a/src/channels.c
+++ b/src/channels.c
@@ -271,6 +271,9 @@ channel_load_one(htsmsg_t *c, int id)
tvh_str_update(&ch->ch_icon, htsmsg_get_str(c, "icon"));
+ htsmsg_get_s32(c, "dvr_extra_time_pre", &ch->ch_dvr_extra_time_pre);
+ htsmsg_get_s32(c, "dvr_extra_time_post", &ch->ch_dvr_extra_time_post);
+
if((tags = htsmsg_get_list(c, "tags")) != NULL) {
HTSMSG_FOREACH(f, tags) {
if(f->hmf_type == HMF_S64) {
@@ -330,6 +333,9 @@ channel_save(channel_t *ch)
htsmsg_add_msg(m, "tags", tags);
+ htsmsg_add_u32(m, "dvr_extra_time_pre", ch->ch_dvr_extra_time_pre);
+ htsmsg_add_u32(m, "dvr_extra_time_post", ch->ch_dvr_extra_time_post);
+
hts_settings_save(m, "channels/%d", ch->ch_id);
htsmsg_destroy(m);
}
@@ -451,6 +457,36 @@ channel_set_icon(channel_t *ch, const char *icon)
htsp_channel_update(ch);
}
+/**
+ * Set the amount of minutes to start before / end after recording on a channel
+ */
+
+void
+channel_set_epg_postpre_time(channel_t *ch, int pre, int mins)
+{
+ if (mins < -10000 || mins > 10000)
+ mins = 0;
+
+ lock_assert(&global_lock);
+
+ tvhlog(LOG_NOTICE, "channels",
+ "Channel \"%s\" epg %s-time set to %d minutes",
+ ch->ch_name, pre ? "pre":"post", mins);
+
+ if (pre) {
+ if (ch->ch_dvr_extra_time_pre == mins)
+ return;
+ else
+ ch->ch_dvr_extra_time_pre = mins;
+ } else {
+ if (ch->ch_dvr_extra_time_post == mins)
+ return;
+ else
+ ch->ch_dvr_extra_time_post = mins;
+ }
+ channel_save(ch);
+ htsp_channel_update(ch);
+}
/**
*
diff --git a/src/channels.h b/src/channels.h
index 314a7e2f..0946e899 100644
--- a/src/channels.h
+++ b/src/channels.h
@@ -48,6 +48,8 @@ typedef struct channel {
gtimer_t ch_epg_timer_head;
gtimer_t ch_epg_timer_current;
+ int ch_dvr_extra_time_pre;
+ int ch_dvr_extra_time_post;
char *ch_icon;
@@ -113,6 +115,8 @@ void channel_delete(channel_t *ch);
void channel_merge(channel_t *dst, channel_t *src);
+void channel_set_epg_postpre_time(channel_t *ch, int pre, int mins);
+
void channel_set_icon(channel_t *ch, const char *icon);
struct xmltv_channel;
diff --git a/src/dvr/dvr_db.c b/src/dvr/dvr_db.c
index f23980a2..8c4c02ea 100644
--- a/src/dvr/dvr_db.c
+++ b/src/dvr/dvr_db.c
@@ -142,6 +142,7 @@ dvr_entry_create_by_event(event_t *e, const char *creator)
char tbuf[30];
struct tm tm;
time_t t;
+ channel_t *ch;
if(e->e_channel == NULL || e->e_title == NULL)
return NULL;
@@ -153,13 +154,13 @@ dvr_entry_create_by_event(event_t *e, const char *creator)
de = calloc(1, sizeof(dvr_entry_t));
de->de_id = ++de_tally;
- de->de_channel = e->e_channel;
+ ch = de->de_channel = e->e_channel;
LIST_INSERT_HEAD(&de->de_channel->ch_dvrs, de, de_channel_link);
de->de_start = e->e_start;
de->de_stop = e->e_stop;
- de->de_start_extra = dvr_extra_time_pre;
- de->de_stop_extra = dvr_extra_time_post;
+ de->de_start_extra = dvr_extra_time_pre + ch->ch_dvr_extra_time_pre;
+ de->de_stop_extra = dvr_extra_time_post + ch->ch_dvr_extra_time_post;
de->de_creator = strdup(creator);
de->de_title = strdup(e->e_title);
de->de_desc = e->e_desc ? strdup(e->e_desc) : NULL;
diff --git a/src/webui/extjs.c b/src/webui/extjs.c
index d37af953..eddbe099 100644
--- a/src/webui/extjs.c
+++ b/src/webui/extjs.c
@@ -329,6 +329,12 @@ extjs_channels_update(htsmsg_t *in)
if((s = htsmsg_get_str(c, "tags")) != NULL)
channel_set_tags_from_list(ch, s);
+
+ if((s = htsmsg_get_str(c, "epg_pre_start")) != NULL)
+ channel_set_epg_postpre_time(ch, 1, atoi(s));
+
+ if((s = htsmsg_get_str(c, "epg_post_end")) != NULL)
+ channel_set_epg_postpre_time(ch, 0, atoi(s));
}
}
@@ -372,6 +378,9 @@ extjs_channels(http_connection_t *hc, const char *remain, void *opaque)
}
htsmsg_add_str(c, "tags", buf);
+ htsmsg_add_s32(c, "epg_pre_start", ch->ch_dvr_extra_time_pre);
+ htsmsg_add_s32(c, "epg_post_end", ch->ch_dvr_extra_time_post);
+
htsmsg_add_msg(array, NULL, c);
}
diff --git a/src/webui/static/app/chconf.js b/src/webui/static/app/chconf.js
index 6c1442d6..413a9652 100644
--- a/src/webui/static/app/chconf.js
+++ b/src/webui/static/app/chconf.js
@@ -27,7 +27,8 @@ tvheadend.comet.on('channeltags', function(m) {
tvheadend.channels = new Ext.data.JsonStore({
autoLoad: true,
root:'entries',
- fields: ['name', 'chid', 'xmltvsrc', 'tags'],
+ fields: ['name', 'chid', 'xmltvsrc', 'tags',
+ 'epg_pre_start', 'epg_post_end'],
id: 'chid',
url: "channels",
baseParams: {
@@ -181,7 +182,42 @@ tvheadend.chconf = function()
valueField: 'identifier',
displayField: 'name'
})
- }, actions
+ },
+ {
+ header: "DVR Pre-Start",
+ dataIndex: 'epg_pre_start',
+ width: 100,
+
+ renderer: function(value, metadata, record, row, col, store) {
+ if (!value) {
+ return 'Not set';
+ } else {
+ return value + ' min';
+ }
+ },
+
+ editor: new fm.NumberField({
+ minValue: 0,
+ maxValue: 1440
+ })
+ },
+ {
+ header: "DVR Post-End",
+ dataIndex: 'epg_post_end',
+ width: 100,
+ renderer: function(value, metadata, record, row, col, store) {
+ if (!value) {
+ return 'Not set';
+ } else {
+ return value + ' min';
+ }
+ },
+
+ editor: new fm.NumberField({
+ minValue: 0,
+ maxValue: 1440
+ })
+ }, actions
]);