source: roaraudio/libroar/ctl.c @ 4385:37924d2f1dae

Last change on this file since 4385:37924d2f1dae was 4385:37924d2f1dae, checked in by phi, 14 years ago

support src == dst in roar_conv_volume()

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