]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
make timerec and autorec updateable
authorGlenn-1990 <g_christiaensen@msn.com>
Wed, 4 Nov 2015 12:14:31 +0000 (13:14 +0100)
committerJaroslav Kysela <perex@perex.cz>
Thu, 5 Nov 2015 19:03:55 +0000 (20:03 +0100)
src/dvr/dvr.h
src/dvr/dvr_autorec.c
src/dvr/dvr_timerec.c
src/htsp_server.c

index 13be260e3130786fe75403959c81b3949de17842..d1671be48efd72b70c33565a252335c8aa4df1a9 100644 (file)
@@ -567,13 +567,9 @@ dvr_entry_create_(int enabled, const char *config_uuid, epg_broadcast_t *e,
                   dvr_prio_t pri, int retention, int removal, const char *comment);
 
 dvr_autorec_entry_t *
-dvr_autorec_create_htsp(const char *dvr_config_name, const char *title, int fulltext,
-                            channel_t *ch, uint32_t enabled, int32_t start,
-                            int32_t start_window, uint32_t days, time_t start_extra,
-                            time_t stop_extra, dvr_prio_t pri, int retention, int removal,
-                            int min_duration, int max_duration, dvr_autorec_dedup_t dup_detect,
-                            const char *owner, const char *creator,
-                            const char *comment, const char *name, const char *directory);
+dvr_autorec_create_htsp(htsmsg_t *conf);
+
+void dvr_autorec_update_htsp(dvr_autorec_entry_t *dae, htsmsg_t *conf);
 
 dvr_autorec_entry_t *
 dvr_autorec_add_series_link(const char *dvr_config_name,
@@ -644,11 +640,9 @@ dvr_timerec_entry_t *
 dvr_timerec_create(const char *uuid, htsmsg_t *conf);
 
 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, int removal,
-                            const char *owner, const char *creator, const char *comment, 
-                            const char *name, const char *directory);
+dvr_timerec_create_htsp(htsmsg_t *conf);
+
+void dvr_timerec_update_htsp(dvr_timerec_entry_t *dte, htsmsg_t *conf);
 
 static inline dvr_timerec_entry_t *
 dvr_timerec_find_by_uuid(const char *uuid)
index 9be718798ea409cd838b9100f4677018e5e544c3..ffcbd348b96735f94936aeeda63c9236344afcca 100644 (file)
@@ -273,51 +273,9 @@ dvr_autorec_create(const char *uuid, htsmsg_t *conf)
 
 
 dvr_autorec_entry_t*
-dvr_autorec_create_htsp(const char *dvr_config_name, const char *title, int fulltext,
-                            channel_t *ch, uint32_t enabled, int32_t start, int32_t start_window,
-                            uint32_t weekdays, time_t start_extra, time_t stop_extra,
-                            dvr_prio_t pri, int retention, int removal,
-                            int min_duration, int max_duration, dvr_autorec_dedup_t dup_detect,
-                            const char *owner, const char *creator, const char *comment, 
-                            const char *name, const char *directory)
+dvr_autorec_create_htsp(htsmsg_t *conf)
 {
   dvr_autorec_entry_t *dae;
-  htsmsg_t *conf, *days;
-
-  conf = htsmsg_create_map();
-  days = htsmsg_create_list();
-
-  htsmsg_add_u32(conf, "enabled",     enabled > 0 ? 1 : 0);
-  htsmsg_add_u32(conf, "retention",   retention);
-  htsmsg_add_u32(conf, "removal",     removal);
-  htsmsg_add_u32(conf, "pri",         pri);
-  htsmsg_add_u32(conf, "minduration", min_duration);
-  htsmsg_add_u32(conf, "maxduration", max_duration);
-  htsmsg_add_s64(conf, "start_extra", start_extra);
-  htsmsg_add_s64(conf, "stop_extra",  stop_extra);
-  htsmsg_add_str(conf, "title",       title);
-  htsmsg_add_u32(conf, "fulltext",    fulltext);
-  htsmsg_add_u32(conf, "record",      dup_detect);
-  htsmsg_add_str(conf, "config_name", dvr_config_name ?: "");
-  htsmsg_add_str(conf, "owner",       owner ?: "");
-  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);
-  if (start_window >= 0)
-    htsmsg_add_s32(conf, "start_window", start_window);
-  if (ch)
-    htsmsg_add_str(conf, "channel", idnode_uuid_as_sstr(&ch->ch_id));
-
-  int i;
-  for (i = 0; i < 7; i++)
-    if (weekdays & (1 << i))
-      htsmsg_add_u32(days, NULL, i + 1);
-
-  htsmsg_add_msg(conf, "weekdays", days);
 
   dae = dvr_autorec_create(NULL, conf);
   htsmsg_destroy(conf);
