source: roaraudio/roard/req.c @ 3732:4525972e9c84

Last change on this file since 3732:4525972e9c84 was 3732:4525972e9c84, checked in by phi, 14 years ago

added support to pass listen sockets

File size: 24.7 KB
Line 
1//req.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2010
5 *
6 *  This file is part of roard 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 *  RoarAudio 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 */
25
26#include "roard.h"
27
28int req_on_noop        (int client, struct roar_message * mes, char * data) {
29 mes->cmd     = ROAR_CMD_OK;
30 mes->datalen = 0;
31 return 0;
32}
33
34int req_on_identify    (int client, struct roar_message * mes, char * data) {
35 struct roar_client * c;
36 int max_len;
37
38 if ( mes->datalen < 1 )
39  return -1;
40
41 clients_get(client, &c);
42
43 if ( mes->data[0] == 1 ) {
44  if ( c->pid == -1 ) {
45   c->pid       = ROAR_NET2HOST32(*(uint32_t*)((mes->data)+1));
46   ROAR_DBG("req_on_identify(): new PID: c->pid = %i", c->pid);
47  }
48
49  ROAR_DBG("req_on_identify(): final PID: c->pid = %i", c->pid);
50
51  max_len = (mes->datalen - 5) < (ROAR_BUFFER_NAME-1) ? (mes->datalen - 5) : (ROAR_BUFFER_NAME-1);
52
53  strncpy(c->name, mes->data + 5, max_len);
54  c->name[max_len] = 0;
55
56  mes->cmd     = ROAR_CMD_OK;
57  mes->datalen = 0;
58
59  ROAR_DBG("req_on_identify(*): client=%i, pid=%i", client, c->pid);
60  ROAR_DBG("req_on_identify(*) = 0");
61  return 0;
62 }
63
64 return -1;
65}
66
67int req_on_auth        (int client, struct roar_message * mes, char * data) {
68 // TODO: add code to support some auth.
69 mes->cmd     = ROAR_CMD_OK;
70 mes->datalen = 0;
71 return 0;
72}
73
74
75int req_on_whoami      (int client, struct roar_message * mes, char * data) {
76 mes->cmd     = ROAR_CMD_OK;
77 mes->datalen = 1;
78 mes->data[0] = client;
79 return 0;
80}
81
82
83int req_on_new_stream  (int client, struct roar_message * mes, char * data) {
84 int stream;
85 struct roar_stream * s;
86 struct roar_stream * source_stream;
87 struct roar_audio_info * info;
88 struct roar_audio_info * source_info;
89
90 ROAR_DBG("req_on_new_stream(client=%i, ...): creating stream...", client);
91 if ((stream = streams_new()) == -1 )
92  return -1;
93
94 ROAR_DBG("req_on_new_stream(client=%i, ...): getting stream...", client);
95 if ( streams_get(stream, (struct roar_stream_server **)&s) == -1 ) {
96  streams_delete(stream);
97  return -1;
98 }
99
100 ROAR_DBG("req_on_new_stream(client=%i, ...): set client of stream...", client);
101 if ( client_stream_add(client, stream) == -1 ) {
102  streams_delete(stream);
103  return -1;
104 }
105
106 ROAR_DBG("req_on_new_stream(client=%i, ...): loading stream from message...", client);
107 if ( roar_stream_m2s(s, mes) == -1 ) {
108  streams_delete(stream);
109  return -1;
110 }
111
112 ROAR_DBG("req_on_new_stream(client=%i, ...): setting id and codec of stream...", client);
113 ROAR_STREAM(s)->id = stream; // roar_stream_m2s() resets this
114 ROAR_STREAM_SERVER(s)->codec_orgi = ROAR_STREAM(s)->info.codec;
115
116 ROAR_DBG("req_on_new_stream(client=%i, ...): setting direction stream...", client);
117 // int streams_set_dir    (int id, int dir, int defaults)
118 if ( streams_set_dir(stream, ROAR_STREAM(s)->dir, 1) == -1 ) {
119  streams_delete(stream);
120  return -1;
121 }
122
123 ROAR_DBG("req_on_new_stream(client=%i, ...): setting up direction specific stream settings...", client);
124 switch (ROAR_STREAM(s)->dir) {
125  case ROAR_DIR_LIGHT_IN:
126  case ROAR_DIR_LIGHT_OUT:
127#ifndef ROAR_WITHOUT_DCOMP_LIGHT
128    info = &(ROAR_STREAM(s)->info);
129
130    info->channels = 0;
131    info->bits     = 0;
132    info->rate     = 0;
133#else
134    streams_delete(stream);
135    return -1;
136#endif
137
138   break;
139  case ROAR_DIR_MIDI_IN:
140  case ROAR_DIR_MIDI_OUT:
141#ifndef ROAR_WITHOUT_DCOMP_MIDI
142    info = &(ROAR_STREAM(s)->info);
143
144    info->channels = ROAR_MIDI_CHANNELS_DEFAULT;
145    info->bits     = ROAR_MIDI_BITS;
146    info->rate     = 0;
147#else
148    streams_delete(stream);
149    return -1;
150#endif
151
152   break;
153
154  case ROAR_DIR_RAW_IN:
155#ifndef ROAR_WITHOUT_DCOMP_RAW
156    if ( ROAR_STREAM(s)->pos_rel_id == -1     ||
157         ROAR_STREAM(s)->pos_rel_id == stream ||
158         streams_get_dir(ROAR_STREAM(s)->pos_rel_id) != ROAR_DIR_RAW_OUT
159       ) {
160     ROAR_STREAM(s)->pos_rel_id = -1; // force this here as it will try to delete itself while deleting
161                                      // in case rel_id == stream
162     streams_delete(stream);
163     return -1;
164    }
165#else
166  case ROAR_DIR_RAW_OUT:
167    streams_delete(stream);
168    return -1;
169#endif
170
171   break;
172  case ROAR_DIR_THRU:
173
174    if ( ROAR_STREAM(s)->pos_rel_id == -1 || ROAR_STREAM(s)->pos_rel_id == stream ) {
175     ROAR_STREAM(s)->pos_rel_id = -1; // force this here as it will try to delete itself while deleting
176                                      // in case rel_id == stream
177     streams_delete(stream);
178     return -1;
179    }
180
181    if ( streams_get(ROAR_STREAM(s)->pos_rel_id, (struct roar_stream_server **)&source_stream) == -1 ) {
182     streams_delete(stream);
183     return -1;
184    }
185
186    info        = &(ROAR_STREAM(s)->info);
187    source_info = &(ROAR_STREAM(source_stream)->info);
188
189    info->channels = source_info->channels;
190    info->bits     = source_info->bits;
191    info->rate     = source_info->rate;
192    info->codec    = source_info->codec;
193    ROAR_STREAM_SERVER(s)->codec_orgi = ROAR_STREAM_SERVER(source_stream)->codec_orgi;
194
195   break;
196  case ROAR_DIR_FILTER:
197    info        = &(ROAR_STREAM(s)->info);
198
199    if ( ROAR_STREAM(s)->pos_rel_id == -1 ) {
200     source_info = g_sa;
201    } else {
202     if ( streams_get(ROAR_STREAM(s)->pos_rel_id, (struct roar_stream_server **)&source_stream) == -1 ) {
203      streams_delete(stream);
204      return -1;
205     }
206     source_info = &(ROAR_STREAM(source_stream)->info);
207    }
208
209    if ( info->channels != source_info->channels || info->bits != source_info->bits ||
210         info->codec    != source_info->codec    || info->rate != source_info->rate ) {
211     // the stream parameters don't match the one of the stream being filtered.
212     // -> delete and reject the stream.
213     streams_delete(stream);
214     return -1;
215    }
216   break;
217 }
218
219 ROAR_DBG("req_on_new_stream(client=%i, ...): returning (OK)...", client);
220
221 mes->cmd     = ROAR_CMD_OK;
222 mes->stream  = stream;
223 mes->datalen = 0;
224
225 return 0;
226}
227
228int req_on_exec_stream (int client, struct roar_message * mes, char * data) {
229 int r;
230
231 ROAR_DBG("req_on_exec_stream(client=%i, mes={stream=%i,...},...): execing stream", client, mes->stream);
232
233 if ( (r = client_stream_exec(client, mes->stream)) == -1 )
234  return -1;
235
236 ROAR_DBG("req_on_exec_stream(client=%i, mes={stream=%i,...},...): returning (OK)...", client, mes->stream);
237 mes->cmd     = ROAR_CMD_OK;
238 mes->datalen = 0;
239
240 return 0;
241}
242
243int req_on_con_stream  (int client, struct roar_message * mes, char * data) {
244 char   host[80] = {0};
245 int    port = 0;
246 int    type;
247 int    fh;
248 int    len;
249
250 if ( mes->datalen < 4 )
251  return -1;
252
253 if ( *(mes->data) != 0 )
254  return -1;
255
256 if ( mes->datalen > 80 ) // we do not support long messages here
257  return -1;
258
259 type = (unsigned)mes->data[1];
260 port = ROAR_NET2HOST16(((uint16_t*)mes->data)[1]);
261
262 len = mes->datalen - 4;
263
264 strncpy(host, &(mes->data[4]), len);
265 host[len] = 0;
266
267 if ( type > ROAR_SOCKET_TYPE_MAX )
268  return -1;
269
270 if ( type == ROAR_SOCKET_TYPE_FILE ) // disabled because of security resons
271  return -1;
272
273 if ( type == ROAR_SOCKET_TYPE_FORK ) // why should we connect to ourself?
274  return -1;
275
276 ROAR_DBG("req_on_con_stream(*): CONNECT(type=%i, host='%s', port=%i)", type, host, port);
277
278 if ( (fh = roar_socket_open(ROAR_SOCKET_MODE_CONNECT, type, host, port)) == -1 )
279  return -1;
280
281 if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
282  close(fh);
283  return 1;
284 }
285
286 mes->datalen = 0;
287 mes->cmd     = ROAR_CMD_OK;
288
289 return 0;
290}
291
292int req_on_passfh      (int client, struct roar_message * mes, char * data) {
293 struct roar_client * c;
294 int sock = clients_get_fh(client);
295 int16_t * d = (int16_t*)mes->data;
296 struct roard_listen * lsock;
297 int listening;
298 int fh;
299 int i;
300
301 if ( (fh = roar_socket_recv_fh(sock, NULL, NULL)) == -1 )
302  return -1;
303
304 if ( mes->stream != -1 ) { // stream pass:
305  if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
306   close(fh);
307   return 1;
308  }
309
310  mes->datalen = 0;
311  mes->cmd     = ROAR_CMD_OK;
312
313  return 0;
314 }
315
316// non-stream pass:
317
318/*
319 0: Version,  16
320 1: Flags,    16
321 2: Protocol, 16
322 3: Byteorder 16
323 Options...
324*/
325
326 if ( mes->datalen < 4*2 )
327  return -1;
328
329 for (i = 0; i < 4; i++) {
330  d[i] = ROAR_NET2HOST16(d[i]);
331 }
332
333 if ( d[0] != 0 ) // version
334  return -1;
335
336 listening = d[1] & ROAR_CLIENTPASS_FLAG_LISTEN;
337
338 if ( listening )
339  d[1] -= ROAR_CLIENTPASS_FLAG_LISTEN;
340
341 if ( d[1] != 0 ) // flags
342  return -1;
343
344 if ( listening ) {
345  if ( get_listen(&lsock, NULL) == -1 )
346   return -1;
347
348  lsock->socket = fh;
349  lsock->proto  = d[2];
350 } else {
351  if ( d[2] != ROAR_PROTO_ROARAUDIO ) // protocol
352   return -1;
353
354  if ( d[3] != ROAR_BYTEORDER_NETWORK ) // byte order
355   return -1;
356
357  if ( (client = clients_new()) == -1 )
358   return -1;
359
360  if ( clients_set_fh(client, fh) == -1 ) {
361   clients_delete(client);
362   return -1;
363  }
364
365  if ( clients_get(client, &c) != -1 ) {
366   roar_nnode_new_from_fh(&(c->nnode), fh, 1);
367  }
368 }
369
370 mes->datalen = 0;
371 mes->cmd     = ROAR_CMD_OK;
372
373 return 0;
374}
375
376#ifdef ROAR_SUPPORT_META
377int req_on_set_meta    (int client, struct roar_message * mes, char * data) {
378 int type;
379 int mode;
380 int namelen, vallen;
381 char   val[255+1];
382 char   name[ROAR_META_MAX_NAMELEN+1];
383
384 if ( mes->datalen < 3 )
385  return -1;
386
387 if ( mes->data[0] != 0 ) // version
388  return -1;
389
390 mode = (unsigned) mes->data[1];
391 type = (unsigned) mes->data[2];
392
393 ROAR_DBG("req_on_set_meta(*): mode=%i, type=%i", mode, type);
394
395 if ( mode == ROAR_META_MODE_CLEAR ) {
396  stream_meta_clear(mes->stream);
397  mes->datalen = 0;
398  mes->cmd     = ROAR_CMD_OK;
399  return 0;
400 } else if ( mode == ROAR_META_MODE_DELETE ) { // unsuppoerted at the moment
401  return -1;
402 } else if ( mode == ROAR_META_MODE_FINALIZE ) {
403  stream_meta_finalize(mes->stream);
404  mes->datalen = 0;
405  mes->cmd     = ROAR_CMD_OK;
406  return 0;
407 } else if ( mode == ROAR_META_MODE_SET || mode == ROAR_META_MODE_ADD ) {
408  if ( mes->datalen < 5 )
409   return -1;
410
411  namelen = (unsigned) mes->data[3];
412  vallen  = (unsigned) mes->data[4];
413
414  ROAR_DBG("req_on_set_meta(*): namelen=%i, vallen=%i", namelen, vallen);
415
416  if ( mes->datalen < (5 + namelen + vallen) )
417   return -1;
418
419  if ( namelen > ROAR_META_MAX_NAMELEN )
420   return -1;
421
422  strncpy(name, &(mes->data[5]), namelen);
423  name[namelen] = 0;
424
425  if ( vallen > 255 )
426   return -1;
427
428  strncpy(val, &(mes->data[5+namelen]), vallen);
429  val[vallen] = 0;
430
431  if ( mode == ROAR_META_MODE_SET ) {
432   if ( stream_meta_set(mes->stream, type, name, val) == -1 )
433    return -1;
434  } else {
435   if ( stream_meta_add(mes->stream, type, name, val) == -1 )
436    return -1;
437  }
438
439  mes->datalen = 0;
440  mes->cmd     = ROAR_CMD_OK;
441  return 0;
442 } else { // unknown mode!
443  return -1;
444 }
445
446 return -1;
447}
448
449int req_on_get_meta    (int client, struct roar_message * mes, char * data) {
450 int vallen;
451 int type;
452 char val[LIBROAR_BUFFER_MSGDATA-1];
453
454 if ( mes->datalen != 2 )
455  return -1;
456
457 if ( mes->data[0] != 0 ) // version
458  return -1;
459
460 type = (unsigned) mes->data[1];
461
462 if ( stream_meta_get(mes->stream, type, NULL, val, LIBROAR_BUFFER_MSGDATA-2) == -1 )
463  return -1;
464
465 vallen = strlen(val);
466
467 mes->cmd     = ROAR_CMD_OK;
468 mes->datalen = 2 + vallen;
469
470 mes->data[0] = 0;
471 mes->data[1] = (unsigned char) vallen;
472
473 val[vallen] = 0;
474
475 strncpy(&(mes->data[2]), val, vallen+1);
476
477 return 0;
478}
479
480int req_on_list_meta   (int client, struct roar_message * mes, char * data) {
481 int i;
482 int len = 0;
483 int types[ROAR_META_MAX_PER_STREAM];
484
485 if ( mes->datalen != 1 )
486  return -1;
487
488 if ( mes->data[0] != 0 ) // version
489  return -1;
490
491 if ( (len = stream_meta_list(mes->stream, types, ROAR_META_MAX_PER_STREAM)) == -1 )
492  return -1;
493
494 mes->cmd     = ROAR_CMD_OK;
495 mes->datalen = 1 + len;
496 mes->data[0] = 0;
497
498 for (i = 0; i < len; i++)
499  mes->data[i+1] = types[i];
500
501 return 0;
502}
503#endif
504
505int req_on_server_oinfo    (int client, struct roar_message * mes, char * data) {
506 struct roar_stream s;
507//ROAR_DIR_OUTPUT
508
509 memset(&s, 0, sizeof(struct roar_stream));
510
511 s.dir           = ROAR_DIR_MIXING;
512 s.pos_rel_id    = -1;
513 s.info.rate     = g_sa->rate;
514 s.info.bits     = g_sa->bits;
515 s.info.channels = g_sa->channels;
516 s.info.codec    = g_sa->codec;
517 s.pos           = g_pos;
518
519 if ( roar_stream_s2m(&s, mes) == -1 )
520  return -1;
521
522 mes->cmd = ROAR_CMD_OK;
523
524 return 0;
525}
526
527
528int req_on_get_standby (int client, struct roar_message * mes, char * data) {
529 mes->cmd = ROAR_CMD_OK;
530 mes->datalen = 2;
531
532 *((uint16_t*)mes->data) = ROAR_HOST2NET16((unsigned) g_standby);
533
534 return 0;
535}
536
537int req_on_set_standby (int client, struct roar_message * mes, char * data) {
538 if ( mes->datalen != 2 )
539  return -1;
540
541 g_standby = ROAR_NET2HOST16(*((uint16_t*)mes->data));
542
543 mes->cmd     = ROAR_CMD_OK;
544 mes->datalen = 0;
545
546 return 0;
547}
548
549int req_on_exit      (int client, struct roar_message * mes, char * data) {
550 int term = 0;
551
552 if ( mes->datalen == 1 )
553  term = mes->data[0];
554
555 mes->cmd     = ROAR_CMD_OK;
556 mes->datalen = 0;
557
558 ROAR_DBG("req_on_exit(*): term=%i", term);
559
560 if ( term ) {
561  cleanup_listen_socket(1);
562 } else {
563  alive = 0;
564 }
565
566 return 0;
567}
568
569int req_on_list_clients(int client, struct roar_message * mes, char * data) {
570 unsigned char filter, cmp;
571 uint32_t id;
572 int clients[ROAR_CLIENTS_MAX];
573 int i, c = 0;
574
575 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
576  return -1;
577
578 // TODO: add code to support filter
579 if ( filter != ROAR_CTL_FILTER_ANY )
580  return -1;
581
582 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
583  if ( g_clients[i] != NULL ) {
584   clients[c++] = i;
585  }
586 }
587
588 roar_ctl_ia2m(mes, clients, c);
589
590 mes->cmd = ROAR_CMD_OK;
591
592 return 0;
593}
594int req_on_list_streams(int client, struct roar_message * mes, char * data) {
595 unsigned char filter, cmp;
596 uint32_t id;
597 int streams[ROAR_STREAMS_MAX];
598 int i, c = 0;
599
600 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
601  return -1;
602
603 // TODO: add code to support filter
604 if ( filter != ROAR_CTL_FILTER_ANY )
605  return -1;
606
607 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
608  if ( g_streams[i] != NULL ) {
609   streams[c++] = i;
610  }
611 }
612
613 roar_ctl_ia2m(mes, streams, c);
614
615 mes->cmd = ROAR_CMD_OK;
616
617 return 0;
618}
619
620int req_on_get_client  (int client, struct roar_message * mes, char * data) {
621 struct roar_client * c;
622
623 if ( mes->datalen != 1 )
624  return -1;
625
626 if ( clients_get(mes->data[0], &c) == -1 )
627  return -1;
628
629 mes->cmd = ROAR_CMD_OK;
630
631 return roar_ctl_c2m(mes, c);
632}
633
634int req_on_get_stream  (int client, struct roar_message * mes, char * data) {
635 struct roar_stream_server * s;
636
637 if ( mes->datalen != 1 )
638  return -1;
639
640 if ( streams_get(mes->data[0], &s) == -1 )
641  return -1;
642
643 mes->cmd = ROAR_CMD_OK;
644 mes->stream = mes->data[0];
645
646 return roar_stream_s2m(ROAR_STREAM(s), mes);
647}
648
649int req_on_get_stream_para (int client, struct roar_message * mes, char * data) {
650 struct roar_stream * s;
651 struct roar_stream_server * ss;
652 struct roar_audio_info * audio_info;
653 uint16_t * d = (uint16_t *) mes->data;
654 int i;
655 char * str;
656
657 if ( mes->datalen != 4 )
658  return -1;
659
660 for (i = 0; i < mes->datalen/2; i++) {
661  d[i] = ROAR_NET2HOST16(d[i]);
662 }
663
664 if ( d[0] != 0 ) {
665  ROAR_WARN("req_on_get_stream_para(*): unsupported command version: %i, %i", d[0], d[1]);
666  return -1;
667 }
668
669 switch (d[1]) {
670  case ROAR_STREAM_PARA_INFO:
671    if ( streams_get(mes->stream, &ss) == -1 ) {
672     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
673     return -1;
674    }
675
676    if ( streams_calc_delay(mes->stream) == -1 ) {
677     ROAR_WARN("req_on_get_stream_para(*): can not calc delay for stream %i", mes->stream);
678    }
679
680    s = ROAR_STREAM(ss);
681
682    audio_info = &(s->info);
683
684    mes->datalen = 2*12;
685
686    d[ 2] = ROAR_OUTPUT_CALC_OUTBUFSIZE(audio_info);
687    d[ 3] = ss->pre_underruns;
688    d[ 4] = ss->post_underruns;
689    d[ 5] = ss->codec_orgi;
690    d[ 6] = (ss->flags & 0xFFFF) | (ss->primary ? ROAR_FLAG_PRIMARY : 0) | (ss->driver_id != -1 ? ROAR_FLAG_OUTPUT : 0);
691    d[ 7] = ss->delay/1000;
692    d[ 8] = ss->state;
693    d[ 9] = (ss->flags & 0xFFFF0000) >> 16;
694    d[10] = ss->mixer_stream;
695    d[11] = ss->role;
696
697    ROAR_DBG("req_on_get_stream_para(*): ss->driver_id=%i", ss->driver_id);
698
699    ROAR_DBG("req_on_get_stream_para(*): delay=%i, send delay=%i", ss->delay, d[7]);
700
701    for (i = 0; i < mes->datalen/2; i++) {
702     d[i] = ROAR_HOST2NET16(d[i]);
703    }
704
705    mes->pos = s->pos;
706   break;
707
708  case ROAR_STREAM_PARA_NAME:
709   str = streams_get_name(mes->stream);
710
711   if ( str == NULL )
712    return -1;
713
714    mes->datalen = 4 + strlen(str);
715
716    if ( mes->datalen > LIBROAR_BUFFER_MSGDATA )
717     return -1;
718
719    strncpy(((char*)&(mes->data))+4, str, mes->datalen);
720
721    d[0] = ROAR_HOST2NET16(d[0]);
722    d[1] = ROAR_HOST2NET16(d[1]);
723   break;
724
725  case ROAR_STREAM_PARA_CHANMAP:
726    if ( streams_get(mes->stream, &ss) == -1 ) {
727     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
728     return -1;
729    }
730
731    s = ROAR_STREAM(ss);
732
733    memcpy(&(mes->data[4]), ss->chanmap.in, s->info.channels);
734    mes->datalen = 2*2 + s->info.channels;
735
736    d[0] = ROAR_HOST2NET16(d[0]);
737    d[1] = ROAR_HOST2NET16(d[1]);
738   break;
739
740  default:
741    ROAR_WARN("req_on_get_stream_para(*): unsupported command: %i", d[1]);
742    return -1;
743 }
744
745 mes->cmd = ROAR_CMD_OK;
746 return 0;
747}
748
749int req_on_set_stream_para (int client, struct roar_message * mes, char * data) {
750 uint16_t * d = (uint16_t *) mes->data;
751 int i;
752
753 if ( mes->datalen < 2*2 )
754  return -1;
755
756 for (i = 0; i < 2; i++) {
757  d[i] = ROAR_NET2HOST16(d[i]);
758 }
759
760 if ( d[0] != 0 )
761  return -1;
762
763 switch (d[1]) {
764  case ROAR_STREAM_PARA_FLAGS:
765    if ( mes->datalen != 2*4 )
766     return -1;
767
768    d[2] = ROAR_NET2HOST16(d[2]);
769    d[3] = ROAR_NET2HOST16(d[3]);
770
771    ROAR_DBG("req_on_set_stream_para(*): request seems to be valid");
772
773    if ( d[2] == ROAR_RESET_FLAG ) {
774     if ( streams_reset_flag(mes->stream, d[3]) == -1 )
775      return -1;
776    } else {
777     if ( streams_set_flag(mes->stream, d[3]) == -1 )
778      return -1;
779    }
780   break;
781  case ROAR_STREAM_PARA_CHANMAP:
782    if ( streams_set_map(mes->stream, &(mes->data[4]), mes->datalen - 4) == -1 )
783     return -1;
784   break;
785  case ROAR_STREAM_PARA_ROLE:
786    if ( mes->datalen != 2*3 )
787     return -1;
788
789    d[2] = ROAR_NET2HOST16(d[2]);
790
791    if ( streams_set_role(mes->stream, d[2]) == -1 )
792     return -1;
793   break;
794  default:
795    ROAR_WARN("req_on_set_stream_para(*): unsupported command version: %i, %i", d[0], d[1]);
796    return -1;
797   break;
798 }
799
800 mes->cmd     = ROAR_CMD_OK;
801 mes->datalen = 0;
802
803 return 0;
804}
805
806int req_on_kick (int client, struct roar_message * mes, char * data) {
807 uint16_t * info = (uint16_t *) mes->data;
808
809 if ( mes->datalen != 4 )
810  return -1;
811
812 info[0] = ROAR_NET2HOST16(info[0]);
813 info[1] = ROAR_NET2HOST16(info[1]);
814
815 if ( info[0] == ROAR_OT_CLIENT ) {
816  clients_delete(info[1]);
817 } else if ( info[0] == ROAR_OT_STREAM ) {
818  if ( streams_get_flag(info[1], ROAR_FLAG_IMMUTABLE) == 1 )
819   return -1;
820
821  streams_delete(info[1]);
822 } else if ( info[0] == ROAR_OT_SOURCE ) {
823  if ( streams_get_flag(info[1], ROAR_FLAG_IMMUTABLE) == 1 )
824   return -1;
825
826  if ( streams_get_flag(info[1], ROAR_FLAG_SOURCE) == 1 ) {
827   streams_delete(info[1]);
828  } else {
829   return -1;
830  }
831 } else {
832  return -1;
833 }
834
835 mes->cmd     = ROAR_CMD_OK;
836 mes->datalen = 0;
837
838 return 0;
839}
840
841int req_on_attach      (int client, struct roar_message * mes, char * data) {
842 uint16_t * info = (uint16_t *) mes->data;
843
844 if ( mes->datalen < 6 )
845  return -1;
846
847 info[0] = ROAR_NET2HOST16(info[0]);
848 info[1] = ROAR_NET2HOST16(info[1]);
849 info[2] = ROAR_NET2HOST16(info[2]);
850
851 if ( info[0] != 0 )
852  return -1;
853
854 if ( info[1] == ROAR_ATTACH_SIMPLE ) {
855  if ( client_stream_move(info[2], mes->stream) == -1 )
856   return -1;
857 } else {
858  return -1;
859 }
860
861 mes->cmd     = ROAR_CMD_OK;
862 mes->datalen = 0;
863
864 return 0;
865}
866
867int req_on_set_vol (int client, struct roar_message * mes, char * data) {
868 struct roar_stream_server * s;
869 uint16_t * info = (uint16_t *) mes->data;
870 uint16_t   version;
871 uint16_t   scale = 65535;
872 int stream;
873 int i;
874 int chans;
875
876 ROAR_DBG("req_on_set_vol(*) = ?");
877 ROAR_DBG("req_on_set_vol(*): mes->datalen=%i", mes->datalen);
878
879 if ( mes->datalen < (4*2) )
880  return -1;
881
882 version = ROAR_NET2HOST16(info[0]);
883 ROAR_DBG("req_on_set_vol(*): version=%i", (int)version);
884
885 switch (version) {
886  case 0:
887    stream = ROAR_NET2HOST16(info[1]);
888   break;
889  case 1:
890    stream = mes->stream;
891    scale  = ROAR_NET2HOST16(info[1]);
892   break;
893  default:
894    return -1;
895   break;
896 }
897 ROAR_DBG("req_on_set_vol(*): stream=%i", stream);
898
899 if ( scale == 0 )
900  return -1;
901
902 // TODO: change this code.
903 //       we should not directly change the stream object but use some stream_*()-func
904 //       for that job.
905
906 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
907  return -1;
908
909 s = g_streams[stream];
910
911 if ( s == NULL )
912  return -1;
913
914 ROAR_DBG("req_on_set_vol(*): s=%p", s);
915
916 info[2] = ROAR_NET2HOST16(info[2]);
917
918 if ( info[2] == ROAR_SET_VOL_ALL ) {
919  chans = (mes->datalen/2) - 3;
920  ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ALL, channes=%i", chans);
921
922  if ( chans >= ROAR_MAX_CHANNELS )
923   return -1;
924
925  ROAR_DBG("req_on_set_vol(*): mixer at %p", s->mixer.mixer);
926
927  for (i = 0; i < chans; i++) {
928   s->mixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
929   ROAR_DBG("req_on_set_vol(*): channel %i: %i", i, ROAR_NET2HOST16(info[i+3]));
930  }
931
932  s->mixer.scale = scale;
933
934  ROAR_DBG("req_on_set_vol(*): mixer changed!");
935
936 } else if ( info[2] == ROAR_SET_VOL_ONE ) {
937  ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ONE");
938  if ( ROAR_NET2HOST16(info[3]) >= ROAR_MAX_CHANNELS )
939   return -1;
940
941  s->mixer.mixer[ROAR_NET2HOST16(info[3])] = ROAR_NET2HOST16(info[4]);
942
943  s->mixer.scale = scale;
944 } else {
945  return -1;
946 }
947
948 if ( streams_set_mixer(stream) == -1 )
949  return -1;
950
951 mes->cmd     = ROAR_CMD_OK;
952 mes->datalen = 0;
953
954 return 0;
955}
956
957int req_on_get_vol (int client, struct roar_message * mes, char * data) {
958 uint16_t * info = (uint16_t *) mes->data;
959 uint16_t   version = -1;
960 int stream;
961 struct roar_stream_server * s;
962 int i;
963 int chans;
964
965 ROAR_DBG("req_on_get_vol(*) = ?");
966 ROAR_DBG("req_on_get_vol(*): mes->datalen=%i", mes->datalen);
967
968 if ( mes->datalen < 2 ) {
969  return -1;
970 }
971
972 version = ROAR_NET2HOST16(info[0]);
973
974 switch (version) {
975  case 0:
976    if ( mes->datalen < (2*2) )
977     return -1;
978
979    stream = ROAR_NET2HOST16(info[1]);
980   break;
981  case 1:
982    stream = mes->stream;
983   break;
984  default:
985    return -1;
986   break;
987 }
988
989 ROAR_DBG("req_on_get_vol(*): stream=%i", stream);
990
991 // TODO: change this code.
992 //       we should not directly change the stream object but use some stream_*()-func
993 //       for that job.
994
995 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
996  return -1;
997
998 s = g_streams[stream];
999
1000 if ( s == NULL )
1001  return -1;
1002
1003 ROAR_DBG("req_on_get_vol(*): s=%p", s);
1004
1005 // ok, we have everything
1006
1007 info[0] = ROAR_HOST2NET16(version);
1008
1009 switch (version) {
1010  case 0:
1011    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1012
1013    for (i = 0; i < chans; i++)
1014     info[2+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1015
1016     mes->datalen = (2 + chans)*2;
1017   break;
1018  case 1:
1019    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1020    info[2] = ROAR_HOST2NET16(s->mixer.scale);
1021    info[3] = ROAR_HOST2NET16(s->mixer.rpg_mul);
1022    info[4] = ROAR_HOST2NET16(s->mixer.rpg_div);
1023
1024    for (i = 0; i < chans; i++)
1025     info[5+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1026
1027     mes->datalen = (5 + chans)*2;
1028   break;
1029  default:
1030    return -1;
1031   break;
1032 }
1033
1034 mes->cmd = ROAR_CMD_OK;
1035
1036 return 0;
1037}
1038
1039int req_on_add_data (int client, struct roar_message * mes, char * data) {
1040 struct roar_buffer * b;
1041 char               * buf;
1042
1043 if ( roar_buffer_new(&b, mes->datalen) == -1 ) {
1044  ROAR_ERR("req_on_add_data(*): Can not alloc buffer space!");
1045  ROAR_DBG("req_on_add_data(*) = -1");
1046  return -1;
1047 }
1048
1049 roar_buffer_get_data(b, (void **)&buf);
1050
1051 if ( data == NULL ) {
1052  memcpy(buf, mes->data, mes->datalen);
1053 } else {
1054  memcpy(buf, data, mes->datalen);
1055 }
1056
1057 if ( stream_add_buffer(mes->stream, b) == -1 ) {
1058  roar_buffer_free(b);
1059  return -1;
1060 }
1061
1062 mes->cmd     = ROAR_CMD_OK_STOP;
1063 mes->datalen = 0;
1064
1065 return 0;
1066}
1067
1068int req_on_beep        (int client, struct roar_message * mes, char * data) {
1069 struct roar_beep bs;
1070 int16_t * info = (int16_t*)mes->data;
1071 int stream;
1072
1073 memset(&bs, 0, sizeof(bs));
1074
1075 if ( mes->datalen > 0 ) {
1076  if ( mes->datalen < 2 )
1077   return -1;
1078
1079  if ( ROAR_NET2HOST16(info[0]) != 0 ) /* version */
1080   return -1;
1081
1082  if ( mes->datalen != 8*2 )
1083   return -1;
1084
1085  bs.vol  = ROAR_NET2HOST16(info[1]);
1086  bs.time = ROAR_NET2HOST16(info[2]);
1087  bs.freq = ROAR_NET2HOST16(info[3]);
1088  bs.type = ROAR_NET2HOST16(info[4]);
1089  bs.x    = ROAR_NET2HOST16(info[5]);
1090  bs.y    = ROAR_NET2HOST16(info[6]);
1091  bs.z    = ROAR_NET2HOST16(info[7]);
1092 }
1093
1094 if ( (stream = beep_start(client, &bs)) == -1 )
1095  return -1;
1096
1097 mes->stream  = stream;
1098 mes->cmd     = ROAR_CMD_OK_STOP;
1099 mes->datalen = 0;
1100
1101 return 0;
1102}
1103
1104//ll
Note: See TracBrowser for help on using the repository browser.