* Add support for prioritized recordings. The user can chose among five
different priorities.
This commit is contained in:
parent
a241570132
commit
769dee0f3b
10 changed files with 156 additions and 13 deletions
3
debian/changelog
vendored
3
debian/changelog
vendored
|
@ -33,6 +33,9 @@ hts-tvheadend (2.11-WIP) hts; urgency=low
|
|||
CWC entries were not correctly updated when a connection was established
|
||||
or lost. This is now fixed. Ticket #144
|
||||
|
||||
* Add support for prioritized recordings. The user can chose among five
|
||||
different priorities.
|
||||
|
||||
hts-tvheadend (2.10) hts; urgency=high
|
||||
|
||||
* Fix a crash in HTSP server.
|
||||
|
|
|
@ -44,6 +44,15 @@ extern struct dvr_entry_list dvrentries;
|
|||
#define DVR_DIR_PER_TITLE 0x40
|
||||
#define DVR_EPISODE_IN_TITLE 0x80
|
||||
|
||||
typedef enum {
|
||||
DVR_PRIO_IMPORTANT,
|
||||
DVR_PRIO_HIGH,
|
||||
DVR_PRIO_NORMAL,
|
||||
DVR_PRIO_LOW,
|
||||
DVR_PRIO_UNIMPORTANT,
|
||||
} dvr_prio_t;
|
||||
|
||||
|
||||
LIST_HEAD(dvr_rec_stream_list, dvr_rec_stream);
|
||||
|
||||
|
||||
|
@ -93,6 +102,8 @@ typedef struct dvr_entry {
|
|||
date and time pre/post/fixed */
|
||||
char *de_desc; /* Description in UTF-8 (from EPG) */
|
||||
|
||||
dvr_prio_t de_pri;
|
||||
|
||||
epg_episode_t de_episode;
|
||||
|
||||
char *de_error;
|
||||
|
@ -165,6 +176,8 @@ typedef struct dvr_autorec_entry {
|
|||
channel_tag_t *dae_channel_tag;
|
||||
LIST_ENTRY(dvr_autorec_entry) dae_channel_tag_link;
|
||||
|
||||
dvr_prio_t dae_pri;
|
||||
|
||||
struct dvr_entry_list dae_spawns;
|
||||
|
||||
} dvr_autorec_entry_t;
|
||||
|
@ -181,7 +194,7 @@ dvr_entry_t *dvr_entry_create_by_event(event_t *e, const char *creator,
|
|||
dvr_entry_t *dvr_entry_create(channel_t *ch, time_t start, time_t stop,
|
||||
const char *title, const char *description,
|
||||
const char *creator, dvr_autorec_entry_t *dae,
|
||||
epg_episode_t *ee);
|
||||
epg_episode_t *ee, dvr_prio_t pri);
|
||||
|
||||
void dvr_init(void);
|
||||
|
||||
|
@ -241,4 +254,11 @@ void autorec_destroy_by_channel(channel_t *ch);
|
|||
|
||||
dvr_autorec_entry_t *autorec_entry_find(const char *id, int create);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
dvr_prio_t dvr_pri2val(const char *s);
|
||||
|
||||
const char *dvr_val2pri(dvr_prio_t v);
|
||||
|
||||
#endif /* DVR_H */
|
||||
|
|
|
@ -137,6 +137,7 @@ autorec_entry_find(const char *id, int create)
|
|||
tally = MAX(atoi(id), tally);
|
||||
}
|
||||
dae->dae_weekdays = 0x7f;
|
||||
dae->dae_pri = DVR_PRIO_NORMAL;
|
||||
|
||||
dae->dae_id = strdup(id);
|
||||
TAILQ_INSERT_TAIL(&autorec_entries, dae, dae_link);
|
||||
|
@ -235,6 +236,8 @@ autorec_record_build(dvr_autorec_entry_t *dae)
|
|||
build_weekday_tags(str, sizeof(str), dae->dae_weekdays);
|
||||
htsmsg_add_str(e, "weekdays", str);
|
||||
|
||||
htsmsg_add_str(e, "pri", dvr_val2pri(dae->dae_pri));
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
|
@ -340,6 +343,9 @@ autorec_record_update(void *opaque, const char *id, htsmsg_t *values,
|
|||
if(!htsmsg_get_u32(values, "enabled", &u32))
|
||||
dae->dae_enabled = u32;
|
||||
|
||||
if((s = htsmsg_get_str(values, "pri")) != NULL)
|
||||
dae->dae_pri = dvr_pri2val(s);
|
||||
|
||||
dvr_autorec_changed(dae);
|
||||
|
||||
return autorec_record_build(dae);
|
||||
|
|
|
@ -49,7 +49,6 @@ static void dvr_timer_expire(void *aux);
|
|||
static void dvr_timer_start_recording(void *aux);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -149,7 +148,7 @@ dvr_entry_t *
|
|||
dvr_entry_create(channel_t *ch, time_t start, time_t stop,
|
||||
const char *title, const char *description,
|
||||
const char *creator, dvr_autorec_entry_t *dae,
|
||||
epg_episode_t *ee)
|
||||
epg_episode_t *ee, dvr_prio_t pri)
|
||||
{
|
||||
dvr_entry_t *de;
|
||||
char tbuf[30];
|
||||
|
@ -168,6 +167,7 @@ dvr_entry_create(channel_t *ch, time_t start, time_t stop,
|
|||
|
||||
de->de_start = start;
|
||||
de->de_stop = stop;
|
||||
de->de_pri = pri;
|
||||
if (ch->ch_dvr_extra_time_pre)
|
||||
de->de_start_extra = ch->ch_dvr_extra_time_pre;
|
||||
else
|
||||
|
@ -219,7 +219,8 @@ dvr_entry_create_by_event(event_t *e, const char *creator,
|
|||
return NULL;
|
||||
|
||||
return dvr_entry_create(e->e_channel, e->e_start, e->e_stop,
|
||||
e->e_title, e->e_desc, creator, dae, &e->e_episode);
|
||||
e->e_title, e->e_desc, creator, dae, &e->e_episode,
|
||||
dae->dae_pri);
|
||||
}
|
||||
|
||||
|
||||
|
@ -326,8 +327,7 @@ dvr_db_load_one(htsmsg_t *c, int id)
|
|||
de->de_stop = stop;
|
||||
de->de_creator = strdup(creator);
|
||||
de->de_title = strdup(title);
|
||||
|
||||
|
||||
de->de_pri = dvr_pri2val(htsmsg_get_str(c, "pri"));
|
||||
|
||||
if(htsmsg_get_s32(c, "start_extra", &d))
|
||||
de->de_start_extra = dvr_extra_time_pre;
|
||||
|
@ -339,6 +339,7 @@ dvr_db_load_one(htsmsg_t *c, int id)
|
|||
else
|
||||
de->de_stop_extra = d;
|
||||
|
||||
|
||||
tvh_str_set(&de->de_desc, htsmsg_get_str(c, "description"));
|
||||
tvh_str_set(&de->de_filename, htsmsg_get_str(c, "filename"));
|
||||
tvh_str_set(&de->de_error, htsmsg_get_str(c, "error"));
|
||||
|
@ -416,6 +417,7 @@ dvr_entry_save(dvr_entry_t *de)
|
|||
if(de->de_desc != NULL)
|
||||
htsmsg_add_str(m, "description", de->de_desc);
|
||||
|
||||
htsmsg_add_str(m, "pri", dvr_val2pri(de->de_pri));
|
||||
|
||||
if(de->de_error != NULL)
|
||||
htsmsg_add_str(m, "error", de->de_error);
|
||||
|
@ -875,3 +877,28 @@ dvr_get_filesize(dvr_entry_t *de)
|
|||
|
||||
return st.st_size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static struct strtab priotab[] = {
|
||||
{ "important", DVR_PRIO_IMPORTANT },
|
||||
{ "high", DVR_PRIO_HIGH },
|
||||
{ "normal", DVR_PRIO_NORMAL },
|
||||
{ "low", DVR_PRIO_LOW },
|
||||
{ "unimportant", DVR_PRIO_UNIMPORTANT },
|
||||
};
|
||||
|
||||
dvr_prio_t
|
||||
dvr_pri2val(const char *s)
|
||||
{
|
||||
return str2val_def(s, priotab, DVR_PRIO_NORMAL);
|
||||
}
|
||||
|
||||
const char *
|
||||
dvr_val2pri(dvr_prio_t v)
|
||||
{
|
||||
return val2str(v, priotab) ?: "invalid";
|
||||
}
|
||||
|
|
|
@ -52,6 +52,15 @@ static void dvr_thread_new_pkt(dvr_entry_t *de, th_pkt_t *pkt);
|
|||
static void dvr_spawn_postproc(dvr_entry_t *de);
|
||||
static void dvr_thread_epilog(dvr_entry_t *de);
|
||||
|
||||
|
||||
const static int prio2weight[5] = {
|
||||
[DVR_PRIO_IMPORTANT] = 500,
|
||||
[DVR_PRIO_HIGH] = 400,
|
||||
[DVR_PRIO_NORMAL] = 300,
|
||||
[DVR_PRIO_LOW] = 200,
|
||||
[DVR_PRIO_UNIMPORTANT] = 100,
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -59,6 +68,7 @@ void
|
|||
dvr_rec_subscribe(dvr_entry_t *de)
|
||||
{
|
||||
char buf[100];
|
||||
int weight;
|
||||
|
||||
assert(de->de_s == NULL);
|
||||
|
||||
|
@ -68,8 +78,13 @@ dvr_rec_subscribe(dvr_entry_t *de)
|
|||
|
||||
pthread_create(&de->de_thread, NULL, dvr_thread, de);
|
||||
|
||||
de->de_s = subscription_create_from_channel(de->de_channel, 1000, buf,
|
||||
&de->de_sq.sq_st, 0);
|
||||
if(de->de_pri)
|
||||
weight = prio2weight[de->de_pri];
|
||||
else
|
||||
weight = 300;
|
||||
|
||||
de->de_s = subscription_create_from_channel(de->de_channel, weight,
|
||||
buf, &de->de_sq.sq_st, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -42,6 +42,26 @@ str2val0(const char *str, struct strtab tab[], int l)
|
|||
|
||||
#define str2val(str, tab) str2val0(str, tab, sizeof(tab) / sizeof(tab[0]))
|
||||
|
||||
|
||||
|
||||
static int str2val0_def(const char *str, struct strtab tab[], int l, int def)
|
||||
__attribute((unused));
|
||||
|
||||
static int
|
||||
str2val0_def(const char *str, struct strtab tab[], int l, int def)
|
||||
{
|
||||
int i;
|
||||
if(str)
|
||||
for(i = 0; i < l; i++)
|
||||
if(!strcasecmp(str, tab[i].str))
|
||||
return tab[i].val;
|
||||
return def;
|
||||
}
|
||||
|
||||
#define str2val_def(str, tab, def) \
|
||||
str2val0_def(str, tab, sizeof(tab) / sizeof(tab[0]), def)
|
||||
|
||||
|
||||
static const char * val2str0(int val, struct strtab tab[], int l)
|
||||
__attribute__((unused));
|
||||
|
||||
|
|
|
@ -766,7 +766,7 @@ htsp_method_subscribe(htsp_connection_t *htsp, htsmsg_t *in)
|
|||
LIST_INSERT_HEAD(&htsp->htsp_subscriptions, hs, hs_link);
|
||||
streaming_target_init(&hs->hs_input, htsp_streaming_input, hs, 0);
|
||||
|
||||
hs->hs_s = subscription_create_from_channel(ch, 500, htsp->htsp_logname,
|
||||
hs->hs_s = subscription_create_from_channel(ch, 150, htsp->htsp_logname,
|
||||
&hs->hs_input, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -490,7 +490,7 @@ rtsp_subscribe(http_connection_t *hc, rtsp_t *rtsp,
|
|||
char *components[5];
|
||||
int nc;
|
||||
char *url = hc->hc_url;
|
||||
int pri = 500;
|
||||
int pri = 150;
|
||||
int subflags = 0;
|
||||
th_subscription_t *s;
|
||||
char urlprefix[128];
|
||||
|
|
|
@ -751,6 +751,7 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque)
|
|||
const char *startstr = http_arg_get(&hc->hc_req_args, "starttime");
|
||||
const char *stopstr = http_arg_get(&hc->hc_req_args, "stoptime");
|
||||
const char *channel = http_arg_get(&hc->hc_req_args, "channelid");
|
||||
const char *pri = http_arg_get(&hc->hc_req_args, "pri");
|
||||
|
||||
channel_t *ch = channel ? channel_find_by_identifier(atoi(channel)) : NULL;
|
||||
|
||||
|
@ -781,7 +782,7 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque)
|
|||
stop += 86400;
|
||||
|
||||
dvr_entry_create(ch, start, stop, title, NULL, hc->hc_representative,
|
||||
NULL, NULL);
|
||||
NULL, NULL, dvr_pri2val(pri));
|
||||
|
||||
out = htsmsg_create_map();
|
||||
htsmsg_add_u32(out, "success", 1);
|
||||
|
@ -941,6 +942,8 @@ extjs_dvrlist(http_connection_t *hc, const char *remain, void *opaque)
|
|||
|
||||
htsmsg_add_str(m, "creator", de->de_creator);
|
||||
|
||||
htsmsg_add_str(m, "pri", dvr_val2pri(de->de_pri));
|
||||
|
||||
switch(de->de_sched_state) {
|
||||
case DVR_SCHEDULED:
|
||||
s = "Scheduled for recording";
|
||||
|
|
|
@ -13,6 +13,20 @@ tvheadend.weekdays = new Ext.data.SimpleStore({
|
|||
]
|
||||
});
|
||||
|
||||
|
||||
// This should be loaded from tvheadend
|
||||
tvheadend.dvrprio = new Ext.data.SimpleStore({
|
||||
fields: ['identifier', 'name'],
|
||||
id: 0,
|
||||
data: [
|
||||
['important', 'Important'],
|
||||
['high', 'High'],
|
||||
['normal', 'Normal'],
|
||||
['low', 'Low'],
|
||||
['unimportant', 'Unimportant'],
|
||||
]
|
||||
});
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -110,6 +124,10 @@ tvheadend.dvrschedule = function() {
|
|||
}
|
||||
}
|
||||
|
||||
function renderPri(value) {
|
||||
return tvheadend.dvrprio.getById(value).data.name;
|
||||
}
|
||||
|
||||
var dvrCm = new Ext.grid.ColumnModel([
|
||||
{
|
||||
width: 250,
|
||||
|
@ -117,10 +135,16 @@ tvheadend.dvrschedule = function() {
|
|||
header: "Title",
|
||||
dataIndex: 'title'
|
||||
},{
|
||||
width: 250,
|
||||
width: 100,
|
||||
id:'episode',
|
||||
header: "Episode",
|
||||
dataIndex: 'episode'
|
||||
},{
|
||||
width: 100,
|
||||
id:'pri',
|
||||
header: "Priority",
|
||||
dataIndex: 'pri',
|
||||
renderer: renderPri
|
||||
},{
|
||||
width: 100,
|
||||
id:'start',
|
||||
|
@ -215,6 +239,16 @@ tvheadend.dvrschedule = function() {
|
|||
increment: 10,
|
||||
format: 'H:i'
|
||||
}),
|
||||
new Ext.form.ComboBox({
|
||||
store: tvheadend.dvrprio,
|
||||
value: "normal",
|
||||
triggerAction: 'all',
|
||||
mode: 'local',
|
||||
fieldLabel: 'Priority',
|
||||
valueField: 'identifier',
|
||||
displayField: 'name',
|
||||
name: 'pri'
|
||||
}),
|
||||
{
|
||||
allowBlank: false,
|
||||
fieldLabel: 'Title',
|
||||
|
@ -363,6 +397,20 @@ tvheadend.autoreceditor = function() {
|
|||
valueField: 'identifier',
|
||||
displayField: 'name'
|
||||
})
|
||||
}, {
|
||||
header: "Priority",
|
||||
dataIndex: 'pri',
|
||||
width: 100,
|
||||
renderer: function(value, metadata, record, row, col, store) {
|
||||
return tvheadend.dvrprio.getById(value).data.name;
|
||||
},
|
||||
editor: new fm.ComboBox({
|
||||
store: tvheadend.dvrprio,
|
||||
triggerAction: 'all',
|
||||
mode: 'local',
|
||||
valueField: 'identifier',
|
||||
displayField: 'name'
|
||||
})
|
||||
},{
|
||||
header: "Created by",
|
||||
dataIndex: 'creator',
|
||||
|
@ -394,6 +442,7 @@ tvheadend.dvr = function() {
|
|||
{name: 'channel'},
|
||||
{name: 'title'},
|
||||
{name: 'episode'},
|
||||
{name: 'pri'},
|
||||
{name: 'description'},
|
||||
{name: 'chicon'},
|
||||
{name: 'start', type: 'date', dateFormat: 'U' /* unix time */},
|
||||
|
@ -419,7 +468,7 @@ tvheadend.dvr = function() {
|
|||
|
||||
tvheadend.autorecRecord = Ext.data.Record.create([
|
||||
'enabled','title','channel','tag','creator','contentgrp','comment',
|
||||
'weekdays'
|
||||
'weekdays', 'pri'
|
||||
]);
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue