source: roaraudio/libroar/ctl.c @ 4708:c9d40761088a

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

updated copyright statements

File size: 20.5 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 struct roar_message m;
231 uint16_t * info = (uint16_t *) m.data;
232 int i;
233
234 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
235
236 m.cmd     = ROAR_CMD_SET_VOL;
237 m.datalen = (3 + channels) * 2;
238 m.stream  = id;
239 info[0] = ROAR_HOST2NET16(1);
240 info[1] = ROAR_HOST2NET16(mixer->scale);
241 info[2] = ROAR_HOST2NET16(ROAR_SET_VOL_ALL);
242
243 for (i = 0; i < channels; i++)
244  info[i+3] = ROAR_HOST2NET16(mixer->mixer[i]);
245
246 if ( roar_req(con, &m, NULL) == -1 )
247  return -1;
248
249 if ( m.cmd != ROAR_CMD_OK )
250  return -1;
251
252 return 0;
253}
254
255int roar_get_vol      (struct roar_connection * con, int id, struct roar_mixer_settings * mixer, int * channels) {
256 struct roar_message m;
257 uint16_t * info = (uint16_t *) m.data;
258 int i;
259
260 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
261
262 m.cmd     = ROAR_CMD_GET_VOL;
263 m.datalen = 2*2;
264 m.stream  = id;
265
266 info[0]   = ROAR_HOST2NET16(1);
267
268 if ( roar_req(con, &m, NULL) == -1 )
269  return -1;
270
271 if ( m.cmd != ROAR_CMD_OK )
272  return -1;
273
274 if ( ROAR_NET2HOST16(info[0]) != 1 )
275  return -1;
276
277 info[1] = ROAR_NET2HOST16(info[1]);
278
279 if ( channels != NULL )
280  *channels = info[1];
281
282 if ( info[1] > ROAR_MAX_CHANNELS )
283  return -1;
284
285 mixer->scale   = ROAR_NET2HOST16(info[2]);
286 mixer->rpg_mul = ROAR_NET2HOST16(info[3]);
287 mixer->rpg_div = ROAR_NET2HOST16(info[4]);
288
289 for (i = 0; i < info[1]; i++)
290  mixer->mixer[i] = ROAR_NET2HOST16(info[i+5]);
291
292 return 0;
293}
294
295// converts: *_m2*, *_*2m
296
297int roar_ctl_f2m      (struct roar_message * m, unsigned char   filter, unsigned char   cmp, uint32_t   id) {
298
299 m->datalen = 7;
300
301 m->data[0] = 0;
302 m->data[1] = filter;
303 m->data[2] = cmp;
304 *((uint32_t*)&(m->data[3])) = ROAR_HOST2NET32(id);
305
306 return 0;
307}
308int roar_ctl_m2f      (struct roar_message * m, unsigned char * filter, unsigned char * cmp, uint32_t * id) {
309
310 if ( m->datalen != 7 )
311  return -1;
312
313 if ( m->data[0] != 0 ) {
314  ROAR_ERR("roar_ctl_m2f(*): version %i not supported!", (int)m->data[0]);
315  return -1;
316 }
317
318 *filter = m->data[1];
319 *cmp    = m->data[2];
320
321 *id = ROAR_NET2HOST32(*((uint32_t*)&(m->data[3])));
322
323 return 0;
324}
325
326int roar_filter_match (const unsigned cmp, const uint32_t a, const uint32_t b) {
327 switch (cmp) {
328  case ROAR_CTL_CMP_ANY:
329    return 1;
330   break;
331  case ROAR_CTL_CMP_EQ:
332    return a == b;
333   break;
334  case ROAR_CTL_CMP_NE:
335    return a != b;
336   break;
337  default:
338    return -1;
339 }
340}
341
342int roar_ctl_ia2m     (struct roar_message * m, int * data, int len) {
343 int i;
344
345 if ( len > LIBROAR_BUFFER_MSGDATA )
346  return -1;
347
348 m->datalen = len;
349
350 for (i = 0; i < len; i++)
351  m->data[i] = data[i];
352
353 return 0;
354}
355int roar_ctl_m2ia     (struct roar_message * m, int * data, int len) {
356 int i;
357
358 if ( m->datalen > len )
359  return -1;
360
361 for (i = 0; i < m->datalen; i++)
362  data[i] = m->data[i];
363
364 return m->datalen;
365}
366
367int roar_ctl_c2m      (struct roar_message * m, struct roar_client * c) {
368 int cur = 0;
369 int h;
370 int i;
371 int max_len;
372 uint32_t pid;
373 size_t len_rest;
374
375 if ( c == NULL )
376  return -1;
377
378 m->data[cur++] = 0;                       // 0: Version
379 m->data[cur++] = c->execed;               // 1: execed
380
381 h = 0;
382 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
383  if ( c->streams[i] != -1 )
384   m->data[cur+1+h++] = c->streams[i];
385 }
386
387 m->data[cur++] = h;                       // 2: num of streams
388 cur += h;
389
390 max_len = strlen(c->name);
391
392 // TODO: add some code to check if this fits in the pkg
393 // NOTE: add this code after we are sure how long this pkg will be
394 //       and fully decieded about this function.
395
396 m->data[cur++] = max_len;
397
398 strncpy((m->data)+cur, c->name, max_len);
399
400 cur += max_len;
401
402 pid = ROAR_HOST2NET32(c->pid);
403 memcpy(&(m->data[cur]), &pid, 4);
404 cur += 4;
405
406 pid = ROAR_HOST2NET32(c->uid);
407 memcpy(&(m->data[cur]), &pid, 4);
408 cur += 4;
409
410 pid = ROAR_HOST2NET32(c->gid);
411 memcpy(&(m->data[cur]), &pid, 4);
412 cur += 4;
413
414 pid = ROAR_HOST2NET32(c->proto);
415 memcpy(&(m->data[cur]), &pid, 4);
416 cur += 4;
417
418 pid = ROAR_HOST2NET32(c->byteorder);
419 memcpy(&(m->data[cur]), &pid, 4);
420 cur += 4;
421
422 len_rest = sizeof(m->data) - cur;
423 if ( roar_nnode_to_blob(&(c->nnode), &(m->data[cur]), &len_rest) == 0 ) {
424  cur += len_rest;
425 }
426
427 m->datalen = cur;
428
429 return 0;
430}
431
432int roar_ctl_m2c      (struct roar_message * m, struct roar_client * c) {
433 int i;
434 int cur;
435 uint32_t pid;
436 size_t len;
437
438 if ( m == NULL || c == NULL )
439  return -1;
440
441 if ( m->datalen == 0 )
442  return -1;
443
444 ROAR_DBG("roar_ctl_m2c(*): got data!, len = %i", m->datalen);
445
446 if ( m->data[0] != 0 ) {
447  ROAR_DBG("roar_ctl_m2c(*): wrong version!");
448  return -1;
449 }
450
451 if ( m->datalen < 3 )
452  return -1;
453
454 ROAR_DBG("roar_ctl_m2c(*): have usable data!");
455
456 c->execed = m->data[1];
457
458 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++)
459  c->streams[i] = -1;
460
461 for (i = 0; i < m->data[2]; i++)
462  c->streams[i] = m->data[3+i];
463
464 cur = 3 + m->data[2];
465
466 strncpy(c->name, (m->data)+cur+1, m->data[cur]);
467 c->name[(int)m->data[cur]] = 0;
468
469 cur += m->data[cur] + 1;
470
471 memcpy(&pid, &(m->data[cur]), 4);
472 c->pid = ROAR_NET2HOST32(pid);
473 cur += 4;
474
475 memcpy(&pid, &(m->data[cur]), 4);
476 c->uid = ROAR_NET2HOST32(pid);
477 cur += 4;
478
479 memcpy(&pid, &(m->data[cur]), 4);
480 c->gid = ROAR_NET2HOST32(pid);
481 cur += 4;
482
483 if ( m->datalen >= cur+4 ) {
484  memcpy(&pid, &(m->data[cur]), 4);
485  c->proto = ROAR_NET2HOST32(pid);
486  cur += 4;
487 } else {
488  c->proto = ROAR_PROTO_NONE;
489 }
490
491 if ( m->datalen >= cur+4 ) {
492  memcpy(&pid, &(m->data[cur]), 4);
493  c->byteorder = ROAR_NET2HOST32(pid);
494  cur += 4;
495 } else {
496  c->byteorder = ROAR_BYTEORDER_UNKNOWN;
497 }
498
499 if ( m->datalen > cur ) {
500  len = m->datalen - cur;
501  if ( roar_nnode_from_blob(&(c->nnode), &(m->data[cur]), &len) == 0 ) {
502   cur += len;
503  } else {
504   if ( roar_nnode_new(&(c->nnode), ROAR_SOCKET_TYPE_UNKNOWN) == -1 )
505    return -1;
506  }
507 } else {
508  if ( roar_nnode_new(&(c->nnode), ROAR_SOCKET_TYPE_UNKNOWN) == -1 )
509   return -1;
510 }
511
512 return 0;
513}
514
515int    roar_str2proto (char * proto) {
516 if ( !strcasecmp(proto, "roar") ) {
517  return ROAR_PROTO_ROARAUDIO;
518 } else if ( !strcasecmp(proto, "roaraudio") ) {
519  return ROAR_PROTO_ROARAUDIO;
520 } else if ( !strcasecmp(proto, "esd") ) {
521  return ROAR_PROTO_ESOUND;
522 } else if ( !strcasecmp(proto, "esound") ) {
523  return ROAR_PROTO_ESOUND;
524 } else if ( !strcasecmp(proto, "auto") ) {
525  return ROAR_PROTO_AUTO;
526 } else if ( !strcasecmp(proto, "(auto)") ) {
527  return ROAR_PROTO_AUTO;
528 } else if ( !strcasecmp(proto, "http") ) {
529  return ROAR_PROTO_HTTP;
530 } else if ( !strcasecmp(proto, "gopher") ) {
531  return ROAR_PROTO_GOPHER;
532 } else if ( !strcasecmp(proto, "icy") ) {
533  return ROAR_PROTO_ICY;
534 } else if ( !strcasecmp(proto, "simple") ) {
535  return ROAR_PROTO_SIMPLE;
536 } else if ( !strcasecmp(proto, "rsound") ) {
537  return ROAR_PROTO_RSOUND;
538 } else if ( !strcasecmp(proto, "rplay") ) {
539  return ROAR_PROTO_RPLAY;
540 } else if ( !strcasecmp(proto, "irc") ) {
541  return ROAR_PROTO_IRC;
542 } else if ( !strcasecmp(proto, "dcc") ) {
543  return ROAR_PROTO_DCC;
544 } else if ( !strcasecmp(proto, "echo") ) {
545  return ROAR_PROTO_ECHO;
546 }
547
548 return -1;
549}
550
551char * roar_proto2str (int    proto) {
552 switch (proto) {
553  case ROAR_PROTO_ROARAUDIO: return "RoarAudio"; break;
554  case ROAR_PROTO_ESOUND:    return "EsounD";    break;
555  case ROAR_PROTO_AUTO:      return "(auto)";    break;
556  case ROAR_PROTO_HTTP:      return "http";      break;
557  case ROAR_PROTO_GOPHER:    return "gopher";    break;
558  case ROAR_PROTO_ICY:       return "ICY";       break;
559  case ROAR_PROTO_SIMPLE:    return "Simple";    break;
560  case ROAR_PROTO_RSOUND:    return "RSound";    break;
561  case ROAR_PROTO_RPLAY:     return "RPlay";     break;
562  case ROAR_PROTO_IRC:       return "IRC";       break;
563  case ROAR_PROTO_DCC:       return "DCC";       break;
564  case ROAR_PROTO_ECHO:      return "Echo";      break;
565  default:
566    return "(unknown)";
567 }
568}
569
570int    roar_str2byteorder (char * byteorder) {
571 if (        !strcasecmp(byteorder, "le")            || !strcasecmp(byteorder, "little") ||
572             !strcasecmp(byteorder, "little endian") || !strcasecmp(byteorder, "1234")   ) {
573  return ROAR_BYTEORDER_LE;
574 } else if ( !strcasecmp(byteorder, "be")            || !strcasecmp(byteorder, "big")    ||
575             !strcasecmp(byteorder, "big endian")    || !strcasecmp(byteorder, "4321")   ) {
576  return ROAR_BYTEORDER_BE;
577 } else if ( !strcasecmp(byteorder, "pdp")           ||
578             !strcasecmp(byteorder, "pdp endian") ) {
579  return ROAR_BYTEORDER_PDP;
580 } else if ( !strcasecmp(byteorder, "network")       ||
581             !strcasecmp(byteorder, "network byteorder") ) {
582  return ROAR_BYTEORDER_NETWORK;
583 }
584
585 return -1;
586}
587
588char * roar_byteorder2str (int    byteorder) {
589 switch (byteorder) {
590  case ROAR_BYTEORDER_LE:      return "little endian"; break;
591  case ROAR_BYTEORDER_BE:      return "big endian";    break;
592  case ROAR_BYTEORDER_PDP:     return "pdp endian";    break;
593//  case ROAR_BYTEORDER_NETWORK: return "network";       break;
594  default:
595    return "(unknown)";
596 }
597}
598
599// grep '^#define ROAR_OT_' roaraudio/proto.h | cut -d' ' -f2 | sed 's/^\(ROAR_OT_\)\(.*\)$/ {\1\2, "\2"},/'
600static struct {
601 const int ot;
602 const char * name;
603} _libroar_ot[] = {
604 {ROAR_OT_CLIENT,   "client"},
605 {ROAR_OT_STREAM,   "stream"},
606 {ROAR_OT_SOURCE,   "source"},
607 {ROAR_OT_SAMPLE,   "sample"},
608 {ROAR_OT_OUTPUT,   "output"},
609 {ROAR_OT_MIXER,    "mixer"},
610 {ROAR_OT_BRIDGE,   "bridge"},
611 {ROAR_OT_LISTEN,   "listen"},
612 {ROAR_OT_ACTION,   "action"},
613 {ROAR_OT_MSGQUEUE, "msgqueue"},
614 {ROAR_OT_MSGBUS,   "msgbus"},
615 {-1, NULL}
616};
617
618int    roar_str2ot        (const char * ot) {
619 int i;
620
621 for (i = 0; _libroar_ot[i].ot != -1; i++)
622  if ( !strcasecmp(ot, _libroar_ot[i].name) )
623   return _libroar_ot[i].ot;
624
625 return -1;
626}
627
628const char * roar_ot2str  (const int    ot) {
629 int i;
630
631 for (i = 0; _libroar_ot[i].ot != -1; i++)
632  if ( _libroar_ot[i].ot == ot )
633   return _libroar_ot[i].name;
634
635 return NULL;
636}
637
638int roar_conv_volume (struct roar_mixer_settings * dst, struct roar_mixer_settings * src, int dstchans, int srcchans) {
639 struct roar_mixer_settings lsrc;
640 int i;
641 uint_least32_t s;
642
643 if ( dst == NULL || src == NULL || dstchans < 0 || srcchans < 0 )
644  return -1;
645
646 if ( dstchans == srcchans ) {
647  if ( dst == src )
648   return 0;
649
650  memcpy(dst, src, sizeof(struct roar_mixer_settings));
651  return 0;
652 }
653
654 if ( dst == src ) {
655  memcpy(&lsrc, src, sizeof(lsrc));
656  src = &lsrc;
657 }
658
659 // sepcal handling for N->1:
660 if ( dstchans == 1 ) {
661  s = 0;
662
663  for (i = 0; i < srcchans; i++)
664   s += src->mixer[i];
665
666  dst->mixer[0] = s / srcchans;
667 } else {
668  switch (srcchans) {
669   case  1:
670     for (i = 0; i < dstchans; i++)
671      dst->mixer[i] = src->mixer[0];
672    break;
673   case 2:
674     switch (dstchans) {
675      case 3:
676        dst->mixer[0] = src->mixer[0];
677        dst->mixer[1] = src->mixer[1];
678        dst->mixer[2] = (src->mixer[0] + src->mixer[1]) / 2;
679       break;
680      case 4:
681        dst->mixer[0] = src->mixer[0];
682        dst->mixer[1] = src->mixer[1];
683        dst->mixer[2] = src->mixer[0];
684        dst->mixer[3] = src->mixer[1];
685       break;
686      case 5:
687        dst->mixer[0] = src->mixer[0];
688        dst->mixer[1] = src->mixer[1];
689        dst->mixer[2] = (src->mixer[0] + src->mixer[1]) / 2;
690        dst->mixer[3] = src->mixer[0];
691        dst->mixer[4] = src->mixer[1];
692       break;
693      case 6:
694        dst->mixer[0] = src->mixer[0];
695        dst->mixer[1] = src->mixer[1];
696        dst->mixer[2] = (src->mixer[0] + src->mixer[1]) / 2;
697        dst->mixer[3] = dst->mixer[2];
698        dst->mixer[4] = src->mixer[0];
699        dst->mixer[5] = src->mixer[1];
700       break;
701      default:
702        return -1;
703       break;
704     }
705    break;
706   case 3:
707     switch (dstchans) {
708      case 2:
709        dst->mixer[0] = src->mixer[0];
710        dst->mixer[1] = src->mixer[1];
711       break;
712      case 4:
713        dst->mixer[0] = src->mixer[0];
714        dst->mixer[1] = src->mixer[1];
715        dst->mixer[2] = src->mixer[0];
716        dst->mixer[3] = src->mixer[1];
717       break;
718      case 5:
719        dst->mixer[0] = src->mixer[0];
720        dst->mixer[1] = src->mixer[1];
721        dst->mixer[2] = src->mixer[2];
722        dst->mixer[3] = src->mixer[0];
723        dst->mixer[4] = src->mixer[1];
724       break;
725      case 6:
726        dst->mixer[0] = src->mixer[0];
727        dst->mixer[1] = src->mixer[1];
728        dst->mixer[2] = src->mixer[2];
729        dst->mixer[3] = src->mixer[2];
730        dst->mixer[4] = src->mixer[0];
731        dst->mixer[5] = src->mixer[1];
732       break;
733      default:
734        return -1;
735       break;
736     }
737    break;
738   case 4:
739     switch (dstchans) {
740      case 2:
741        dst->mixer[0] = (src->mixer[0] + src->mixer[2]) / 2;
742        dst->mixer[1] = (src->mixer[1] + src->mixer[3]) / 2;
743       break;
744      case 3:
745        dst->mixer[0] = (src->mixer[0] + src->mixer[2]) / 2;
746        dst->mixer[1] = (src->mixer[1] + src->mixer[3]) / 2;
747        dst->mixer[2] = (dst->mixer[0] + dst->mixer[1]) / 2;
748       break;
749      case 5:
750        dst->mixer[0] = src->mixer[0];
751        dst->mixer[1] = src->mixer[1];
752        dst->mixer[2] = (src->mixer[0] + src->mixer[2] + src->mixer[1] + src->mixer[3]) / 4;
753        dst->mixer[3] = src->mixer[2];
754        dst->mixer[4] = src->mixer[3];
755       break;
756      case 6:
757        dst->mixer[0] = src->mixer[0];
758        dst->mixer[1] = src->mixer[1];
759        dst->mixer[2] = (src->mixer[0] + src->mixer[2] + src->mixer[1] + src->mixer[3]) / 4;
760        dst->mixer[3] = dst->mixer[2];
761        dst->mixer[4] = src->mixer[2];
762        dst->mixer[5] = src->mixer[3];
763       break;
764      default:
765        return -1;
766       break;
767     }
768    break;
769   case 5:
770     switch (dstchans) {
771      case 2:
772        dst->mixer[0] = (src->mixer[0] + src->mixer[3]) / 2;
773        dst->mixer[1] = (src->mixer[1] + src->mixer[4]) / 2;
774       break;
775      case 3:
776        dst->mixer[0] = (src->mixer[0] + src->mixer[3]) / 2;
777        dst->mixer[1] = (src->mixer[1] + src->mixer[4]) / 2;
778        dst->mixer[2] = src->mixer[2];
779       break;
780      case 4:
781        dst->mixer[0] = src->mixer[0];
782        dst->mixer[1] = src->mixer[1];
783        dst->mixer[2] = src->mixer[3];
784        dst->mixer[3] = src->mixer[4];
785       break;
786      case 6:
787        dst->mixer[0] = src->mixer[0];
788        dst->mixer[1] = src->mixer[1];
789        dst->mixer[2] = src->mixer[2];
790        dst->mixer[3] = src->mixer[2];
791        dst->mixer[4] = src->mixer[3];
792        dst->mixer[5] = src->mixer[4];
793       break;
794      default:
795        return -1;
796       break;
797     }
798    break;
799   case 6:
800     switch (dstchans) {
801      case 2:
802        dst->mixer[0] = (src->mixer[0] + src->mixer[4]) / 2;
803        dst->mixer[1] = (src->mixer[1] + src->mixer[5]) / 2;
804       break;
805      case 3:
806        dst->mixer[0] = (src->mixer[0] + src->mixer[4]) / 2;
807        dst->mixer[1] = (src->mixer[1] + src->mixer[5]) / 2;
808        dst->mixer[2] = src->mixer[2];
809       break;
810      case 4:
811        dst->mixer[0] = src->mixer[0];
812        dst->mixer[1] = src->mixer[1];
813        dst->mixer[2] = src->mixer[4];
814        dst->mixer[3] = src->mixer[5];
815       break;
816      case 5:
817        dst->mixer[0] = src->mixer[0];
818        dst->mixer[1] = src->mixer[1];
819        dst->mixer[2] = src->mixer[2];
820        dst->mixer[3] = src->mixer[4];
821        dst->mixer[4] = src->mixer[5];
822       break;
823      default:
824        return -1;
825       break;
826     }
827    break;
828   default:
829     return -1;
830    break;
831  }
832 }
833
834 dst->scale   = src->scale;
835 dst->rpg_mul = src->rpg_mul;
836 dst->rpg_div = src->rpg_div;
837
838 return 0;
839}
840
841//ll
Note: See TracBrowser for help on using the repository browser.