@@ -330,6 +288,16 @@ dvr_autorec_create_htsp(const char *dvr_config_name, const char *title, int full
   return dae;
 }
 
+void
+dvr_autorec_update_htsp(dvr_autorec_entry_t *dae, htsmsg_t *conf)
+{
+  idnode_update(&dae->dae_id, conf);
+  dvr_autorec_save(dae);
+  dvr_autorec_changed(dae, 1);
+  tvhlog(LOG_INFO, "autorec", "\"%s\" on \"%s\": Updated", dae->dae_title ? dae->dae_title : "",
+      (dae->dae_channel && dae->dae_channel->ch_name) ? dae->dae_channel->ch_name : "any channel");
+}
+
 /**
  *
  */
index 58aff0dc980a7dbf8cc8f933c9ded381d88d3406..fc99331d28ff6c209b0b0d905c53d32aef914f96 100644 (file)
@@ -202,47 +202,14 @@ dvr_timerec_create(const char *uuid, htsmsg_t *conf)
 }
 
 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, int removal,
-                            const char *owner, const char *creator, const char *comment, 
-                            const char *name, const char *directory)
+dvr_timerec_create_htsp(htsmsg_t *conf)
 {
   dvr_timerec_entry_t *dte;
-  htsmsg_t *conf, *days;
-
-  conf = htsmsg_create_map();
-  days = htsmsg_create_list();
-
-  htsmsg_add_u32(conf, "enabled",     enabled > 0 ? 1 : 0);
-  htsmsg_add_u32(conf, "retention",   retention);
-  htsmsg_add_u32(conf, "removal",     removal);
-  htsmsg_add_u32(conf, "pri",         pri);
-  htsmsg_add_str(conf, "title",       title);
-  htsmsg_add_str(conf, "config_name", dvr_config_name ?: "");
-  htsmsg_add_str(conf, "owner",       owner ?: "");
-  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);
-
-  if (ch)
-    htsmsg_add_str(conf, "channel", idnode_uuid_as_sstr(&ch->ch_id));
-
-  int i;
-  for (i = 0; i < 7; i++)
-    if (weekdays & (1 << i))
-      htsmsg_add_u32(days, NULL, i + 1);
-
-  htsmsg_add_msg(conf, "weekdays", days);
 
   dte = dvr_timerec_create(NULL, conf);
   htsmsg_destroy(conf);
 
