source: roaraudio/libroar/ctl.c @ 4740:f3abf82e2ead

Last change on this file since 4740:f3abf82e2ead was 4740:f3abf82e2ead, checked in by phi, 13 years ago

Added support for UNMAPPED volume control (Closes: #55)

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