Index: ChangeLog
===================================================================
--- ChangeLog	(revision 5953)
+++ ChangeLog	(revision 5955)
@@ -5,4 +5,6 @@
 	* Code cleanup.
 	* Removed roarfish(1) (Closes: #339)
+	* Implemented read-only support for RAUM files using uniraum,
+	  support using libRAUM got disabled (See #233).
 
 v. 1.0beta10 - Tue Oct 15 2013 12:03 CEST
Index: configure
===================================================================
--- configure	(revision 5953)
+++ configure	(revision 5955)
@@ -694,4 +694,5 @@
 test_lib_defmake ROAR_HAVE_LIBAO         %            libao         ao         -- ao/ao.h ao/plugin.h
 test_lib_defmake ROAR_HAVE_LIBRAUM       %            RAUM          raum       -- raum.h
+test_lib_defmake ROAR_HAVE_LIBUNIRAUM    %            uniraum       uniraum    -- uniraum/uniraum.h
 test_lib_defmake ROAR_HAVE_LIBOGG        %            libogg        ogg        -- ogg/ogg.h
 test_lib_defmake ROAR_HAVE_LIBVORBIS     %            libvorbis     vorbis     -- vorbis/codec.h
Index: roard/Makefile
===================================================================
--- roard/Makefile	(revision 5917)
+++ roard/Makefile	(revision 5955)
@@ -5,5 +5,5 @@
 DRV=driver_esd.o driver_ao.o driver_roar.o driver_oss.o driver_shout.o driver_sndio.o driver_dmx.o driver_pwmled.o driver_i2cdmx.o driver_sysclock.o driver_wmm.o driver_dstr.o driver_alsa.o driver_rsound.o driver_portaudio.o driver_pulsesimple.o driver_jack.o driver_artsc.o
 CF_CODEC=codecfilter_cmd.o codecfilter_vorbis.o codecfilter_celt.o codecfilter_speex.o codecfilter_alaw.o codecfilter_mulaw.o codecfilter_sndfile.o codecfilter_fishsound.o codecfilter_flac.o codecfilter_roardmx.o
-CF_CONTAINER=codecfilter_wave.o codecfilter_raum.o codecfilter_au.o
+CF_CONTAINER=codecfilter_wave.o codecfilter_au.o codecfilter_uniraum.o
 EMUL=emul_simple.o emul_rsound.o
 HWMIXER=hwmixer_dstr.o hwmixer_oss.o
@@ -22,5 +22,5 @@
 CODEC_CELT= $(lib_celt) $(lib_celt0)
 CODECLIBS = $(lib_vorbisfile) $(lib_vorbisenc) $(lib_vorbis) $(lib_fishsound) $(lib_speex) $(lib_speexdsp) $(CODEC_CELT) $(lib_flac)
-CONTLIBS  = $(lib_oggz) $(lib_sndfile) $(lib_ogg) $(lib_raum)
+CONTLIBS  = $(lib_oggz) $(lib_sndfile) $(lib_ogg) $(lib_uniraum)
 OWNLIBS   = $(LIBROAREIO) $(LIBROARLIGHT) $(LIBROARMIDI) $(LIBROARDSP) $(LIBROAR)
 LIBS      = $(DRVLIBS) $(CODECLIBS) $(CONTLIBS) $(OWNLIBS) $(lib_slp)
Index: roard/codecfilter.c
===================================================================
--- roard/codecfilter.c	(revision 5823)
+++ roard/codecfilter.c	(revision 5955)
@@ -83,8 +83,15 @@
 #endif
 
+#if 0
 #ifdef ROAR_HAVE_LIBRAUM
  {ROAR_CODEC_RAUM, "RAUM", "RAUM Container Format", NULL, cf_raum_setup, ROAR_CODECFILTER_WRITE,
   ROAR_SUBSYS_WAVEFORM|ROAR_SUBSYS_MIDI|ROAR_SUBSYS_LIGHT|ROAR_SUBSYS_RAW|ROAR_SUBSYS_COMPLEX,
   cont_fw_cf_open, cont_fw_cf_close, NULL, cont_fw_cf_write, cont_fw_cf_read, cont_fw_cf_flush, NULL, cont_fw_cf_ctl},
+#endif
+#endif
+#ifdef ROAR_HAVE_LIBUNIRAUM
+ {ROAR_CODEC_RAUM, "uniraum", "RAUM Container Format", NULL, NULL, ROAR_CODECFILTER_READ,
+  ROAR_SUBSYS_WAVEFORM|ROAR_SUBSYS_MIDI|ROAR_SUBSYS_LIGHT|ROAR_SUBSYS_RAW|ROAR_SUBSYS_COMPLEX,
+  cf_uniraum_open, cf_uniraum_close, NULL, cf_uniraum_write, cf_uniraum_read, cf_uniraum_flush, NULL, cf_uniraum_ctl}, 
 #endif
 
Index: roard/codecfilter_uniraum.c
===================================================================
--- roard/codecfilter_uniraum.c	(revision 5955)
+++ roard/codecfilter_uniraum.c	(revision 5955)
@@ -0,0 +1,719 @@
+//codecfilter_wave.c:
+
+/*
+ *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2013
+ *
+ *  This file is part of roard a part of RoarAudio,
+ *  a cross-platform sound system for both, home and professional use.
+ *  See README for details.
+ *
+ *  This file is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3
+ *  as published by the Free Software Foundation.
+ *
+ *  RoarAudio is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this software; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "roard.h"
+
+#ifdef ROAR_HAVE_LIBUNIRAUM
+
+#include <uniraum/uniraum.h>
+
+#define MAX_STREAMS 4
+
+struct codecfilter_uniraum_inst; 
+
+struct codecfilter_uniraum_inst_stream {
+ size_t refc;
+ struct codecfilter_uniraum_inst * parent;
+ struct roar_stream_server * ss;
+ int stream;
+ uniraum_stream_t * uniraumstream;
+ uniraum_mapping_t * uniraummapping;
+ uniraum_data_t * dataqueue;
+};
+
+struct codecfilter_uniraum_inst {
+ size_t refc;
+ struct roar_stream_server * ss;
+ struct roar_vio_calls vio;
+ uniraum_file_t * file;
+ struct codecfilter_uniraum_inst_stream stream[MAX_STREAMS];
+ size_t streams;
+ int got_eof;
+ int is_execed;
+};
+
+static inline void __stream_ref(struct codecfilter_uniraum_inst_stream * self);
+static inline void __stream_unref(struct codecfilter_uniraum_inst_stream * self);
+static inline int __read_more_data(struct codecfilter_uniraum_inst * self, int stream);
+static inline void __stream_pushdata(struct codecfilter_uniraum_inst_stream * self);
+static inline void __stream_setup_vio(struct codecfilter_uniraum_inst_stream * self);
+
+static inline void __inst_ref(struct codecfilter_uniraum_inst * self) {
+ self->refc++;
+}
+
+static inline void __inst_unref(struct codecfilter_uniraum_inst * self) {
+ self->refc--;
+ if ( self->refc )
+  return;
+ uniraum_unref(self->file);
+ self->file = NULL;
+ roar_mm_free(self);
+}
+
+struct codecfilter_uniraum_inst_stream * __stream_get(struct codecfilter_uniraum_inst * self, int stream) {
+ size_t i;
+
+ for (i = 0; i < MAX_STREAMS; i++) {
+  if ( self->stream[i].refc && self->stream[i].stream == stream ) {
+   __stream_ref(&(self->stream[i]));
+   return &(self->stream[i]);
+  }
+ }
+
+ roar_err_set(ROAR_ERROR_NOENT);
+ return NULL;
+}
+
+struct codecfilter_uniraum_inst_stream * __stream_new(struct codecfilter_uniraum_inst * self, int stream) {
+ struct codecfilter_uniraum_inst_stream * ret;
+ size_t i;
+
+ ret = __stream_get(self, stream);
+ if ( ret != NULL ) {
+  __stream_unref(ret);
+  roar_err_set(ROAR_ERROR_EXIST);
+  return NULL;
+ }
+
+ for (i = 0; i < MAX_STREAMS; i++) {
+  ret = &(self->stream[i]);
+  if ( !ret->refc ) {
+   memset(ret, 0, sizeof(*ret));
+   ret->refc = 1;
+   ret->parent = self;
+   ret->ss = NULL;
+   ret->stream = stream;
+   ret->uniraumstream = NULL;
+   ret->uniraummapping = NULL;
+   ret->dataqueue = NULL;
+   if ( streams_new_virtual(ROAR_STREAM(self->ss)->id, &(ret->ss)) == -1 ) {
+    ret->refc = 0;
+    return NULL;
+   }
+   __stream_setup_vio(ret);
+   __stream_ref(ret);
+   self->streams++;
+   return ret;
+  }
+ }
+
+ roar_err_set(ROAR_ERROR_NOSPC);
+ return NULL;
+}
+
+static inline void __stream_ref(struct codecfilter_uniraum_inst_stream * self) {
+ self->refc++;
+}
+
+static inline void __stream_unref(struct codecfilter_uniraum_inst_stream * self) {
+ self->refc--;
+ if ( self->refc )
+  return;
+ self->parent->streams--;
+ __inst_unref(self->parent);
+ uniraum_stream_unref(self->uniraumstream);
+ uniraum_mapping_unref(self->uniraummapping);
+ roar_buffer_free(self->dataqueue);
+ roar_mm_free(self);
+}
+
+static ssize_t        __v_read    (struct roar_vio_calls * vio, void *buf, size_t count) {
+ struct codecfilter_uniraum_inst_stream * self = vio->inst;
+ ssize_t done = 0;
+ size_t len;
+ int ret;
+
+ ROAR_DBG("__v_read(vio=%p, buf=%p, count=%llu) = ?", vio, buf, (long long unsigned int)count);
+
+ while (count) {
+  ROAR_DBG("__v_read(vio=%p, buf=?, count=?): %llu bytes left to do", vio, (long long unsigned int)count);
+  len = count;
+  if ( self->dataqueue == NULL ) {
+   len = 0;
+  } else if ( roar_buffer_shift_out(&(self->dataqueue), buf, &len) == -1 ) {
+   ROAR_DBG("__v_read(vio=%p, buf=%p, count=?): roar_errorstring=%s", vio, buf, roar_errorstring);
+   break;
+  }
+
+  if ( len == 0 ) {
+   __stream_pushdata(self);
+   len = count;
+   if ( self->dataqueue == NULL ) {
+    len = 0;
+   } else if ( roar_buffer_shift_out(&(self->dataqueue), buf, &len) == -1 ) {
+    ROAR_DBG("__v_read(vio=%p, buf=%p, count=?): roar_errorstring=%s", vio, buf, roar_errorstring);
+    break;
+   }
+   ROAR_DBG("__v_read(vio=%p, buf=?, count=?) = ?", vio);
+   if ( len == 0 ) {
+    do {
+     ret = __read_more_data(self->parent, self->stream);
+    } while (ret == 0 && self->dataqueue == NULL);
+    //__stream_pushdata(self);
+    len = count;
+    ROAR_DBG("__v_read(vio=%p, buf=?, count=?): self->dataqueue=%p, buf=%p", vio, self->dataqueue, buf);
+    if ( roar_buffer_shift_out(&(self->dataqueue), buf, &len) == -1 ) {
+     ROAR_DBG("__v_read(vio=%p, buf=?, count=?): roar_errorstring=%s", vio, roar_errorstring);
+     break;
+    }
+   }
+  }
+
+  buf   += len;
+  count -= len;
+  done  += len;
+ }
+
+ ROAR_DBG("__v_read(vio=%p, buf=%p, count=?) = %lli", vio, buf, (long long int)done);
+ return done;
+}
+
+static ssize_t        __v_write   (struct roar_vio_calls * vio, void *buf, size_t count) {
+ // TODO: add support here to write a stream.
+ roar_err_set(ROAR_ERROR_NOSYS);
+ return -1;
+}
+
+static roar_off_t     __v_lseek   (struct roar_vio_calls * vio, roar_off_t offset, int whence) {
+ roar_err_set(ROAR_ERROR_NOSYS);
+ return -1;
+}
+
+static int            __v_sync    (struct roar_vio_calls * vio) {
+ // TODO: add support here to flush the mapping of this stream and stuff.
+ roar_err_set(ROAR_ERROR_NOSYS);
+ return -1;
+}
+
+static int            __v_ctl     (struct roar_vio_calls * vio, roar_vio_ctl_t cmd, void * data) {
+ roar_err_set(ROAR_ERROR_NOSYS);
+ return -1;
+}
+
+static int            __v_close   (struct roar_vio_calls * vio) {
+ // TODO: add support here to terminate the stream and write KICK command and sttuff.
+ __stream_unref(vio->inst);
+ roar_vio_clear_calls(vio);
+ return 0;
+}
+
+static inline void __stream_setup_vio(struct codecfilter_uniraum_inst_stream * self) {
+ struct roar_vio_calls * vio = &(self->ss->vio);
+ roar_vio_clear_calls(vio);
+ vio->inst  = self;
+ vio->read  = __v_read;
+ vio->write = __v_write;
+ vio->lseek = __v_lseek;
+ vio->sync  = __v_sync;
+ vio->ctl   = __v_ctl;
+ vio->close = __v_close;
+ __stream_ref(self);
+}
+
+
+static inline void __stream_pushdata(struct codecfilter_uniraum_inst_stream * self) {
+ uniraum_req_t * req = NULL;
+ uniraum_data_t * data;
+ int queue_filled;
+
+ ROAR_DBG("__stream_pushdata(self=%p) = ?", self);
+
+ do {
+  ROAR_DBG("__stream_pushdata(self=%p) = ?", self);
+  do {
+   ROAR_DBG("__stream_pushdata(self=%p): self->uniraummapping=%p", self, self->uniraummapping);
+   data = uniraum_mapping_dataout(self->uniraummapping);
+   queue_filled = data != NULL;
+   ROAR_DBG("__stream_pushdata(self=%p): queue_filled=%i", self, queue_filled);
+   if ( queue_filled ) {
+    if ( roar_buffer_moveintoqueue(&(self->dataqueue), &data) == -1 ) {
+     ROAR_ERR("__stream_pushdata(self=%p): lost data (can not push into queue): %s", self, roar_errorstring);
+     uniraum_data_unref(data);
+     queue_filled = 0;
+    }
+   }
+  } while (queue_filled);
+
+  req = uniraum_stream_reqout(self->uniraumstream);
+  ROAR_DBG("__stream_pushdata(self=%p): req=%p", self, req);
+  if ( req != NULL ) {
+   if ( uniraum_reqget_type(req) == ROAR_CMD_ADD_DATA ) {
+    ROAR_DBG("__stream_pushdata(self=%p): self->uniraummapping=%p, req=%p is data.", self, self->uniraummapping, req);
+    if ( uniraum_mapping_reqin(self->uniraummapping, req) == -1 ) {
+     ROAR_ERR("__stream_pushdata(self=%p): Can not push data into mapping. Bad.", self);
+    }
+   }
+   uniraum_requnref(req);
+  }
+ } while (req != NULL);
+}
+
+static inline int __handle_meta_data(struct codecfilter_uniraum_inst * self, uniraum_req_t * in, int stream) {
+ struct codecfilter_uniraum_inst_stream * streamobj;
+ int server_stream = -1;
+ const char * key;
+ const char * value;
+ int mode;
+
+ if ( stream == -1 ) {
+  server_stream = ROAR_STREAM(self->ss)->id;
+ } else {
+  streamobj = __stream_get(self, stream);
+  if ( streamobj == NULL )
+   return -1;
+  server_stream = ROAR_STREAM(streamobj->ss)->id;
+  __stream_unref(streamobj);
+ }
+
+ if ( uniraum_reqget_meta(in, &key, &value, &mode) == -1 ) {
+  roar_err_set(uniraum_error(self->file));
+  return -1;
+ }
+
+ switch (mode) {
+  case ROAR_META_MODE_SET:
+    return stream_meta_set(server_stream, roar_meta_inttype(key), key, value);
+   break;
+  case ROAR_META_MODE_ADD:
+    return stream_meta_add(server_stream, roar_meta_inttype(key), key, value);
+   break;
+  case ROAR_META_MODE_CLEAR:
+    return stream_meta_clear(server_stream);
+   break;
+  case ROAR_META_MODE_FINALIZE:
+    return stream_meta_finalize(server_stream);
+   break;
+  case ROAR_META_MODE_DELETE:
+    roar_err_set(ROAR_ERROR_NOTSUP);
+    return -1;
+   break;
+ }
+
+ roar_err_set(ROAR_ERROR_BADRQC);
+ return -1;
+}
+
+static inline int __handle_req_global(struct codecfilter_uniraum_inst * self, uniraum_req_t * in, int type) {
+ ROAR_DBG("__handle_req_global(self=%p, in=%p, type=%i) = ?", self, in, type);
+
+ switch (type) {
+  case ROAR_CMD_NOOP:
+  case ROAR_CMD_CAPS:
+  case ROAR_CMD_RAUM_SEEKTABLE:
+    // NOOPs.
+    return 0;
+   break;
+  case ROAR_CMD_QUIT:
+    self->got_eof = 1;
+    ROAR_DBG("__handle_req_global(self=%p, in=%p, type=%i) = 0 // EOF mark", self, in, type);
+    return 0;
+   break;
+  case ROAR_CMD_SET_META:
+    return __handle_meta_data(self, in, -1);
+   break;
+  default:
+    ROAR_DBG("__handle_req_global(self=%p, in=%p, type=%i) = 0 // error=NSTYPE", self, in, type);
+    roar_err_set(ROAR_ERROR_NSTYPE);
+    return -1;
+   break;
+ }
+}
+
+static inline void __handle_req_stream_update_codec(struct roar_audio_info * info) {
+ switch (info->codec) {
+  case ROAR_CODEC_RAUM_VORBIS:
+    info->codec = ROAR_CODEC_OGG_VORBIS;
+   break;
+  case ROAR_CODEC_RAUM_FLAC:
+   break;
+ }
+}
+
+static inline int __handle_req_stream(struct codecfilter_uniraum_inst * self, uniraum_req_t * in, int type, int stream) {
+ struct codecfilter_uniraum_inst_stream * streamobj;
+ struct roar_audio_info info;
+ int stream_dir = -1;
+ int ret = -1;
+ int err;
+
+ ROAR_DBG("__handle_req_stream(self=%p, in=%p, type=%i, stream=%i) = ?", self, in, type, stream);
+
+ if ( type == ROAR_CMD_NEW_STREAM ) {
+  streamobj = __stream_new(self, stream);
+  if ( streamobj == NULL )
+   return -1;
+
+  streamobj->uniraumstream = uniraum_stream_new(in);
+  ret = streamobj->uniraumstream == NULL ? -1 : 0;
+ } else {
+  streamobj = __stream_get(self, stream);
+  if ( streamobj == NULL )
+   return -1;
+  ret = uniraum_stream_reqin(streamobj->uniraumstream, in);
+  ROAR_DBG("__handle_req_stream(self=%p, in=%p, type=%i, stream=%i): ret=%i", self, in, type, stream, ret);
+ }
+
+ if ( ret == -1 ) {
+  err = roar_error;
+  __stream_unref(streamobj);
+  roar_err_set(err);
+  ROAR_DBG("__handle_req_stream(self=%p, in=%p, type=%i, stream=%i) = -1 // error=%s", self, in, type, stream, roar_errorstring);
+  return -1;
+ }
+
+ switch (type) {
+  case ROAR_CMD_RAUM_SEEKTABLE:
+  case ROAR_CMD_ADD_DATA:
+  case ROAR_CMD_KICK:
+    // NOOPs.
+    ret = 0;
+   break;
+  case ROAR_CMD_SET_META:
+    ret = __handle_meta_data(self, in, stream);
+   break;
+  case ROAR_CMD_EXEC_STREAM:
+    self->is_execed = stream;
+    ret = 0;
+   break;
+  case ROAR_CMD_NEW_STREAM:
+    stream_dir = uniraum_stream_get_dir(streamobj->uniraumstream);
+    info = ROAR_STREAM(streamobj->ss)->info = *uniraum_stream_get_auinfo(streamobj->uniraumstream);
+    __handle_req_stream_update_codec(&(ROAR_STREAM(streamobj->ss)->info));
+    ROAR_DBG("__handle_req_stream(self=%p, in=%p, type=%i, stream=%i): stream_dir=%i, codec=%s", self, in, type, stream, stream_dir, roar_codec2str(ROAR_STREAM(streamobj->ss)->info.codec));
+    streamobj->ss->codec_orgi = ROAR_STREAM(streamobj->ss)->info.codec;
+    streams_set_dir(ROAR_STREAM(streamobj->ss)->id, stream_dir, 1);
+    streams_set_fh(ROAR_STREAM(streamobj->ss)->id, -2);
+    streamobj->uniraummapping = uniraum_mapping_new(stream,
+                                                    UNIRAUM_IN, ROAR_VIO_DFT_RAW,
+                                                    &info);
+   break;
+  case ROAR_CMD_SET_VOL:
+  case ROAR_CMD_SET_STREAM_PARA:
+  default:
+    roar_err_set(ROAR_ERROR_NSTYPE);
+    ret = -1;
+   break;
+ }
+
+ err = roar_error;
+
+ __stream_pushdata(streamobj);
+ __stream_unref(streamobj);
+
+ roar_err_set(err);
+ ROAR_DBG("__handle_req_stream(self=%p, in=%p, type=%i, stream=%i) = %i // error=%s", self, in, type, stream, ret, roar_errorstring);
+ return ret;
+}
+
+static inline int __handle_req(struct codecfilter_uniraum_inst * self, uniraum_req_t * in, int type, int stream) {
+ ROAR_DBG("__handle_req(self=%p, in=%p, type=%i, stream=%i) = ?", self, in, type, stream);
+
+ if ( stream == -1 ) {
+  return __handle_req_global(self, in, type);
+ } else {
+  return __handle_req_stream(self, in, type, stream);
+ }
+}
+
+static inline int __read_more_data_execed(struct codecfilter_uniraum_inst * self) {
+/*
+ssize_t          uniraum_read_execed (uniraum_file_t * state,       void * buf, size_t len);
+uniraum_req_t *  uniraum_reqdata(int stream, uniraum_pos_t pos, const void * data, size_t len);
+uniraum_req_t *  uniraum_reqend_stream(int stream, uniraum_pos_t pos);
+*/
+
+ uniraum_req_t * data = NULL;
+ char buf[1024];
+ ssize_t ret;
+
+ ROAR_DBG("__read_more_data_execed(self=%p) = ?", self);
+
+ ret = uniraum_read_execed(self->file, buf, sizeof(buf));
+ if ( ret < 0 ) {
+  ROAR_DBG("__read_more_data_execed(self=%p) = -1 // EOF?", self);
+  self->got_eof = 1;
+  roar_err_set(uniraum_error(self->file));
+  return -1;
+ } else if ( ret == 0 ) {
+  self->got_eof = 1;
+ } else {
+  data = uniraum_reqdata(self->is_execed, 0, buf, ret);
+ }
+
+ if ( data == NULL ) {
+  ROAR_DBG("__read_more_data_execed(self=%p) = -1", self);
+  roar_err_set(uniraum_error(self->file));
+  return -1;
+ }
+
+ __handle_req_stream(self, data, uniraum_reqget_type(data), self->is_execed);
+ uniraum_requnref(data);
+
+ ROAR_DBG("__read_more_data_execed(self=%p) = 0", self);
+ return 0;
+}
+
+static inline int __read_more_data(struct codecfilter_uniraum_inst * self, int stream) {
+ uniraum_req_t * in;
+ int instream;
+ int intype;
+ int err;
+
+ ROAR_DBG("__read_more_data(self=%p, stream=%i) = ?", self, stream);
+
+ if ( self->got_eof ) {
+  roar_err_set(ROAR_ERROR_NONE);
+  return -1;
+ } else if ( self->is_execed != -1 ) {
+  if ( self->is_execed == stream ) {
+   __read_more_data_execed(self);
+   ROAR_DBG("__read_more_data(self=%p, stream=%i) = 0", self, stream);
+   return 0;
+  } else {
+   roar_err_set(ROAR_ERROR_BADSTATE);
+   return -1;
+  }
+ }
+
+ ROAR_DBG("__read_more_data(self=%p, stream=%i) = ?", self, stream);
+
+ do {
+  in = uniraum_reqin(self->file);
+  if ( in == NULL ) {
+   err = uniraum_error(self->file);
+   if ( err == ROAR_ERROR_AGAIN ) {
+    if ( uniraum_read(self->file) == -1 ) {
+     roar_err_set(uniraum_error(self->file));
+     ROAR_DBG("__read_more_data(self=%p, stream=%i): Can not read input data (EOF?): %s", self, stream, roar_errorstring);
+     self->got_eof = 1;
+     return -1;
+    }
+    in = uniraum_reqin(self->file);
+    if ( in == NULL ) {
+     roar_err_set(uniraum_error(self->file));
+     return -1;
+    }
+   } else {
+    roar_err_set(err);
+    return -1;
+   }
+  }
+  intype   = uniraum_reqget_type(in);
+  instream = uniraum_reqget_stream(in);
+  __handle_req(self, in, intype, instream);
+  uniraum_requnref(in);
+ } while ( self->is_execed == -1 && !self->got_eof &&
+           ((stream != -1 && stream != instream) || (stream == -1 && intype != ROAR_CMD_ADD_DATA)) );
+
+ ROAR_DBG("__read_more_data(self=%p, stream=%i) = 0", self, stream);
+ return 0;
+}
+
+static ssize_t        __s_read    (struct roar_vio_calls * vio, void *buf, size_t count) {
+ ROAR_DBG("__s_read(vio=%p, buf=%p, count=?) = ?", vio, buf);
+ return stream_vio_s_read(((struct codecfilter_uniraum_inst*)vio->inst)->ss, buf, count);
+}
+static ssize_t        __s_write   (struct roar_vio_calls * vio, void *buf, size_t count) {
+ return stream_vio_s_write(((struct codecfilter_uniraum_inst*)vio->inst)->ss, buf, count);
+}
+static roar_off_t     __s_lseek   (struct roar_vio_calls * vio, roar_off_t offset, int whence) {
+ roar_err_set(ROAR_ERROR_NOSYS);
+ return -1;
+}
+static int            __s_sync    (struct roar_vio_calls * vio) {
+ roar_err_set(ROAR_ERROR_NOSYS);
+ return -1;
+}
+static int            __s_ctl     (struct roar_vio_calls * vio, roar_vio_ctl_t cmd, void * data) {
+ return stream_vio_s_ctl(((struct codecfilter_uniraum_inst*)vio->inst)->ss, cmd, data);
+}
+static int            __s_close   (struct roar_vio_calls * vio) {
+ roar_err_set(ROAR_ERROR_NOSYS);
+ return -1;
+}
+
+static inline void __init_s_vio(struct codecfilter_uniraum_inst * self) {
+ roar_vio_clear_calls(&(self->vio));
+ self->vio.inst  = self;
+ self->vio.read  = __s_read;
+ self->vio.write = __s_write;
+ self->vio.lseek = __s_lseek;
+ self->vio.sync  = __s_sync;
+ self->vio.ctl   = __s_ctl;
+ self->vio.close = __s_close;
+}
+
+static inline int __open_file(struct codecfilter_uniraum_inst * self) {
+ int dir;
+ int flags;
+
+ ROAR_DBG("__open_file(self=%p) = ?", self);
+
+ if ( self->file != NULL ) {
+  ROAR_DBG("__open_file(self=%p) = -1 // error=ALREADY", self);
+  roar_err_set(ROAR_ERROR_ALREADY);
+  return -1;
+ }
+
+ dir = streams_get_ssdir(ROAR_STREAM(self->ss)->id);
+
+ switch (dir) {
+  case STREAM_DIR_IN:
+    flags = O_RDONLY;
+   break;
+  case STREAM_DIR_OUT:
+    flags = O_WRONLY;
+   break;
+  case STREAM_DIR_BIDIR:
+    flags = O_RDWR;
+   break;
+  default:
+    roar_err_set(ROAR_ERROR_NOTSUP);
+    return -1;
+   break;
+ }
+
+ __init_s_vio(self);
+
+ ROAR_DBG("__open_file(self=%p) = ?", self);
+
+ self->file = uniraum_openvio(&(self->vio), flags);
+ if ( self->file == NULL ) {
+  roar_err_set(uniraum_error(NULL));
+  ROAR_DBG("__open_file(self=%p): Can not open uniraum file object: %s", self, roar_errorstring);
+  return -1;
+ }
+
+ ROAR_DBG("__open_file(self=%p) = 0", self);
+ return 0;
+}
+
+int cf_uniraum_open (CODECFILTER_USERDATA_T * inst, int codec,
+                     struct roar_stream_server * info,
+                     struct roar_codecfilter   * filter) {
+ struct codecfilter_uniraum_inst * self;
+
+ self = roar_mm_malloc(sizeof(struct codecfilter_uniraum_inst));
+ if ( self == NULL )
+  return -1;
+
+ memset(self, 0, sizeof(struct codecfilter_uniraum_inst));
+ self->refc = 1;
+ self->ss   = info;
+ self->file = NULL;
+ self->got_eof = 0;
+ self->is_execed = -1;
+
+ *inst = self;
+
+ return 0;
+}
+
+int cf_uniraum_close(CODECFILTER_USERDATA_T   inst) {
+ struct codecfilter_uniraum_inst * self = inst;
+
+ __inst_unref(self);
+
+ ROAR_DBG("cf_uniraum_close(inst=%p) = 0", inst);
+ return 0;
+}
+
+int cf_uniraum_write(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
+ struct codecfilter_uniraum_inst * self = inst;
+
+ if ( self->file == NULL )
+  if ( __open_file(self) == -1 )
+   return -1;
+
+ roar_err_set(ROAR_ERROR_BADFH);
+ return -1;
+}
+
+int cf_uniraum_read (CODECFILTER_USERDATA_T   inst, char * buf, int len) {
+ struct codecfilter_uniraum_inst * self = inst;
+ ROAR_DBG("cf_uniraum_read(inst=%p, buf=%p, len=%i) = ?", inst, buf, len);
+
+ if ( self == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return -1;
+ }
+
+ if ( self->file == NULL )
+  if ( __open_file(self) == -1 )
+   return -1;
+
+ if ( !self->streams )
+  __read_more_data(self, -1);
+
+ if ( self->got_eof ) {
+  ROAR_DBG("cf_uniraum_read(inst=%p, buf=%p, len=%i) = 0 // EOF", inst, buf, len);
+  return 0;
+ } else {
+  ROAR_DBG("cf_uniraum_read(inst=%p, buf=%p, len=%i) = -1 // errno=EAGAIN", inst, buf, len);
+  errno = EAGAIN;
+  return -1;
+ }
+}
+
+int cf_uniraum_flush(CODECFILTER_USERDATA_T   inst) {
+ struct codecfilter_uniraum_inst * self = inst;
+ int r = uniraum_write(self->file);
+
+ if ( r == -1 )
+  roar_err_set(uniraum_error(self->file));
+
+ return r;
+}
+
+int cf_uniraum_ctl  (CODECFILTER_USERDATA_T   inst, int cmd, void * data) {
+ struct codecfilter_uniraum_inst * self = inst;
+ int_least32_t type = cmd & ROAR_STREAM_CTL_TYPEMASK;
+
+ cmd -= type;
+
+ ROAR_DBG("cf_uniraum_ctl(*): cmd=0x%.8x, type=0x%.8x, pcmd=0x%.8x",
+          cmd, type, ROAR_CODECFILTER_CTL2CMD(cmd));
+
+ switch (cmd) {
+  case ROAR_CODECFILTER_CTL2CMD(ROAR_CODECFILTER_CTL_META_UPDATE):
+    if ( type != ROAR_STREAM_CTL_TYPE_VOID )
+     return -1;
+    roar_err_set(ROAR_ERROR_NOTSUP);
+    return -1;
+   break;
+  default:
+    ROAR_DBG("cf_uniraum_ctl(*): Unknown command: cmd=0x%.8x, type=0x%.8x, pcmd=0x%.8x",
+                    cmd, type, ROAR_CODECFILTER_CTL2CMD(cmd));
+    roar_err_set(ROAR_ERROR_BADRQC);
+    return -1;
+   break;
+ }
+}
+
+
+#endif
+
+//ll
Index: roard/include/codecfilter.h
===================================================================
--- roard/include/codecfilter.h	(revision 5823)
+++ roard/include/codecfilter.h	(revision 5955)
@@ -114,4 +114,8 @@
 #endif
 
+#ifdef ROAR_HAVE_LIBUNIRAUM
+#include "codecfilter_uniraum.h"
+#endif
+
 #include "container_framework.h"
 
Index: roard/include/codecfilter_uniraum.h
===================================================================
--- roard/include/codecfilter_uniraum.h	(revision 5955)
+++ roard/include/codecfilter_uniraum.h	(revision 5955)
@@ -0,0 +1,47 @@
+//codecfilter_uniraum.h:
+
+/*
+ *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2013
+ *
+ *  This file is part of roard a part of RoarAudio,
+ *  a cross-platform sound system for both, home and professional use.
+ *  See README for details.
+ *
+ *  This file is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3
+ *  as published by the Free Software Foundation.
+ *
+ *  RoarAudio is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this software; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _CODECFILTER_UNIRAUM_H_
+#define _CODECFILTER_UNIRAUM_H_
+
+#include <roaraudio.h>
+
+#ifdef ROAR_HAVE_LIBUNIRAUM
+
+int cf_uniraum_open (CODECFILTER_USERDATA_T * inst, int codec,
+                     struct roar_stream_server * info,
+                     struct roar_codecfilter   * filter);
+int cf_uniraum_close(CODECFILTER_USERDATA_T   inst);
+//int cf_uniraum_pause(CODECFILTER_USERDATA_T   inst, int newstate);
+int cf_uniraum_write(CODECFILTER_USERDATA_T   inst, char * buf, int len);
+int cf_uniraum_read (CODECFILTER_USERDATA_T   inst, char * buf, int len);
+int cf_uniraum_flush(CODECFILTER_USERDATA_T   inst);
+//int cf_uniraum_delay(CODECFILTER_USERDATA_T   inst, uint_least32_t * delay);
+int cf_uniraum_ctl  (CODECFILTER_USERDATA_T   inst, int cmd, void * data);
+
+#endif
+#endif
+
+//ll
Index: roard/streams.c
===================================================================
--- roard/streams.c	(revision 5823)
+++ roard/streams.c	(revision 5955)
@@ -566,6 +566,8 @@
  ROAR_DBG("streams_set_role(id=%i, role=%i) = ?", id, role);
 
- if ( old_role == role )
+ if ( old_role == role ) {
+  ROAR_DBG("streams_set_role(id=%i, role=%i) = 0", id, role);
   return 0;
+ }
 
  if ( old_role != role && old_role != -1 && role != -1 ) {
@@ -813,7 +815,9 @@
    break;
   default:
+    ROAR_DBG("streams_set_fh(id=%i, fh=%i): codec=%s(%i)", id, fh, roar_codec2str(s->info.codec), s->info.codec);
     if ( codecfilter_open(&(ss->codecfilter_inst), &(ss->codecfilter), NULL,
                      s->info.codec, ss) == -1 ) {
      streams_delete(id); // TODO: FIXME: is this correct? shoudn't we return -1 in any case here?
+     ROAR_DBG("streams_set_fh(id=%i, fh=%i) = -1", id, fh);
      return -1;
     }
