]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
[dvr] add "directory" option to auto and time recorder entries to htsp/19
authorSam Stenvall <neggelandia@gmail.com>
Wed, 7 Jan 2015 10:33:42 +0000 (12:33 +0200)
committerJaroslav Kysela <perex@perex.cz>
Wed, 7 Jan 2015 14:56:15 +0000 (15:56 +0100)
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

docs/html/dvr_autorec.html
docs/html/dvr_timerec.html
src/dvr/dvr.h
src/dvr/dvr_autorec.c
src/dvr/dvr_db.c
src/dvr/dvr_rec.c
src/dvr/dvr_timerec.c
src/htsp_server.c
src/webui/static/app/dvr.js

index 1a482ecfd69cf31d36cd1e6ac6b6c0bcf2db0d4c..a69e4e041393c376400dd0c76aeea33c26f527c2 100644 (file)
@@ -51,6 +51,10 @@ Check or clear this box to enable or disable this rule.
 <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.
index 9643d280011a78d51bae4799d901473268ad0438..083e76bbedce0a3d0293026af90ce41896627480 100644 (file)
@@ -50,6 +50,10 @@ Check or clear this box to enable or disable this rule.
 <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* *
index c4f1a93c13caa14a5ab3aaedddffe2123808c424..91bd209600396634f7fb21c579611abbd3bec019 100644 (file)
@@ -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) */
@@ -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;
 
@@ -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;
 
@@ -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,
@@ -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)
index be7ef861b3499ea165e72a3db6186093e6986294..7e5f07096d6a9785a38125ad4fbb5d6898234958 100644 (file)
@@ -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;
@@ -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);
@@ -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);
@@ -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,
index 91f233461cc10f5474f10e087764e403b31103c2..f96c84c6cf77879b91aeae4129605b602247ae24 100644 (file)
@@ -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);
 
@@ -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",
@@ -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;
 
index ab893fbdb91c0dd35b2f6ab184f0d3d3ac606788..7784e2c324eb5bf274952aa535b13d16775589d5 100644 (file)
@@ -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)
index a593318a0118fc1acbda6c75cc5c71e354091f15..5d29577635c9d49afbb5a6861c2bc3ee6140ded0 100644 (file)
@@ -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;
@@ -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);
 
@@ -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",
index 673540a57e63c7d9fe37039276dfdb3be27a3787..2206d48474166582ed70603e77430319d52ba7db 100644 (file)
@@ -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
@@ -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);
 
@@ -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);
 
@@ -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;
@@ -1637,6 +1641,8 @@ 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))
@@ -1644,7 +1650,7 @@ htsp_method_addAutorecEntry(htsp_connection_t *htsp, htsmsg_t *in)
 
   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();
@@ -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;
 
@@ -1728,6 +1734,8 @@ 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))
@@ -1735,7 +1743,7 @@ htsp_method_addTimerecEntry(htsp_connection_t *htsp, htsmsg_t *in)
 
   /* 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();
index 2d81cfd86c6b7c8ac38da6ccb98f5ee33bb2283e..d617076a9d9a2975b796085280aaeeacdd35453a 100644 (file)
@@ -434,6 +434,7 @@ tvheadend.autorec_editor = function(panel, index) {
         columns: {
             enabled:      { width: 50 },
             name:         { width: 200 },
+            directory:    { width: 200 },
             title:        { width: 300 },
             channel:      { width: 200 },
             tag:          { width: 200 },
@@ -452,13 +453,13 @@ tvheadend.autorec_editor = function(panel, index) {
         add: {
             url: 'api/dvr/autorec',
             params: {
-               list: 'enabled,name,title,channel,tag,content_type,minduration,' +
+               list: 'enabled,name,directory,title,channel,tag,content_type,minduration,' +
                      'maxduration,weekdays,start,start_window,pri,config_name,comment'
             },
             create: { }
         },
         del: true,
-        list: 'enabled,name,title,channel,tag,content_type,minduration,' +
+        list: 'enabled,name,directory,title,channel,tag,content_type,minduration,' +
               'maxduration,weekdays,start,start_window,pri,config_name,owner,creator,comment',
         columns: {
             weekdays: {
@@ -492,6 +493,7 @@ tvheadend.timerec_editor = function(panel, index) {
         columns: {
             enabled:      { width: 50 },
             name:         { width: 200 },
+            directory:    { width: 200 },
             title:        { width: 300 },
             channel:      { width: 200 },
             weekdays:     { width: 160 },
@@ -506,12 +508,12 @@ tvheadend.timerec_editor = function(panel, index) {
         add: {
             url: 'api/dvr/timerec',
             params: {
-               list: 'enabled,name,title,channel,weekdays,start,stop,pri,config_name,comment'
+               list: 'enabled,name,directory,title,channel,weekdays,start,stop,pri,config_name,comment'
             },
             create: { }
         },
         del: true,
-        list: 'enabled,name,title,channel,weekdays,start,stop,pri,config_name,owner,creator,comment',
+        list: 'enabled,name,directory,title,channel,weekdays,start,stop,pri,config_name,owner,creator,comment',
         columns: {
             weekdays: {
                 renderer: function(st) { return tvheadend.weekdaysRenderer(st); }