diff --git a/src/dvr/dvr_inotify.c b/src/dvr/dvr_inotify.c
index 6311b3b0a..c0c198e84 100644
--- a/src/dvr/dvr_inotify.c
+++ b/src/dvr/dvr_inotify.c
@@ -29,7 +29,8 @@
 #define EVENT_SIZE    (sizeof(struct inotify_event))
 #define EVENT_BUF_LEN (5 * EVENT_SIZE + NAME_MAX)
 #define EVENT_MASK    IN_DELETE    | IN_DELETE_SELF | \
-                      IN_MOVE_SELF | IN_MOVED_FROM | IN_MOVED_TO
+                      IN_MOVE_SELF | IN_MOVED_FROM | IN_MOVED_TO | \
+                      IN_CREATE
                       
 static int                         _inot_fd;
 static RB_HEAD(,dvr_inotify_entry) _inot_tree;
@@ -44,7 +45,8 @@ typedef struct dvr_inotify_entry
 {
   RB_ENTRY(dvr_inotify_entry) link;
   char *path;
-  int fd;
+  int wd;
+  int parent_wd;
   LIST_HEAD(, dvr_inotify_filename) entries;
 } dvr_inotify_entry_t;
 
@@ -102,67 +104,96 @@ static int dvr_inotify_exists ( dvr_inotify_entry_t *die, dvr_entry_t *de )
 /**
  * Add an entry for monitoring
  */
