diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h
index ad9c30f..4473da4 100644
--- a/src/dvb/dvb.h
+++ b/src/dvb/dvb.h
@@ -183,6 +183,7 @@ typedef struct th_dvb_adapter {
   gtimer_t tda_mux_scanner_timer;
 
   pthread_mutex_t tda_delivery_mutex;
+  pthread_t tda_delivery_thread;
   struct service_list tda_transports; /* Currently bound transports */
 
   gtimer_t tda_fe_monitor_timer;
@@ -204,6 +205,7 @@ typedef struct th_dvb_adapter {
 
   int tda_unc_is_delta;  /* 1 if we believe FE_READ_UNCORRECTED_BLOCKS
 			  * return dela values */
+  int tda_opened;
 
 } th_dvb_adapter_t;
 
@@ -243,6 +245,8 @@ int dvb_adapter_destroy(th_dvb_adapter_t *tda);
 
 void dvb_adapter_notify(th_dvb_adapter_t *tda);
 
+void dvb_adapter_restart(th_dvb_adapter_t *tda);
+
 htsmsg_t *dvb_adapter_build_msg(th_dvb_adapter_t *tda);
 
 htsmsg_t *dvb_fe_opts(th_dvb_adapter_t *tda, const char *which);
diff --git a/src/dvb/dvb_adapter.c b/src/dvb/dvb_adapter.c
index 433107a..1b9d33a 100644
--- a/src/dvb/dvb_adapter.c
+++ b/src/dvb/dvb_adapter.c
@@ -63,6 +63,8 @@ tda_alloc(void)
 
   tda->tda_allpids_dmx_fd = -1;
   tda->tda_dump_fd = -1;
+  tda->tda_opened = 0;
+  tda->tda_fe_fd = -1;
 
   return tda;
 }
@@ -177,8 +179,7 @@ dvb_adapter_set_qmon(th_dvb_adapter_t *tda, int on)
 void
 dvb_adapter_set_dump_muxes(th_dvb_adapter_t *tda, int on)
 {
-  if(tda->tda_dump_muxes == on)
-    return;
+  if(tda->tda_dump_muxes == on)    return;
 
   lock_assert(&global_lock);
 
@@ -257,7 +258,6 @@ tda_add(int adapter_num)
   int fe, i, r;
   th_dvb_adapter_t *tda;
   char buf[400];
-  pthread_t ptid;
 
   snprintf(path, sizeof(path), "/dev/dvb/adapter%d", adapter_num);
   snprintf(fname, sizeof(fname), "%s/frontend0", path);
@@ -281,6 +281,7 @@ tda_add(int adapter_num)
 
 
   tda->tda_fe_fd = fe;
+  tda->tda_opened = 1;
 
   tda->tda_fe_info = malloc(sizeof(struct dvb_frontend_info));
 
@@ -321,8 +322,8 @@ tda_add(int adapter_num)
 
   TAILQ_INSERT_TAIL(&dvb_adapters, tda, tda_global_link);
 
-  pthread_create(&ptid, NULL, dvb_adapter_input_dvr, tda);
-
+  pthread_create(&tda->tda_delivery_thread, NULL, dvb_adapter_input_dvr, tda);
+  
   dvb_table_init(tda);
 
   if(tda->tda_sat)
@@ -391,6 +392,38 @@ dvb_adapter_init(uint32_t adapter_mask)
     dvb_mux_load(tda);
 }
 
+static void dvb_close_idle_adapter(th_dvb_adapter_t *tda) 
+{
+  tvhlog(LOG_DEBUG, "dvb", "\"%s\" is idle, closing all device file descriptors", tda->tda_rootpath);
+  if (tda->tda_delivery_thread != 0) {
+     pthread_cancel(tda->tda_delivery_thread);
+     pthread_join(tda->tda_delivery_thread, NULL);
+     tda->tda_delivery_thread = 0;
+  }
+  dvb_fe_stop(tda->tda_mux_current);
+  if (tda->tda_fe_fd != -1) {
+    close(tda->tda_fe_fd);
+    tda->tda_fe_fd = -1;
+  }
+  tda->tda_opened = 0;
+}
+
+/**
+ * Restart an adapter that has been closed by dvb_close_idle_adapter()
+ */
+void 
+dvb_adapter_restart(th_dvb_adapter_t *tda) 
+{    
+    char fname[256];
+    snprintf(fname, sizeof(fname), "%s/frontend0", tda->tda_rootpath);
+    tda->tda_fe_fd = tvh_open(fname, O_RDWR | O_NONBLOCK, 0);
+    if (tda->tda_fe_fd != -1) {
+      tda->tda_opened = 1;
+      pthread_create(&tda->tda_delivery_thread, NULL, dvb_adapter_input_dvr, tda);      
+    } else {
+      tda->tda_opened = 0;
+    }
+}
 
 /**
  * If nobody is subscribing, cycle thru all muxes to get some stats
@@ -420,17 +453,28 @@ dvb_adapter_mux_scanner(void *aux)
     return;
   }
 
+  if (tda->tda_opened == 0)
+    return; // Tuner is closed
+
   if(!tda->tda_idlescan && TAILQ_FIRST(&tda->tda_scan_queues[0]) == NULL) {
     /* Idlescan is disabled and no muxes are bad */
 
