source: roaraudio/libroar/ctl.c

tip
Last change on this file was 6072:35623ca70423, checked in by phi, 9 years ago

updated lookup table for protocols

File size: 24.0 KB
RevLine 
[0]1//ctl.c:
2
[690]3/*
[6052]4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2015
[690]5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
[3517]21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
[690]23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
[0]36#include "libroar.h"
37
[1162]38int roar_get_clientid  (struct roar_connection * con) {
39 struct roar_message mes;
40
41 memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
42
43 mes.cmd     = ROAR_CMD_WHOAMI;
[5144]44 mes.stream  = -1;
45 mes.datalen =  0;
[1162]46
47 if ( roar_req(con, &mes, NULL) == -1 )
48  return -1;
49
50 if ( mes.cmd != ROAR_CMD_OK )
51  return -1;
52
53 if ( mes.datalen != 1 )
54  return -1;
55
56 return mes.data[0];
57}
58
[5236]59int roar_server_oinfo  (struct roar_connection * con, struct roar_stream * s, int dir) {
[0]60 struct roar_message mes;
61
[133]62 memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
63
[0]64 mes.cmd     = ROAR_CMD_SERVER_OINFO;
[4614]65
66 if ( dir == -1 ) {
67  mes.datalen = 0;
68 } else {
69  mes.datalen = 2;
70  mes.data[0] = 0;
71  mes.data[1] = dir;
72 }
[0]73
74 if ( roar_req(con, &mes, NULL) == -1 )
75  return -1;
76
77 if ( mes.cmd != ROAR_CMD_OK )
78  return -1;
79
[4614]80 if ( roar_stream_m2s(s, &mes) == -1 )
[0]81  return -1;
82
83 return 0;
84}
85
86int roar_get_standby   (struct roar_connection * con) {
87 struct roar_message mes;
[6036]88 uint16_t * d16 = (uint16_t *)mes.data;
[0]89
[133]90 memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
91
[0]92 mes.cmd = ROAR_CMD_GET_STANDBY;
[5144]93 mes.stream  = -1;
94 mes.datalen =  0;
[0]95
96 if ( roar_req(con, &mes, NULL) == -1 )
97  return -1;
98
99 if ( mes.cmd != ROAR_CMD_OK )
100  return -1;
101
[6036]102 return ROAR_NET2HOST16(*d16);
[0]103}
104
105int roar_set_standby   (struct roar_connection * con, int state) {
106 struct roar_message mes;
[6036]107 uint16_t * d16 = (uint16_t *)mes.data;
[0]108
[133]109 memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
110
[0]111 mes.cmd = ROAR_CMD_SET_STANDBY;
[5144]112 mes.stream  = -1;
113 mes.datalen =  2;
[0]114
[6036]115 *d16 = ROAR_HOST2NET16((unsigned) state);
[0]116
117 if ( roar_req(con, &mes, NULL) == -1 )
118  return -1;
119
120 if ( mes.cmd != ROAR_CMD_OK )
121  return -1;
122
123 return 0;
124}
125
[578]126int roar_terminate (struct roar_connection * con, int terminate) {
[0]127 struct roar_message mes;
128
[133]129 memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
130
[578]131 mes.cmd     = ROAR_CMD_EXIT;
[5144]132 mes.stream  = -1;
133 mes.datalen =  1;
[578]134 mes.data[0] = terminate;
135
[0]136 if ( roar_req(con, &mes, NULL) == -1 )
137  return -1;
138
139 if ( mes.cmd != ROAR_CMD_OK )
140  return -1;
141
142 return 0;
143}
144
[4333]145int roar_list_filtered(struct roar_connection * con, int * items,   int max, int cmd, unsigned char filter, unsigned char cmp, uint32_t id) {
[0]146 struct roar_message m;
147
[133]148 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
149
[4333]150 roar_ctl_f2m(&m, filter, cmp, id);
[0]151 m.cmd = cmd;
152
153 if ( roar_req(con, &m, NULL) == -1 )
154  return -1;
155
156 return roar_ctl_m2ia(&m, items, max);
157}
158
[4333]159int roar_list         (struct roar_connection * con, int * items,   int max, int cmd) {
160 return roar_list_filtered(con, items, max, cmd, ROAR_CTL_FILTER_ANY, ROAR_CTL_CMP_ANY, ROAR_CTL_FILTER_ANY);
161}
162
[0]163int roar_get_client   (struct roar_connection * con, struct roar_client * client, int id) {
164 struct roar_message m;
[5608]165 char * data = NULL;
166 int ret;
[0]167
[133]168 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
169
[0]170 m.cmd     = ROAR_CMD_GET_CLIENT;
[5144]171 m.stream  = -1;
172 m.datalen =  1;
[0]173 m.data[0] = id;
174
175 ROAR_DBG("roar_get_client(*): id = %i", id);
176
[5608]177 if ( roar_req(con, &m, &data) == -1 )
[0]178  return -1;
179
180 if ( m.cmd != ROAR_CMD_OK )
181  return -1;
182
183 ROAR_DBG("roar_get_client(*): got ok");
184
[5608]185 ret = roar_ctl_m2c2(&m, client, data);
186
187 if ( data != NULL )
188  roar_mm_free(data);
189
190 return ret;
[0]191}
192
193int roar_get_stream   (struct roar_connection * con, struct roar_stream * stream, int id) {
194 struct roar_message m;
195
[133]196 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
197
[0]198 m.cmd     = ROAR_CMD_GET_STREAM;
199 m.datalen = 1;
200 m.data[0] = id;
201
[4873]202 roar_err_set(ROAR_ERROR_UNKNOWN);
[798]203
204 if ( roar_req(con, &m, NULL) == -1 ) {
[4873]205  roar_err_set(ROAR_ERROR_PROTO);
[0]206  return -1;
[798]207 }
[0]208
209 if ( m.cmd != ROAR_CMD_OK )
210  return -1;
211
212 return roar_stream_m2s(stream, &m);
213}
214
215int roar_kick         (struct roar_connection * con, int type, int id) {
216 struct roar_message m;
[17]217 uint16_t * info = (uint16_t *) m.data;
[0]218
[133]219 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
220
[0]221 m.cmd     = ROAR_CMD_KICK;
222 m.datalen = 4;
[299]223 info[0] = ROAR_HOST2NET16(type);
224 info[1] = ROAR_HOST2NET16(id);
[0]225
226 if ( roar_req(con, &m, NULL) == -1 )
227  return -1;
228
229 if ( m.cmd != ROAR_CMD_OK )
230  return -1;
231
232 return 0;
233}
234
[5236]235int roar_set_vol     (struct roar_connection * con, int id, struct roar_mixer_settings * mixer, int   channels, int mode) {
[17]236 struct roar_message m;
237 uint16_t * info = (uint16_t *) m.data;
238 int i;
239
[133]240 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
241
[17]242 m.cmd     = ROAR_CMD_SET_VOL;
243 m.datalen = (3 + channels) * 2;
[3530]244 m.stream  = id;
245 info[0] = ROAR_HOST2NET16(1);
246 info[1] = ROAR_HOST2NET16(mixer->scale);
[4740]247 info[2] = ROAR_HOST2NET16(mode);
[17]248
249 for (i = 0; i < channels; i++)
[300]250  info[i+3] = ROAR_HOST2NET16(mixer->mixer[i]);
[17]251
252 if ( roar_req(con, &m, NULL) == -1 )
253  return -1;
254
255 if ( m.cmd != ROAR_CMD_OK )
256  return -1;
257
258 return 0;
259}
260
[24]261int roar_get_vol      (struct roar_connection * con, int id, struct roar_mixer_settings * mixer, int * channels) {
262 struct roar_message m;
263 uint16_t * info = (uint16_t *) m.data;
264 int i;
265
[133]266 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
267
[24]268 m.cmd     = ROAR_CMD_GET_VOL;
269 m.datalen = 2*2;
[3529]270 m.stream  = id;
271
272 info[0]   = ROAR_HOST2NET16(1);
[24]273
274 if ( roar_req(con, &m, NULL) == -1 )
275  return -1;
276
277 if ( m.cmd != ROAR_CMD_OK )
278  return -1;
279
[3529]280 if ( ROAR_NET2HOST16(info[0]) != 1 )
[24]281  return -1;
282
[300]283 info[1] = ROAR_NET2HOST16(info[1]);
284
[24]285 if ( channels != NULL )
286  *channels = info[1];
287
288 if ( info[1] > ROAR_MAX_CHANNELS )
289  return -1;
290
[3529]291 mixer->scale   = ROAR_NET2HOST16(info[2]);
292 mixer->rpg_mul = ROAR_NET2HOST16(info[3]);
293 mixer->rpg_div = ROAR_NET2HOST16(info[4]);
[2374]294
[24]295 for (i = 0; i < info[1]; i++)
[3529]296  mixer->mixer[i] = ROAR_NET2HOST16(info[i+5]);
[24]297
298 return 0;
299}
[0]300
301// converts: *_m2*, *_*2m
302
303int roar_ctl_f2m      (struct roar_message * m, unsigned char   filter, unsigned char   cmp, uint32_t   id) {
304
305 m->datalen = 7;
306
307 m->data[0] = 0;
308 m->data[1] = filter;
309 m->data[2] = cmp;
[5145]310 m->data[3] = (id & 0xFF000000LU) >> 24;
311 m->data[4] = (id & 0x00FF0000LU) >> 16;
312 m->data[5] = (id & 0x0000FF00LU) >>  8;
313 m->data[6] = (id & 0x000000FFLU) >>  0;
[0]314
315 return 0;
316}
317int roar_ctl_m2f      (struct roar_message * m, unsigned char * filter, unsigned char * cmp, uint32_t * id) {
[5145]318 register uint32_t idreg;
[0]319
320 if ( m->datalen != 7 )
321  return -1;
322
323 if ( m->data[0] != 0 ) {
[5148]324  ROAR_DBG("roar_ctl_m2f(*): version %i not supported!", (int)m->data[0]);
325  roar_err_set(ROAR_ERROR_NSVERSION);
[0]326  return -1;
327 }
328
329 *filter = m->data[1];
330 *cmp    = m->data[2];
331
[5145]332 idreg   = ((uint32_t)(unsigned char)m->data[3]) << 24;
333 idreg  |= ((uint32_t)(unsigned char)m->data[4]) << 16;
334 idreg  |= ((uint32_t)(unsigned char)m->data[5]) <<  8;
335 idreg  |= ((uint32_t)(unsigned char)m->data[6]) <<  0;
336 *id     = idreg;
[0]337
338 return 0;
339}
340
[4332]341int roar_filter_match (const unsigned cmp, const uint32_t a, const uint32_t b) {
[4333]342 switch (cmp) {
[4332]343  case ROAR_CTL_CMP_ANY:
344    return 1;
345   break;
346  case ROAR_CTL_CMP_EQ:
347    return a == b;
348   break;
349  case ROAR_CTL_CMP_NE:
350    return a != b;
351   break;
352  default:
[5145]353    roar_err_set(ROAR_ERROR_NOTSUP);
[4332]354    return -1;
355 }
356}
357
[5357]358int roar_ctl_ia2m     (struct roar_message * m, int * data, size_t len) {
359 size_t i;
[0]360
[5145]361 if ( len > LIBROAR_BUFFER_MSGDATA ) {
362  roar_err_set(ROAR_ERROR_MSGSIZE);
[0]363  return -1;
[5145]364 }
[0]365
366 m->datalen = len;
367
368 for (i = 0; i < len; i++)
369  m->data[i] = data[i];
370
371 return 0;
372}
[5357]373int roar_ctl_m2ia     (struct roar_message * m, int * data, size_t len) {
374 size_t i;
[0]375
[5145]376 if ( m->datalen > len ) {
377  roar_err_set(ROAR_ERROR_MSGSIZE);
[0]378  return -1;
[5145]379 }
[0]380
381 for (i = 0; i < m->datalen; i++)
382  data[i] = m->data[i];
383
384 return m->datalen;
385}
386
[5608]387int roar_ctl_c2m2     (struct roar_message * m, struct roar_client * c, void ** data) {
388 char * d;
389 size_t cur = 0;
[0]390 int h;
391 int i;
392 int max_len;
[434]393 uint32_t pid;
[5145]394 size_t nnode_len;
[5608]395 size_t needed_len = 3 + 5*4 + 18 /* 18 = current max size for blob */;
[0]396
397 if ( c == NULL )
398  return -1;
399
[5608]400 if ( data != NULL )
401  *data = NULL;
402
403 max_len = strlen(c->name);
404 needed_len += max_len;
405
406 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++)
407  if ( c->streams[i] != -1 )
408   needed_len++;
409
410 if ( needed_len > sizeof(m->data) ) {
411  if ( data == NULL ) {
412   needed_len -= max_len;
413   if ( needed_len > sizeof(m->data) ) {
414    roar_panic(ROAR_FATAL_ERROR_CPU_FAILURE, "needed_len > sizeof(m->data) happend.");
415    roar_err_set(ROAR_ERROR_BADCKSUM);
416    return -1;
417   }
418   max_len = sizeof(m->data) - needed_len;
419   needed_len = sizeof(m->data);
420   d = m->data;
421  } else {
422   d = roar_mm_malloc(needed_len);
423   if ( d == NULL )
424    return -1;
425   *data = d;
426  }
427 } else {
428  d = m->data;
429 }
430
431 d[cur++] = 0;                       // 0: Version
432 d[cur++] = c->execed;               // 1: execed
[0]433
434 h = 0;
[5608]435 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++)
[0]436  if ( c->streams[i] != -1 )
[5608]437   d[cur+1+h++] = c->streams[i];
[0]438
[5608]439 d[cur++] = h;                       // 2: num of streams
[0]440 cur += h;
441
442 // TODO: add some code to check if this fits in the pkg
443 // NOTE: add this code after we are sure how long this pkg will be
444 //       and fully decieded about this function.
445
[5608]446 d[cur++] = max_len;
[0]447
[5608]448 strncpy(d+cur, c->name, max_len);
[0]449
450 cur += max_len;
451
[434]452 pid = ROAR_HOST2NET32(c->pid);
[5608]453 memcpy(&(d[cur]), &pid, 4);
[438]454 cur += 4;
[434]455
[438]456 pid = ROAR_HOST2NET32(c->uid);
[5608]457 memcpy(&(d[cur]), &pid, 4);
[438]458 cur += 4;
459
460 pid = ROAR_HOST2NET32(c->gid);
[5608]461 memcpy(&(d[cur]), &pid, 4);
[434]462 cur += 4;
463
[2544]464 pid = ROAR_HOST2NET32(c->proto);
[5608]465 memcpy(&(d[cur]), &pid, 4);
[2544]466 cur += 4;
467
[2616]468 pid = ROAR_HOST2NET32(c->byteorder);
[5608]469 memcpy(&(d[cur]), &pid, 4);
[2616]470 cur += 4;
471
[5608]472 if ( cur > needed_len ) {
[5145]473  roar_panic(ROAR_FATAL_ERROR_MEMORY_CORRUPTION, NULL);
474 }
475
[5608]476 nnode_len = needed_len - cur;
477 if ( roar_nnode_to_blob(&(c->nnode), &(d[cur]), &nnode_len) == 0 ) {
[5145]478  cur += nnode_len;
[2811]479 }
480
[5608]481 if ( cur > needed_len ) {
482  roar_panic(ROAR_FATAL_ERROR_MEMORY_CORRUPTION, NULL);
483 }
484
[0]485 m->datalen = cur;
486
487 return 0;
488}
489
[5608]490int roar_ctl_m2c2      (struct roar_message * m, struct roar_client * c, void * data) {
491 char * d = data;
[434]492 uint32_t pid;
[2811]493 size_t len;
[5357]494 size_t cur;
495 int i;
[0]496
[5145]497 if ( m == NULL || c == NULL ) {
498  roar_err_set(ROAR_ERROR_FAULT);
[0]499  return -1;
[5145]500 }
[0]501
[5145]502 if ( m->datalen == 0 ) {
503  roar_err_set(ROAR_ERROR_MSGSIZE);
[0]504  return -1;
[5145]505 }
[0]506
[5608]507 if ( d == NULL ) {
508  if ( m->datalen > sizeof(m->data) ) {
509   roar_err_set(ROAR_ERROR_FAULT);
510   return -1;
511  }
512  d = m->data;
513 }
514
[0]515 ROAR_DBG("roar_ctl_m2c(*): got data!, len = %i", m->datalen);
516
[5608]517 if ( d[0] != 0 ) {
[0]518  ROAR_DBG("roar_ctl_m2c(*): wrong version!");
[5145]519  roar_err_set(ROAR_ERROR_NSVERSION);
[0]520  return -1;
521 }
522
[5145]523 if ( m->datalen < 3 ) {
524  roar_err_set(ROAR_ERROR_MSGSIZE);
[0]525  return -1;
[5145]526 }
[0]527
528 ROAR_DBG("roar_ctl_m2c(*): have usable data!");
529
[5608]530 c->execed = d[1];
[0]531
532 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++)
533  c->streams[i] = -1;
534
[5608]535 if ( d[2] < 0 || d[2] > ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT ) {
[5145]536  roar_err_set(ROAR_ERROR_TOOMANYARGS);
537  return -1;
538 }
539
[5608]540 for (i = 0; i < d[2]; i++)
541  c->streams[i] = d[3+i];
[0]542
[5608]543 cur = 3 + d[2];
[0]544
[5608]545 // check length here!
546 strncpy(c->name, d+cur+1, d[cur] > (sizeof(c->name)-1) ? sizeof(c->name)-1 : d[cur]);
547 c->name[(size_t)d[cur] > (sizeof(c->name)-1) ? sizeof(c->name)-1 : (size_t)d[cur]] = 0;
[0]548
[5608]549 cur += d[cur] + 1;
[434]550
[5608]551 memcpy(&pid, &(d[cur]), 4);
[434]552 c->pid = ROAR_NET2HOST32(pid);
553 cur += 4;
554
[5608]555 memcpy(&pid, &(d[cur]), 4);
[438]556 c->uid = ROAR_NET2HOST32(pid);
557 cur += 4;
558
[5608]559 memcpy(&pid, &(d[cur]), 4);
[438]560 c->gid = ROAR_NET2HOST32(pid);
561 cur += 4;
562
[2544]563 if ( m->datalen >= cur+4 ) {
[5608]564  memcpy(&pid, &(d[cur]), 4);
[2544]565  c->proto = ROAR_NET2HOST32(pid);
566  cur += 4;
567 } else {
568  c->proto = ROAR_PROTO_NONE;
569 }
570
[2616]571 if ( m->datalen >= cur+4 ) {
[5608]572  memcpy(&pid, &(d[cur]), 4);
[2616]573  c->byteorder = ROAR_NET2HOST32(pid);
574  cur += 4;
575 } else {
576  c->byteorder = ROAR_BYTEORDER_UNKNOWN;
577 }
578
[2811]579 if ( m->datalen > cur ) {
580  len = m->datalen - cur;
[5608]581  if ( roar_nnode_from_blob(&(c->nnode), &(d[cur]), &len) == 0 ) {
[2811]582   cur += len;
583  } else {
584   if ( roar_nnode_new(&(c->nnode), ROAR_SOCKET_TYPE_UNKNOWN) == -1 )
585    return -1;
586  }
587 } else {
588  if ( roar_nnode_new(&(c->nnode), ROAR_SOCKET_TYPE_UNKNOWN) == -1 )
589   return -1;
590 }
591
[0]592 return 0;
593}
594
[5608]595int roar_ctl_c2m      (struct roar_message * m, struct roar_client * c) {
596 return roar_ctl_c2m2(m, c, NULL);
597}
598int roar_ctl_m2c      (struct roar_message * m, struct roar_client * c) {
599 return roar_ctl_m2c2(m, c, NULL);
600}
601
[5189]602static struct {
603 int id;
604 const char * name;
605} _proto[] = {
606 {ROAR_PROTO_NONE,        "none"},
607 {ROAR_PROTO_ROARAUDIO,   "RoarAudio"},
608 {ROAR_PROTO_ESOUND,      "EsounD"},
609 {ROAR_PROTO_ESOUND,      "ESD"}, // alias
610 {ROAR_PROTO_AUTO,        "(auto)"},
611 {ROAR_PROTO_HTTP,        "http"},
612 {ROAR_PROTO_GOPHER,      "gopher"},
613 {ROAR_PROTO_ICY,         "ICY"},
614 {ROAR_PROTO_SIMPLE,      "Simple"},
615 {ROAR_PROTO_RSOUND,      "RSound"},
616 {ROAR_PROTO_RPLAY,       "RPlay"},
617 {ROAR_PROTO_IRC,         "IRC"},
618 {ROAR_PROTO_DCC,         "DCC"},
619 {ROAR_PROTO_ECHO,        "Echo"},
620 {ROAR_PROTO_DISCARD,     "Discard"},
621 {ROAR_PROTO_WHOIS,       "Whois"},
622 {ROAR_PROTO_FINGER,      "Finger"},
623 {ROAR_PROTO_QUOTE,       "quote"},
624 {ROAR_PROTO_DAYTIME,     "daytime"},
[5449]625 {ROAR_PROTO_GAME,        "game"},
[5462]626 {ROAR_PROTO_TELNET,      "telnet"},
627 {ROAR_PROTO_DHCP,        "dhcp"},
628 {ROAR_PROTO_SSH,         "ssh"},
629 {ROAR_PROTO_TIME,        "time"},
630 {ROAR_PROTO_RLOGIN,      "rlogin"},
[5621]631 {ROAR_PROTO_RPLD,        "rpld"},
632 {ROAR_PROTO_MPD,         "mpd"},
[6072]633 {ROAR_PROTO_RTP,         "rtp"},
634 {ROAR_PROTO_RTCP,        "rtcp"},
635 {ROAR_PROTO_RTSP,        "rtsp"},
636 {ROAR_PROTO_SIP,         "sip"},
637 {ROAR_PROTO_DYNAMIC0,    "dynamic0"},
638 {ROAR_PROTO_DYNAMIC1,    "dynamic1"},
639 {ROAR_PROTO_DYNAMIC2,    "dynamic2"},
640 {ROAR_PROTO_DYNAMIC3,    "dynamic3"},
641 {ROAR_PROTO_DYNAMIC4,    "dynamic4"},
642 {ROAR_PROTO_DYNAMIC5,    "dynamic5"},
643 {ROAR_PROTO_DYNAMIC6,    "dynamic6"},
644 {ROAR_PROTO_DYNAMIC7,    "dynamic7"},
645 {ROAR_PROTO_DYNAMIC8,    "dynamic8"},
646 {ROAR_PROTO_DYNAMIC9,    "dynamic9"},
647 {ROAR_PROTO_DYNAMIC10,   "dynamic10"},
648 {ROAR_PROTO_DYNAMIC11,   "dynamic11"},
649 {ROAR_PROTO_DYNAMIC12,   "dynamic12"},
650 {ROAR_PROTO_DYNAMIC13,   "dynamic13"},
651 {ROAR_PROTO_DYNAMIC14,   "dynamic14"},
652 {ROAR_PROTO_DYNAMIC15,   "dynamic15"},
653 {ROAR_PROTO_USER0,       "user0"},
654 {ROAR_PROTO_USER1,       "user1"},
655 {ROAR_PROTO_USER2,       "user2"},
656 {ROAR_PROTO_USER3,       "user3"},
657 {ROAR_PROTO_USER4,       "user4"},
658 {ROAR_PROTO_USER5,       "user5"},
659 {ROAR_PROTO_USER6,       "user6"},
660 {ROAR_PROTO_USER7,       "user7"},
661 {ROAR_PROTO_USER8,       "user8"},
662 {ROAR_PROTO_USER9,       "user9"},
663 {ROAR_PROTO_USER10,      "user10"},
664 {ROAR_PROTO_USER11,      "user11"},
665 {ROAR_PROTO_USER12,      "user12"},
666 {ROAR_PROTO_USER13,      "user13"},
667 {ROAR_PROTO_USER14,      "user14"},
668 {ROAR_PROTO_USER15,      "user15"},
[5189]669 {-1, NULL}
670};
671
[5112]672int    roar_str2proto (const char * proto) {
[5189]673 size_t i;
674
675 for (i = 0; _proto[i].id != -1; i++)
676  if ( !strcasecmp(proto, _proto[i].name) )
677   return _proto[i].id;
[2548]678
[5145]679 roar_err_set(ROAR_ERROR_NOENT);
[2548]680 return -1;
681}
682
[5360]683const char * roar_proto2str (const int    proto) {
[5189]684 size_t i;
685
686 roar_err_set(ROAR_ERROR_NONE);
687
688 for (i = 0; _proto[i].id != -1; i++)
689  if ( proto == _proto[i].id )
[5360]690   return _proto[i].name;
[5189]691
692 roar_err_set(ROAR_ERROR_NOENT);
693 return "(unknown)";
[2548]694}
695
[5112]696int    roar_str2byteorder (const char * byteorder) {
[2615]697 if (        !strcasecmp(byteorder, "le")            || !strcasecmp(byteorder, "little") ||
698             !strcasecmp(byteorder, "little endian") || !strcasecmp(byteorder, "1234")   ) {
699  return ROAR_BYTEORDER_LE;
700 } else if ( !strcasecmp(byteorder, "be")            || !strcasecmp(byteorder, "big")    ||
701             !strcasecmp(byteorder, "big endian")    || !strcasecmp(byteorder, "4321")   ) {
702  return ROAR_BYTEORDER_BE;
703 } else if ( !strcasecmp(byteorder, "pdp")           ||
704             !strcasecmp(byteorder, "pdp endian") ) {
705  return ROAR_BYTEORDER_PDP;
706 } else if ( !strcasecmp(byteorder, "network")       ||
707             !strcasecmp(byteorder, "network byteorder") ) {
708  return ROAR_BYTEORDER_NETWORK;
709 }
710
[5145]711 roar_err_set(ROAR_ERROR_NOENT);
[2615]712 return -1;
713}
714
[5360]715const char * roar_byteorder2str (const int    byteorder) {
[2615]716 switch (byteorder) {
717  case ROAR_BYTEORDER_LE:      return "little endian"; break;
718  case ROAR_BYTEORDER_BE:      return "big endian";    break;
719  case ROAR_BYTEORDER_PDP:     return "pdp endian";    break;
720//  case ROAR_BYTEORDER_NETWORK: return "network";       break;
721  default:
722    return "(unknown)";
723 }
724}
725
[4327]726// grep '^#define ROAR_OT_' roaraudio/proto.h | cut -d' ' -f2 | sed 's/^\(ROAR_OT_\)\(.*\)$/ {\1\2, "\2"},/'
727static struct {
728 const int ot;
729 const char * name;
730} _libroar_ot[] = {
731 {ROAR_OT_CLIENT,   "client"},
732 {ROAR_OT_STREAM,   "stream"},
733 {ROAR_OT_SOURCE,   "source"},
734 {ROAR_OT_SAMPLE,   "sample"},
735 {ROAR_OT_OUTPUT,   "output"},
736 {ROAR_OT_MIXER,    "mixer"},
737 {ROAR_OT_BRIDGE,   "bridge"},
738 {ROAR_OT_LISTEN,   "listen"},
739 {ROAR_OT_ACTION,   "action"},
740 {ROAR_OT_MSGQUEUE, "msgqueue"},
741 {ROAR_OT_MSGBUS,   "msgbus"},
742 {-1, NULL}
743};
744
745int    roar_str2ot        (const char * ot) {
746 int i;
747
748 for (i = 0; _libroar_ot[i].ot != -1; i++)
749  if ( !strcasecmp(ot, _libroar_ot[i].name) )
750   return _libroar_ot[i].ot;
751
[5145]752 roar_err_set(ROAR_ERROR_NOENT);
[4327]753 return -1;
754}
755
756const char * roar_ot2str  (const int    ot) {
757 int i;
758
759 for (i = 0; _libroar_ot[i].ot != -1; i++)
760  if ( _libroar_ot[i].ot == ot )
761   return _libroar_ot[i].name;
762
[5145]763 roar_err_set(ROAR_ERROR_NOENT);
[4327]764 return NULL;
765}
766
[4384]767int roar_conv_volume (struct roar_mixer_settings * dst, struct roar_mixer_settings * src, int dstchans, int srcchans) {
[4385]768 struct roar_mixer_settings lsrc;
[4384]769 int i;
770 uint_least32_t s;
771
[5145]772 if ( dst == NULL || src == NULL ) {
773  roar_err_set(ROAR_ERROR_FAULT);
[4384]774  return -1;
[5145]775 }
776
777 if ( dstchans < 0 || srcchans < 0 ) {
778  roar_err_set(ROAR_ERROR_INVAL);
779  return -1;
780 }
[4384]781
782 if ( dstchans == srcchans ) {
[4385]783  if ( dst == src )
784   return 0;
785
[4384]786  memcpy(dst, src, sizeof(struct roar_mixer_settings));
787  return 0;
788 }
789
[4385]790 if ( dst == src ) {
791  memcpy(&lsrc, src, sizeof(lsrc));
792  src = &lsrc;
793 }
794
[4384]795 // sepcal handling for N->1:
796 if ( dstchans == 1 ) {
797  s = 0;
798
799  for (i = 0; i < srcchans; i++)
800   s += src->mixer[i];
801
802  dst->mixer[0] = s / srcchans;
803 } else {
804  switch (srcchans) {
805   case  1:
806     for (i = 0; i < dstchans; i++)
807      dst->mixer[i] = src->mixer[0];
808    break;
809   case 2:
810     switch (dstchans) {
811      case 3:
812        dst->mixer[0] = src->mixer[0];
813        dst->mixer[1] = src->mixer[1];
814        dst->mixer[2] = (src->mixer[0] + src->mixer[1]) / 2;
815       break;
816      case 4:
817        dst->mixer[0] = src->mixer[0];
818        dst->mixer[1] = src->mixer[1];
819        dst->mixer[2] = src->mixer[0];
820        dst->mixer[3] = src->mixer[1];
821       break;
822      case 5:
823        dst->mixer[0] = src->mixer[0];
824        dst->mixer[1] = src->mixer[1];
825        dst->mixer[2] = (src->mixer[0] + src->mixer[1]) / 2;
826        dst->mixer[3] = src->mixer[0];
827        dst->mixer[4] = src->mixer[1];
828       break;
829      case 6:
830        dst->mixer[0] = src->mixer[0];
831        dst->mixer[1] = src->mixer[1];
832        dst->mixer[2] = (src->mixer[0] + src->mixer[1]) / 2;
833        dst->mixer[3] = dst->mixer[2];
834        dst->mixer[4] = src->mixer[0];
835        dst->mixer[5] = src->mixer[1];
836       break;
837      default:
[5145]838        roar_err_set(ROAR_ERROR_NOTSUP);
[4384]839        return -1;
840       break;
841     }
842    break;
843   case 3:
844     switch (dstchans) {
845      case 2:
846        dst->mixer[0] = src->mixer[0];
847        dst->mixer[1] = src->mixer[1];
848       break;
849      case 4:
850        dst->mixer[0] = src->mixer[0];
851        dst->mixer[1] = src->mixer[1];
852        dst->mixer[2] = src->mixer[0];
853        dst->mixer[3] = src->mixer[1];
854       break;
855      case 5:
856        dst->mixer[0] = src->mixer[0];
857        dst->mixer[1] = src->mixer[1];
858        dst->mixer[2] = src->mixer[2];
859        dst->mixer[3] = src->mixer[0];
860        dst->mixer[4] = src->mixer[1];
861       break;
862      case 6:
863        dst->mixer[0] = src->mixer[0];
864        dst->mixer[1] = src->mixer[1];
865        dst->mixer[2] = src->mixer[2];
866        dst->mixer[3] = src->mixer[2];
867        dst->mixer[4] = src->mixer[0];
868        dst->mixer[5] = src->mixer[1];
869       break;
870      default:
[5145]871        roar_err_set(ROAR_ERROR_NOTSUP);
[4384]872        return -1;
873       break;
874     }
875    break;
876   case 4:
877     switch (dstchans) {
878      case 2:
879        dst->mixer[0] = (src->mixer[0] + src->mixer[2]) / 2;
880        dst->mixer[1] = (src->mixer[1] + src->mixer[3]) / 2;
881       break;
882      case 3:
883        dst->mixer[0] = (src->mixer[0] + src->mixer[2]) / 2;
884        dst->mixer[1] = (src->mixer[1] + src->mixer[3]) / 2;
885        dst->mixer[2] = (dst->mixer[0] + dst->mixer[1]) / 2;
886       break;
887      case 5:
888        dst->mixer[0] = src->mixer[0];
889        dst->mixer[1] = src->mixer[1];
890        dst->mixer[2] = (src->mixer[0] + src->mixer[2] + src->mixer[1] + src->mixer[3]) / 4;
891        dst->mixer[3] = src->mixer[2];
892        dst->mixer[4] = src->mixer[3];
893       break;
894      case 6:
895        dst->mixer[0] = src->mixer[0];
896        dst->mixer[1] = src->mixer[1];
897        dst->mixer[2] = (src->mixer[0] + src->mixer[2] + src->mixer[1] + src->mixer[3]) / 4;
898        dst->mixer[3] = dst->mixer[2];
899        dst->mixer[4] = src->mixer[2];
900        dst->mixer[5] = src->mixer[3];
901       break;
902      default:
[5145]903        roar_err_set(ROAR_ERROR_NOTSUP);
[4384]904        return -1;
905       break;
906     }
907    break;
908   case 5:
909     switch (dstchans) {
910      case 2:
911        dst->mixer[0] = (src->mixer[0] + src->mixer[3]) / 2;
912        dst->mixer[1] = (src->mixer[1] + src->mixer[4]) / 2;
913       break;
914      case 3:
915        dst->mixer[0] = (src->mixer[0] + src->mixer[3]) / 2;
916        dst->mixer[1] = (src->mixer[1] + src->mixer[4]) / 2;
917        dst->mixer[2] = src->mixer[2];
918       break;
919      case 4:
920        dst->mixer[0] = src->mixer[0];
921        dst->mixer[1] = src->mixer[1];
922        dst->mixer[2] = src->mixer[3];
923        dst->mixer[3] = src->mixer[4];
924       break;
925      case 6:
926        dst->mixer[0] = src->mixer[0];
927        dst->mixer[1] = src->mixer[1];
928        dst->mixer[2] = src->mixer[2];
929        dst->mixer[3] = src->mixer[2];
930        dst->mixer[4] = src->mixer[3];
931        dst->mixer[5] = src->mixer[4];
932       break;
933      default:
[5145]934        roar_err_set(ROAR_ERROR_NOTSUP);
[4384]935        return -1;
936       break;
937     }
938    break;
939   case 6:
940     switch (dstchans) {
941      case 2:
942        dst->mixer[0] = (src->mixer[0] + src->mixer[4]) / 2;
943        dst->mixer[1] = (src->mixer[1] + src->mixer[5]) / 2;
944       break;
945      case 3:
946        dst->mixer[0] = (src->mixer[0] + src->mixer[4]) / 2;
947        dst->mixer[1] = (src->mixer[1] + src->mixer[5]) / 2;
948        dst->mixer[2] = src->mixer[2];
949       break;
950      case 4:
951        dst->mixer[0] = src->mixer[0];
952        dst->mixer[1] = src->mixer[1];
953        dst->mixer[2] = src->mixer[4];
954        dst->mixer[3] = src->mixer[5];
955       break;
956      case 5:
957        dst->mixer[0] = src->mixer[0];
958        dst->mixer[1] = src->mixer[1];
959        dst->mixer[2] = src->mixer[2];
960        dst->mixer[3] = src->mixer[4];
961        dst->mixer[4] = src->mixer[5];
962       break;
963      default:
[5145]964        roar_err_set(ROAR_ERROR_NOTSUP);
[4384]965        return -1;
966       break;
967     }
968    break;
969   default:
[5145]970     roar_err_set(ROAR_ERROR_NOTSUP);
[4384]971     return -1;
972    break;
973  }
974 }
975
976 dst->scale   = src->scale;
977 dst->rpg_mul = src->rpg_mul;
978 dst->rpg_div = src->rpg_div;
979
980 return 0;
981}
982
[0]983//ll
Note: See TracBrowser for help on using the repository browser.