-  if (dte)
-  {
+  if (dte) {
     dvr_timerec_save(dte);
     dvr_timerec_check(dte);
   }
@@ -250,6 +217,17 @@ dvr_timerec_create_htsp(const char *dvr_config_name, const char *title,
   return dte;
 }
 
+void
+dvr_timerec_update_htsp (dvr_timerec_entry_t *dte, htsmsg_t *conf)
+{
+  idnode_update(&dte->dte_id, conf);
+  dvr_timerec_save(dte);
+  dvr_timerec_check(dte);
+  htsp_timerec_entry_update(dte);
+  tvhlog(LOG_INFO, "timerec", "\"%s\" on \"%s\": Updated", dte->dte_title ? dte->dte_title : "",
+      (dte->dte_channel && dte->dte_channel->ch_name) ? dte->dte_channel->ch_name : "any channel");
+}
+
 /**
  *
  */
index a88101be9a6ff9570c556d513b7e0bf173282012..44620bc9341732240d3e7e69529ee8c540e3ba2b 100644 (file)
@@ -487,6 +487,150 @@ htsp_user_access_channel(htsp_connection_t *htsp, channel_t *ch)
 if (!htsp_user_access_channel(htsp, ch))\
   return htsp_error("User cannot access this channel");
 
+static const char *
+htsp_dvr_config_name( htsp_connection_t *htsp, const char *config_name )
+{
+  dvr_config_t *cfg = NULL, *cfg2;
+  access_t *perm = htsp->htsp_granted_access;
+  htsmsg_field_t *f;
+  const char *uuid;
+  static char ubuf[UUID_HEX_SIZE];
+
+  lock_assert(&global_lock);
+
+  config_name = config_name ?: "";
+
+  if (perm->aa_dvrcfgs == NULL)
+    return config_name; /* no change */
+
+  HTSMSG_FOREACH(f, perm->aa_dvrcfgs) {
+    uuid = htsmsg_field_get_str(f) ?: "";
+    if (strcmp(uuid, config_name) == 0)
+      return config_name;
+    cfg2 = dvr_config_find_by_uuid(uuid);
+    if (cfg2 && strcmp(cfg2->dvr_config_name, config_name) == 0)
+      return uuid;
+    if (!cfg)
+      cfg = cfg2;
+  }
+
+  if (!cfg && perm->aa_username)
+    tvhlog(LOG_INFO, "htsp", "User '%s' has no valid dvr config in ACL, using default...", perm->aa_username);
+
+  return cfg ? idnode_uuid_as_str(&cfg->dvr_id, ubuf) : NULL;
+}
+
+/**
+ * Converts htsp input to internal API
+ * @param htsp, current htsp connection
+ * @param in, the htsp message input from client
+ * @param autorec, true for autorecs, false for timerecs
+ * @param add, true for new instances, false for update calls
+ * @return the htsmsg_t config to be added or updated with idnode
+ */
+static htsmsg_t *
+serierec_convert(htsp_connection_t *htsp, htsmsg_t *in, channel_t *ch, int autorec, int add)
+{
+  htsmsg_t *conf,*days;
+  uint32_t u32;
+  int64_t s64;
+  int32_t approx_time, start, start_window, s32;
+  int retval;
+  const char *str;
+
+  conf = htsmsg_create_map();
+  days = htsmsg_create_list();
+
+  if (autorec) { // autorec specific
+    if (!(retval = htsmsg_get_u32(in, "minduration", &u32)) || add)
+      htsmsg_add_u32(conf, "minduration", !retval ? u32 : 0);  // 0 = any
+    if (!(retval = htsmsg_get_u32(in, "maxduration", &u32)) || add)
+      htsmsg_add_u32(conf, "maxduration", !retval ? u32 : 0);  // 0 = any
+    if (!(retval = htsmsg_get_u32(in, "fulltext", &u32)) || add)
+      htsmsg_add_u32(conf, "fulltext", !retval ? u32 : 0);     // 0 = off
+    if (!(retval = htsmsg_get_u32(in, "dupDetect", &u32)) || add)
+      htsmsg_add_u32(conf, "record", !retval ? u32 : DVR_AUTOREC_RECORD_ALL);
+    if (!(retval = htsmsg_get_s64(in, "startExtra", &s64)) || add)
+      htsmsg_add_s64(conf, "start_extra", !retval ? (s64 < 0 ? 0 : s64)  : 0); // 0 = dvr config
+    if (!(retval = htsmsg_get_s64(in, "stopExtra", &s64)) || add)
+      htsmsg_add_s64(conf, "stop_extra", !retval ? (s64 < 0 ? 0 : s64) : 0);   // 0 = dvr config
+
+    if (add) { // for add, stay compatible with older "approxTime
+      if(htsmsg_get_s32(in, "approxTime", &approx_time))
+        approx_time = -1;
+      if(htsmsg_get_s32(in, "start", &start))
+        start = -1;
+      if(htsmsg_get_s32(in, "startWindow", &start_window))
+        start_window = -1;
+      if (start < 0 || start_window < 0)
+        start = start_window = -1;
+      if (start < 0 && approx_time >= 0) {
+        start = approx_time - 15;
+        if (start < 0)
+          start += 24 * 60;
+        start_window = start + 30;
+        if (start_window >= 24 * 60)
+          start_window -= 24 * 60;
+
+        htsmsg_add_s32(conf, "start", start >= 0 ? start : -1); // -1 = any time
+        htsmsg_add_s32(conf, "start_window", start_window >= 0 ? start_window : -1); // -1 = any duration
+      }
+    }
+    else { // for update, we don't care about "approxTime"
+      if(!htsmsg_get_s32(in, "start", &s32))
+        htsmsg_add_s32(conf, "start", s32 >= 0 ? s32 : -1);        // -1 = any time
+      if(!htsmsg_get_s32(in, "startWindow", &s32))
+        htsmsg_add_s32(conf, "start_window", s32 >= 0 ? s32 : -1); // -1 = any duration
+    }
+  }
+  else { //timerec specific
+    if (!(retval = htsmsg_get_u32(in, "start", &u32)) || add)
+      htsmsg_add_u32(conf, "start", !retval ? u32 : 0);
+    if (!(retval = htsmsg_get_u32(in, "stop", &u32)) || add)
+      htsmsg_add_u32(conf, "stop", !retval ? u32 : 0);
+  }
+
+  if (!(retval = htsmsg_get_u32(in, "enabled", &u32)) || add)
+    htsmsg_add_u32(conf, "enabled", !retval ? (u32 > 0 ? 1 : 0) : 1); // default on
+  if (!(retval = htsmsg_get_u32(in, "retention", &u32)) || add)
+    htsmsg_add_u32(conf, "retention", !retval ? u32 : 0); // 0 = dvr config
+  if (!(retval = htsmsg_get_u32(in, "removal", &u32)) || add)
+    htsmsg_add_u32(conf, "removal", !retval ? u32 : 0);   // 0 = dvr config
+  if(!(retval = htsmsg_get_u32(in, "priority", &u32)) || add)
+    htsmsg_add_u32(conf, "pri", !retval ? u32 : DVR_PRIO_NORMAL);
+  if ((str = htsmsg_get_str(in, "name")) || add)
+    htsmsg_add_str(conf, "name", str ?: "");
+  if ((str = htsmsg_get_str(in, "comment")) || add)
+    htsmsg_add_str(conf, "comment", str ?: "");
+  if ((str = htsmsg_get_str(in, "directory")) || add)
+    htsmsg_add_str(conf, "directory", str ?: "");
+  if((str = htsmsg_get_str(in, "title")) || add)
+    htsmsg_add_str(conf, "title", str ?: "");
+
+  /* Only on creation */
+  if (add) {
+    str = htsp_dvr_config_name(htsp, htsmsg_get_str(in, "configName"));
+    htsmsg_add_str(conf, "config_name", str ?: "");
+    htsmsg_add_str(conf, "owner",   htsp->htsp_granted_access->aa_username ?: "");
+    htsmsg_add_str(conf, "creator", htsp->htsp_granted_access->aa_representative ?: "");
+  }
+
+  /* Weekdays only if present */
+  if(!(retval = htsmsg_get_u32(in, "daysOfWeek", &u32))) {
+    int i;
+    for (i = 0; i < 7; i++)
+      if (u32 & (1 << i))
+        htsmsg_add_u32(days, NULL, i + 1);
+    htsmsg_add_msg(conf, "weekdays", days);  // not set = all days
+  }
+
+  /* Allow channel to be cleared on update -> any channel */
+  if (ch || !add) {
+    htsmsg_add_str(conf, "channel", ch ? idnode_uuid_as_sstr(&ch->ch_id) : "");
+  }
+  return conf;
+}
+
 /* **************************************************************************
  * File helpers
  * *************************************************************************/
@@ -1439,39 +1583,6 @@ htsp_method_getEpgObject(htsp_connection_t *htsp, htsmsg_t *in)
   return out;
 }
 