-static void dvr_inotify_add_one ( dvr_entry_t *de, htsmsg_t *m )
+//static void dvr_inotify_add_one ( dvr_entry_t *de, htsmsg_t *m )
+static void dvr_inotify_add_one ( dvr_entry_t *de, int fd, const char *filename )
 {
   dvr_inotify_filename_t *dif;
   dvr_inotify_entry_t *e;
-  const char *filename;
+//  const char *filename;
   char path[PATH_MAX];
-  int fd = atomic_get(&_inot_fd);
-
-  filename = htsmsg_get_str(m, "filename");
-  if (filename == NULL || fd < 0)
-    return;
-
+//  int fd = atomic_get(&_inot_fd);
+  char *dir = NULL;
+  int len, append = 0;
+
+//  filename = htsmsg_get_str(m, "filename");
+//  if (filename == NULL || fd < 0)
+//    return;
+
+  dir = tvh_strdupa(filename);
+  // check for newly created dir
+  if((len = strlen(filename)) > 5 && !strcmp(filename + len - 5, "dummy")) {
+    append = 1;
+    dir = dirname(dir);
+    tvherror(LS_DVR_INOTIFY, "add inotify watch for newly created directory \"%s\" ", dir);
+  }
+    
   /* Since filename might be inside a symlinked directory
    * we want to get the true name otherwise when we move
    * a file we will not match correctly since some files
    * may point to /mnt/a/z.ts and some to /mnt/b/z.ts
    */
-  if (!realpath(filename, path))
+  if (!realpath(dir, path)) {
+    tvhwarn(LS_DVR_INOTIFY, "failed to add inotify watch for \"%s\" (err=%s)", filename,strerror(errno));
     return;
+  }
+
+  // append dummmy filename which will be stripped by dirname, leaving new dir path
+  if(append)
+    strcat(path, "/dummy.ts");
 
   SKEL_ALLOC(dvr_inotify_entry_skel);
   dvr_inotify_entry_skel->path = dirname(path);
   
   e = RB_INSERT_SORTED(&_inot_tree, dvr_inotify_entry_skel, link, _str_cmp);
-  if (!e) {
+  if (e) {
+    SKEL_FREE(dvr_inotify_entry_skel);
+    if (dvr_inotify_exists(e, de))
+      return;
+  } else {
     e       = dvr_inotify_entry_skel;
     SKEL_USED(dvr_inotify_entry_skel);
     e->path = strdup(e->path);
-    e->fd   = inotify_add_watch(fd, e->path, EVENT_MASK);
+    e->wd   = inotify_add_watch(fd, e->path, EVENT_MASK);
   }
 
-  if (!dvr_inotify_exists(e, de)) {
+//  if (!dvr_inotify_exists(e, de)) {
 
     dif = malloc(sizeof(*dif));
     dif->de = de;
 
     LIST_INSERT_HEAD(&e->entries, dif, link);
 
-    if (e->fd < 0) {
-      tvherror(LS_DVR, "failed to add inotify watch to %s (err=%s)",
+    if (e->wd < 0) {
+      tvherror(LS_DVR, "failed to add inotify watch for \"%s\" (err=%s)",
                e->path, strerror(errno));
       dvr_inotify_del(de);
     } else {
-      tvhdebug(LS_DVR, "adding inotify watch to %s (fd=%d)",
-               e->path, e->fd);
+      tvhdebug(LS_DVR, "adding inotify watch for \"%s\" (wd=%d)",
+               e->path, e->wd);
     }
 
-  }
+//  }
 }
 
 void dvr_inotify_add ( dvr_entry_t *de )
 {
   htsmsg_field_t *f;
   htsmsg_t *m;
+  const char *filename;
+//  char path[PATH_MAX];
+  int fd = atomic_get(&_inot_fd);
 
-  if (atomic_get(&_inot_fd) < 0 || de->de_files == NULL)
+  if (fd < 0 || de->de_files == NULL)
     return;
 
-  HTSMSG_FOREACH(f, de->de_files)
-    if ((m = htsmsg_field_get_map(f)) != NULL)
-      dvr_inotify_add_one(de, m);
+  HTSMSG_FOREACH(f, de->de_files) {
+    if ((m = htsmsg_field_get_map(f)) != NULL) {
+      filename = htsmsg_get_str(m, "filename");
+      if (filename == NULL)
+        continue;
+      dvr_inotify_add_one(de, fd, filename);
+      }
+    }
 }
 
 /*
@@ -186,8 +217,8 @@ void dvr_inotify_del ( dvr_entry_t *de )
         if (LIST_FIRST(&e->entries) == NULL) {
           RB_REMOVE(&_inot_tree, e, link);
           fd = atomic_get(&_inot_fd);
-          if (e->fd >= 0 && fd >= 0)
-            inotify_rm_watch(fd, e->fd);
+          if (e->wd >= 0 && fd >= 0)
+            inotify_rm_watch(fd, e->wd);
           free(e->path);
           free(e);
         }
@@ -216,11 +247,11 @@ int dvr_inotify_count ( void )
  */
 static dvr_inotify_entry_t *
 _dvr_inotify_find
-  ( int fd )
+  ( int wd )
 {
   dvr_inotify_entry_t *e = NULL;
   RB_FOREACH(e, &_inot_tree, link)
-    if (e->fd == fd)
+    if (e->wd == wd)
       break;
   return e;
 }
@@ -230,7 +261,7 @@ _dvr_inotify_find
  */
 static void
 _dvr_inotify_moved
-  ( int from_fd, const char *from, const char *to, int to_fd )
+  ( int from_wd, const char *from, const char *to, int to_wd )
 {
   dvr_inotify_filename_t *dif;
   dvr_inotify_entry_t *die;
@@ -242,13 +273,13 @@ _dvr_inotify_moved
   char realdir[PATH_MAX];
   char new_path[PATH_MAX+PATH_MAX+1];
   char ubuf[UUID_HEX_SIZE];
-  char *file, *dir = NULL;
+  char *file = NULL, *dir = NULL;
 
-  if (!(die = _dvr_inotify_find(from_fd)))
+  if (!(die = _dvr_inotify_find(from_wd)))
     return;
 
   snprintf(path, sizeof(path), "%s/%s", die->path, from);
-  tvhdebug(LS_DVR, "inotify: moved from_fd: %d path: \"%s\" to: \"%s\" to_fd: %d", from_fd, path, to?:"<none>", to_fd);
+  tvhdebug(LS_DVR, "inotify: moved from_wd: %d path: \"%s\" to: \"%s\" to_wd: %d", from_wd, path, to?:"<none>", to_wd);
 
   de = NULL;
   LIST_FOREACH(dif, &die->entries, link) {
@@ -295,19 +326,21 @@ _dvr_inotify_moved
     /* "to" will be NULL on a delete */
     if (to) {
       /* If we have moved to another directory we are inotify watching
-       * then we get an fd for the directory we are moving to which is
+       * then we get a wd for the directory we are moving to which is
        * different to the one we are moving from. So fetch the
        * directory details for that.
        */
-      if (to_fd != -1 && to_fd != from_fd) {
-        if (!(die = _dvr_inotify_find(to_fd))) {
-          tvhdebug(LS_DVR, "Failed to _dvr_inotify_find for fd: %d", to_fd);
+      if (to_wd != -1 && to_wd != from_wd) {
+        if (!(die = _dvr_inotify_find(to_wd))) {
+          tvhdebug(LS_DVR, "Failed to _dvr_inotify_find for wd: %d", to_wd);
           return;
         }
       }
       snprintf(new_path, sizeof(path), "%s/%s", die->path, to);
       tvhdebug(LS_DVR, "inotify: moved from name: \"%s\" to: \"%s\" for \"%s\"", path, new_path, idnode_uuid_as_str(&de->de_id, ubuf));
       htsmsg_set_str(m, "filename", new_path);
+//      dvr_inotify_add_one(de, m);
+      dvr_inotify_del(de);
       idnode_changed(&de->de_id);
     } else {
       htsmsg_field_destroy(de->de_files, f);
@@ -326,9 +359,9 @@ _dvr_inotify_moved
  */
 static void
 _dvr_inotify_delete
-  ( int fd, const char *path )
+  ( int wd, const char *path )
 {
-  _dvr_inotify_moved(fd, path, NULL, -1);
+  _dvr_inotify_moved(wd, path, NULL, -1);
 }
 
 /*
@@ -336,20 +369,42 @@ _dvr_inotify_delete
  */
 static void
 _dvr_inotify_moved_all
-  ( int fd, const char *to )
+  ( int wd, const char *to )
 {
   dvr_inotify_filename_t *f;
   dvr_inotify_entry_t *die;
   dvr_entry_t *de;
+  htsmsg_t *m = NULL;
+  htsmsg_field_t *fld = NULL;
+  const char *filename;
+  char *file = NULL;
 
-  if (!(die = _dvr_inotify_find(fd)))
+  if (!(die = _dvr_inotify_find(wd)))
     return;
 
   while ((f = LIST_FIRST(&die->entries))) {
+//    if (!f->de)
+//    continue;
     de = f->de;
-    htsp_dvr_entry_update(de);
-    idnode_notify_changed(&de->de_id);
-    dvr_inotify_del(de);
+    HTSMSG_FOREACH(fld, de->de_files) {
+      if ((m = htsmsg_field_get_map(fld)) != NULL) {
+        filename = htsmsg_get_str(m, "filename");
+        if (!filename)
+          continue;
+      }
+      tvhdebug(LS_DVR, "inotify: moved from name: dddddddddddddddddd   \"%s\"", filename);
+      file = basename(tvh_strdupa(filename));
+
+      if (strcmp(file, "dummy") == 0) {
+        tvhdebug(LS_DVR, "inotify: moved from name: dddddddddddddddddd dummy matched  \"%s\"", file);
+        dvr_entry_destroy(de, 0);
+        break;
+      } else {
+        htsp_dvr_entry_update(de);
+        idnode_notify_changed(&de->de_id);
+        dvr_inotify_del(de);
+      }
+    }
   }
 }
 
@@ -358,9 +413,44 @@ _dvr_inotify_moved_all
  */
 static void
 _dvr_inotify_delete_all
-  ( int fd )
+  ( int wd )
+{
+  _dvr_inotify_moved_all(wd, NULL);
+}
+
+/*
+ * Directory created
+ */
+static void
+_dvr_inotify_create
+  ( int wd, const char *dir )
 {
-  _dvr_inotify_moved_all(fd, NULL);
+  dvr_entry_t *de = NULL; // dummy de needed to add new dir
+  htsmsg_t *m,  *l = htsmsg_create_list();
+  dvr_inotify_entry_t *die;
+  char path[PATH_MAX];
+  char title[PATH_MAX];
+
+  if (!(die = _dvr_inotify_find(wd)))
+    return;
+
+  tvhdebug(LS_DVR_INOTIFY, "inotify: created new dir \"%s\" in path: \"%s\" ", dir, die->path);
+  snprintf(path, sizeof(path), "%s/%s/", die->path, dir);
+  snprintf(title, sizeof(title), "Dummy holder for %s", path);
+
+  m = htsmsg_create_map();  // create temporary map for dir path
+  strcat(path, "dummy");  // add dummy filename which will get stripped
+  htsmsg_set_str(m, "filename", path);
+  htsmsg_add_msg(l, NULL, m);
+
+  de = dvr_entry_create(NULL, NULL, 0);
+  de->de_files = htsmsg_copy(l);
+  lang_str_set(&de->de_title, title, "eng");
+  m = htsmsg_create_map();  // create temporary map for dir path
+  htsmsg_set_str(m, "filename", path);
+
+  //dvr_inotify_add_one (de, m);
+  dvr_inotify_add (de);
 }
 
 /*
@@ -371,17 +461,17 @@ void* _dvr_inotify_thread ( void *p )
   int fd, i, len;
   char buf[EVENT_BUF_LEN];
   const char *from;
-  int fromfd;
+  int fromwd;
   int cookie;
   struct inotify_event *ev;
   char from_prev[NAME_MAX + 1] = "";
-  int fromfd_prev = 0;
+  int fromwd_prev = 0;
   int cookie_prev = 0;
 
   while (tvheadend_is_running()) {
 
     /* Read events */
-    fromfd = 0;
+    fromwd = 0;
     cookie = 0;
     from   = NULL;
     i      = 0;
@@ -396,7 +486,7 @@ void* _dvr_inotify_thread ( void *p )
     tvh_mutex_lock(&global_lock);
     while (i < len) {
       ev = (struct inotify_event *)&buf[i];
-      tvhtrace(LS_DVR_INOTIFY, "i=%d len=%d name=%s", i, len, ev->name);
+      tvhtrace(LS_DVR_INOTIFY, "index=%d read_length=%d watch_descriptor=%d", i, len, ev->wd);
       i += EVENT_SIZE + ev->len;
       if (i > len)
         break;
@@ -404,48 +494,69 @@ void* _dvr_inotify_thread ( void *p )
       /* Moved */
       if (ev->mask & IN_MOVED_FROM) {
         from   = ev->name;
-        fromfd = ev->wd;
+        fromwd = ev->wd;
         cookie = ev->cookie;
-        tvhtrace(LS_DVR_INOTIFY, "i=%d len=%d from=%s cookie=%d ", i, len, from, cookie);
+        tvhtrace(LS_DVR_INOTIFY, "IN_MOVED_FROM \"%s\" cookie=%d ", from, cookie);
+        if (ev->mask & IN_ISDIR)
+          tvhtrace(LS_DVR_INOTIFY, "IN_ISDIR \"%s\"", ev->name);
         continue;
 
       } else if (ev->mask & IN_MOVED_TO) {
-        tvhtrace(LS_DVR_INOTIFY, "i=%d len=%d to_cookie=%d from_cookie=%d cookie_prev=%d", i, len, ev->cookie, cookie, cookie_prev);
+        tvhtrace(LS_DVR_INOTIFY, "IN_MOVED_TO \"%s\" to_cookie=%d from_cookie=%d cookie_prev=%d", ev->name, ev->cookie, cookie, cookie_prev);
+        if (ev->mask & IN_ISDIR)
+          tvhtrace(LS_DVR_INOTIFY, "IN_ISDIR \"%s\"", ev->name);
           if (from && ev->cookie == cookie) {
-            _dvr_inotify_moved(fromfd, from, ev->name, ev->wd);
+            _dvr_inotify_moved(fromwd, from, ev->name, ev->wd);
             from = NULL;
 	    cookie = 0;
           } else if (from_prev[0] != '\0' && ev->cookie == cookie_prev) {
-             _dvr_inotify_moved(fromfd_prev, from_prev, ev->name, ev->wd);
+             _dvr_inotify_moved(fromwd_prev, from_prev, ev->name, ev->wd);
              from_prev[0] = '\0';
 	     cookie_prev = 0;
 	  }
 
       /* Removed */
       } else if (ev->mask & IN_DELETE) {
+        tvhtrace(LS_DVR_INOTIFY, "IN_DELETE \"%s\"", ev->name);
         _dvr_inotify_delete(ev->wd, ev->name);
-    
+
       /* Moved self */
       } else if (ev->mask & IN_MOVE_SELF) {
+        tvhtrace(LS_DVR_INOTIFY, "IN_MOVE_SELF watch_descriptor=%d", ev->wd);
         _dvr_inotify_moved_all(ev->wd, NULL);
-    
+
       /* Removed self */
       } else if (ev->mask & IN_DELETE_SELF) {
+        tvhtrace(LS_DVR_INOTIFY, "IN_DELETE_SELF watch_descriptor=%d", ev->wd);
         _dvr_inotify_delete_all(ev->wd);
+
+      /* Create directory */
+      } else if (ev->mask & IN_CREATE) {
+        tvhtrace(LS_DVR_INOTIFY, "IN_CREATE \"%s\"", ev->name);
+       if (ev->mask & IN_ISDIR) {
+         tvhtrace(LS_DVR_INOTIFY, "IN_ISDIR \"%s\"", ev->name);
+        _dvr_inotify_create(ev->wd,ev->name);
+       }
+
+      /* Watch removed */
+      } else if (ev->mask & IN_IGNORED) {
+        tvhtrace(LS_DVR_INOTIFY, "IN_IGNORED watch_descriptor=%d", ev->wd);
       }
+
+      else tvhwarn(LS_DVR_INOTIFY, "NO matching flags for \"%s\" watch_descriptor=%d", ev->name, ev->wd);
     }
     // if still old "from", assume matching "to" is not coming
     if (from_prev[0] != '\0') {
-      _dvr_inotify_moved(fromfd_prev, from_prev, NULL, -1);
+      _dvr_inotify_moved(fromwd_prev, from_prev, NULL, -1);
       from_prev[0] = '\0';
       cookie_prev = 0;
     }
     // if unmatched "from", save in case matching "to" is coming in next read
     if (from) {
       strcpy(from_prev, from);
-      fromfd_prev = fromfd;
+      fromwd_prev = fromwd;
       cookie_prev = cookie;
-      tvhdebug(LS_DVR_INOTIFY, "i=%d len=%d cookie_prev=%d from_prev=%s fd=%d EOR", i, len, cookie_prev, from_prev, fromfd_prev);
+      tvhtrace(LS_DVR_INOTIFY, "i=%d len=%d cookie_prev=%d from_prev=\"%s\" wd=%d EOR", i, len, cookie_prev, from_prev, fromwd_prev);
     }
     tvh_mutex_unlock(&global_lock);
   }
