source: roaraudio/libroar/ctl.c @ 5144:9126d33415d7

Last change on this file since 5144:9126d33415d7 was 5144:9126d33415d7, checked in by phi, 13 years ago

corrected stream ID, set it to -1 if unused.

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