source: roaraudio/libroar/ctl.c @ 5360:3dd9d1fd1b0e

Last change on this file since 5360:3dd9d1fd1b0e was 5360:3dd9d1fd1b0e, checked in by phi, 12 years ago

added const keywords, removed an uneeded cast to non-const

File size: 21.2 KB
RevLine 
[0]1//ctl.c:
2
[690]3/*
[4708]4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2011
[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;
88
[133]89 memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
90
[0]91 mes.cmd = ROAR_CMD_GET_STANDBY;
[5144]92 mes.stream  = -1;
93 mes.datalen =  0;
[0]94
95 if ( roar_req(con, &mes, NULL) == -1 )
96  return -1;
97
98 if ( mes.cmd != ROAR_CMD_OK )
99  return -1;
100
101 return ROAR_NET2HOST16(*((uint16_t*)mes.data));
102}
103
104int roar_set_standby   (struct roar_connection * con, int state) {
105 struct roar_message mes;
106
[133]107 memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
108
[0]109 mes.cmd = ROAR_CMD_SET_STANDBY;
[5144]110 mes.stream  = -1;
111 mes.datalen =  2;
[0]112
113 *((uint16_t*)mes.data) = ROAR_HOST2NET16((unsigned) state);
114
115 if ( roar_req(con, &mes, NULL) == -1 )
116  return -1;
117
118 if ( mes.cmd != ROAR_CMD_OK )
119  return -1;
120
121 return 0;
122}
123
[578]124int roar_terminate (struct roar_connection * con, int terminate) {
[0]125 struct roar_message mes;
126
[133]127 memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
128
[578]129 mes.cmd     = ROAR_CMD_EXIT;
[5144]130 mes.stream  = -1;
131 mes.datalen =  1;
[578]132 mes.data[0] = terminate;
133
[0]134 if ( roar_req(con, &mes, NULL) == -1 )
135  return -1;
136
137 if ( mes.cmd != ROAR_CMD_OK )
138  return -1;
139
140 return 0;
141}
142
[4333]143int roar_list_filtered(struct roar_connection * con, int * items,   int max, int cmd, unsigned char filter, unsigned char cmp, uint32_t id) {
[0]144 struct roar_message m;
145
[133]146 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
147
[4333]148 roar_ctl_f2m(&m, filter, cmp, id);
[0]149 m.cmd = cmd;
150
151 if ( roar_req(con, &m, NULL) == -1 )
152  return -1;
153
154 return roar_ctl_m2ia(&m, items, max);
155}
156
[4333]157int roar_list         (struct roar_connection * con, int * items,   int max, int cmd) {
158 return roar_list_filtered(con, items, max, cmd, ROAR_CTL_FILTER_ANY, ROAR_CTL_CMP_ANY, ROAR_CTL_FILTER_ANY);
159}
160
[0]161int roar_get_client   (struct roar_connection * con, struct roar_client * client, int id) {
162 struct roar_message m;
163
[133]164 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
165
[0]166 m.cmd     = ROAR_CMD_GET_CLIENT;
[5144]167 m.stream  = -1;
168 m.datalen =  1;
[0]169 m.data[0] = id;
170
171 ROAR_DBG("roar_get_client(*): id = %i", id);
172
173 if ( roar_req(con, &m, NULL) == -1 )
174  return -1;
175
176 if ( m.cmd != ROAR_CMD_OK )
177  return -1;
178
179 ROAR_DBG("roar_get_client(*): got ok");
180
181 return roar_ctl_m2c(&m, client);
182}
183
184int roar_get_stream   (struct roar_connection * con, struct roar_stream * stream, int id) {
185 struct roar_message m;
186
[133]187 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
188
[0]189 m.cmd     = ROAR_CMD_GET_STREAM;
190 m.datalen = 1;
191 m.data[0] = id;
192
[4873]193 roar_err_set(ROAR_ERROR_UNKNOWN);
[798]194
195 if ( roar_req(con, &m, NULL) == -1 ) {
[4873]196  roar_err_set(ROAR_ERROR_PROTO);
[0]197  return -1;
[798]198 }
[0]199
200 if ( m.cmd != ROAR_CMD_OK )
201  return -1;
202
203 return roar_stream_m2s(stream, &m);
204}
205
206int roar_kick         (struct roar_connection * con, int type, int id) {
207 struct roar_message m;
[17]208 uint16_t * info = (uint16_t *) m.data;
[0]209
[133]210 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
211
[0]212 m.cmd     = ROAR_CMD_KICK;
213 m.datalen = 4;
[299]214 info[0] = ROAR_HOST2NET16(type);
215 info[1] = ROAR_HOST2NET16(id);
[0]216
217 if ( roar_req(con, &m, NULL) == -1 )
218  return -1;
219
220 if ( m.cmd != ROAR_CMD_OK )
221  return -1;
222
223 return 0;
224}
225
[5236]226int roar_set_vol     (struct roar_connection * con, int id, struct roar_mixer_settings * mixer, int   channels, int mode) {
[17]227 struct roar_message m;
228 uint16_t * info = (uint16_t *) m.data;
229 int i;
230
[133]231 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
232
[17]233 m.cmd     = ROAR_CMD_SET_VOL;
234 m.datalen = (3 + channels) * 2;
[3530]235 m.stream  = id;
236 info[0] = ROAR_HOST2NET16(1);
237 info[1] = ROAR_HOST2NET16(mixer->scale);
[4740]238 info[2] = ROAR_HOST2NET16(mode);
[17]239
240 for (i = 0; i < channels; i++)
[300]241  info[i+3] = ROAR_HOST2NET16(mixer->mixer[i]);
[17]242
243 if ( roar_req(con, &m, NULL) == -1 )
244  return -1;
245
246 if ( m.cmd != ROAR_CMD_OK )
247  return -1;
248
249 return 0;
250}
251
[24]252int roar_get_vol      (struct roar_connection * con, int id, struct roar_mixer_settings * mixer, int * channels) {
253 struct roar_message m;
254 uint16_t * info = (uint16_t *) m.data;
255 int i;
256
[133]257 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
258
[24]259 m.cmd     = ROAR_CMD_GET_VOL;
260 m.datalen = 2*2;
[3529]261 m.stream  = id;
262
263 info[0]   = ROAR_HOST2NET16(1);
[24]264
265 if ( roar_req(con, &m, NULL) == -1 )
266  return -1;
267
268 if ( m.cmd != ROAR_CMD_OK )
269  return -1;
270
[3529]271 if ( ROAR_NET2HOST16(info[0]) != 1 )
[24]272  return -1;
273
[300]274 info[1] = ROAR_NET2HOST16(info[1]);
275
[24]276 if ( channels != NULL )
277  *channels = info[1];
278
279 if ( info[1] > ROAR_MAX_CHANNELS )
280  return -1;
281
[3529]282 mixer->scale   = ROAR_NET2HOST16(info[2]);
283 mixer->rpg_mul = ROAR_NET2HOST16(info[3]);
284 mixer->rpg_div = ROAR_NET2HOST16(info[4]);
[2374]285
[24]286 for (i = 0; i < info[1]; i++)
[3529]287  mixer->mixer[i] = ROAR_NET2HOST16(info[i+5]);
[24]288
289 return 0;
290}
[0]291
292// converts: *_m2*, *_*2m
293
294int roar_ctl_f2m      (struct roar_message * m, unsigned char   filter, unsigned char   cmp, uint32_t   id) {
295
296 m->datalen = 7;
297
298 m->data[0] = 0;
299 m->data[1] = filter;
300 m->data[2] = cmp;
[5145]301 m->data[3] = (id & 0xFF000000LU) >> 24;
302 m->data[4] = (id & 0x00FF0000LU) >> 16;
303 m->data[5] = (id & 0x0000FF00LU) >>  8;
304 m->data[6] = (id & 0x000000FFLU) >>  0;
[0]305
306 return 0;
307}
308int roar_ctl_m2f      (struct roar_message * m, unsigned char * filter, unsigned char * cmp, uint32_t * id) {
[5145]309 register uint32_t idreg;
[0]310
311 if ( m->datalen != 7 )
312  return -1;
313
314 if ( m->data[0] != 0 ) {
[5148]315  ROAR_DBG("roar_ctl_m2f(*): version %i not supported!", (int)m->data[0]);
316  roar_err_set(ROAR_ERROR_NSVERSION);
[0]317  return -1;
318 }
319
320 *filter = m->data[1];
321 *cmp    = m->data[2];
322
[5145]323 idreg   = ((uint32_t)(unsigned char)m->data[3]) << 24;
324 idreg  |= ((uint32_t)(unsigned char)m->data[4]) << 16;
325 idreg  |= ((uint32_t)(unsigned char)m->data[5]) <<  8;
326 idreg  |= ((uint32_t)(unsigned char)m->data[6]) <<  0;
327 *id     = idreg;
[0]328
329 return 0;
330}
331
[4332]332int roar_filter_match (const unsigned cmp, const uint32_t a, const uint32_t b) {
[4333]333 switch (cmp) {
[4332]334  case ROAR_CTL_CMP_ANY:
335    return 1;
336   break;
337  case ROAR_CTL_CMP_EQ:
338    return a == b;
339   break;
340  case ROAR_CTL_CMP_NE:
341    return a != b;
342   break;
343  default:
[5145]344    roar_err_set(ROAR_ERROR_NOTSUP);
[4332]345    return -1;
346 }
347}
348
[5357]349int roar_ctl_ia2m     (struct roar_message * m, int * data, size_t len) {
350 size_t i;
[0]351
[5145]352 if ( len > LIBROAR_BUFFER_MSGDATA ) {
353  roar_err_set(ROAR_ERROR_MSGSIZE);
[0]354  return -1;
[5145]355 }
[0]356
357 m->datalen = len;
358
359 for (i = 0; i < len; i++)
360  m->data[i] = data[i];
361
362 return 0;
363}
[5357]364int roar_ctl_m2ia     (struct roar_message * m, int * data, size_t len) {
365 size_t i;
[0]366
[5145]367 if ( m->datalen > len ) {
368  roar_err_set(ROAR_ERROR_MSGSIZE);
[0]369  return -1;
[5145]370 }
[0]371
372 for (i = 0; i < m->datalen; i++)
373  data[i] = m->data[i];
374
375 return m->datalen;
376}
377
378int roar_ctl_c2m      (struct roar_message * m, struct roar_client * c) {
379 int cur = 0;
380 int h;
381 int i;
382 int max_len;
[434]383 uint32_t pid;
[5145]384 signed long int len_rest;
385 size_t nnode_len;
[0]386
387 if ( c == NULL )
388  return -1;
389
390 m->data[cur++] = 0;                       // 0: Version
391 m->data[cur++] = c->execed;               // 1: execed
392
393 h = 0;
394 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
395  if ( c->streams[i] != -1 )
396   m->data[cur+1+h++] = c->streams[i];
397 }
398
399 m->data[cur++] = h;                       // 2: num of streams
400 cur += h;
401
402 max_len = strlen(c->name);
403
404 // TODO: add some code to check if this fits in the pkg
405 // NOTE: add this code after we are sure how long this pkg will be
406 //       and fully decieded about this function.
407
408 m->data[cur++] = max_len;
409
410 strncpy((m->data)+cur, c->name, max_len);
411
412 cur += max_len;
413
[434]414 pid = ROAR_HOST2NET32(c->pid);
[438]415 memcpy(&(m->data[cur]), &pid, 4);
416 cur += 4;
[434]417
[438]418 pid = ROAR_HOST2NET32(c->uid);
419 memcpy(&(m->data[cur]), &pid, 4);
420 cur += 4;
421
422 pid = ROAR_HOST2NET32(c->gid);
[434]423 memcpy(&(m->data[cur]), &pid, 4);
424 cur += 4;
425
[2544]426 pid = ROAR_HOST2NET32(c->proto);
427 memcpy(&(m->data[cur]), &pid, 4);
428 cur += 4;
429
[2616]430 pid = ROAR_HOST2NET32(c->byteorder);
431 memcpy(&(m->data[cur]), &pid, 4);
432 cur += 4;
433
[5145]434 len_rest = (long int)sizeof(m->data) - (long int)cur;
435 if ( len_rest < 0 ) {
436  roar_panic(ROAR_FATAL_ERROR_MEMORY_CORRUPTION, NULL);
437 }
438
439 nnode_len = len_rest;
440 if ( roar_nnode_to_blob(&(c->nnode), &(m->data[cur]), &nnode_len) == 0 ) {
441  cur += nnode_len;
[2811]442 }
443
[0]444 m->datalen = cur;
445
446 return 0;
447}
448
449int roar_ctl_m2c      (struct roar_message * m, struct roar_client * c) {
[434]450 uint32_t pid;
[2811]451 size_t len;
[5357]452 size_t cur;
453 int i;
[0]454
[5145]455 if ( m == NULL || c == NULL ) {
456  roar_err_set(ROAR_ERROR_FAULT);
[0]457  return -1;
[5145]458 }
[0]459
[5145]460 if ( m->datalen == 0 ) {
461  roar_err_set(ROAR_ERROR_MSGSIZE);
[0]462  return -1;
[5145]463 }
[0]464
465 ROAR_DBG("roar_ctl_m2c(*): got data!, len = %i", m->datalen);
466
467 if ( m->data[0] != 0 ) {
468  ROAR_DBG("roar_ctl_m2c(*): wrong version!");
[5145]469  roar_err_set(ROAR_ERROR_NSVERSION);
[0]470  return -1;
471 }
472
[5145]473 if ( m->datalen < 3 ) {
474  roar_err_set(ROAR_ERROR_MSGSIZE);
[0]475  return -1;
[5145]476 }
[0]477
478 ROAR_DBG("roar_ctl_m2c(*): have usable data!");
479
480 c->execed = m->data[1];
481
482 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++)
483  c->streams[i] = -1;
484
[5145]485 if ( m->data[2] < 0 || m->data[2] > ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT ) {
486  roar_err_set(ROAR_ERROR_TOOMANYARGS);
487  return -1;
488 }
489
[0]490 for (i = 0; i < m->data[2]; i++)
491  c->streams[i] = m->data[3+i];
492
493 cur = 3 + m->data[2];
494
495 strncpy(c->name, (m->data)+cur+1, m->data[cur]);
[17]496 c->name[(int)m->data[cur]] = 0;
[0]497
[434]498 cur += m->data[cur] + 1;
499
500 memcpy(&pid, &(m->data[cur]), 4);
501 c->pid = ROAR_NET2HOST32(pid);
502 cur += 4;
503
[438]504 memcpy(&pid, &(m->data[cur]), 4);
505 c->uid = ROAR_NET2HOST32(pid);
506 cur += 4;
507
508 memcpy(&pid, &(m->data[cur]), 4);
509 c->gid = ROAR_NET2HOST32(pid);
510 cur += 4;
511
[2544]512 if ( m->datalen >= cur+4 ) {
513  memcpy(&pid, &(m->data[cur]), 4);
514  c->proto = ROAR_NET2HOST32(pid);
515  cur += 4;
516 } else {
517  c->proto = ROAR_PROTO_NONE;
518 }
519
[2616]520 if ( m->datalen >= cur+4 ) {
521  memcpy(&pid, &(m->data[cur]), 4);
522  c->byteorder = ROAR_NET2HOST32(pid);
523  cur += 4;
524 } else {
525  c->byteorder = ROAR_BYTEORDER_UNKNOWN;
526 }
527
[2811]528 if ( m->datalen > cur ) {
529  len = m->datalen - cur;
530  if ( roar_nnode_from_blob(&(c->nnode), &(m->data[cur]), &len) == 0 ) {
531   cur += len;
532  } else {
533   if ( roar_nnode_new(&(c->nnode), ROAR_SOCKET_TYPE_UNKNOWN) == -1 )
534    return -1;
535  }
536 } else {
537  if ( roar_nnode_new(&(c->nnode), ROAR_SOCKET_TYPE_UNKNOWN) == -1 )
538   return -1;
539 }
540
[0]541 return 0;
542}
543
[5189]544static struct {
545 int id;
546 const char * name;
547} _proto[] = {
548 {ROAR_PROTO_NONE,        "none"},
549 {ROAR_PROTO_ROARAUDIO,   "RoarAudio"},
550 {ROAR_PROTO_ESOUND,      "EsounD"},
551 {ROAR_PROTO_ESOUND,      "ESD"}, // alias
552 {ROAR_PROTO_AUTO,        "(auto)"},
553 {ROAR_PROTO_HTTP,        "http"},
554 {ROAR_PROTO_GOPHER,      "gopher"},
555 {ROAR_PROTO_ICY,         "ICY"},
556 {ROAR_PROTO_SIMPLE,      "Simple"},
557 {ROAR_PROTO_RSOUND,      "RSound"},
558 {ROAR_PROTO_RPLAY,       "RPlay"},
559 {ROAR_PROTO_IRC,         "IRC"},
560 {ROAR_PROTO_DCC,         "DCC"},
561 {ROAR_PROTO_ECHO,        "Echo"},
562 {ROAR_PROTO_DISCARD,     "Discard"},
563 {ROAR_PROTO_WHOIS,       "Whois"},
564 {ROAR_PROTO_FINGER,      "Finger"},
565 {ROAR_PROTO_QUOTE,       "quote"},
566 {ROAR_PROTO_DAYTIME,     "daytime"},
567 {-1, NULL}
568};
569
[5112]570int    roar_str2proto (const char * proto) {
[5189]571 size_t i;
572
573 for (i = 0; _proto[i].id != -1; i++)
574  if ( !strcasecmp(proto, _proto[i].name) )
575   return _proto[i].id;
[2548]576
[5145]577 roar_err_set(ROAR_ERROR_NOENT);
[2548]578 return -1;
579}
580
[5360]581const char * roar_proto2str (const int    proto) {
[5189]582 size_t i;
583
584 roar_err_set(ROAR_ERROR_NONE);
585
586 for (i = 0; _proto[i].id != -1; i++)
587  if ( proto == _proto[i].id )
[5360]588   return _proto[i].name;
[5189]589
590 roar_err_set(ROAR_ERROR_NOENT);
591 return "(unknown)";
[2548]592}
593
[5112]594int    roar_str2byteorder (const char * byteorder) {
[2615]595 if (        !strcasecmp(byteorder, "le")            || !strcasecmp(byteorder, "little") ||
596             !strcasecmp(byteorder, "little endian") || !strcasecmp(byteorder, "1234")   ) {
597  return ROAR_BYTEORDER_LE;
598 } else if ( !strcasecmp(byteorder, "be")            || !strcasecmp(byteorder, "big")    ||
599             !strcasecmp(byteorder, "big endian")    || !strcasecmp(byteorder, "4321")   ) {
600  return ROAR_BYTEORDER_BE;
601 } else if ( !strcasecmp(byteorder, "pdp")           ||
602             !strcasecmp(byteorder, "pdp endian") ) {
603  return ROAR_BYTEORDER_PDP;
604 } else if ( !strcasecmp(byteorder, "network")       ||
605             !strcasecmp(byteorder, "network byteorder") ) {
606  return ROAR_BYTEORDER_NETWORK;
607 }
608
[5145]609 roar_err_set(ROAR_ERROR_NOENT);
[2615]610 return -1;
611}
612
[5360]613const char * roar_byteorder2str (const int    byteorder) {
[2615]614 switch (byteorder) {
615  case ROAR_BYTEORDER_LE:      return "little endian"; break;
616  case ROAR_BYTEORDER_BE:      return "big endian";    break;
617  case ROAR_BYTEORDER_PDP:     return "pdp endian";    break;
618//  case ROAR_BYTEORDER_NETWORK: return "network";       break;
619  default:
620    return "(unknown)";
621 }
622}
623
[4327]624// grep '^#define ROAR_OT_' roaraudio/proto.h | cut -d' ' -f2 | sed 's/^\(ROAR_OT_\)\(.*\)$/ {\1\2, "\2"},/'
625static struct {
626 const int ot;
627 const char * name;
628} _libroar_ot[] = {
629 {ROAR_OT_CLIENT,   "client"},
630 {ROAR_OT_STREAM,   "stream"},
631 {ROAR_OT_SOURCE,   "source"},
632 {ROAR_OT_SAMPLE,   "sample"},
633 {ROAR_OT_OUTPUT,   "output"},
634 {ROAR_OT_MIXER,    "mixer"},
635 {ROAR_OT_BRIDGE,   "bridge"},
636 {ROAR_OT_LISTEN,   "listen"},
637 {ROAR_OT_ACTION,   "action"},
638 {ROAR_OT_MSGQUEUE, "msgqueue"},
639 {ROAR_OT_MSGBUS,   "msgbus"},
640 {-1, NULL}
641};
642
643int    roar_str2ot        (const char * ot) {
644 int i;
645
646 for (i = 0; _libroar_ot[i].ot != -1; i++)
647  if ( !strcasecmp(ot, _libroar_ot[i].name) )
648   return _libroar_ot[i].ot;
649
[5145]650 roar_err_set(ROAR_ERROR_NOENT);
[4327]651 return -1;
652}
653
654const char * roar_ot2str  (const int    ot) {
655 int i;
656
657 for (i = 0; _libroar_ot[i].ot != -1; i++)
658  if ( _libroar_ot[i].ot == ot )
659   return _libroar_ot[i].name;
660
[5145]661 roar_err_set(ROAR_ERROR_NOENT);
[4327]662 return NULL;
663}
664
[4384]665int roar_conv_volume (struct roar_mixer_settings * dst, struct roar_mixer_settings * src, int dstchans, int srcchans) {
[4385]666 struct roar_mixer_settings lsrc;
[4384]667 int i;
668 uint_least32_t s;
669
[5145]670 if ( dst == NULL || src == NULL ) {
671  roar_err_set(ROAR_ERROR_FAULT);
[4384]672  return -1;
[5145]673 }
674
675 if ( dstchans < 0 || srcchans < 0 ) {
676  roar_err_set(ROAR_ERROR_INVAL);
677  return -1;
678 }
[4384]679
680 if ( dstchans == srcchans ) {
[4385]681  if ( dst == src )
682   return 0;
683
[4384]684  memcpy(dst, src, sizeof(struct roar_mixer_settings));
685  return 0;
686 }
687
[4385]688 if ( dst == src ) {
689  memcpy(&lsrc, src, sizeof(lsrc));
690  src = &lsrc;
691 }
692
[4384]693 // sepcal handling for N->1:
694 if ( dstchans == 1 ) {
695  s = 0;
696
697  for (i = 0; i < srcchans; i++)
698   s += src->mixer[i];
699
700  dst->mixer[0] = s / srcchans;
701 } else {
702  switch (srcchans) {
703   case  1:
704     for (i = 0; i < dstchans; i++)
705      dst->mixer[i] = src->mixer[0];
706    break;
707   case 2:
708     switch (dstchans) {
709      case 3:
710        dst->mixer[0] = src->mixer[0];
711        dst->mixer[1] = src->mixer[1];
712        dst->mixer[2] = (src->mixer[0] + src->mixer[1]) / 2;
713       break;
714      case 4:
715        dst->mixer[0] = src->mixer[0];
716        dst->mixer[1] = src->mixer[1];
717        dst->mixer[2] = src->mixer[0];
718        dst->mixer[3] = src->mixer[1];
719       break;
720      case 5:
721        dst->mixer[0] = src->mixer[0];
722        dst->mixer[1] = src->mixer[1];
723        dst->mixer[2] = (src->mixer[0] + src->mixer[1]) / 2;
724        dst->mixer[3] = src->mixer[0];
725        dst->mixer[4] = src->mixer[1];
726       break;
727      case 6:
728        dst->mixer[0] = src->mixer[0];
729        dst->mixer[1] = src->mixer[1];
730        dst->mixer[2] = (src->mixer[0] + src->mixer[1]) / 2;
731        dst->mixer[3] = dst->mixer[2];
732        dst->mixer[4] = src->mixer[0];
733        dst->mixer[5] = src->mixer[1];
734       break;
735      default:
[5145]736        roar_err_set(ROAR_ERROR_NOTSUP);
[4384]737        return -1;
738       break;
739     }
740    break;
741   case 3:
742     switch (dstchans) {
743      case 2:
744        dst->mixer[0] = src->mixer[0];
745        dst->mixer[1] = src->mixer[1];
746       break;
747      case 4:
748        dst->mixer[0] = src->mixer[0];
749        dst->mixer[1] = src->mixer[1];
750        dst->mixer[2] = src->mixer[0];
751        dst->mixer[3] = src->mixer[1];
752       break;
753      case 5:
754        dst->mixer[0] = src->mixer[0];
755        dst->mixer[1] = src->mixer[1];
756        dst->mixer[2] = src->mixer[2];
757        dst->mixer[3] = src->mixer[0];
758        dst->mixer[4] = src->mixer[1];
759       break;
760      case 6:
761        dst->mixer[0] = src->mixer[0];
762        dst->mixer[1] = src->mixer[1];
763        dst->mixer[2] = src->mixer[2];
764        dst->mixer[3] = src->mixer[2];
765        dst->mixer[4] = src->mixer[0];
766        dst->mixer[5] = src->mixer[1];
767       break;
768      default:
[5145]769        roar_err_set(ROAR_ERROR_NOTSUP);
[4384]770        return -1;
771       break;
772     }
773    break;
774   case 4:
775     switch (dstchans) {
776      case 2:
777        dst->mixer[0] = (src->mixer[0] + src->mixer[2]) / 2;
778        dst->mixer[1] = (src->mixer[1] + src->mixer[3]) / 2;
779       break;
780      case 3:
781        dst->mixer[0] = (src->mixer[0] + src->mixer[2]) / 2;
782        dst->mixer[1] = (src->mixer[1] + src->mixer[3]) / 2;
783        dst->mixer[2] = (dst->mixer[0] + dst->mixer[1]) / 2;
784       break;
785      case 5:
786        dst->mixer[0] = src->mixer[0];
787        dst->mixer[1] = src->mixer[1];
788        dst->mixer[2] = (src->mixer[0] + src->mixer[2] + src->mixer[1] + src->mixer[3]) / 4;
789        dst->mixer[3] = src->mixer[2];
790        dst->mixer[4] = src->mixer[3];
791       break;
792      case 6:
793        dst->mixer[0] = src->mixer[0];
794        dst->mixer[1] = src->mixer[1];
795        dst->mixer[2] = (src->mixer[0] + src->mixer[2] + src->mixer[1] + src->mixer[3]) / 4;
796        dst->mixer[3] = dst->mixer[2];
797        dst->mixer[4] = src->mixer[2];
798        dst->mixer[5] = src->mixer[3];
799       break;
800      default:
[5145]801        roar_err_set(ROAR_ERROR_NOTSUP);
[4384]802        return -1;
803       break;
804     }
805    break;
806   case 5:
807     switch (dstchans) {
808      case 2:
809        dst->mixer[0] = (src->mixer[0] + src->mixer[3]) / 2;
810        dst->mixer[1] = (src->mixer[1] + src->mixer[4]) / 2;
811       break;
812      case 3:
813        dst->mixer[0] = (src->mixer[0] + src->mixer[3]) / 2;
814        dst->mixer[1] = (src->mixer[1] + src->mixer[4]) / 2;
815        dst->mixer[2] = src->mixer[2];
816       break;
817      case 4:
818        dst->mixer[0] = src->mixer[0];
819        dst->mixer[1] = src->mixer[1];
820        dst->mixer[2] = src->mixer[3];
821        dst->mixer[3] = src->mixer[4];
822       break;
823      case 6:
824        dst->mixer[0] = src->mixer[0];
825        dst->mixer[1] = src->mixer[1];
826        dst->mixer[2] = src->mixer[2];
827        dst->mixer[3] = src->mixer[2];
828        dst->mixer[4] = src->mixer[3];
829        dst->mixer[5] = src->mixer[4];
830       break;
831      default:
[5145]832        roar_err_set(ROAR_ERROR_NOTSUP);
[4384]833        return -1;
834       break;
835     }
836    break;
837   case 6:
838     switch (dstchans) {
839      case 2:
840        dst->mixer[0] = (src->mixer[0] + src->mixer[4]) / 2;
841        dst->mixer[1] = (src->mixer[1] + src->mixer[5]) / 2;
842       break;
843      case 3:
844        dst->mixer[0] = (src->mixer[0] + src->mixer[4]) / 2;
845        dst->mixer[1] = (src->mixer[1] + src->mixer[5]) / 2;
846        dst->mixer[2] = src->mixer[2];
847       break;
848      case 4:
849        dst->mixer[0] = src->mixer[0];
850        dst->mixer[1] = src->mixer[1];
851        dst->mixer[2] = src->mixer[4];
852        dst->mixer[3] = src->mixer[5];
853       break;
854      case 5:
855        dst->mixer[0] = src->mixer[0];
856        dst->mixer[1] = src->mixer[1];
857        dst->mixer[2] = src->mixer[2];
858        dst->mixer[3] = src->mixer[4];
859        dst->mixer[4] = src->mixer[5];
860       break;
861      default:
[5145]862        roar_err_set(ROAR_ERROR_NOTSUP);
[4384]863        return -1;
864       break;
865     }
866    break;
867   default:
[5145]868     roar_err_set(ROAR_ERROR_NOTSUP);
[4384]869     return -1;
870    break;
871  }
872 }
873
874 dst->scale   = src->scale;
875 dst->rpg_mul = src->rpg_mul;
876 dst->rpg_div = src->rpg_div;
877
878 return 0;
879}
880
[0]881//ll
Note: See TracBrowser for help on using the repository browser.