-    if(!tda->tda_qmon)
-      return; // Quality monitoring is disabled
-
-    /* If the currently tuned mux is ok, we can stick to it */
+    if(tda->tda_qmon) // Check if quality monitoring is enabled
+    {
+      /* If the currently tuned mux is ok, we can stick to it */
     
-    tdmi = tda->tda_mux_current;
-    if(tdmi != NULL && tdmi->tdmi_quality > 90)
+      tdmi = tda->tda_mux_current;
+      if(tdmi != NULL && tdmi->tdmi_quality > 90)
+      {
+        dvb_close_idle_adapter(tda);
+        return;
+      }
+    }
+    else
+    {
+      dvb_close_idle_adapter(tda);
       return;
+    }
   }
 
   /* Alternate between the other two (bad and OK) */
@@ -510,6 +554,15 @@ dvb_adapter_clean(th_dvb_adapter_t *tda)
 
 
 
+static void
+dvb_adapter_close_fd(void *aux) 
+{
+  int *fd = aux;
+  if (*fd != -1) {
+    close(*fd);
+    *fd = -1;
+  }
+}
 
 /**
  *
@@ -527,8 +580,7 @@ dvb_adapter_input_dvr(void *aux)
     tvhlog(LOG_ALERT, "dvb", "%s: unable to open dvr", tda->tda_dvr_path);
     return NULL;
   }
-
-
+  pthread_cleanup_push(dvb_adapter_close_fd, &fd);
   while(1) {
     r = read(fd, tsb, sizeof(tsb));
 
@@ -553,6 +605,7 @@ dvb_adapter_input_dvr(void *aux)
 
     pthread_mutex_unlock(&tda->tda_delivery_mutex);
   }
+  pthread_cleanup_pop(1);
 }
 
 
diff --git a/src/dvb/dvb_fe.c b/src/dvb/dvb_fe.c
index 9e7b789..f4cc9fd 100644
--- a/src/dvb/dvb_fe.c
+++ b/src/dvb/dvb_fe.c
@@ -422,21 +422,21 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason)
   
   char buf[256];
   int r;
- 
 
   lock_assert(&global_lock);
 
-  if(tda->tda_mux_current == tdmi)
-    return 0;
+  if(!tda->tda_opened)
+  {
+    dvb_adapter_restart(tda);
+  }
+
+  if(tda->tda_mux_current != NULL)
+    dvb_fe_stop(tda->tda_mux_current);
   
   if(tdmi->tdmi_scan_queue != NULL) {
     TAILQ_REMOVE(tdmi->tdmi_scan_queue, tdmi, tdmi_scan_link);
     tdmi->tdmi_scan_queue = NULL;
   }
-
-  if(tda->tda_mux_current != NULL)
-    dvb_fe_stop(tda->tda_mux_current);
-
     
   if(tda->tda_type == FE_QPSK) {
 	
diff --git a/src/wrappers.c b/src/wrappers.c
index ce38af9..cad4848 100644
--- a/src/wrappers.c
+++ b/src/wrappers.c
@@ -1,4 +1,5 @@
 #include <fcntl.h>
+#include <unistd.h>
 #include <sys/types.h>          /* See NOTES */
 #include <sys/socket.h>
 #include "tvheadend.h"
@@ -16,7 +17,6 @@ tvh_open(const char *pathname, int flags, mode_t mode)
   return fd;
 }
 
-
 int
 tvh_socket(int domain, int type, int protocol)
 {