-static const char *
-htsp_dvr_config_name( htsp_connection_t *htsp, const char *config_name )
-{
-  dvr_config_t *cfg = NULL, *cfg2;
-  access_t *perm = htsp->htsp_granted_access;
-  htsmsg_field_t *f;
-  const char *uuid;
-  static char ubuf[UUID_HEX_SIZE];
-
-  lock_assert(&global_lock);
-
-  config_name = config_name ?: "";
-
-  if (perm->aa_dvrcfgs == NULL)
-    return config_name; /* no change */
-
-  HTSMSG_FOREACH(f, perm->aa_dvrcfgs) {
-    uuid = htsmsg_field_get_str(f) ?: "";
-    if (strcmp(uuid, config_name) == 0)
-      return config_name;
-    cfg2 = dvr_config_find_by_uuid(uuid);
-    if (cfg2 && strcmp(cfg2->dvr_config_name, config_name) == 0)
-      return uuid;
-    if (!cfg)
-      cfg = cfg2;
-  }
-
-  if (!cfg && perm->aa_username)
-    tvhlog(LOG_INFO, "htsp", "User '%s' has no valid dvr config in ACL, using default...", perm->aa_username);
-
-  return cfg ? idnode_uuid_as_str(&cfg->dvr_id, ubuf) : NULL;
-}
-
 /**
  *
  */
