Index: libroar/ctl.c
===================================================================
--- libroar/ctl.c	(revision 6072)
+++ libroar/ctl.c	(revision 0)
@@ -1,82 +1,19 @@
 //ctl.c:
 
-/*
- *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2015
- *
- *  This file is part of libroar 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.
- *
- *  libroar 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.
- *
- *  NOTE for everyone want's to change something and send patches:
- *  read README and HACKING! There a addition information on
- *  the license of this document you need to read before you send
- *  any patches.
- *
- *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
- *  or libpulse*:
- *  The libs libroaresd, libroararts and libroarpulse link this lib
- *  and are therefore GPL. Because of this it may be illigal to use
- *  them with any software that uses libesd, libartsc or libpulse*.
- */
-
 #include "libroar.h"
 
-int roar_get_clientid  (struct roar_connection * con) {
- struct roar_message mes;
-
- memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
-
- mes.cmd     = ROAR_CMD_WHOAMI;
- mes.stream  = -1;
- mes.datalen =  0;
-
- if ( roar_req(con, &mes, NULL) == -1 )
-  return -1;
-
- if ( mes.cmd != ROAR_CMD_OK )
-  return -1;
-
- if ( mes.datalen != 1 )
-  return -1;
-
- return mes.data[0];
-}
-
-int roar_server_oinfo  (struct roar_connection * con, struct roar_stream * s, int dir) {
- struct roar_message mes;
-
- memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
+int roar_server_oinfo   (struct roar_connection * con, struct roar_stream * sa) {
+ struct roar_message mes;
 
  mes.cmd     = ROAR_CMD_SERVER_OINFO;
-
- if ( dir == -1 ) {
-  mes.datalen = 0;
- } else {
-  mes.datalen = 2;
-  mes.data[0] = 0;
-  mes.data[1] = dir;
- }
-
- if ( roar_req(con, &mes, NULL) == -1 )
-  return -1;
-
- if ( mes.cmd != ROAR_CMD_OK )
-  return -1;
-
- if ( roar_stream_m2s(s, &mes) == -1 )
+ mes.datalen = 0;
+
+ if ( roar_req(con, &mes, NULL) == -1 )
+  return -1;
+
+ if ( mes.cmd != ROAR_CMD_OK )
+  return -1;
+
+ if ( roar_stream_m2s(sa, &mes) == -1 )
   return -1;
 
@@ -86,67 +23,52 @@
 int roar_get_standby   (struct roar_connection * con) {
  struct roar_message mes;
- uint16_t * d16 = (uint16_t *)mes.data;
-
- memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
 
  mes.cmd = ROAR_CMD_GET_STANDBY;
- mes.stream  = -1;
- mes.datalen =  0;
-
- if ( roar_req(con, &mes, NULL) == -1 )
-  return -1;
-
- if ( mes.cmd != ROAR_CMD_OK )
-  return -1;
-
- return ROAR_NET2HOST16(*d16);
+ mes.datalen = 0;
+
+ if ( roar_req(con, &mes, NULL) == -1 )
+  return -1;
+
+ if ( mes.cmd != ROAR_CMD_OK )
+  return -1;
+
+ return ROAR_NET2HOST16(*((uint16_t*)mes.data));
 }
 
 int roar_set_standby   (struct roar_connection * con, int state) {
  struct roar_message mes;
- uint16_t * d16 = (uint16_t *)mes.data;
-
- memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
 
  mes.cmd = ROAR_CMD_SET_STANDBY;
- mes.stream  = -1;
- mes.datalen =  2;
-
- *d16 = ROAR_HOST2NET16((unsigned) state);
-
- if ( roar_req(con, &mes, NULL) == -1 )
-  return -1;
-
- if ( mes.cmd != ROAR_CMD_OK )
-  return -1;
-
- return 0;
-}
-
-int roar_terminate (struct roar_connection * con, int terminate) {
- struct roar_message mes;
-
- memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
-
- mes.cmd     = ROAR_CMD_EXIT;
- mes.stream  = -1;
- mes.datalen =  1;
- mes.data[0] = terminate;
-
- if ( roar_req(con, &mes, NULL) == -1 )
-  return -1;
-
- if ( mes.cmd != ROAR_CMD_OK )
-  return -1;
-
- return 0;
-}
-
-int roar_list_filtered(struct roar_connection * con, int * items,   int max, int cmd, unsigned char filter, unsigned char cmp, uint32_t id) {
- struct roar_message m;
-
- memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
-
- roar_ctl_f2m(&m, filter, cmp, id);
+ mes.datalen = 2;
+
+ *((uint16_t*)mes.data) = ROAR_HOST2NET16((unsigned) state);
+
+ if ( roar_req(con, &mes, NULL) == -1 )
+  return -1;
+
+ if ( mes.cmd != ROAR_CMD_OK )
+  return -1;
+
+ return 0;
+}
+
+int roar_exit   (struct roar_connection * con) {
+ struct roar_message mes;
+
+ mes.cmd = ROAR_CMD_EXIT;
+ mes.datalen = 0;
+ if ( roar_req(con, &mes, NULL) == -1 )
+  return -1;
+
+ if ( mes.cmd != ROAR_CMD_OK )
+  return -1;
+
+ return 0;
+}
+
+int roar_list         (struct roar_connection * con, int * items,   int max, int cmd) {
+ struct roar_message m;
+
+ roar_ctl_f2m_any(&m);
  m.cmd = cmd;
 
@@ -157,23 +79,14 @@
 }
 
-int roar_list         (struct roar_connection * con, int * items,   int max, int cmd) {
- return roar_list_filtered(con, items, max, cmd, ROAR_CTL_FILTER_ANY, ROAR_CTL_CMP_ANY, ROAR_CTL_FILTER_ANY);
-}
-
 int roar_get_client   (struct roar_connection * con, struct roar_client * client, int id) {
  struct roar_message m;
- char * data = NULL;
- int ret;
-
- memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
 
  m.cmd     = ROAR_CMD_GET_CLIENT;
- m.stream  = -1;
- m.datalen =  1;
+ m.datalen = 1;
  m.data[0] = id;
 
  ROAR_DBG("roar_get_client(*): id = %i", id);
 
- if ( roar_req(con, &m, &data) == -1 )
+ if ( roar_req(con, &m, NULL) == -1 )
   return -1;
 
@@ -183,16 +96,9 @@
  ROAR_DBG("roar_get_client(*): got ok");
 
- ret = roar_ctl_m2c2(&m, client, data);
-
- if ( data != NULL )
-  roar_mm_free(data);
-
- return ret;
+ return roar_ctl_m2c(&m, client);
 }
 
 int roar_get_stream   (struct roar_connection * con, struct roar_stream * stream, int id) {
  struct roar_message m;
-
- memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
 
  m.cmd     = ROAR_CMD_GET_STREAM;
@@ -200,10 +106,6 @@
  m.data[0] = id;
 
- roar_err_set(ROAR_ERROR_UNKNOWN);
-
- if ( roar_req(con, &m, NULL) == -1 ) {
-  roar_err_set(ROAR_ERROR_PROTO);
-  return -1;
- }
+ if ( roar_req(con, &m, NULL) == -1 )
+  return -1;
 
  if ( m.cmd != ROAR_CMD_OK )
@@ -215,12 +117,10 @@
 int roar_kick         (struct roar_connection * con, int type, int id) {
  struct roar_message m;
- uint16_t * info = (uint16_t *) m.data;
-
- memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
+ uint16_t * info = m.data;
 
  m.cmd     = ROAR_CMD_KICK;
  m.datalen = 4;
- info[0] = ROAR_HOST2NET16(type);
- info[1] = ROAR_HOST2NET16(id);
+ info[0] = type;
+ info[1] = id;
 
  if ( roar_req(con, &m, NULL) == -1 )
@@ -233,69 +133,4 @@
 }
 
-int roar_set_vol     (struct roar_connection * con, int id, struct roar_mixer_settings * mixer, int   channels, int mode) {
- struct roar_message m;
- uint16_t * info = (uint16_t *) m.data;
- int i;
-
- memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
-
- m.cmd     = ROAR_CMD_SET_VOL;
- m.datalen = (3 + channels) * 2;
- m.stream  = id;
- info[0] = ROAR_HOST2NET16(1);
- info[1] = ROAR_HOST2NET16(mixer->scale);
- info[2] = ROAR_HOST2NET16(mode);
-
- for (i = 0; i < channels; i++)
-  info[i+3] = ROAR_HOST2NET16(mixer->mixer[i]);
-
- if ( roar_req(con, &m, NULL) == -1 )
-  return -1;
-
- if ( m.cmd != ROAR_CMD_OK )
-  return -1;
-
- return 0;
-}
-
-int roar_get_vol      (struct roar_connection * con, int id, struct roar_mixer_settings * mixer, int * channels) {
- struct roar_message m;
- uint16_t * info = (uint16_t *) m.data;
- int i;
-
- memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
-
- m.cmd     = ROAR_CMD_GET_VOL;
- m.datalen = 2*2;
- m.stream  = id;
-
- info[0]   = ROAR_HOST2NET16(1);
-
- if ( roar_req(con, &m, NULL) == -1 )
-  return -1;
-
- if ( m.cmd != ROAR_CMD_OK )
-  return -1;
-
- if ( ROAR_NET2HOST16(info[0]) != 1 )
-  return -1;
-
- info[1] = ROAR_NET2HOST16(info[1]);
-
- if ( channels != NULL )
-  *channels = info[1];
-
- if ( info[1] > ROAR_MAX_CHANNELS )
-  return -1;
-
- mixer->scale   = ROAR_NET2HOST16(info[2]);
- mixer->rpg_mul = ROAR_NET2HOST16(info[3]);
- mixer->rpg_div = ROAR_NET2HOST16(info[4]);
-
- for (i = 0; i < info[1]; i++)
-  mixer->mixer[i] = ROAR_NET2HOST16(info[i+5]);
-
- return 0;
-}
 
 // converts: *_m2*, *_*2m
@@ -308,13 +143,9 @@
  m->data[1] = filter;
  m->data[2] = cmp;
- m->data[3] = (id & 0xFF000000LU) >> 24;
- m->data[4] = (id & 0x00FF0000LU) >> 16;
- m->data[5] = (id & 0x0000FF00LU) >>  8;
- m->data[6] = (id & 0x000000FFLU) >>  0;
+ *((uint32_t*)&(m->data[3])) = ROAR_HOST2NET32(id);
 
  return 0;
 }
 int roar_ctl_m2f      (struct roar_message * m, unsigned char * filter, unsigned char * cmp, uint32_t * id) {
- register uint32_t idreg;
 
  if ( m->datalen != 7 )
@@ -322,6 +153,5 @@
 
  if ( m->data[0] != 0 ) {
-  ROAR_DBG("roar_ctl_m2f(*): version %i not supported!", (int)m->data[0]);
-  roar_err_set(ROAR_ERROR_NSVERSION);
+  ROAR_ERR("roar_ctl_m2f(*): version %i not supported!", m->data[0]);
   return -1;
  }
@@ -330,37 +160,14 @@
  *cmp    = m->data[2];
 
- idreg   = ((uint32_t)(unsigned char)m->data[3]) << 24;
- idreg  |= ((uint32_t)(unsigned char)m->data[4]) << 16;
- idreg  |= ((uint32_t)(unsigned char)m->data[5]) <<  8;
- idreg  |= ((uint32_t)(unsigned char)m->data[6]) <<  0;
- *id     = idreg;
-
- return 0;
-}
-
-int roar_filter_match (const unsigned cmp, const uint32_t a, const uint32_t b) {
- switch (cmp) {
-  case ROAR_CTL_CMP_ANY:
-    return 1;
-   break;
-  case ROAR_CTL_CMP_EQ:
-    return a == b;
-   break;
-  case ROAR_CTL_CMP_NE:
-    return a != b;
-   break;
-  default:
-    roar_err_set(ROAR_ERROR_NOTSUP);
-    return -1;
- }
-}
-
-int roar_ctl_ia2m     (struct roar_message * m, int * data, size_t len) {
- size_t i;
-
- if ( len > LIBROAR_BUFFER_MSGDATA ) {
-  roar_err_set(ROAR_ERROR_MSGSIZE);
-  return -1;
- }
+ *id = ROAR_NET2HOST32(*((uint32_t*)&(m->data[3])));
+
+ return 0;
+}
+
+int roar_ctl_ia2m     (struct roar_message * m, int * data, int len) {
+ int i;
+
+ if ( len > LIBROAR_BUFFER_MSGDATA )
+  return -1;
 
  m->datalen = len;
@@ -371,11 +178,9 @@
  return 0;
 }
-int roar_ctl_m2ia     (struct roar_message * m, int * data, size_t len) {
- size_t i;
-
- if ( m->datalen > len ) {
-  roar_err_set(ROAR_ERROR_MSGSIZE);
-  return -1;
- }
+int roar_ctl_m2ia     (struct roar_message * m, int * data, int len) {
+ int i;
+
+ if ( m->datalen > len )
+  return -1;
 
  for (i = 0; i < m->datalen; i++)
@@ -385,58 +190,26 @@
 }
 
-int roar_ctl_c2m2     (struct roar_message * m, struct roar_client * c, void ** data) {
- char * d;
- size_t cur = 0;
+int roar_ctl_c2m      (struct roar_message * m, struct roar_client * c) {
+ int cur = 0;
  int h;
  int i;
  int max_len;
- uint32_t pid;
- size_t nnode_len;
- size_t needed_len = 3 + 5*4 + 18 /* 18 = current max size for blob */;
 
  if ( c == NULL )
   return -1;
 
- if ( data != NULL )
-  *data = NULL;
+ m->data[cur++] = 0;                       // 0: Version
+ m->data[cur++] = c->execed;               // 1: execed
+
+ h = 0;
+ for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
+  if ( c->streams[i] != -1 )
+   m->data[cur+1+h++] = c->streams[i];
+ }
+
+ m->data[cur++] = h;                       // 2: num of streams
+ cur += h;
 
  max_len = strlen(c->name);
- needed_len += max_len;
-
- for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++)
-  if ( c->streams[i] != -1 )
-   needed_len++;
-
- if ( needed_len > sizeof(m->data) ) {
-  if ( data == NULL ) {
-   needed_len -= max_len;
-   if ( needed_len > sizeof(m->data) ) {
-    roar_panic(ROAR_FATAL_ERROR_CPU_FAILURE, "needed_len > sizeof(m->data) happend.");
-    roar_err_set(ROAR_ERROR_BADCKSUM);
-    return -1;
-   }
-   max_len = sizeof(m->data) - needed_len;
-   needed_len = sizeof(m->data);
-   d = m->data;
-  } else {
-   d = roar_mm_malloc(needed_len);
-   if ( d == NULL )
-    return -1;
-   *data = d;
-  }
- } else {
-  d = m->data;
- }
-
- d[cur++] = 0;                       // 0: Version
- d[cur++] = c->execed;               // 1: execed
-
- h = 0;
- for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++)
-  if ( c->streams[i] != -1 )
-   d[cur+1+h++] = c->streams[i];
-
- d[cur++] = h;                       // 2: num of streams
- cur += h;
 
  // TODO: add some code to check if this fits in the pkg
@@ -444,537 +217,49 @@
  //       and fully decieded about this function.
 
- d[cur++] = max_len;
-
- strncpy(d+cur, c->name, max_len);
+ m->data[cur++] = max_len;
+
+ strncpy((m->data)+cur, c->name, max_len);
 
  cur += max_len;
 
- pid = ROAR_HOST2NET32(c->pid);
- memcpy(&(d[cur]), &pid, 4);
- cur += 4;
-
- pid = ROAR_HOST2NET32(c->uid);
- memcpy(&(d[cur]), &pid, 4);
- cur += 4;
-
- pid = ROAR_HOST2NET32(c->gid);
- memcpy(&(d[cur]), &pid, 4);
- cur += 4;
-
- pid = ROAR_HOST2NET32(c->proto);
- memcpy(&(d[cur]), &pid, 4);
- cur += 4;
-
- pid = ROAR_HOST2NET32(c->byteorder);
- memcpy(&(d[cur]), &pid, 4);
- cur += 4;
-
- if ( cur > needed_len ) {
-  roar_panic(ROAR_FATAL_ERROR_MEMORY_CORRUPTION, NULL);
+ m->datalen = cur;
+
+ return 0;
+}
+
+int roar_ctl_m2c      (struct roar_message * m, struct roar_client * c) {
+ int i;
+ int cur;
+
+ if ( m == NULL || c == NULL )
+  return -1;
+
+ if ( m->datalen == 0 )
+  return -1;
+
+ ROAR_DBG("roar_ctl_m2c(*): got data!, len = %i", m->datalen);
+
+ if ( m->data[0] != 0 ) {
+  ROAR_DBG("roar_ctl_m2c(*): wrong version!");
+  return -1;
  }
 
- nnode_len = needed_len - cur;
- if ( roar_nnode_to_blob(&(c->nnode), &(d[cur]), &nnode_len) == 0 ) {
-  cur += nnode_len;
- }
-
- if ( cur > needed_len ) {
-  roar_panic(ROAR_FATAL_ERROR_MEMORY_CORRUPTION, NULL);
- }
-
- m->datalen = cur;
-
- return 0;
-}
-
-int roar_ctl_m2c2      (struct roar_message * m, struct roar_client * c, void * data) {
- char * d = data;
- uint32_t pid;
- size_t len;
- size_t cur;
- int i;
-
- if ( m == NULL || c == NULL ) {
-  roar_err_set(ROAR_ERROR_FAULT);
-  return -1;
- }
-
- if ( m->datalen == 0 ) {
-  roar_err_set(ROAR_ERROR_MSGSIZE);
-  return -1;
- }
-
- if ( d == NULL ) {
-  if ( m->datalen > sizeof(m->data) ) {
-   roar_err_set(ROAR_ERROR_FAULT);
-   return -1;
-  }
-  d = m->data;
- }
-
- ROAR_DBG("roar_ctl_m2c(*): got data!, len = %i", m->datalen);
-
- if ( d[0] != 0 ) {
-  ROAR_DBG("roar_ctl_m2c(*): wrong version!");
-  roar_err_set(ROAR_ERROR_NSVERSION);
-  return -1;
- }
-
- if ( m->datalen < 3 ) {
-  roar_err_set(ROAR_ERROR_MSGSIZE);
-  return -1;
- }
+ if ( m->datalen < 3 )
+  return -1;
 
  ROAR_DBG("roar_ctl_m2c(*): have usable data!");
 
- c->execed = d[1];
+ c->execed = m->data[1];
 
  for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++)
   c->streams[i] = -1;
 
- if ( d[2] < 0 || d[2] > ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT ) {
-  roar_err_set(ROAR_ERROR_TOOMANYARGS);
-  return -1;
- }
-
- for (i = 0; i < d[2]; i++)
-  c->streams[i] = d[3+i];
-
- cur = 3 + d[2];
-
- // check length here!
- strncpy(c->name, d+cur+1, d[cur] > (sizeof(c->name)-1) ? sizeof(c->name)-1 : d[cur]);
- c->name[(size_t)d[cur] > (sizeof(c->name)-1) ? sizeof(c->name)-1 : (size_t)d[cur]] = 0;
-
- cur += d[cur] + 1;
-
- memcpy(&pid, &(d[cur]), 4);
- c->pid = ROAR_NET2HOST32(pid);
- cur += 4;
-
- memcpy(&pid, &(d[cur]), 4);
- c->uid = ROAR_NET2HOST32(pid);
- cur += 4;
-
- memcpy(&pid, &(d[cur]), 4);
- c->gid = ROAR_NET2HOST32(pid);
- cur += 4;
-
- if ( m->datalen >= cur+4 ) {
-  memcpy(&pid, &(d[cur]), 4);
-  c->proto = ROAR_NET2HOST32(pid);
-  cur += 4;
- } else {
-  c->proto = ROAR_PROTO_NONE;
- }
-
- if ( m->datalen >= cur+4 ) {
-  memcpy(&pid, &(d[cur]), 4);
-  c->byteorder = ROAR_NET2HOST32(pid);
-  cur += 4;
- } else {
-  c->byteorder = ROAR_BYTEORDER_UNKNOWN;
- }
-
- if ( m->datalen > cur ) {
-  len = m->datalen - cur;
-  if ( roar_nnode_from_blob(&(c->nnode), &(d[cur]), &len) == 0 ) {
-   cur += len;
-  } else {
-   if ( roar_nnode_new(&(c->nnode), ROAR_SOCKET_TYPE_UNKNOWN) == -1 )
-    return -1;
-  }
- } else {
-  if ( roar_nnode_new(&(c->nnode), ROAR_SOCKET_TYPE_UNKNOWN) == -1 )
-   return -1;
- }
-
- return 0;
-}
-
-int roar_ctl_c2m      (struct roar_message * m, struct roar_client * c) {
- return roar_ctl_c2m2(m, c, NULL);
-}
-int roar_ctl_m2c      (struct roar_message * m, struct roar_client * c) {
- return roar_ctl_m2c2(m, c, NULL);
-}
-
-static struct {
- int id;
- const char * name;
-} _proto[] = {
- {ROAR_PROTO_NONE,        "none"},
- {ROAR_PROTO_ROARAUDIO,   "RoarAudio"},
- {ROAR_PROTO_ESOUND,      "EsounD"},
- {ROAR_PROTO_ESOUND,      "ESD"}, // alias
- {ROAR_PROTO_AUTO,        "(auto)"},
- {ROAR_PROTO_HTTP,        "http"},
- {ROAR_PROTO_GOPHER,      "gopher"},
- {ROAR_PROTO_ICY,         "ICY"},
- {ROAR_PROTO_SIMPLE,      "Simple"},
- {ROAR_PROTO_RSOUND,      "RSound"},
- {ROAR_PROTO_RPLAY,       "RPlay"},
- {ROAR_PROTO_IRC,         "IRC"},
- {ROAR_PROTO_DCC,         "DCC"},
- {ROAR_PROTO_ECHO,        "Echo"},
- {ROAR_PROTO_DISCARD,     "Discard"},
- {ROAR_PROTO_WHOIS,       "Whois"},
- {ROAR_PROTO_FINGER,      "Finger"},
- {ROAR_PROTO_QUOTE,       "quote"},
- {ROAR_PROTO_DAYTIME,     "daytime"},
- {ROAR_PROTO_GAME,        "game"},
- {ROAR_PROTO_TELNET,      "telnet"},
- {ROAR_PROTO_DHCP,        "dhcp"},
- {ROAR_PROTO_SSH,         "ssh"},
- {ROAR_PROTO_TIME,        "time"},
- {ROAR_PROTO_RLOGIN,      "rlogin"},
- {ROAR_PROTO_RPLD,        "rpld"},
- {ROAR_PROTO_MPD,         "mpd"},
- {ROAR_PROTO_RTP,         "rtp"},
- {ROAR_PROTO_RTCP,        "rtcp"},
- {ROAR_PROTO_RTSP,        "rtsp"},
- {ROAR_PROTO_SIP,         "sip"},
- {ROAR_PROTO_DYNAMIC0,    "dynamic0"},
- {ROAR_PROTO_DYNAMIC1,    "dynamic1"},
- {ROAR_PROTO_DYNAMIC2,    "dynamic2"},
- {ROAR_PROTO_DYNAMIC3,    "dynamic3"},
- {ROAR_PROTO_DYNAMIC4,    "dynamic4"},
- {ROAR_PROTO_DYNAMIC5,    "dynamic5"},
- {ROAR_PROTO_DYNAMIC6,    "dynamic6"},
- {ROAR_PROTO_DYNAMIC7,    "dynamic7"},
- {ROAR_PROTO_DYNAMIC8,    "dynamic8"},
- {ROAR_PROTO_DYNAMIC9,    "dynamic9"},
- {ROAR_PROTO_DYNAMIC10,   "dynamic10"},
- {ROAR_PROTO_DYNAMIC11,   "dynamic11"},
- {ROAR_PROTO_DYNAMIC12,   "dynamic12"},
- {ROAR_PROTO_DYNAMIC13,   "dynamic13"},
- {ROAR_PROTO_DYNAMIC14,   "dynamic14"},
- {ROAR_PROTO_DYNAMIC15,   "dynamic15"},
- {ROAR_PROTO_USER0,       "user0"},
- {ROAR_PROTO_USER1,       "user1"},
- {ROAR_PROTO_USER2,       "user2"},
- {ROAR_PROTO_USER3,       "user3"},
- {ROAR_PROTO_USER4,       "user4"},
- {ROAR_PROTO_USER5,       "user5"},
- {ROAR_PROTO_USER6,       "user6"},
- {ROAR_PROTO_USER7,       "user7"},
- {ROAR_PROTO_USER8,       "user8"},
- {ROAR_PROTO_USER9,       "user9"},
- {ROAR_PROTO_USER10,      "user10"},
- {ROAR_PROTO_USER11,      "user11"},
- {ROAR_PROTO_USER12,      "user12"},
- {ROAR_PROTO_USER13,      "user13"},
- {ROAR_PROTO_USER14,      "user14"},
- {ROAR_PROTO_USER15,      "user15"},
- {-1, NULL}
-};
-
-int    roar_str2proto (const char * proto) {
- size_t i;
-
- for (i = 0; _proto[i].id != -1; i++)
-  if ( !strcasecmp(proto, _proto[i].name) )
-   return _proto[i].id;
-
- roar_err_set(ROAR_ERROR_NOENT);
- return -1;
-}
-
-const char * roar_proto2str (const int    proto) {
- size_t i;
-
- roar_err_set(ROAR_ERROR_NONE);
-
- for (i = 0; _proto[i].id != -1; i++)
-  if ( proto == _proto[i].id )
-   return _proto[i].name;
-
- roar_err_set(ROAR_ERROR_NOENT);
- return "(unknown)";
-}
-
-int    roar_str2byteorder (const char * byteorder) {
- if (        !strcasecmp(byteorder, "le")            || !strcasecmp(byteorder, "little") ||
-             !strcasecmp(byteorder, "little endian") || !strcasecmp(byteorder, "1234")   ) {
-  return ROAR_BYTEORDER_LE;
- } else if ( !strcasecmp(byteorder, "be")            || !strcasecmp(byteorder, "big")    ||
-             !strcasecmp(byteorder, "big endian")    || !strcasecmp(byteorder, "4321")   ) {
-  return ROAR_BYTEORDER_BE;
- } else if ( !strcasecmp(byteorder, "pdp")           ||
-             !strcasecmp(byteorder, "pdp endian") ) {
-  return ROAR_BYTEORDER_PDP;
- } else if ( !strcasecmp(byteorder, "network")       ||
-             !strcasecmp(byteorder, "network byteorder") ) {
-  return ROAR_BYTEORDER_NETWORK;
- }
-
- roar_err_set(ROAR_ERROR_NOENT);
- return -1;
-}
-
-const char * roar_byteorder2str (const int    byteorder) {
- switch (byteorder) {
-  case ROAR_BYTEORDER_LE:      return "little endian"; break;
-  case ROAR_BYTEORDER_BE:      return "big endian";    break;
-  case ROAR_BYTEORDER_PDP:     return "pdp endian";    break;
-//  case ROAR_BYTEORDER_NETWORK: return "network";       break;
-  default:
-    return "(unknown)";
- }
-}
-
-// grep '^#define ROAR_OT_' roaraudio/proto.h | cut -d' ' -f2 | sed 's/^\(ROAR_OT_\)\(.*\)$/ {\1\2, "\2"},/'
-static struct {
- const int ot;
- const char * name;
-} _libroar_ot[] = {
- {ROAR_OT_CLIENT,   "client"},
- {ROAR_OT_STREAM,   "stream"},
- {ROAR_OT_SOURCE,   "source"},
- {ROAR_OT_SAMPLE,   "sample"},
- {ROAR_OT_OUTPUT,   "output"},
- {ROAR_OT_MIXER,    "mixer"},
- {ROAR_OT_BRIDGE,   "bridge"},
- {ROAR_OT_LISTEN,   "listen"},
- {ROAR_OT_ACTION,   "action"},
- {ROAR_OT_MSGQUEUE, "msgqueue"},
- {ROAR_OT_MSGBUS,   "msgbus"},
- {-1, NULL}
-};
-
-int    roar_str2ot        (const char * ot) {
- int i;
-
- for (i = 0; _libroar_ot[i].ot != -1; i++)
-  if ( !strcasecmp(ot, _libroar_ot[i].name) )
-   return _libroar_ot[i].ot;
-
- roar_err_set(ROAR_ERROR_NOENT);
- return -1;
-}
-
-const char * roar_ot2str  (const int    ot) {
- int i;
-
- for (i = 0; _libroar_ot[i].ot != -1; i++)
-  if ( _libroar_ot[i].ot == ot )
-   return _libroar_ot[i].name;
-
- roar_err_set(ROAR_ERROR_NOENT);
- return NULL;
-}
-
-int roar_conv_volume (struct roar_mixer_settings * dst, struct roar_mixer_settings * src, int dstchans, int srcchans) {
- struct roar_mixer_settings lsrc;
- int i;
- uint_least32_t s;
-
- if ( dst == NULL || src == NULL ) {
-  roar_err_set(ROAR_ERROR_FAULT);
-  return -1;
- }
-
- if ( dstchans < 0 || srcchans < 0 ) {
-  roar_err_set(ROAR_ERROR_INVAL);
-  return -1;
- }
-
- if ( dstchans == srcchans ) {
-  if ( dst == src )
-   return 0;
-
-  memcpy(dst, src, sizeof(struct roar_mixer_settings));
-  return 0;
- }
-
- if ( dst == src ) {
-  memcpy(&lsrc, src, sizeof(lsrc));
-  src = &lsrc;
- }
-
- // sepcal handling for N->1:
- if ( dstchans == 1 ) {
-  s = 0;
-
-  for (i = 0; i < srcchans; i++)
-   s += src->mixer[i];
-
-  dst->mixer[0] = s / srcchans;
- } else {
-  switch (srcchans) {
-   case  1:
-     for (i = 0; i < dstchans; i++)
-      dst->mixer[i] = src->mixer[0];
-    break;
-   case 2:
-     switch (dstchans) {
-      case 3:
-        dst->mixer[0] = src->mixer[0];
-        dst->mixer[1] = src->mixer[1];
-        dst->mixer[2] = (src->mixer[0] + src->mixer[1]) / 2;
-       break;
-      case 4:
-        dst->mixer[0] = src->mixer[0];
-        dst->mixer[1] = src->mixer[1];
-        dst->mixer[2] = src->mixer[0];
-        dst->mixer[3] = src->mixer[1];
-       break;
-      case 5:
-        dst->mixer[0] = src->mixer[0];
-        dst->mixer[1] = src->mixer[1];
-        dst->mixer[2] = (src->mixer[0] + src->mixer[1]) / 2;
-        dst->mixer[3] = src->mixer[0];
-        dst->mixer[4] = src->mixer[1];
-       break;
-      case 6:
-        dst->mixer[0] = src->mixer[0];
-        dst->mixer[1] = src->mixer[1];
-        dst->mixer[2] = (src->mixer[0] + src->mixer[1]) / 2;
-        dst->mixer[3] = dst->mixer[2];
-        dst->mixer[4] = src->mixer[0];
-        dst->mixer[5] = src->mixer[1];
-       break;
-      default:
-        roar_err_set(ROAR_ERROR_NOTSUP);
-        return -1;
-       break;
-     }
-    break;
-   case 3:
-     switch (dstchans) {
-      case 2:
-        dst->mixer[0] = src->mixer[0];
-        dst->mixer[1] = src->mixer[1];
-       break;
-      case 4:
-        dst->mixer[0] = src->mixer[0];
-        dst->mixer[1] = src->mixer[1];
-        dst->mixer[2] = src->mixer[0];
-        dst->mixer[3] = src->mixer[1];
-       break;
-      case 5:
-        dst->mixer[0] = src->mixer[0];
-        dst->mixer[1] = src->mixer[1];
-        dst->mixer[2] = src->mixer[2];
-        dst->mixer[3] = src->mixer[0];
-        dst->mixer[4] = src->mixer[1];
-       break;
-      case 6:
-        dst->mixer[0] = src->mixer[0];
-        dst->mixer[1] = src->mixer[1];
-        dst->mixer[2] = src->mixer[2];
-        dst->mixer[3] = src->mixer[2];
-        dst->mixer[4] = src->mixer[0];
-        dst->mixer[5] = src->mixer[1];
-       break;
-      default:
-        roar_err_set(ROAR_ERROR_NOTSUP);
-        return -1;
-       break;
-     }
-    break;
-   case 4:
-     switch (dstchans) {
-      case 2:
-        dst->mixer[0] = (src->mixer[0] + src->mixer[2]) / 2;
-        dst->mixer[1] = (src->mixer[1] + src->mixer[3]) / 2;
-       break;
-      case 3:
-        dst->mixer[0] = (src->mixer[0] + src->mixer[2]) / 2;
-        dst->mixer[1] = (src->mixer[1] + src->mixer[3]) / 2;
-        dst->mixer[2] = (dst->mixer[0] + dst->mixer[1]) / 2;
-       break;
-      case 5:
-        dst->mixer[0] = src->mixer[0];
-        dst->mixer[1] = src->mixer[1];
-        dst->mixer[2] = (src->mixer[0] + src->mixer[2] + src->mixer[1] + src->mixer[3]) / 4;
-        dst->mixer[3] = src->mixer[2];
-        dst->mixer[4] = src->mixer[3];
-       break;
-      case 6:
-        dst->mixer[0] = src->mixer[0];
-        dst->mixer[1] = src->mixer[1];
-        dst->mixer[2] = (src->mixer[0] + src->mixer[2] + src->mixer[1] + src->mixer[3]) / 4;
-        dst->mixer[3] = dst->mixer[2];
-        dst->mixer[4] = src->mixer[2];
-        dst->mixer[5] = src->mixer[3];
-       break;
-      default:
-        roar_err_set(ROAR_ERROR_NOTSUP);
-        return -1;
-       break;
-     }
-    break;
-   case 5:
-     switch (dstchans) {
-      case 2:
-        dst->mixer[0] = (src->mixer[0] + src->mixer[3]) / 2;
-        dst->mixer[1] = (src->mixer[1] + src->mixer[4]) / 2;
-       break;
-      case 3:
-        dst->mixer[0] = (src->mixer[0] + src->mixer[3]) / 2;
-        dst->mixer[1] = (src->mixer[1] + src->mixer[4]) / 2;
-        dst->mixer[2] = src->mixer[2];
-       break;
-      case 4:
-        dst->mixer[0] = src->mixer[0];
-        dst->mixer[1] = src->mixer[1];
-        dst->mixer[2] = src->mixer[3];
-        dst->mixer[3] = src->mixer[4];
-       break;
-      case 6:
-        dst->mixer[0] = src->mixer[0];
-        dst->mixer[1] = src->mixer[1];
-        dst->mixer[2] = src->mixer[2];
-        dst->mixer[3] = src->mixer[2];
-        dst->mixer[4] = src->mixer[3];
-        dst->mixer[5] = src->mixer[4];
-       break;
-      default:
-        roar_err_set(ROAR_ERROR_NOTSUP);
-        return -1;
-       break;
-     }
-    break;
-   case 6:
-     switch (dstchans) {
-      case 2:
-        dst->mixer[0] = (src->mixer[0] + src->mixer[4]) / 2;
-        dst->mixer[1] = (src->mixer[1] + src->mixer[5]) / 2;
-       break;
-      case 3:
-        dst->mixer[0] = (src->mixer[0] + src->mixer[4]) / 2;
-        dst->mixer[1] = (src->mixer[1] + src->mixer[5]) / 2;
-        dst->mixer[2] = src->mixer[2];
-       break;
-      case 4:
-        dst->mixer[0] = src->mixer[0];
-        dst->mixer[1] = src->mixer[1];
-        dst->mixer[2] = src->mixer[4];
-        dst->mixer[3] = src->mixer[5];
-       break;
-      case 5:
-        dst->mixer[0] = src->mixer[0];
-        dst->mixer[1] = src->mixer[1];
-        dst->mixer[2] = src->mixer[2];
-        dst->mixer[3] = src->mixer[4];
-        dst->mixer[4] = src->mixer[5];
-       break;
-      default:
-        roar_err_set(ROAR_ERROR_NOTSUP);
-        return -1;
-       break;
-     }
-    break;
-   default:
-     roar_err_set(ROAR_ERROR_NOTSUP);
-     return -1;
-    break;
-  }
- }
-
- dst->scale   = src->scale;
- dst->rpg_mul = src->rpg_mul;
- dst->rpg_div = src->rpg_div;
+ for (i = 0; i < m->data[2]; i++)
+  c->streams[i] = m->data[3+i];
+
+ cur = 3 + m->data[2];
+
+ strncpy(c->name, (m->data)+cur+1, m->data[cur]);
+ c->name[m->data[cur]] = 0;
 
  return 0;
