source: roaraudio/roard/req.c @ 3802:958585351e28

Last change on this file since 3802:958585351e28 was 3802:958585351e28, checked in by phi, 14 years ago

converted listen socket handling mostly to VIOs

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