@@ -1740,74 +1851,25 @@ htsp_method_addAutorecEntry(htsp_connection_t *htsp, htsmsg_t *in)
 {
   htsmsg_t *out;
   dvr_autorec_entry_t *dae;
-  const char *dvr_config_name, *title, *comment, *name, *directory;
-  int64_t start_extra, stop_extra;
-  uint32_t u32, days_of_week, priority, min_duration, max_duration, dup_detect;
-  uint32_t retention, removal, enabled, fulltext;
-  int32_t approx_time, start, start_window;
+  const char *str;
+  uint32_t u32;
   channel_t *ch = NULL;
 
   /* Options */
-  if(!(title = htsmsg_get_str(in, "title")))
+  if(!(str = htsmsg_get_str(in, "title")))
     return htsp_error("Invalid arguments");
-  if(htsmsg_get_u32(in, "fulltext", &fulltext))
-    fulltext = 0;
-  dvr_config_name = htsp_dvr_config_name(htsp, htsmsg_get_str(in, "configName"));
-  if(!htsmsg_get_u32(in, "channelId", &u32))
+
+  /* Do we have a channel? No = any */
+  if (!htsmsg_get_u32(in, "channelId", &u32)) {
     ch = channel_find_by_id(u32);
-  if(htsmsg_get_u32(in, "maxDuration", &max_duration))
-    max_duration = 0;    // 0 = any
-  if(htsmsg_get_u32(in, "minDuration", &min_duration))
-    min_duration = 0;    // 0 = any
-  if(htsmsg_get_u32(in, "retention", &retention))
-    retention = 0;       // 0 = dvr config
-  if(htsmsg_get_u32(in, "removal", &removal))
-    removal = 0;         // 0 = dvr config
-  if(htsmsg_get_u32(in, "daysOfWeek", &days_of_week))
-    days_of_week = 0x7f; // all days
-  if(htsmsg_get_u32(in, "priority", &priority))
-    priority = DVR_PRIO_NORMAL;
-  if(htsmsg_get_u32(in, "enabled", &enabled))
-    enabled = 1;
-  if(htsmsg_get_s32(in, "approxTime", &approx_time))
-    approx_time = -1;
-  if(htsmsg_get_s32(in, "start", &start))
-    start = -1;
-  if(htsmsg_get_s32(in, "startWindow", &start_window))
-    start_window = -1;
-  if (start < 0 || start_window < 0)
-    start = start_window = -1;
-  if (start < 0 && approx_time >= 0) {
-    start = approx_time - 15;
-    if (start < 0)
-      start += 24 * 60;
-    start_window = start + 30;
-    if (start_window >= 24 * 60)
-      start_window -= 24 * 60;
-  }
-  if(htsmsg_get_s64(in, "startExtra", &start_extra))
-    start_extra = 0;     // 0 = dvr config
-  if(htsmsg_get_s64(in, "stopExtra", &stop_extra))
-    stop_extra  = 0;     // 0 = dvr config
-  if (!(comment = htsmsg_get_str(in, "comment")))
-    comment = "";
-  if (!(name = htsmsg_get_str(in, "name")))
-    name = "";
-  if (!(directory = htsmsg_get_str(in, "directory")))
-    directory = "";
-  if(htsmsg_get_u32(in, "dupDetect", &dup_detect))
-    dup_detect = DVR_AUTOREC_RECORD_ALL;
 
-  /* Check access */
-  if (ch && !htsp_user_access_channel(htsp, ch))
-    return htsp_error("User does not have access");
+    /* Check access channel */
+    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, fulltext,
-      ch, enabled, start, start_window, days_of_week,
-      start_extra, stop_extra, priority, retention, removal,
-      min_duration, max_duration, dup_detect,
-      htsp->htsp_granted_access->aa_username, htsp->htsp_granted_access->aa_representative,
-      comment, name, directory);
+  /* Create autorec config from htsp and add */
+  dae = dvr_autorec_create_htsp(serierec_convert(htsp, in, ch, 1, 1));
 
   /* create response */
   out = htsmsg_create_map();
@@ -1823,6 +1885,54 @@ htsp_method_addAutorecEntry(htsp_connection_t *htsp, htsmsg_t *in)
   return out;
 }
 
