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 ]);