Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[dvr] add "directory" option to auto and time recorder entries to
override directory settings for matching recordings.

Useful for e.g. recording multiple different shows into a single
directory (e.g. news).

Fixes #2123, fixes #2448
  • Loading branch information
Jalle19 authored and perexg committed Jan 7, 2015
1 parent 09bd4c4 commit c51b162
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 48 deletions.
4 changes: 4 additions & 0 deletions docs/html/dvr_autorec.html
Expand Up @@ -51,6 +51,10 @@
<dd>
The name you've given to the rule, e.g. 'Stuff involving Jeremy Clarkson'.
<p>
<dt><b>Directory</b>
<dd>
When specified, this setting overrides the subdirectory rules specified by the DVR configuration and puts all recordings done by this entry into the specified subdirectory. Useful for e.g. recording multiple different news broadcasts into one common subdirectory called "News".
<p>
<dt><b>Title (Regexp)</b>
<dd>
The title of the programme to look for. Note that this accepts case-insensitive regular expressions, so you can use pattern matching as Tvheadend scans the EPG for programmes to record.
Expand Down
4 changes: 4 additions & 0 deletions docs/html/dvr_timerec.html
Expand Up @@ -50,6 +50,10 @@
<dd>
The name you've given to the rule, e.g. 'Evening cartoons for the children'.
<p>
<dt><b>Directory</b>
<dd>
When specified, this setting overrides the subdirectory rules specified by the DVR configuration and puts all recordings done by this entry into the specified subdirectory. Useful for e.g. recording multiple different news broadcasts into one common subdirectory called "News".
<p>
<dt><b>Title</b>
<dd>
Not sure how this differs from **Name* *
Expand Down
9 changes: 7 additions & 2 deletions src/dvr/dvr.h
Expand Up @@ -159,6 +159,8 @@ typedef struct dvr_entry {
char *de_comment;
char *de_filename; /* Initially null if no filename has been
generated yet */
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_desc; /* Description in UTF-8 (from EPG) */
uint32_t de_content_type; /* Content type (from EPG) (only code) */
Expand Down Expand Up @@ -240,6 +242,7 @@ typedef struct dvr_autorec_entry {
TAILQ_ENTRY(dvr_autorec_entry) dae_link;

char *dae_name;
char *dae_directory;
dvr_config_t *dae_config;
LIST_ENTRY(dvr_autorec_entry) dae_config_link;

Expand Down Expand Up @@ -294,6 +297,7 @@ typedef struct dvr_timerec_entry {
TAILQ_ENTRY(dvr_timerec_entry) dte_link;

char *dte_name;
char *dte_directory;
dvr_config_t *dte_config;
LIST_ENTRY(dvr_timerec_entry) dte_config_link;

Expand Down Expand Up @@ -490,7 +494,7 @@ dvr_autorec_create_htsp(const char *dvr_config_name, const char *title,
time_t stop_extra, dvr_prio_t pri, int retention,
int min_duration, int max_duration,
const char *owner, const char *creator,
const char *comment, const char *name);
const char *comment, const char *name, const char *directory);

dvr_autorec_entry_t *
dvr_autorec_add_series_link(const char *dvr_config_name,
Expand Down Expand Up @@ -542,7 +546,8 @@ dvr_timerec_entry_t*
dvr_timerec_create_htsp(const char *dvr_config_name, const char *title,
channel_t *ch, uint32_t enabled, uint32_t start, uint32_t stop,
uint32_t weekdays, dvr_prio_t pri, int retention,
const char *owner, const char *creator, const char *comment, const char *name);
const char *owner, const char *creator, const char *comment,
const char *name, const char *directory);

static inline dvr_timerec_entry_t *
dvr_timerec_find_by_uuid(const char *uuid)
Expand Down
11 changes: 10 additions & 1 deletion src/dvr/dvr_autorec.c
Expand Up @@ -210,7 +210,8 @@ dvr_autorec_create_htsp(const char *dvr_config_name, const char *title,
uint32_t weekdays, time_t start_extra, time_t stop_extra,
dvr_prio_t pri, int retention,
int min_duration, int max_duration,
const char *owner, const char *creator, const char *comment, const char *name)
const char *owner, const char *creator, const char *comment,
const char *name, const char *directory)
{
dvr_autorec_entry_t *dae;
htsmsg_t *conf, *days;
Expand All @@ -231,6 +232,7 @@ dvr_autorec_create_htsp(const char *dvr_config_name, const char *title,
htsmsg_add_str(conf, "creator", creator ?: "");
htsmsg_add_str(conf, "comment", comment ?: "");
htsmsg_add_str(conf, "name", name ?: "");
htsmsg_add_str(conf, "directory", directory ?: "");

if (start >= 0)
htsmsg_add_s32(conf, "start", start);
Expand Down Expand Up @@ -308,6 +310,7 @@ autorec_entry_destroy(dvr_autorec_entry_t *dae, int delconf)
LIST_REMOVE(dae, dae_config_link);

free(dae->dae_name);
free(dae->dae_directory);
free(dae->dae_owner);
free(dae->dae_creator);
free(dae->dae_comment);
Expand Down Expand Up @@ -848,6 +851,12 @@ const idclass_t dvr_autorec_entry_class = {
.id = "name",
.name = "Name",
.off = offsetof(dvr_autorec_entry_t, dae_name),
},
{
.type = PT_STR,
.id = "directory",
.name = "Directory",
.off = offsetof(dvr_autorec_entry_t, dae_directory),
},
{
.type = PT_STR,
Expand Down
15 changes: 14 additions & 1 deletion src/dvr/dvr_db.c
Expand Up @@ -514,9 +514,15 @@ dvr_entry_create_(const char *config_uuid, epg_broadcast_t *e,
if (e)
htsmsg_add_u32(conf, "broadcast", e->id);
if (dae)
{
htsmsg_add_str(conf, "autorec", idnode_uuid_as_str(&dae->dae_id));
htsmsg_add_str(conf, "directory", dae->dae_directory ?: "");
}
if (dte)
{
htsmsg_add_str(conf, "timerec", idnode_uuid_as_str(&dte->dte_id));
htsmsg_add_str(conf, "directory", dte->dte_directory ?: "");
}

de = dvr_entry_create(NULL, conf);

Expand Down Expand Up @@ -1845,6 +1851,13 @@ const idclass_t dvr_entry_class = {
.off = offsetof(dvr_entry_t, de_filename),
.opts = PO_RDONLY,
},
{
.type = PT_STR,
.id = "directory",
.name = "Directory",
.off = offsetof(dvr_entry_t, de_directory),
.opts = PO_RDONLY,
},
{
.type = PT_U32,
.id = "errorcode",
Expand Down Expand Up @@ -2047,7 +2060,7 @@ dvr_entry_delete(dvr_entry_t *de)

snprintf(path, sizeof(path), "%s", cfg->dvr_storage);

if(cfg->dvr_title_dir || cfg->dvr_channel_dir || cfg->dvr_dir_per_day) {
if(cfg->dvr_title_dir || cfg->dvr_channel_dir || cfg->dvr_dir_per_day || de->de_directory) {
char *p;
int l;

Expand Down
59 changes: 35 additions & 24 deletions src/dvr/dvr_rec.c
Expand Up @@ -198,39 +198,50 @@ pvr_generate_filename(dvr_entry_t *de, const streaming_start_t *ss)
if (path[strlen(path)-1] == '/')
path[strlen(path)-1] = '\0';

/* Append per-day directory */
if (cfg->dvr_dir_per_day) {
localtime_r(&de->de_start, &tm);
strftime(fullname, sizeof(fullname), "%F", &tm);
s = cleanup_filename(fullname, cfg);
/* Use the specified directory if set, otherwise construct it from the DVR
configuration */
if (de->de_directory) {
char *directory = strdup(de->de_directory);
s = cleanup_filename(directory, cfg);
if (s == NULL)
return -1;
snprintf(path + strlen(path), sizeof(path) - strlen(path), "/%s", s);
free(s);
}
} else {
/* Append per-day directory */
if (cfg->dvr_dir_per_day) {
localtime_r(&de->de_start, &tm);
strftime(fullname, sizeof(fullname), "%F", &tm);
s = cleanup_filename(fullname, cfg);
if (s == NULL)
return -1;
snprintf(path + strlen(path), sizeof(path) - strlen(path), "/%s", s);
free(s);
}

/* Append per-channel directory */
if (cfg->dvr_channel_dir) {
char *chname = strdup(DVR_CH_NAME(de));
s = cleanup_filename(chname, cfg);
free(chname);
if (s == NULL)
/* Append per-channel directory */
if (cfg->dvr_channel_dir) {
char *chname = strdup(DVR_CH_NAME(de));
s = cleanup_filename(chname, cfg);
free(chname);
if (s == NULL)
return -1;
snprintf(path + strlen(path), sizeof(path) - strlen(path), "/%s", s);
free(s);
}
snprintf(path + strlen(path), sizeof(path) - strlen(path), "/%s", s);
free(s);
}

// TODO: per-brand, per-season
// TODO: per-brand, per-season

/* Append per-title directory */
if (cfg->dvr_title_dir) {
char *title = strdup(lang_str_get(de->de_title, NULL));
s = cleanup_filename(title, cfg);
free(title);
if (s == NULL)
/* Append per-title directory */
if (cfg->dvr_title_dir) {
char *title = strdup(lang_str_get(de->de_title, NULL));
s = cleanup_filename(title, cfg);
free(title);
if (s == NULL)
return -1;
snprintf(path + strlen(path), sizeof(path) - strlen(path), "/%s", s);
free(s);
snprintf(path + strlen(path), sizeof(path) - strlen(path), "/%s", s);
free(s);
}
}

if (makedirs(path, cfg->dvr_muxcnf.m_directory_permissions) != 0)
Expand Down
10 changes: 9 additions & 1 deletion src/dvr/dvr_timerec.c
Expand Up @@ -204,7 +204,8 @@ dvr_timerec_entry_t*
dvr_timerec_create_htsp(const char *dvr_config_name, const char *title,
channel_t *ch, uint32_t enabled, uint32_t start, uint32_t stop,
uint32_t weekdays, dvr_prio_t pri, int retention,
const char *owner, const char *creator, const char *comment, const char *name)
const char *owner, const char *creator, const char *comment,
const char *name, const char *directory)
{
dvr_timerec_entry_t *dte;
htsmsg_t *conf, *days;
Expand All @@ -221,6 +222,7 @@ dvr_timerec_create_htsp(const char *dvr_config_name, const char *title,
htsmsg_add_str(conf, "creator", creator ?: "");
htsmsg_add_str(conf, "comment", comment ?: "");
htsmsg_add_str(conf, "name", name ?: "");
htsmsg_add_str(conf, "directory", directory ?: "");
htsmsg_add_u32(conf, "start", start);
htsmsg_add_u32(conf, "stop", stop);

Expand Down Expand Up @@ -539,6 +541,12 @@ const idclass_t dvr_timerec_entry_class = {
.off = offsetof(dvr_timerec_entry_t, dte_title),
.def.s = "Time-%x-%R",
},
{
.type = PT_STR,
.id = "directory",
.name = "Directory",
.off = offsetof(dvr_timerec_entry_t, dte_directory),
},
{
.type = PT_STR,
.id = "channel",
Expand Down
38 changes: 23 additions & 15 deletions src/htsp_server.c
Expand Up @@ -68,7 +68,7 @@

static void *htsp_server, *htsp_server_2;

#define HTSP_PROTO_VERSION 18
#define HTSP_PROTO_VERSION 19

#define HTSP_ASYNC_OFF 0x00
#define HTSP_ASYNC_ON 0x01
Expand Down Expand Up @@ -766,15 +766,17 @@ htsp_build_autorecentry(dvr_autorec_entry_t *dae, const char *method)
htsmsg_add_s64(out, "stopExtra", dae->dae_stop_extra);

if(dae->dae_title)
htsmsg_add_str(out, "title", dae->dae_title);
htsmsg_add_str(out, "title", dae->dae_title);
if(dae->dae_name)
htsmsg_add_str(out, "name", dae->dae_name);
htsmsg_add_str(out, "name", dae->dae_name);
if(dae->dae_directory)
htsmsg_add_str(out, "directory", dae->dae_directory);
if(dae->dae_owner)
htsmsg_add_str(out, "owner", dae->dae_owner);
htsmsg_add_str(out, "owner", dae->dae_owner);
if(dae->dae_creator)
htsmsg_add_str(out, "creator", dae->dae_creator);
htsmsg_add_str(out, "creator", dae->dae_creator);
if(dae->dae_channel)
htsmsg_add_u32(out, "channel", channel_get_id(dae->dae_channel));
htsmsg_add_u32(out, "channel", channel_get_id(dae->dae_channel));

htsmsg_add_str(out, "method", method);

Expand All @@ -798,15 +800,17 @@ htsp_build_timerecentry(dvr_timerec_entry_t *dte, const char *method)
htsmsg_add_s32(out, "stop", dte->dte_stop);

if(dte->dte_title)
htsmsg_add_str(out, "title", dte->dte_title);
htsmsg_add_str(out, "title", dte->dte_title);
if(dte->dte_name)
htsmsg_add_str(out, "name", dte->dte_name);
htsmsg_add_str(out, "name", dte->dte_name);
if(dte->dte_directory)
htsmsg_add_str(out, "directory", dte->dte_directory);
if(dte->dte_owner)
htsmsg_add_str(out, "owner", dte->dte_owner);
htsmsg_add_str(out, "owner", dte->dte_owner);
if(dte->dte_creator)
htsmsg_add_str(out, "creator", dte->dte_creator);
htsmsg_add_str(out, "creator", dte->dte_creator);
if(dte->dte_channel)
htsmsg_add_u32(out, "channel", channel_get_id(dte->dte_channel));
htsmsg_add_u32(out, "channel", channel_get_id(dte->dte_channel));

htsmsg_add_str(out, "method", method);

Expand Down Expand Up @@ -1588,7 +1592,7 @@ htsp_method_addAutorecEntry(htsp_connection_t *htsp, htsmsg_t *in)
{
htsmsg_t *out;
dvr_autorec_entry_t *dae;
const char *dvr_config_name, *title, *creator, *comment, *name;
const char *dvr_config_name, *title, *creator, *comment, *name, *directory;
int64_t start_extra, stop_extra;
uint32_t u32, days_of_week, priority, min_duration, max_duration, retention, enabled;
int32_t approx_time, start, start_window;
Expand Down Expand Up @@ -1637,14 +1641,16 @@ htsp_method_addAutorecEntry(htsp_connection_t *htsp, htsmsg_t *in)
comment = "";
if (!(name = htsmsg_get_str(in, "name")))
name = "";
if (!(directory = htsmsg_get_str(in, "directory")))
directory = "";

/* Check access */
if (ch && !htsp_user_access_channel(htsp, ch))
return htsp_error("User does not have access");

dae = dvr_autorec_create_htsp(dvr_config_name, title, ch, enabled, start, start_window, days_of_week,
start_extra, stop_extra, priority, retention, min_duration, max_duration,
htsp->htsp_granted_access->aa_username, creator, comment, name);
htsp->htsp_granted_access->aa_username, creator, comment, name, directory);

/* create response */
out = htsmsg_create_map();
Expand Down Expand Up @@ -1697,7 +1703,7 @@ htsp_method_addTimerecEntry(htsp_connection_t *htsp, htsmsg_t *in)
{
htsmsg_t *out;
dvr_timerec_entry_t *dte;
const char *dvr_config_name, *title, *creator, *comment, *name;
const char *dvr_config_name, *title, *creator, *comment, *name, *directory;
uint32_t u32, days_of_week, priority, retention, start, stop, enabled;
channel_t *ch = NULL;

Expand Down Expand Up @@ -1728,14 +1734,16 @@ htsp_method_addTimerecEntry(htsp_connection_t *htsp, htsmsg_t *in)
comment = "";
if (!(name = htsmsg_get_str(in, "name")))
name = "";
if (!(directory = htsmsg_get_str(in, "directory")))
directory = "";

/* Check access */
if (ch && !htsp_user_access_channel(htsp, ch))
return htsp_error("User does not have access");

/* Add actual timerec */
dte = dvr_timerec_create_htsp(dvr_config_name, title, ch, enabled, start, stop, days_of_week,
priority, retention, htsp->htsp_granted_access->aa_username, creator, comment, name);
priority, retention, htsp->htsp_granted_access->aa_username, creator, comment, name, directory);

/* create response */
out = htsmsg_create_map();
Expand Down

0 comments on commit c51b162

Please sign in to comment.