+
+/**
+ * update a Dvr autorec entry
+ */
+static htsmsg_t *
+htsp_method_updateAutorecEntry(htsp_connection_t *htsp, htsmsg_t *in)
+{
+  htsmsg_t *out;
+  const char *daeId;
+  dvr_autorec_entry_t *dae;
+  int64_t s64;
+  channel_t *ch = NULL;
+
+  if (!(daeId = htsmsg_get_str(in, "id")))
+    return htsp_error("Missing argument 'id'");
+
+  if((dae = dvr_autorec_find_by_uuid(daeId)) == NULL)
+    return htsp_error("id not found");
+
+  if(dvr_autorec_entry_verify(dae, htsp->htsp_granted_access, 0))
+    return htsp_error("User does not have access");
+
+  /* Check access old channel*/
+  if (dae->dae_channel && !htsp_user_access_channel(htsp, dae->dae_channel))
+    return htsp_error("User does not have access");
+
+  /* Do we have a channel? No = keep old one */
+  if (!htsmsg_get_s64(in, "channelId", &s64)) //s64 -> -1 = any channel
+  {
+    if (s64 >= 0)
+      ch = channel_find_by_id((uint32_t)s64);
+
+    /* Check access new channel */
+    if (ch && !htsp_user_access_channel(htsp, ch))
+      return htsp_error("User does not have access");
+  }
+
+  /* Update autorec config from htsp and save */
+  dvr_autorec_update_htsp(dae, serierec_convert(htsp, in, ch, 1, 0));
+
+  /* create response */
+  out = htsmsg_create_map();
+  htsmsg_add_u32(out, "success", 1);
+
+  return out;
+}
+
+
 /**
  * delete a Dvr autorec entry
  */
@@ -1863,49 +1973,25 @@ htsp_method_addTimerecEntry(htsp_connection_t *htsp, htsmsg_t *in)
 {
   htsmsg_t *out;
   dvr_timerec_entry_t *dte;
-  const char *dvr_config_name, *title, *comment, *name, *directory;
-  uint32_t u32, days_of_week, priority, retention, removal, start = 0, stop = 0, enabled;
+  const char *str;
   channel_t *ch = NULL;
+  uint32_t u32;
 
   /* Options */
-  if(!(title = htsmsg_get_str(in, "title")))
+  if(!(str = htsmsg_get_str(in, "title")))
     return htsp_error("Invalid arguments");
 
-  htsmsg_get_u32(in, "start", &start);
-  htsmsg_get_u32(in, "stop", &stop);
-  if (stop == start)
-    stop = start+1;
-
-  if (!htsmsg_get_u32(in, "channelId", &u32))
+  /* Do we have a channel? No = any */
+  if (!htsmsg_get_u32(in, "channelId", &u32)) {
     ch = channel_find_by_id(u32);
-  dvr_config_name = htsp_dvr_config_name(htsp, htsmsg_get_str(in, "configName"));
 
-  if(htsmsg_get_u32(in, "retention", &retention))
-    retention = 0;       // 0 = dvr config
-  if(htsmsg_get_u32(in, "removal", &removal))
-    removal = 0;         // 0 = dvr config
-  if(htsmsg_get_u32(in, "daysOfWeek", &days_of_week))
-    days_of_week = 0x7f; // all days
-  if(htsmsg_get_u32(in, "priority", &priority))
-    priority = DVR_PRIO_NORMAL;
-  if(htsmsg_get_u32(in, "enabled", &enabled))
-    enabled = 1;
-
-  if (!(comment = htsmsg_get_str(in, "comment")))
-    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");
+    /* Check access channel */
+    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, removal, htsp->htsp_granted_access->aa_username,
-      htsp->htsp_granted_access->aa_representative, comment, name, directory);
+  /* Create timerec config from htsp and add */
+  dte = dvr_timerec_create_htsp(serierec_convert(htsp, in, ch, 0, 1));
 
   /* create response */
   out = htsmsg_create_map();
@@ -1921,6 +2007,52 @@ htsp_method_addTimerecEntry(htsp_connection_t *htsp, htsmsg_t *in)
   return out;
 }
 
