Index: roard/clients.c
===================================================================
--- roard/clients.c	(revision 4713)
+++ roard/clients.c	(revision 4815)
@@ -360,4 +360,6 @@
  int have_stream;
 
+ ROAR_DBG("clients_check_all(void) = ?");
+
  FD_ZERO(&r);
  FD_ZERO(&w);
@@ -371,4 +373,6 @@
    continue;
 
+  ROAR_DBG("clients_check_all(void): i(client)=%i", i);
+
   if ( (fh = c->fh) != -1 ) {
    have++;
@@ -390,4 +394,5 @@
 
   for (j = 0; j < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; j++) {
+   ROAR_DBG("clients_check_all(void): i(client)=%i, j(stream)=%i", i, j);
    if ( (fh = streams_get_fh(c->streams[j])) != -1 ) {
     ROAR_DBG("clients_check_all(*): g_clients[i=%i]->streams[j=%i] = %i, fh = %i", i, j, c->streams[j], fh);
@@ -412,4 +417,6 @@
   }
  }
+
+ ROAR_DBG("clients_check_all(void): max_fh=%i", max_fh);
 
  if ( max_fh == -1 )
@@ -513,4 +520,5 @@
  return have;
 #else
+ ROAR_DBG("clients_check_all(void) = -1");
  return -1;
 #endif
Index: roard/driver.c
===================================================================
--- roard/driver.c	(revision 4812)
+++ roard/driver.c	(revision 4815)
@@ -50,5 +50,5 @@
 #define ROAR_DEFAULT_OSS_DEV "no default device"
 #endif
- { "oss", "Open Sound System", ROAR_DEFAULT_OSS_DEV, STREAM_DIR_OUT, DRV_FLAG_FHSEC, ROAR_SUBSYS_WAVEFORM,
+ { "oss", "Open Sound System", ROAR_DEFAULT_OSS_DEV, STREAM_DIR_BIDIR, DRV_FLAG_FHSEC, ROAR_SUBSYS_WAVEFORM,
    NULL, NULL, driver_oss_open},
 #endif
@@ -203,4 +203,20 @@
    }
 
+   // if this driver does not support input we need to check if it is used in input mode.
+   if ( !(g_driver[i].mode & STREAM_DIR_IN) ) {
+    if ( sstream == NULL )
+     return -1;
+
+    if ( streams_get_flag(ROAR_STREAM(sstream)->id, ROAR_FLAG_RECSOURCE) ) {
+     if ( streams_get_flag(ROAR_STREAM(sstream)->id, ROAR_FLAG_AUTOCONF) == 1 ) {
+      if ( streams_reset_flag(ROAR_STREAM(sstream)->id, ROAR_FLAG_RECSOURCE) == -1 )
+       return -1;
+     } else {
+      ROAR_WARN("driver_openvio(*): driver(%s) is not abled to record data and autoconf flag is not set.", driver);
+      return -1;
+     }
+    }
+   }
+
    ROAR_DBG("driver_openvio(*): Opening VIO driver %s(%i)...", driver, i);
    return g_driver[i].vio_init(calls, device, info, fh, sstream);
Index: roard/driver_oss.c
===================================================================
--- roard/driver_oss.c	(revision 4708)
+++ roard/driver_oss.c	(revision 4815)
@@ -37,4 +37,5 @@
 
  vio->write    = driver_oss_write;
+ vio->read     = driver_oss_read;
  vio->nonblock = driver_oss_nonblock;
  vio->sync     = driver_oss_sync;
@@ -48,4 +49,6 @@
 
 int driver_oss_open_device(struct driver_oss * self) {
+ int    flags  = 0;
+ int    rw     = 0;
  int    fh     = self->fh;
  char * device = self->device;
@@ -64,5 +67,15 @@
  }
 
- if ( (fh = open(device, O_WRONLY, 0644)) == -1 ) {
+ if ( self->ssid != -1 ) {
+  rw = streams_get_flag(self->ssid, ROAR_FLAG_RECSOURCE);
+ }
+
+ if ( rw ) {
+  flags |= O_RDWR;
+ } else {
+  flags |= O_WRONLY;
+ }
+
+ if ( (fh = open(device, flags, 0644)) == -1 ) {
   ROAR_ERR("driver_oss_open_device(*): Can not open OSS device: %s: %s", device, strerror(errno));
   return -1;
@@ -324,6 +337,9 @@
  }
 
+ ROAR_DBG("driver_oss_config_device(*): self->ssid=%i, fh=%i", self->ssid, fh);
+ streams_set_fh(self->ssid, -2);
  self->need_config = 0;
 
+ ROAR_DBG("driver_oss_config_device(*) = 0");
  return 0;
 }
@@ -343,4 +359,7 @@
  self->ssid = -1;
  self->fh   = fh;
+
+ if ( sstream != NULL )
+  self->ssid = ROAR_STREAM(sstream)->id;
 
  if ( fh != -1 ) {
@@ -528,4 +547,17 @@
 }
 
+ssize_t driver_oss_read     (struct roar_vio_calls * vio, void *buf, size_t count) {
+ if ( _get(vio,fh) == -1 )
+  return -1;
+
+ if ( _get(vio,need_config) ) {
+  if ( driver_oss_config_device(vio->inst) == -1 ) {
+   return -1;
+  }
+ }
+
+ return read(_get(vio,fh), buf, count);
+}
+
 #endif
 //ll
Index: roard/include/driver.h
===================================================================
--- roard/include/driver.h	(revision 4812)
+++ roard/include/driver.h	(revision 4815)
@@ -147,4 +147,18 @@
 #define DRV_FLAG_FHSEC          0x01
 
+#define ROAR_DRIVER_CTL_NOOP            ROAR_STREAM_CTL_COMP_DRV|0x0000 /* noop... */
+#define ROAR_DRIVER_CTL_BASE            ROAR_STREAM_CTL_COMP_DRV|0x0000 /* Base ops... */
+
+#define ROAR_DRIVER_CTL_SET             0x0002
+#define ROAR_DRIVER_CTL_GET             0x0003
+
+#define ROAR_DRIVER_CTL_RECORD          0x0010
+#define ROAR_DRIVER_CTL_SET_RECORD      ROAR_DRIVER_CTL_BASE|ROAR_DRIVER_CTL_RECORD|ROAR_DRIVER_CTL_SET
+
+
+#define ROAR_DRIVER_CTL2CMD(x)          ((x) & (~ROAR_STREAM_CTL_COMP_DRV))
+
+
+
 struct roar_driver {
  char * name;
Index: roard/include/driver_oss.h
===================================================================
--- roard/include/driver_oss.h	(revision 4708)
+++ roard/include/driver_oss.h	(revision 4815)
@@ -45,4 +45,5 @@
 
 ssize_t driver_oss_write    (struct roar_vio_calls * vio, void *buf, size_t count);
+ssize_t driver_oss_read     (struct roar_vio_calls * vio, void *buf, size_t count);
 int     driver_oss_nonblock (struct roar_vio_calls * vio, int state);
 int     driver_oss_close_vio(struct roar_vio_calls * vio);
Index: roard/include/streams.h
===================================================================
--- roard/include/streams.h	(revision 4753)
+++ roard/include/streams.h	(revision 4815)
@@ -210,6 +210,8 @@
 ssize_t stream_vio_read (int stream, void *buf, size_t count);
 ssize_t stream_vio_write(int stream, void *buf, size_t count);
+int     stream_vio_ctl  (int stream, int cmd,   void * data);
 ssize_t stream_vio_s_read (struct roar_stream_server * stream, void *buf, size_t count);
 ssize_t stream_vio_s_write(struct roar_stream_server * stream, void *buf, size_t count);
+int     stream_vio_s_ctl  (struct roar_stream_server * stream, int cmd,   void * data);
 
 #endif
Index: roard/roard.c
===================================================================
--- roard/roard.c	(revision 4811)
+++ roard/roard.c	(revision 4815)
@@ -940,4 +940,6 @@
   } else if ( !strcmp(k, "passmixer") ) {
    flag = ROAR_FLAG_PASSMIXER;
+  } else if ( !strcmp(k, "recsource") ) {
+   flag = ROAR_FLAG_RECSOURCE;
   } else {
    return -1;
@@ -1158,4 +1160,6 @@
   } else if ( strcmp(k, "passmixer") == 0 ) {
    streams_set_flag(stream, ROAR_FLAG_PASSMIXER);
+  } else if ( strcmp(k, "recsource") == 0 ) {
+   streams_set_flag(stream, ROAR_FLAG_RECSOURCE);
   } else {
    ROAR_ERR("add_output(*): unknown option '%s'", k);
Index: roard/streams.c
===================================================================
--- roard/streams.c	(revision 4753)
+++ roard/streams.c	(revision 4815)
@@ -590,10 +590,10 @@
   return -1;
 
- if ( ss->ready ) {
+ if ( ss->ready && !(s->fh == -1 && fh == -2) ) {
   ROAR_DBG("streams_set_fh(id=%i, fh=%i) = -1 // try to set fh for stream which is already ready", id, fh);
   return -1;
  }
 
- dir = ROAR_STREAM(ss)->dir;
+ dir = s->dir;
 
  ROAR_DBG("streams_set_fh(id=%i, fh=%i): g_streams[id]->id=%i", id, fh, s->id);
@@ -902,4 +902,5 @@
 int streams_set_flag     (int id, uint32_t flag) {
  int parent;
+ int tmp;
 
  _CHECK_SID(id);
@@ -978,4 +979,10 @@
   }
 
+  if ( g_streams[id]->ready ) {
+   tmp = 1;
+   if ( stream_vio_ctl(id, ROAR_VIO_CTL_SET_RECORD, &tmp) == -1 )
+    return -1;
+  }
+
   streams_recsource_id = id;
  }
@@ -1000,4 +1007,6 @@
 
 int streams_reset_flag   (int id, uint32_t flag) {
+ int tmp;
+
  _CHECK_SID(id);
 
@@ -1011,7 +1020,14 @@
  }
 
- if ( flag & ROAR_FLAG_RECSOURCE )
-  if ( streams_recsource_id == id )
-   streams_recsource_id = -1;
+ if ( (flag & ROAR_FLAG_RECSOURCE) && streams_recsource_id == id ) {
+  if ( g_streams[id]->ready ) {
+   tmp = 0;
+   if ( stream_vio_ctl(id, ROAR_VIO_CTL_SET_RECORD, &tmp) == -1 )
+    return -1;
+  }
+
+  streams_recsource_id = -1;
+ }
+
 
  if ( flag & ROAR_FLAG_MMAP ) {
@@ -1959,4 +1975,8 @@
   case ROAR_DIR_BIDIR:
    break;
+  case ROAR_DIR_OUTPUT:
+    if ( !streams_get_flag(id, ROAR_FLAG_RECSOURCE) )
+     return 0;
+   break;
   default:
 /*
@@ -2057,5 +2077,5 @@
  struct roar_buffer        *  bufbuf = NULL;
  struct roar_remove_state     removalstate;
- void  * ip;
+ void  * ip              = g_output_buffer;
  void  * obuf;
  int     olen;
@@ -2130,4 +2150,7 @@
    break;
 
+  case ROAR_DIR_RECORD:
+    ip = g_input_buffer;
+   break;
   default:
     return 0;
@@ -2161,9 +2184,7 @@
   ROAR_DBG("streams_send_mon(id=%i): obuf=%p, olen=%i", id, obuf, olen);
  } else {
-  obuf = g_output_buffer;
+  obuf = ip;
   olen = g_output_buffer_len;
  }
-
- ip = g_output_buffer;
 
  if ( antiecho ) {
@@ -2335,4 +2356,9 @@
 }
 
+int     stream_vio_ctl  (int stream, int cmd,   void * data) {
+ _CHECK_SID(stream);
+
+ return stream_vio_s_ctl(g_streams[stream], cmd, data);
+}
 
 ssize_t stream_vio_s_read (struct roar_stream_server * stream, void *buf, size_t count) {
@@ -2443,3 +2469,10 @@
 }
 
+int     stream_vio_s_ctl  (struct roar_stream_server * stream, int cmd,   void * data) {
+ if ( stream == NULL )
+  return -1;
+
+ return roar_vio_ctl(stream->viop, cmd, data);
+}
+
 //ll
Index: roard/waveform.c
===================================================================
--- roard/waveform.c	(revision 4708)
+++ roard/waveform.c	(revision 4815)
@@ -62,4 +62,18 @@
 
 int waveform_update_mixer (void) {
+ size_t len;
+
+ // read recorded data...:
+ if ( streams_recsource_id != -1 ) {
+  len = g_input_buffer_len;
+  if ( stream_shift_out_buffer(streams_recsource_id, g_input_buffer, &len) == -1 ) {
+   ROAR_WARN("waveform_update_mixer(void): can not read record buffer.");
+   memset(g_input_buffer, 0, g_input_buffer_len);
+  } else {
+   if ( len < g_input_buffer_len )
+    memset(g_input_buffer+len, 0, g_input_buffer_len-len);
+  }
+ }
+
  if ( streams_get_flag(g_waveform_mixer.stream, ROAR_FLAG_MUTE) == 1 ) {
   memset(g_output_buffer, 0, (g_sa->bits*ROAR_OUTPUT_BUFFER_SAMPLES*g_sa->channels)/8);
