- better duplicate handling - better subtitle handling

This commit is contained in:
dero 2015-03-05 21:13:51 +01:00 committed by Jaroslav Kysela
parent ce78f14570
commit 2b22bc75a1
9 changed files with 275 additions and 67 deletions

View file

@ -163,6 +163,7 @@ typedef struct dvr_entry {
char *de_directory; /* Can be set for autorec entries, will override any
directory setting from the configuration */
lang_str_t *de_title; /* Title in UTF-8 (from EPG) */
lang_str_t *de_subtitle; /* Subtitle in UTF-8 (from EPG) */
lang_str_t *de_desc; /* Description in UTF-8 (from EPG) */
uint32_t de_content_type; /* Content type (from EPG) (only code) */
@ -244,6 +245,16 @@ typedef struct dvr_entry {
#define DVR_CH_NAME(e) ((e)->de_channel == NULL ? (e)->de_channel_name : channel_get_name((e)->de_channel))
typedef enum {
DVR_AUTOREC_RECORD_ALL = 0,
DVR_AUTOREC_RECORD_DIFFERENT_EPISODE_NUMBER = 1,
DVR_AUTOREC_RECORD_DIFFERENT_SUBTITLE = 2,
DVR_AUTOREC_RECORD_DIFFERENT_DESCRIPTION = 3,
DVR_AUTOREC_RECORD_ONCE_PER_WEEK = 4,
DVR_AUTOREC_RECORD_ONCE_PER_DAY = 5
} dvr_autorec_dedup_t;
/**
* Autorec entry
*/
@ -291,9 +302,12 @@ typedef struct dvr_autorec_entry {
int dae_minduration;
int dae_maxduration;
int dae_retention;
time_t dae_start_extra;
time_t dae_stop_extra;
int dae_record;
} dvr_autorec_entry_t;
TAILQ_HEAD(dvr_autorec_entry_queue, dvr_autorec_entry);
@ -432,7 +446,7 @@ dvr_entry_t *
dvr_entry_create_htsp( const char *dvr_config_uuid,
channel_t *ch, time_t start, time_t stop,
time_t start_extra, time_t stop_extra,
const char *title, const char *description,
const char *title, const char* subtitle, const char *description,
const char *lang, epg_genre_t *content_type,
const char *owner, const char *creator,
dvr_autorec_entry_t *dae,
@ -441,7 +455,7 @@ dvr_entry_create_htsp( const char *dvr_config_uuid,
dvr_entry_t *
dvr_entry_update( dvr_entry_t *de,
const char* de_title, const char *de_desc, const char *lang,
const char* de_title, const char* de_subtitle, const char *de_desc, const char *lang,
time_t de_start, time_t de_stop,
time_t de_start_extra, time_t de_stop_extra,
dvr_prio_t pri, int retention );
@ -506,7 +520,7 @@ dvr_entry_t *
dvr_entry_create_(const char *config_uuid, epg_broadcast_t *e,
channel_t *ch, time_t start, time_t stop,
time_t start_extra, time_t stop_extra,
const char *title, const char *description,
const char *title, const char* subtitle, const char *description,
const char *lang, epg_genre_t *content_type,
const char *owner, const char *creator,
dvr_autorec_entry_t *dae, dvr_timerec_entry_t *tae,

View file

@ -1,6 +1,6 @@
/*
* tvheadend, Automatic recordings
* Copyright (C) 2010 Andreas Öman
* Copyright (C) 2010 Andreas <EFBFBD>man
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -867,6 +867,20 @@ dvr_autorec_entry_class_content_type_list(void *o)
return m;
}
static htsmsg_t *
dvr_autorec_entry_class_dedup_list ( void *o )
{
static const struct strtab tab[] = {
{ "Record all", DVR_AUTOREC_RECORD_ALL },
{ "Record if different episode number", DVR_AUTOREC_RECORD_DIFFERENT_EPISODE_NUMBER },
{ "Record if different subtitle", DVR_AUTOREC_RECORD_DIFFERENT_SUBTITLE },
{ "Record if different description", DVR_AUTOREC_RECORD_DIFFERENT_DESCRIPTION },
{ "Record once per week", DVR_AUTOREC_RECORD_ONCE_PER_WEEK },
{ "Record once per day", DVR_AUTOREC_RECORD_ONCE_PER_DAY },
};
return strtab2htsmsg(tab);
}
const idclass_t dvr_autorec_entry_class = {
.ic_class = "dvrautorec",
.ic_caption = "DVR Auto-Record Entry",
@ -999,6 +1013,14 @@ const idclass_t dvr_autorec_entry_class = {
.def.i = DVR_PRIO_NORMAL,
.off = offsetof(dvr_autorec_entry_t, dae_pri),
},
{
.type = PT_U32,
.id = "record",
.name = "Duplicate Handling",
.def.i = DVR_AUTOREC_RECORD_ALL,
.off = offsetof(dvr_autorec_entry_t, dae_record),
.list = dvr_autorec_entry_class_dedup_list,
},
{
.type = PT_INT,
.id = "retention",

View file

@ -44,6 +44,7 @@ static void dvr_timer_expire(void *aux);
static void dvr_timer_start_recording(void *aux);
static void dvr_timer_stop_recording(void *aux);
static int dvr_entry_class_disp_title_set(void *o, const void *v);
static int dvr_entry_class_disp_subtitle_set(void *o, const void *v);
/*
* Start / stop time calculators
@ -261,10 +262,9 @@ dvr_make_title(char *output, size_t outlen, dvr_entry_t *de)
".", "S%02d", NULL, "E%02d", NULL);
}
if (cfg->dvr_subtitle_in_title) {
if(de->de_bcast && de->de_bcast->episode && de->de_bcast->episode->subtitle)
if (cfg->dvr_subtitle_in_title && de->de_subtitle) {
snprintf(output + strlen(output), outlen - strlen(output),
".%s", lang_str_get(de->de_bcast->episode->subtitle, NULL));
".%s", lang_str_get(de->de_subtitle, NULL));
}
localtime_r(&de->de_start, &tm);
@ -306,7 +306,7 @@ dvr_entry_set_timer(dvr_entry_t *de)
de->de_sched_state = DVR_MISSED_TIME;
else
_dvr_entry_completed(de);
gtimer_arm_abs(&de->de_timer, dvr_timer_expire, de,
gtimer_arm_abs(&de->de_timer, dvr_timer_expire, de,
de->de_stop + dvr_entry_get_retention(de) * 86400);
} else if (de->de_sched_state == DVR_RECORDING) {
@ -429,6 +429,11 @@ dvr_entry_create(const char *uuid, htsmsg_t *conf)
(s = htsmsg_get_str(conf, "disp_title")) != NULL)
dvr_entry_class_disp_title_set(de, s);
/* special case, becaous PO_NOSAVE, load ignores it */
if (de->de_subtitle == NULL &&
(s = htsmsg_get_str(conf, "disp_subtitle")) != NULL)
dvr_entry_class_disp_subtitle_set(de, s);
de->de_refcnt = 1;
LIST_INSERT_HEAD(&dvrentries, de, de_global_link);
@ -456,7 +461,7 @@ dvr_entry_t *
dvr_entry_create_(const char *config_uuid, epg_broadcast_t *e,
channel_t *ch, time_t start, time_t stop,
time_t start_extra, time_t stop_extra,
const char *title, const char *description,
const char *title, const char* subtitle, const char *description,
const char *lang, epg_genre_t *content_type,
const char *owner,
const char *creator, dvr_autorec_entry_t *dae,
@ -487,6 +492,8 @@ dvr_entry_create_(const char *config_uuid, epg_broadcast_t *e,
htsmsg_add_u32(conf, "dvb_eid", e->dvb_eid);
if (e->episode && e->episode->title)
lang_str_serialize(e->episode->title, conf, "title");
if (e->episode && e->episode->subtitle)
lang_str_serialize(e->episode->subtitle, conf, "subtitle");
if (e->description)
lang_str_serialize(e->description, conf, "description");
else if (e->episode && e->episode->description)
@ -508,6 +515,12 @@ dvr_entry_create_(const char *config_uuid, epg_broadcast_t *e,
lang_str_serialize(l, conf, "description");
lang_str_destroy(l);
}
if (subtitle) {
l = lang_str_create();
lang_str_add(l, subtitle, lang, 0);
lang_str_serialize(l, conf, "subtitle");
lang_str_destroy(l);
}
}
if (content_type)
htsmsg_add_u32(conf, "content_type", content_type->code / 16);
@ -552,7 +565,7 @@ dvr_entry_t *
dvr_entry_create_htsp(const char *config_uuid,
channel_t *ch, time_t start, time_t stop,
time_t start_extra, time_t stop_extra,
const char *title,
const char *title, const char* subtitle,
const char *description, const char *lang,
epg_genre_t *content_type,
const char *owner,
@ -566,7 +579,7 @@ dvr_entry_create_htsp(const char *config_uuid,
return dvr_entry_create_(cfg ? idnode_uuid_as_str(&cfg->dvr_id) : NULL,
NULL,
ch, start, stop, start_extra, stop_extra,
title, description, lang, content_type,
title, subtitle, description, lang, content_type,
owner, creator, dae, NULL, pri, retention,
comment);
}
@ -589,47 +602,109 @@ dvr_entry_create_by_event(const char *config_uuid,
return dvr_entry_create_(config_uuid, e,
e->channel, e->start, e->stop,
start_extra, stop_extra,
NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
LIST_FIRST(&e->episode->genre),
owner, creator, dae, NULL, pri, retention,
comment);
}
static inline int strempty(const char* c) {
return !c || c[0] == 0;
}
static inline int lang_str_empty(lang_str_t* str) {
return strempty(lang_str_get(str, NULL));
}
/**
*
*/
static int _dvr_duplicate_event ( epg_broadcast_t *e )
static dvr_entry_t* _dvr_duplicate_event(dvr_entry_t* de)
{
dvr_entry_t *de;
epg_episode_num_t empty_epnum;
int has_epnum = 1;
if (!de->de_autorec)
return NULL;
/* skip episode duplicate check below if no episode number */
memset(&empty_epnum, 0, sizeof(empty_epnum));
if (epg_episode_number_cmp(&empty_epnum, &e->episode->epnum) == 0)
has_epnum = 0;
int record = de->de_autorec->dae_record;
LIST_FOREACH(de, &dvrentries, de_global_link) {
if (de->de_bcast) {
if (de->de_bcast->episode == e->episode) return 1;
struct tm de_start;
localtime_r(&de->de_start, &de_start);
if (has_epnum) {
int ep_dup_det = de->de_config->dvr_episode_duplicate;
switch (record) {
case DVR_AUTOREC_RECORD_ALL:
return NULL;
case DVR_AUTOREC_RECORD_DIFFERENT_EPISODE_NUMBER:
if (strempty(de->de_episode))
return NULL;
break;
case DVR_AUTOREC_RECORD_DIFFERENT_SUBTITLE:
if (lang_str_empty(de->de_subtitle))
return NULL;
break;
case DVR_AUTOREC_RECORD_DIFFERENT_DESCRIPTION:
if (lang_str_empty(de->de_desc))
return NULL;
break;
case DVR_AUTOREC_RECORD_ONCE_PER_WEEK:
de_start.tm_mday -= (de_start.tm_wday + 6) % 7; // week = mon-sun
mktime(&de_start); // adjusts de_start
break;
}
if (ep_dup_det) {
const char* de_title = lang_str_get(de->de_bcast->episode->title, NULL);
const char* e_title = lang_str_get(e->episode->title, NULL);
// title not defined, can't be deduped
if (lang_str_empty(de->de_title))
return NULL;
/* duplicate if title and episode match */
if (de_title && e_title && strcmp(de_title, e_title) == 0
&& epg_episode_number_cmp(&de->de_bcast->episode->epnum, &e->episode->epnum) == 0) {
return 1;
}
}
dvr_entry_t *de2;
LIST_FOREACH(de2, &dvrentries, de_global_link) {
if (de == de2)
continue;
// only earlier recordings qualify as master
if (de2->de_start > de->de_start)
continue;
// only successful earlier recordings qualify as master
if (de2->de_sched_state == DVR_MISSED_TIME || (de2->de_sched_state == DVR_COMPLETED && de2->de_last_error != SM_CODE_OK))
continue;
// if titles are not defined or do not match, don't dedup
if (lang_str_compare(de->de_title, de2->de_title))
continue;
switch (record) {
case DVR_AUTOREC_RECORD_DIFFERENT_EPISODE_NUMBER:
if (!strcmp(de->de_episode, de2->de_episode))
return de2;
break;
case DVR_AUTOREC_RECORD_DIFFERENT_SUBTITLE:
if (!lang_str_compare(de->de_subtitle, de2->de_subtitle))
return de2;
break;
case DVR_AUTOREC_RECORD_DIFFERENT_DESCRIPTION:
if (!lang_str_compare(de->de_desc, de2->de_desc))
return de2;
break;
case DVR_AUTOREC_RECORD_ONCE_PER_WEEK: {
struct tm de2_start;
localtime_r(&de2->de_start, &de2_start);
de2_start.tm_mday -= (de2_start.tm_wday + 6) % 7; // week = mon-sun
mktime(&de2_start); // adjusts de2_start
if (de_start.tm_year == de2_start.tm_year && de_start.tm_yday == de2_start.tm_yday)
return de2;
break;
}
case DVR_AUTOREC_RECORD_ONCE_PER_DAY: {
struct tm de2_start;
localtime_r(&de2->de_start, &de2_start);
if (de_start.tm_year == de2_start.tm_year && de_start.tm_yday == de2_start.tm_yday)
return de2;
break;
}
}
}
return 0;
return NULL;
}
/**
@ -641,7 +716,11 @@ dvr_entry_create_by_autorec(epg_broadcast_t *e, dvr_autorec_entry_t *dae)
char buf[200];
/* Dup detection */
if (_dvr_duplicate_event(e)) return;
dvr_entry_t* de;
LIST_FOREACH(de, &dvrentries, de_global_link) {
if (de->de_bcast == e || (de->de_bcast && de->de_bcast->episode == e->episode))
return;
}
snprintf(buf, sizeof(buf), "Auto recording%s%s",
dae->dae_creator ? " by: " : "",
@ -651,6 +730,8 @@ dvr_entry_create_by_autorec(epg_broadcast_t *e, dvr_autorec_entry_t *dae)
dae->dae_start_extra, dae->dae_stop_extra,
dae->dae_owner, buf, dae, dae->dae_pri, dae->dae_retention,
dae->dae_comment);
}
/**
@ -684,6 +765,7 @@ dvr_entry_dec_ref(dvr_entry_t *de)
free(de->de_creator);
free(de->de_comment);
if (de->de_title) lang_str_destroy(de->de_title);
if (de->de_subtitle) lang_str_destroy(de->de_subtitle);
if (de->de_desc) lang_str_destroy(de->de_desc);
if (de->de_bcast) de->de_bcast->putref((epg_object_t*)de->de_bcast);
free(de->de_channel_name);
@ -769,7 +851,7 @@ dvr_timer_expire(void *aux)
}
static dvr_entry_t *_dvr_entry_update
( dvr_entry_t *de, epg_broadcast_t *e, const char *title,
( dvr_entry_t *de, epg_broadcast_t *e, const char *title, const char* subtitle,
const char *desc, const char *lang, time_t start, time_t stop,
time_t start_extra, time_t stop_extra, dvr_prio_t pri, int retention )
{
@ -819,7 +901,13 @@ static dvr_entry_t *_dvr_entry_update
if (!de->de_title) de->de_title = lang_str_create();
save = lang_str_add(de->de_title, title, lang, 1);
}
/* Subtitle*/
if (subtitle) {
if (!de->de_subtitle) de->de_subtitle = lang_str_create();
save = lang_str_add(de->de_subtitle, subtitle, lang, 1);
}
/* EID */
if (e && e->dvb_eid != de->de_dvb_eid) {
de->de_dvb_eid = e->dvb_eid;
@ -873,12 +961,12 @@ static dvr_entry_t *_dvr_entry_update
dvr_entry_t *
dvr_entry_update
(dvr_entry_t *de,
const char* de_title, const char *de_desc, const char *lang,
const char* de_title, const char* de_subtitle, const char *de_desc, const char *lang,
time_t de_start, time_t de_stop,
time_t de_start_extra, time_t de_stop_extra,
dvr_prio_t pri, int retention)
{
return _dvr_entry_update(de, NULL, de_title, de_desc, lang,
return _dvr_entry_update(de, NULL, de_title, de_subtitle, de_desc, lang,
de_start, de_stop, de_start_extra, de_stop_extra,
pri, retention);
}
@ -930,7 +1018,7 @@ dvr_event_replaced(epg_broadcast_t *e, epg_broadcast_t *new_e)
e->start, e->stop);
e->getref(e);
de->de_bcast = e;
_dvr_entry_update(de, e, NULL, NULL, NULL, 0, 0, 0, 0, DVR_PRIO_NOTSET, 0);
_dvr_entry_update(de, e, NULL, NULL, NULL, NULL, 0, 0, 0, 0, DVR_PRIO_NOTSET, 0);
break;
}
}
@ -943,7 +1031,7 @@ void dvr_event_updated ( epg_broadcast_t *e )
dvr_entry_t *de;
de = dvr_entry_find_by_event(e);
if (de)
_dvr_entry_update(de, e, NULL, NULL, NULL, 0, 0, 0, 0, DVR_PRIO_NOTSET, 0);
_dvr_entry_update(de, e, NULL, NULL, NULL, NULL, 0, 0, 0, 0, DVR_PRIO_NOTSET, 0);
else {
LIST_FOREACH(de, &dvrentries, de_global_link) {
if (de->de_sched_state != DVR_SCHEDULED) continue;
@ -959,7 +1047,7 @@ void dvr_event_updated ( epg_broadcast_t *e )
e->start, e->stop);
e->getref(e);
de->de_bcast = e;
_dvr_entry_update(de, e, NULL, NULL, NULL, 0, 0, 0, 0, DVR_PRIO_NOTSET, 0);
_dvr_entry_update(de, e, NULL, NULL, NULL, NULL, 0, 0, 0, 0, DVR_PRIO_NOTSET, 0);
break;
}
}
@ -1020,6 +1108,12 @@ dvr_timer_start_recording(void *aux)
return;
}
// if duplicate, then delete it now, don't record!
if (_dvr_duplicate_event(de)) {
dvr_entry_cancel_delete(de);
return;
}
de->de_sched_state = DVR_RECORDING;
de->de_rec_state = DVR_RS_PENDING;
@ -1539,13 +1633,46 @@ dvr_entry_class_disp_title_get(void *o)
return &s;
}
static int
dvr_entry_class_disp_subtitle_set(void *o, const void *v)
{
dvr_entry_t *de = (dvr_entry_t *)o;
const char *s = "";
if (v == NULL || *((char *)v) == '\0')
v = "UnknownSubtitle";
if (de->de_subtitle)
s = lang_str_get(de->de_subtitle, NULL);
if (strcmp(s, v)) {
lang_str_destroy(de->de_subtitle);
de->de_subtitle = lang_str_create();
lang_str_add(de->de_subtitle, v, NULL, 0);
return 1;
}
return 0;
}
static const void *
dvr_entry_class_disp_subtitle_get(void *o)
{
dvr_entry_t *de = (dvr_entry_t *)o;
static const char *s;
s = "";
if (de->de_subtitle) {
s = lang_str_get(de->de_subtitle, NULL);
if (s == NULL)
s = "";
}
return &s;
}
static const void *
dvr_entry_class_disp_description_get(void *o)
{
dvr_entry_t *de = (dvr_entry_t *)o;
static const char *s;
s = "";
if (de->de_title) {
if (de->de_desc) {
s = lang_str_get(de->de_desc, NULL);
if (s == NULL)
s = "";
@ -1654,6 +1781,16 @@ dvr_entry_class_channel_icon_url_get(void *o)
return &s;
}
static const void *
dvr_entry_class_duplicate_get(void *o)
{
static time_t null = 0;
dvr_entry_t *de = (dvr_entry_t *)o;
de = _dvr_duplicate_event(de);
return de ? &de->de_start : &null;
}
htsmsg_t *
dvr_entry_class_duration_list(void *o, const char *not_set, int max, int step)
{
@ -1803,6 +1940,21 @@ const idclass_t dvr_entry_class = {
.set = dvr_entry_class_disp_title_set,
.opts = PO_NOSAVE,
},
{
.type = PT_LANGSTR,
.id = "subtitle",
.name = "Subtitle",
.off = offsetof(dvr_entry_t, de_subtitle),
.opts = PO_RDONLY,
},
{
.type = PT_STR,
.id = "disp_subtitle",
.name = "Subtitle",
.get = dvr_entry_class_disp_subtitle_get,
.set = dvr_entry_class_disp_subtitle_set,
.opts = PO_NOSAVE,
},
{
.type = PT_LANGSTR,
.id = "description",
@ -1984,6 +2136,13 @@ const idclass_t dvr_entry_class = {
.get = dvr_entry_class_sched_status_get,
.opts = PO_RDONLY | PO_NOSAVE | PO_HIDDEN,
},
{
.type = PT_TIME,
.id = "duplicate",
.name = "Rerun of",
.get = dvr_entry_class_duplicate_get,
.opts = PO_RDONLY | PO_NOSAVE,
},
{
.type = PT_STR,
.id = "comment",
@ -2038,7 +2197,7 @@ static struct strtab priotab[] = {
{ "high", DVR_PRIO_HIGH },
{ "normal", DVR_PRIO_NORMAL },
{ "low", DVR_PRIO_LOW },
{ "unimportant", DVR_PRIO_UNIMPORTANT },
{ "unimportant", DVR_PRIO_UNIMPORTANT }
};
dvr_prio_t

View file

@ -155,7 +155,7 @@ dvr_timerec_check(dvr_timerec_entry_t *dte)
dte->dte_creator ?: "");
de = dvr_entry_create_(idnode_uuid_as_str(&dte->dte_config->dvr_id),
NULL, dte->dte_channel,
start, stop, 0, 0, title,
start, stop, 0, 0, title, NULL,
NULL, NULL, NULL, dte->dte_owner, buf,
NULL, dte, dte->dte_pri, dte->dte_retention,
dte->dte_comment);

View file

@ -1289,7 +1289,7 @@ const char *epg_episode_get_subtitle
return lang_str_get(e->subtitle, lang);
}
const char *epg_episode_get_summary
const char *epg_episode_get_summary
( const epg_episode_t *e, const char *lang )
{
if (!e || !e->summary) return NULL;

View file

@ -290,6 +290,8 @@ const char *epg_episode_get_title
( const epg_episode_t *e, const char *lang );
const char *epg_episode_get_subtitle
( const epg_episode_t *e, const char *lang );
lang_str_t *epg_episode_get_subtitle2
( const epg_episode_t *e );
const char *epg_episode_get_summary
( const epg_episode_t *e, const char *lang );
const char *epg_episode_get_description
@ -511,6 +513,8 @@ const char *epg_broadcast_get_title
( epg_broadcast_t *b, const char *lang );
const char *epg_broadcast_get_subtitle
( epg_broadcast_t *b, const char *lang );
lang_str_t *epg_broadcast_get_subtitle2
( epg_broadcast_t *b );
const char *epg_broadcast_get_summary
( epg_broadcast_t *b, const char *lang );
const char *epg_broadcast_get_description

View file

@ -1413,7 +1413,7 @@ htsp_method_addDvrEntry(htsp_connection_t *htsp, htsmsg_t *in)
epg_broadcast_t *e = NULL;
dvr_entry_t *de;
dvr_entry_sched_state_t dvr_status;
const char *dvr_config_name, *title, *desc, *creator, *lang, *comment;
const char *dvr_config_name, *title, *desc, *subtitle, *creator, *lang, *comment;
int64_t start, stop, start_extra, stop_extra;
uint32_t u32, priority, retention;
channel_t *ch = NULL;
@ -1454,6 +1454,10 @@ htsp_method_addDvrEntry(htsp_connection_t *htsp, htsmsg_t *in)
!(title = htsmsg_get_str(in, "title")))
return htsp_error("Invalid arguments");
/* Optional attributes */
if (!(subtitle = htsmsg_get_str(in, "subtitle")))
subtitle = "";
/* Optional attributes */
if (!(desc = htsmsg_get_str(in, "description")))
desc = "";
@ -1461,7 +1465,7 @@ htsp_method_addDvrEntry(htsp_connection_t *htsp, htsmsg_t *in)
// create the dvr entry
de = dvr_entry_create_htsp(dvr_config_name, ch, start, stop,
start_extra, stop_extra,
title, desc, lang, 0,
title, subtitle, desc, lang, 0,
htsp->htsp_granted_access->aa_username,
creator, NULL,
priority, retention, comment);
@ -1506,7 +1510,7 @@ htsp_method_updateDvrEntry(htsp_connection_t *htsp, htsmsg_t *in)
uint32_t dvrEntryId;
dvr_entry_t *de;
time_t start, stop, start_extra, stop_extra, priority, retention;
const char *title, *desc, *lang;
const char *title, *subtitle, *desc, *lang;
if(htsmsg_get_u32(in, "id", &dvrEntryId))
return htsp_error("Missing argument 'id'");
@ -1528,11 +1532,12 @@ htsp_method_updateDvrEntry(htsp_connection_t *htsp, htsmsg_t *in)
retention = htsmsg_get_u32_or_default(in, "retention", 0);
priority = htsmsg_get_u32_or_default(in, "priority", DVR_PRIO_NORMAL);
title = htsmsg_get_str(in, "title");
subtitle = htsmsg_get_str(in, "title");
desc = htsmsg_get_str(in, "description");
lang = htsmsg_get_str(in, "language");
if (!lang) lang = htsp->htsp_language;
de = dvr_entry_update(de, title, desc, lang, start, stop,
de = dvr_entry_update(de, title, subtitle, desc, lang, start, stop,
start_extra, stop_extra, priority, retention);
//create response

View file

@ -799,7 +799,7 @@ main(int argc, char **argv)
OPENSSL_config(NULL);
SSL_load_error_strings();
SSL_library_init();
/* Initialise configuration */
uuid_init();
idnode_init();

View file

@ -11,14 +11,15 @@ tvheadend.dvrDetails = function(uuid) {
var params = d[0].params;
var chicon = params[0].value;
var title = params[1].value;
var episode = params[2].value;
var start_real = params[3].value;
var stop_real = params[4].value;
var duration = params[5].value;
var desc = params[6].value;
var status = params[7].value;
var filesize = params[8].value;
var comment = params[9].value;
var subtitle = params[2].value;
var episode = params[3].value;
var start_real = params[4].value;
var stop_real = params[5].value;
var duration = params[6].value;
var desc = params[7].value;
var status = params[8].value;
var filesize = params[9].value;
var comment = params[10].value;
var content = '';
var but;
@ -27,6 +28,8 @@ tvheadend.dvrDetails = function(uuid) {
if (title)
content += '<div class="x-epg-title">' + title + '</div>';
if (subtitle)
content += '<div class="x-epg-title">' + subtitle + '</div>';
if (episode)
content += '<div class="x-epg-title">' + episode + '</div>';
if (start_real)
@ -64,7 +67,7 @@ tvheadend.dvrDetails = function(uuid) {
url: 'api/idnode/load',
params: {
uuid: uuid,
list: 'channel_icon,disp_title,episode,start_real,stop_real,' +
list: 'channel_icon,disp_title,disp_subtitle,episode,start_real,stop_real,' +
'duration,disp_description,status,filesize,comment'
},
success: function(d) {
@ -214,7 +217,7 @@ tvheadend.dvr_upcoming = function(panel, index) {
}
},
del: true,
list: 'disp_title,episode,pri,start_real,stop_real,' +
list: 'duplicate,disp_title,disp_subtitle,episode,pri,start_real,stop_real,' +
'duration,filesize,channel,owner,creator,config_name,' +
'sched_status,errors,data_errors,comment',
columns: {
@ -282,7 +285,7 @@ tvheadend.dvr_finished = function(panel, index) {
del: true,
delquestion: 'Do you really want to delete the selected recordings?<br/><br/>' +
'The associated file will be removed from the storage.',
list: 'disp_title,episode,start_real,stop_real,' +
list: 'disp_title,disp_subtitle,episode,start_real,stop_real,' +
'duration,filesize,channelname,owner,creator,' +
'config_name,sched_status,errors,data_errors,url,comment',
columns: {
@ -362,7 +365,7 @@ tvheadend.dvr_failed = function(panel, index) {
del: true,
delquestion: 'Do you really want to delete the selected recordings?<br/><br/>' +
'The associated file will be removed from the storage.',
list: 'disp_title,episode,start_real,stop_real,' +
list: 'disp_title,disp_subtitle,episode,start_real,stop_real,' +
'duration,filesize,channelname,owner,creator,config_name,' +
'status,sched_status,errors,data_errors,url,comment',
columns: {
@ -457,6 +460,7 @@ tvheadend.autorec_editor = function(panel, index) {
renderer: function(st) { return tvheadend.weekdaysRenderer(st); }
},
pri: { width: 80 },
dedup: { width: 160 },
retention: { width: 80 },
config_name: { width: 120 },
owner: { width: 100 },
@ -467,13 +471,13 @@ tvheadend.autorec_editor = function(panel, index) {
url: 'api/dvr/autorec',
params: {
list: 'enabled,name,directory,title,fulltext,channel,tag,content_type,minduration,' +
'maxduration,weekdays,start,start_window,pri,config_name,comment'
'maxduration,weekdays,start,start_window,pri,dedup,config_name,comment'
},
create: { }
},
del: true,
list: 'enabled,name,directory,title,fulltext,channel,tag,content_type,minduration,' +
'maxduration,weekdays,start,start_window,pri,config_name,owner,creator,comment',
'maxduration,weekdays,start,start_window,pri,dedup,config_name,owner,creator,comment',
sort: {
field: 'name',
direction: 'ASC'