+/**
+ * update a Dvr timerec entry
+ */
+static htsmsg_t *
+htsp_method_updateTimerecEntry(htsp_connection_t *htsp, htsmsg_t *in)
+{
+  htsmsg_t *out;
+  const char *dteId;
+  dvr_timerec_entry_t *dte;
+  int64_t s64;
+  channel_t *ch = NULL;
+
+  if (!(dteId = htsmsg_get_str(in, "id")))
+    return htsp_error("Missing argument 'id'");
+
+  if((dte = dvr_timerec_find_by_uuid(dteId)) == NULL)
+    return htsp_error("id not found");
+
+  if(dvr_timerec_entry_verify(dte, htsp->htsp_granted_access, 0))
+    return htsp_error("User does not have access");
+
+  /* Check access old channel */
+  if (dte->dte_channel && !htsp_user_access_channel(htsp, dte->dte_channel))
+    return htsp_error("User does not have access");
+
+  /* Do we have a channel? No = keep old one */
+  if (!htsmsg_get_s64(in, "channelId", &s64)) //s64 -> -1 = any channel
+  {
+    if (s64 >= 0)
+      ch = channel_find_by_id((uint32_t)s64);
+
+    /* Check access new channel */
+    if (ch && !htsp_user_access_channel(htsp, ch))
+      return htsp_error("User does not have access");
+  }
+
+  /* Update timerec config from htsp and save */
+  dvr_timerec_update_htsp(dte, serierec_convert(htsp, in, ch, 0, 0));
+
+  /* create response */
+  out = htsmsg_create_map();
+  htsmsg_add_u32(out, "success", 1);
+
+  return out;
+}
+
 /**
  * delete a Dvr timerec entry
  */
@@ -2589,8 +2721,10 @@ struct {
   { "cancelDvrEntry",           htsp_method_cancelDvrEntry,     ACCESS_HTSP_RECORDER},
   { "deleteDvrEntry",           htsp_method_deleteDvrEntry,     ACCESS_HTSP_RECORDER},
   { "addAutorecEntry",          htsp_method_addAutorecEntry,    ACCESS_HTSP_RECORDER},
+  { "updateAutorecEntry",       htsp_method_updateAutorecEntry, ACCESS_HTSP_RECORDER},
   { "deleteAutorecEntry",       htsp_method_deleteAutorecEntry, ACCESS_HTSP_RECORDER},
   { "addTimerecEntry",          htsp_method_addTimerecEntry,    ACCESS_HTSP_RECORDER},
+  { "updateTimerecEntry",       htsp_method_updateTimerecEntry, ACCESS_HTSP_RECORDER},
   { "deleteTimerecEntry",       htsp_method_deleteTimerecEntry, ACCESS_HTSP_RECORDER},
   { "getDvrCutpoints",          htsp_method_getDvrCutpoints,    ACCESS_HTSP_RECORDER},
   { "getTicket",                htsp_method_getTicket,          ACCESS_HTSP_STREAMING},