source: roaraudio/libroar/ctl.c @ 4614:3b1ab4d465e8

Last change on this file since 4614:3b1ab4d465e8 was 4614:3b1ab4d465e8, checked in by phi, 13 years ago

Support dir parameter in OINFO command (Closes: #31)

File size: 20.2 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 * 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 }
541
542 return -1;
543}
544
545char * roar_proto2str (int    proto) {
546 switch (proto) {
547  case ROAR_PROTO_ROARAUDIO: return "RoarAudio"; break;
548  case ROAR_PROTO_ESOUND:    return "EsounD";    break;
549  case ROAR_PROTO_AUTO:      return "(auto)";    break;
550  case ROAR_PROTO_HTTP:      return "http";      break;
551  case ROAR_PROTO_GOPHER:    return "gopher";    break;
552  case ROAR_PROTO_ICY:       return "ICY";       break;
553  case ROAR_PROTO_SIMPLE:    return "Simple";    break;
554  case ROAR_PROTO_RSOUND:    return "RSound";    break;
555  case ROAR_PROTO_RPLAY:     return "RPlay";     break;
556  default:
557    return "(unknown)";
558 }
559}
560
561int    roar_str2byteorder (char * byteorder) {
562 if (        !strcasecmp(byteorder, "le")            || !strcasecmp(byteorder, "little") ||
563             !strcasecmp(byteorder, "little endian") || !strcasecmp(byteorder, "1234")   ) {
564  return ROAR_BYTEORDER_LE;
565 } else if ( !strcasecmp(byteorder, "be")            || !strcasecmp(byteorder, "big")    ||
566             !strcasecmp(byteorder, "big endian")    || !strcasecmp(byteorder, "4321")   ) {
567  return ROAR_BYTEORDER_BE;
568 } else if ( !strcasecmp(byteorder, "pdp")           ||
569             !strcasecmp(byteorder, "pdp endian") ) {
570  return ROAR_BYTEORDER_PDP;
571 } else if ( !strcasecmp(byteorder, "network")       ||
572             !strcasecmp(byteorder, "network byteorder") ) {
573  return ROAR_BYTEORDER_NETWORK;
574 }
575
576 return -1;
577}
578
579char * roar_byteorder2str (int    byteorder) {
580 switch (byteorder) {
581  case ROAR_BYTEORDER_LE:      return "little endian"; break;
582  case ROAR_BYTEORDER_BE:      return "big endian";    break;
583  case ROAR_BYTEORDER_PDP:     return "pdp endian";    break;
584//  case ROAR_BYTEORDER_NETWORK: return "network";       break;
585  default:
586    return "(unknown)";
587 }
588}
589
590// grep '^#define ROAR_OT_' roaraudio/proto.h | cut -d' ' -f2 | sed 's/^\(ROAR_OT_\)\(.*\)$/ {\1\2, "\2"},/'
591static struct {
592 const int ot;
593 const char * name;
594} _libroar_ot[] = {
595 {ROAR_OT_CLIENT,   "client"},
596 {ROAR_OT_STREAM,   "stream"},
597 {ROAR_OT_SOURCE,   "source"},
598 {ROAR_OT_SAMPLE,   "sample"},
599 {ROAR_OT_OUTPUT,   "output"},
600 {ROAR_OT_MIXER,    "mixer"},
601 {ROAR_OT_BRIDGE,   "bridge"},
602 {ROAR_OT_LISTEN,   "listen"},
603 {ROAR_OT_ACTION,   "action"},
604 {ROAR_OT_MSGQUEUE, "msgqueue"},
605 {ROAR_OT_MSGBUS,   "msgbus"},
606 {-1, NULL}
607};
608
609int    roar_str2ot        (const char * ot) {
610 int i;
611
612 for (i = 0; _libroar_ot[i].ot != -1; i++)
613  if ( !strcasecmp(ot, _libroar_ot[i].name) )
614   return _libroar_ot[i].ot;
615
616 return -1;
617}
618
619const char * roar_ot2str  (const int    ot) {
620 int i;
621
622 for (i = 0; _libroar_ot[i].ot != -1; i++)
623  if ( _libroar_ot[i].ot == ot )
624   return _libroar_ot[i].name;
625
626 return NULL;
627}
628
629int roar_conv_volume (struct roar_mixer_settings * dst, struct roar_mixer_settings * src, int dstchans, int srcchans) {
630 struct roar_mixer_settings lsrc;
631 int i;
632 uint_least32_t s;
633
634 if ( dst == NULL || src == NULL || dstchans < 0 || srcchans < 0 )
635  return -1;
636
637 if ( dstchans == srcchans ) {
638  if ( dst == src )
639   return 0;
640
641  memcpy(dst, src, sizeof(struct roar_mixer_settings));
642  return 0;
643 }
644
645 if ( dst == src ) {
646  memcpy(&lsrc, src, sizeof(lsrc));
647  src = &lsrc;
648 }
649
650 // sepcal handling for N->1:
651 if ( dstchans == 1 ) {
652  s = 0;
653
654  for (i = 0; i < srcchans; i++)
655   s += src->mixer[i];
656
657  dst->mixer[0] = s / srcchans;
658 } else {
659  switch (srcchans) {
660   case  1:
661     for (i = 0; i < dstchans; i++)
662      dst->mixer[i] = src->mixer[0];
663    break;
664   case 2:
665     switch (dstchans) {
666      case 3:
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       break;
671      case 4:
672        dst->mixer[0] = src->mixer[0];
673        dst->mixer[1] = src->mixer[1];
674        dst->mixer[2] = src->mixer[0];
675        dst->mixer[3] = src->mixer[1];
676       break;
677      case 5:
678        dst->mixer[0] = src->mixer[0];
679        dst->mixer[1] = src->mixer[1];
680        dst->mixer[2] = (src->mixer[0] + src->mixer[1]) / 2;
681        dst->mixer[3] = src->mixer[0];
682        dst->mixer[4] = src->mixer[1];
683       break;
684      case 6:
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        dst->mixer[3] = dst->mixer[2];
689        dst->mixer[4] = src->mixer[0];
690        dst->mixer[5] = src->mixer[1];
691       break;
692      default:
693        return -1;
694       break;
695     }
696    break;
697   case 3:
698     switch (dstchans) {
699      case 2:
700        dst->mixer[0] = src->mixer[0];
701        dst->mixer[1] = src->mixer[1];
702       break;
703      case 4:
704        dst->mixer[0] = src->mixer[0];
705        dst->mixer[1] = src->mixer[1];
706        dst->mixer[2] = src->mixer[0];
707        dst->mixer[3] = src->mixer[1];
708       break;
709      case 5:
710        dst->mixer[0] = src->mixer[0];
711        dst->mixer[1] = src->mixer[1];
712        dst->mixer[2] = src->mixer[2];
713        dst->mixer[3] = src->mixer[0];
714        dst->mixer[4] = src->mixer[1];
715       break;
716      case 6:
717        dst->mixer[0] = src->mixer[0];
718        dst->mixer[1] = src->mixer[1];
719        dst->mixer[2] = src->mixer[2];
720        dst->mixer[3] = src->mixer[2];
721        dst->mixer[4] = src->mixer[0];
722        dst->mixer[5] = src->mixer[1];
723       break;
724      default:
725        return -1;
726       break;
727     }
728    break;
729   case 4:
730     switch (dstchans) {
731      case 2:
732        dst->mixer[0] = (src->mixer[0] + src->mixer[2]) / 2;
733        dst->mixer[1] = (src->mixer[1] + src->mixer[3]) / 2;
734       break;
735      case 3:
736        dst->mixer[0] = (src->mixer[0] + src->mixer[2]) / 2;
737        dst->mixer[1] = (src->mixer[1] + src->mixer[3]) / 2;
738        dst->mixer[2] = (dst->mixer[0] + dst->mixer[1]) / 2;
739       break;
740      case 5:
741        dst->mixer[0] = src->mixer[0];
742        dst->mixer[1] = src->mixer[1];
743        dst->mixer[2] = (src->mixer[0] + src->mixer[2] + src->mixer[1] + src->mixer[3]) / 4;
744        dst->mixer[3] = src->mixer[2];
745        dst->mixer[4] = src->mixer[3];
746       break;
747      case 6:
748        dst->mixer[0] = src->mixer[0];
749        dst->mixer[1] = src->mixer[1];
750        dst->mixer[2] = (src->mixer[0] + src->mixer[2] + src->mixer[1] + src->mixer[3]) / 4;
751        dst->mixer[3] = dst->mixer[2];
752        dst->mixer[4] = src->mixer[2];
753        dst->mixer[5] = src->mixer[3];
754       break;
755      default:
756        return -1;
757       break;
758     }
759    break;
760   case 5:
761     switch (dstchans) {
762      case 2:
763        dst->mixer[0] = (src->mixer[0] + src->mixer[3]) / 2;
764        dst->mixer[1] = (src->mixer[1] + src->mixer[4]) / 2;
765       break;
766      case 3:
767        dst->mixer[0] = (src->mixer[0] + src->mixer[3]) / 2;
768        dst->mixer[1] = (src->mixer[1] + src->mixer[4]) / 2;
769        dst->mixer[2] = src->mixer[2];
770       break;
771      case 4:
772        dst->mixer[0] = src->mixer[0];
773        dst->mixer[1] = src->mixer[1];
774        dst->mixer[2] = src->mixer[3];
775        dst->mixer[3] = src->mixer[4];
776       break;
777      case 6:
778        dst->mixer[0] = src->mixer[0];
779        dst->mixer[1] = src->mixer[1];
780        dst->mixer[2] = src->mixer[2];
781        dst->mixer[3] = src->mixer[2];
782        dst->mixer[4] = src->mixer[3];
783        dst->mixer[5] = src->mixer[4];
784       break;
785      default:
786        return -1;
787       break;
788     }
789    break;
790   case 6:
791     switch (dstchans) {
792      case 2:
793        dst->mixer[0] = (src->mixer[0] + src->mixer[4]) / 2;
794        dst->mixer[1] = (src->mixer[1] + src->mixer[5]) / 2;
795       break;
796      case 3:
797        dst->mixer[0] = (src->mixer[0] + src->mixer[4]) / 2;
798        dst->mixer[1] = (src->mixer[1] + src->mixer[5]) / 2;
799        dst->mixer[2] = src->mixer[2];
800       break;
801      case 4:
802        dst->mixer[0] = src->mixer[0];
803        dst->mixer[1] = src->mixer[1];
804        dst->mixer[2] = src->mixer[4];
805        dst->mixer[3] = src->mixer[5];
806       break;
807      case 5:
808        dst->mixer[0] = src->mixer[0];
809        dst->mixer[1] = src->mixer[1];
810        dst->mixer[2] = src->mixer[2];
811        dst->mixer[3] = src->mixer[4];
812        dst->mixer[4] = src->mixer[5];
813       break;
814      default:
815        return -1;
816       break;
817     }
818    break;
819   default:
820     return -1;
821    break;
822  }
823 }
824
825 dst->scale   = src->scale;
826 dst->rpg_mul = src->rpg_mul;
827 dst->rpg_div = src->rpg_div;
828
829 return 0;
830}
831
832//ll
Note: See TracBrowser for help on using the repository browser.