source: roaraudio/roard/req.c @ 4442:2d3a1ad3edcc

Last change on this file since 4442:2d3a1ad3edcc was 4442:2d3a1ad3edcc, checked in by phi, 13 years ago

make config default string symbolic, do not use it for server_info.

File size: 35.2 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
28// include for uname() used by req_on_server_info()
29#ifdef ROAR_HAVE_UNAME
30#include <sys/utsname.h>
31#endif
32
33static void * _dataspace(struct roar_message * mes, char ** data, uint32_t flags[2], size_t len) {
34 if ( len <= LIBROAR_BUFFER_MSGDATA )
35  return mes->data;
36
37 if ( *data != NULL )
38  free(*data);
39
40 *data = malloc(len);
41
42 ROAR_DBG("_dataspace(mes=%p, data=%p, flags=%p, len=%llu): *data=%p", mes, data, flags, (long long unsigned int)len, *data);
43
44 if ( *data == NULL )
45  return NULL;
46
47 flags[1] |= COMMAND_FLAG_OUT_LONGDATA;
48
49 return *data;
50}
51
52int req_on_noop        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
53 mes->cmd     = ROAR_CMD_OK;
54 mes->pos     = g_pos;
55 mes->datalen = 0;
56 return 0;
57}
58
59int req_on_identify    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
60 struct roar_client * c;
61 int max_len;
62
63 if ( mes->datalen < 1 )
64  return -1;
65
66 clients_get(client, &c);
67
68 if ( mes->data[0] == 1 ) {
69  if ( c->pid == -1 ) {
70   c->pid       = ROAR_NET2HOST32(*(uint32_t*)((mes->data)+1));
71   ROAR_DBG("req_on_identify(): new PID: c->pid = %i", c->pid);
72  }
73
74  ROAR_DBG("req_on_identify(): final PID: c->pid = %i", c->pid);
75
76  max_len = (mes->datalen - 5) < (ROAR_BUFFER_NAME-1) ? (mes->datalen - 5) : (ROAR_BUFFER_NAME-1);
77
78  strncpy(c->name, mes->data + 5, max_len);
79  c->name[max_len] = 0;
80
81  mes->cmd     = ROAR_CMD_OK;
82  mes->pos     = g_pos;
83  mes->datalen = 0;
84
85  ROAR_DBG("req_on_identify(*): client=%i, pid=%i", client, c->pid);
86  ROAR_DBG("req_on_identify(*) = 0");
87  return 0;
88 }
89
90 return -1;
91}
92
93int req_on_auth        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
94 // TODO: add code to support some auth.
95 mes->cmd     = ROAR_CMD_OK;
96 mes->pos     = g_pos;
97 mes->datalen = 0;
98 return 0;
99}
100
101
102int req_on_whoami      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
103 mes->cmd     = ROAR_CMD_OK;
104 mes->pos     = g_pos;
105 mes->datalen = 1;
106 mes->data[0] = client;
107 return 0;
108}
109
110
111int req_on_new_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
112 int stream;
113 struct roar_stream * s;
114 struct roar_stream * source_stream;
115 struct roar_audio_info * info;
116 struct roar_audio_info * source_info;
117
118 ROAR_DBG("req_on_new_stream(client=%i, ...): creating stream...", client);
119 if ((stream = streams_new()) == -1 )
120  return -1;
121
122 ROAR_DBG("req_on_new_stream(client=%i, ...): stream=%i", client, stream);
123
124 ROAR_DBG("req_on_new_stream(client=%i, ...): getting stream...", client);
125 if ( streams_get(stream, (struct roar_stream_server **)&s) == -1 ) {
126  streams_delete(stream);
127  return -1;
128 }
129
130 ROAR_DBG("req_on_new_stream(client=%i, ...): set client of stream...", client);
131 if ( client_stream_add(client, stream) == -1 ) {
132  streams_delete(stream);
133  return -1;
134 }
135
136 ROAR_DBG("req_on_new_stream(client=%i, ...): loading stream from message...", client);
137 if ( roar_stream_m2s(s, mes) == -1 ) {
138  streams_delete(stream);
139  return -1;
140 }
141
142 ROAR_DBG("req_on_new_stream(client=%i, ...): setting id and codec of stream...", client);
143 ROAR_STREAM(s)->id = stream; // roar_stream_m2s() resets this
144 ROAR_STREAM_SERVER(s)->codec_orgi = ROAR_STREAM(s)->info.codec;
145
146 ROAR_DBG("req_on_new_stream(client=%i, ...): setting direction stream...", client);
147 // int streams_set_dir    (int id, int dir, int defaults)
148 if ( streams_set_dir(stream, ROAR_STREAM(s)->dir, 1) == -1 ) {
149  streams_delete(stream);
150  return -1;
151 }
152
153 ROAR_DBG("req_on_new_stream(client=%i, ...): setting up direction specific stream settings...", client);
154 switch (ROAR_STREAM(s)->dir) {
155  case ROAR_DIR_LIGHT_IN:
156  case ROAR_DIR_LIGHT_OUT:
157#ifndef ROAR_WITHOUT_DCOMP_LIGHT
158    info = &(ROAR_STREAM(s)->info);
159
160    info->channels = 0;
161    info->bits     = 0;
162    info->rate     = 0;
163#else
164    streams_delete(stream);
165    return -1;
166#endif
167
168   break;
169  case ROAR_DIR_MIDI_IN:
170  case ROAR_DIR_MIDI_OUT:
171#ifndef ROAR_WITHOUT_DCOMP_MIDI
172    info = &(ROAR_STREAM(s)->info);
173
174    info->channels = ROAR_MIDI_CHANNELS_DEFAULT;
175    info->bits     = ROAR_MIDI_BITS;
176    info->rate     = 0;
177#else
178    streams_delete(stream);
179    return -1;
180#endif
181
182   break;
183
184  case ROAR_DIR_RAW_IN:
185#ifndef ROAR_WITHOUT_DCOMP_RAW
186    if ( ROAR_STREAM(s)->pos_rel_id == -1     ||
187         ROAR_STREAM(s)->pos_rel_id == stream ||
188         streams_get_dir(ROAR_STREAM(s)->pos_rel_id) != ROAR_DIR_RAW_OUT
189       ) {
190     ROAR_STREAM(s)->pos_rel_id = -1; // force this here as it will try to delete itself while deleting
191                                      // in case rel_id == stream
192     streams_delete(stream);
193     return -1;
194    }
195#else
196  case ROAR_DIR_RAW_OUT:
197    streams_delete(stream);
198    return -1;
199#endif
200
201   break;
202  case ROAR_DIR_THRU:
203
204    if ( ROAR_STREAM(s)->pos_rel_id == -1 || ROAR_STREAM(s)->pos_rel_id == stream ) {
205     ROAR_STREAM(s)->pos_rel_id = -1; // force this here as it will try to delete itself while deleting
206                                      // in case rel_id == stream
207     streams_delete(stream);
208     return -1;
209    }
210
211    if ( streams_get(ROAR_STREAM(s)->pos_rel_id, (struct roar_stream_server **)&source_stream) == -1 ) {
212     streams_delete(stream);
213     return -1;
214    }
215
216    info        = &(ROAR_STREAM(s)->info);
217    source_info = &(ROAR_STREAM(source_stream)->info);
218
219    info->channels = source_info->channels;
220    info->bits     = source_info->bits;
221    info->rate     = source_info->rate;
222    info->codec    = source_info->codec;
223    ROAR_STREAM_SERVER(s)->codec_orgi = ROAR_STREAM_SERVER(source_stream)->codec_orgi;
224
225   break;
226  case ROAR_DIR_FILTER:
227    info        = &(ROAR_STREAM(s)->info);
228
229    if ( ROAR_STREAM(s)->pos_rel_id == -1 ) {
230     source_info = g_sa;
231    } else {
232     if ( streams_get(ROAR_STREAM(s)->pos_rel_id, (struct roar_stream_server **)&source_stream) == -1 ) {
233      streams_delete(stream);
234      return -1;
235     }
236     source_info = &(ROAR_STREAM(source_stream)->info);
237    }
238
239    if ( info->channels != source_info->channels || info->bits != source_info->bits ||
240         info->codec    != source_info->codec    || info->rate != source_info->rate ) {
241     // the stream parameters don't match the one of the stream being filtered.
242     // -> delete and reject the stream.
243     streams_delete(stream);
244     return -1;
245    }
246   break;
247 }
248
249 ROAR_DBG("req_on_new_stream(client=%i, ...): returning (OK, stream=%i)...", client, stream);
250
251 mes->cmd     = ROAR_CMD_OK;
252 mes->stream  = stream;
253 mes->datalen = 0;
254
255 return 0;
256}
257
258int req_on_exec_stream (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
259 int r;
260
261 ROAR_DBG("req_on_exec_stream(client=%i, mes={stream=%i,...},...): execing stream", client, mes->stream);
262
263
264 if ( streams_is_ready(mes->stream) ) {
265  flags[1] |= COMMAND_FLAG_OUT_CLOSECON;
266 } else {
267  if ( (r = client_stream_exec(client, mes->stream)) == -1 )
268   return -1;
269 }
270
271 ROAR_DBG("req_on_exec_stream(client=%i, mes={stream=%i,...},...): returning (OK)...", client, mes->stream);
272 mes->cmd     = ROAR_CMD_OK;
273 mes->datalen = 0;
274
275 return 0;
276}
277
278int req_on_con_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
279 char   host[80] = {0};
280 int    port = 0;
281 int    type;
282 int    fh;
283 int    len;
284
285 if ( mes->datalen < 4 )
286  return -1;
287
288 if ( *(mes->data) != 0 )
289  return -1;
290
291 if ( mes->datalen > 80 ) // we do not support long messages here
292  return -1;
293
294 type = (unsigned)mes->data[1];
295 port = ROAR_NET2HOST16(((uint16_t*)mes->data)[1]);
296
297 len = mes->datalen - 4;
298
299 strncpy(host, &(mes->data[4]), len);
300 host[len] = 0;
301
302 if ( type > ROAR_SOCKET_TYPE_MAX )
303  return -1;
304
305 if ( type == ROAR_SOCKET_TYPE_FILE ) // disabled because of security resons
306  return -1;
307
308 if ( type == ROAR_SOCKET_TYPE_FORK ) // why should we connect to ourself?
309  return -1;
310
311 ROAR_DBG("req_on_con_stream(*): CONNECT(type=%i, host='%s', port=%i)", type, host, port);
312
313 if ( (fh = roar_socket_open(ROAR_SOCKET_MODE_CONNECT, type, host, port)) == -1 )
314  return -1;
315
316 if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
317  close(fh);
318  return 1;
319 }
320
321 mes->datalen = 0;
322 mes->cmd     = ROAR_CMD_OK;
323
324 return 0;
325}
326
327int req_on_passfh      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
328 int sock = clients_get_fh(client);
329 int16_t * d = (int16_t*)mes->data;
330 struct roard_listen * lsock;
331 int listening;
332 int fh;
333 int i;
334
335 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...) = ?", client, mes->stream);
336
337 if ( (fh = roar_socket_recv_fh(sock, NULL, NULL)) == -1 ) {
338  ROAR_WARN("req_on_passfh(client=%i, mes={stream=%i,...},...): was unabled to get filehandle from remote end. bad.", client, mes->stream);
339  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (ERROR)...", client, mes->stream);
340  return -1;
341 }
342
343 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): fh=%i", client, mes->stream, fh);
344
345 if ( mes->stream != -1 ) { // stream pass:
346  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): This is a stream passfh", client, mes->stream);
347
348  if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
349   close(fh);
350   ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (ERROR)...", client, mes->stream);
351   return -1;
352  }
353
354  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (OK)...", client, mes->stream);
355
356  mes->datalen = 0;
357  mes->cmd     = ROAR_CMD_OK;
358
359  return 0;
360 }
361
362// non-stream pass:
363
364 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): This is a client passfh", client, mes->stream);
365
366/*
367 0: Version,   16
368 1: Flags,     16
369 2: Protocol,  16
370 3: Byteorder, 16
371 Options...
372*/
373
374 if ( mes->datalen < 4*2 )
375  return -1;
376
377 for (i = 0; i < 4; i++) {
378  d[i] = ROAR_NET2HOST16(d[i]);
379 }
380
381 if ( d[0] != 0 ) // version
382  return -1;
383
384 listening = d[1] & ROAR_CLIENTPASS_FLAG_LISTEN;
385
386 if ( listening )
387  d[1] -= ROAR_CLIENTPASS_FLAG_LISTEN;
388
389 if ( d[1] != 0 ) // flags
390  return -1;
391
392 if ( listening ) {
393  if ( get_listen(&lsock, NULL) == -1 ) {
394   close(fh);
395   return -1;
396  }
397
398  roar_vio_open_fh_socket(&(lsock->sock), fh);
399  lsock->used   = 1;
400  lsock->proto  = d[2];
401 } else {
402  if ( clients_new_from_fh(fh, d[2], d[3], 1) == -1 )
403   return -1;
404 }
405
406 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (OK)...", client, mes->stream);
407
408 mes->datalen = 0;
409 mes->cmd     = ROAR_CMD_OK;
410
411 return 0;
412}
413
414#ifdef ROAR_SUPPORT_META
415int req_on_set_meta    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
416 int type;
417 int mode;
418 int namelen, vallen;
419 char   val[255+1];
420 char   name[ROAR_META_MAX_NAMELEN+1];
421
422 if ( mes->datalen < 3 )
423  return -1;
424
425 if ( mes->data[0] != 0 ) // version
426  return -1;
427
428 mode = (unsigned) mes->data[1];
429 type = (unsigned) mes->data[2];
430
431 ROAR_DBG("req_on_set_meta(*): mode=%i, type=%i", mode, type);
432
433 if ( mode == ROAR_META_MODE_CLEAR ) {
434  stream_meta_clear(mes->stream);
435  mes->datalen = 0;
436  mes->cmd     = ROAR_CMD_OK;
437  return 0;
438 } else if ( mode == ROAR_META_MODE_DELETE ) { // unsuppoerted at the moment
439  return -1;
440 } else if ( mode == ROAR_META_MODE_FINALIZE ) {
441  stream_meta_finalize(mes->stream);
442  mes->datalen = 0;
443  mes->cmd     = ROAR_CMD_OK;
444  return 0;
445 } else if ( mode == ROAR_META_MODE_SET || mode == ROAR_META_MODE_ADD ) {
446  if ( mes->datalen < 5 )
447   return -1;
448
449  namelen = (unsigned) mes->data[3];
450  vallen  = (unsigned) mes->data[4];
451
452  ROAR_DBG("req_on_set_meta(*): namelen=%i, vallen=%i", namelen, vallen);
453
454  if ( mes->datalen < (5 + namelen + vallen) )
455   return -1;
456
457  if ( namelen > ROAR_META_MAX_NAMELEN )
458   return -1;
459
460  strncpy(name, &(mes->data[5]), namelen);
461  name[namelen] = 0;
462
463  if ( vallen > 255 )
464   return -1;
465
466  strncpy(val, &(mes->data[5+namelen]), vallen);
467  val[vallen] = 0;
468
469  if ( mode == ROAR_META_MODE_SET ) {
470   if ( stream_meta_set(mes->stream, type, name, val) == -1 )
471    return -1;
472  } else {
473   if ( stream_meta_add(mes->stream, type, name, val) == -1 )
474    return -1;
475  }
476
477  mes->datalen = 0;
478  mes->cmd     = ROAR_CMD_OK;
479  return 0;
480 } else { // unknown mode!
481  return -1;
482 }
483
484 return -1;
485}
486
487int req_on_get_meta    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
488 int vallen;
489 int type;
490 char val[LIBROAR_BUFFER_MSGDATA-1];
491
492 if ( mes->datalen != 2 )
493  return -1;
494
495 if ( mes->data[0] != 0 ) // version
496  return -1;
497
498 type = (unsigned) mes->data[1];
499
500 if ( stream_meta_get(mes->stream, type, NULL, val, LIBROAR_BUFFER_MSGDATA-2) == -1 )
501  return -1;
502
503 vallen = strlen(val);
504
505 mes->cmd     = ROAR_CMD_OK;
506 mes->datalen = 2 + vallen;
507
508 mes->data[0] = 0;
509 mes->data[1] = (unsigned char) vallen;
510
511 val[vallen] = 0;
512
513 strncpy(&(mes->data[2]), val, vallen+1);
514
515 return 0;
516}
517
518int req_on_list_meta   (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
519 int i;
520 int len = 0;
521 int types[ROAR_META_MAX_PER_STREAM];
522
523 if ( mes->datalen != 1 )
524  return -1;
525
526 if ( mes->data[0] != 0 ) // version
527  return -1;
528
529 if ( (len = stream_meta_list(mes->stream, types, ROAR_META_MAX_PER_STREAM)) == -1 )
530  return -1;
531
532 mes->cmd     = ROAR_CMD_OK;
533 mes->datalen = 1 + len;
534 mes->data[0] = 0;
535
536 for (i = 0; i < len; i++)
537  mes->data[i+1] = types[i];
538
539 return 0;
540}
541#endif
542
543int req_on_server_info (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
544#ifdef ROAR_HAVE_UNAME
545 struct utsname utsname;
546#endif
547 struct roar_server_info info;
548 uint16_t * d16;
549
550 if ( mes->datalen != 4 )
551  return -1;
552
553 d16 = (uint16_t*)mes->data;
554
555 // check version.
556 if ( ROAR_NET2HOST16(d16[0]) != 0 )
557  return -1;
558
559 switch (ROAR_NET2HOST16(d16[1])) {
560  case ROAR_IT_SERVER:
561   memset(&info, 0, sizeof(info));
562
563   info.version = "roard/" PACKAGE_VERSION " <" DEVICE_VENDOR_STRING ">";
564
565   if ( !!strcmp(g_config->location, CONF_DEF_STRING) )
566    info.location = g_config->location;
567
568   if ( !!strcmp(g_config->description, CONF_DEF_STRING) )
569   info.description = g_config->description;
570
571#ifdef ROAR_HAVE_UNAME
572   if ( uname(&utsname) == 0 ) {
573    info.un.sysname  = utsname.sysname;
574    info.un.release  = utsname.release;
575    info.un.nodename = utsname.nodename;
576    info.un.machine  = utsname.machine;
577   }
578#endif
579
580   *data = NULL;
581
582   if ( roar_server_info_to_mes(mes, &info, data) == -1 )
583    return -1;
584
585   if ( *data != NULL )
586    flags[1] |= COMMAND_FLAG_OUT_LONGDATA;
587  break;
588  default: /* unknown request */
589    return -1;
590   break;
591 }
592
593 mes->cmd = ROAR_CMD_OK;
594
595 return 0;
596}
597
598int req_on_server_oinfo    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
599 struct roar_stream s;
600//ROAR_DIR_OUTPUT
601
602 memset(&s, 0, sizeof(struct roar_stream));
603
604 s.dir           = ROAR_DIR_MIXING;
605 s.pos_rel_id    = -1;
606 s.info.rate     = g_sa->rate;
607 s.info.bits     = g_sa->bits;
608 s.info.channels = g_sa->channels;
609 s.info.codec    = g_sa->codec;
610 s.pos           = g_pos;
611
612 if ( roar_stream_s2m(&s, mes) == -1 )
613  return -1;
614
615 mes->cmd = ROAR_CMD_OK;
616
617 return 0;
618}
619
620
621int req_on_get_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
622 mes->cmd     = ROAR_CMD_OK;
623 mes->pos     = g_pos;
624 mes->datalen = 2;
625
626 *((uint16_t*)mes->data) = ROAR_HOST2NET16((unsigned) g_standby);
627
628 return 0;
629}
630
631int req_on_set_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
632 if ( mes->datalen != 2 )
633  return -1;
634
635 g_standby = ROAR_NET2HOST16(*((uint16_t*)mes->data));
636
637 mes->cmd     = ROAR_CMD_OK;
638 mes->pos     = g_pos;
639 mes->datalen = 0;
640
641 return 0;
642}
643
644int req_on_exit      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
645 int term = 0;
646
647 if ( mes->datalen == 1 )
648  term = mes->data[0];
649
650 mes->cmd     = ROAR_CMD_OK;
651 mes->pos     = g_pos;
652 mes->datalen = 0;
653
654 ROAR_DBG("req_on_exit(*): term=%i", term);
655
656 if ( term ) {
657  cleanup_listen_socket(1);
658 } else {
659  alive = 0;
660 }
661
662 return 0;
663}
664
665int req_on_list_clients(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
666 unsigned char filter, cmp;
667 uint32_t id;
668 int clients[ROAR_CLIENTS_MAX];
669 int i, c = 0;
670
671 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
672  return -1;
673
674 // TODO: add code to support filter
675 if ( filter != ROAR_CTL_FILTER_ANY )
676  return -1;
677
678 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
679  if ( g_clients[i] != NULL ) {
680   clients[c++] = i;
681  }
682 }
683
684 roar_ctl_ia2m(mes, clients, c);
685
686 mes->cmd = ROAR_CMD_OK;
687
688 return 0;
689}
690int req_on_list_streams(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
691 unsigned char filter, cmp;
692 uint32_t id;
693 int streams[ROAR_STREAMS_MAX];
694 int i, c = 0;
695 int match;
696
697 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
698  return -1;
699
700 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
701  if ( g_streams[i] == NULL )
702   continue;
703
704  match = 0;
705
706  switch (filter) {
707   case ROAR_CTL_FILTER_ANY:
708     match = 1;
709    break;
710   case ROAR_CTL_FILTER_DIR:
711     match = roar_filter_match(cmp, id, ROAR_STREAM(g_streams[i])->dir);
712    break;
713   default: // unsupported filter...
714     return -1;
715    break;
716  }
717
718  if ( match )
719   streams[c++] = i;
720 }
721
722 roar_ctl_ia2m(mes, streams, c);
723
724 mes->cmd = ROAR_CMD_OK;
725
726 return 0;
727}
728
729int req_on_get_client  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
730 struct roar_client * c;
731
732 if ( mes->datalen != 1 )
733  return -1;
734
735 if ( clients_get(mes->data[0], &c) == -1 )
736  return -1;
737
738 mes->cmd = ROAR_CMD_OK;
739
740 return roar_ctl_c2m(mes, c);
741}
742
743int req_on_get_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
744 struct roar_stream_server * s;
745
746 if ( mes->datalen != 1 )
747  return -1;
748
749 if ( streams_get(mes->data[0], &s) == -1 )
750  return -1;
751
752 mes->cmd = ROAR_CMD_OK;
753 mes->stream = mes->data[0];
754
755 return roar_stream_s2m(ROAR_STREAM(s), mes);
756}
757
758int req_on_get_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
759 struct roar_stream * s;
760 struct roar_stream_server * ss;
761 struct roar_audio_info * audio_info;
762 struct roar_stream_ltm * ltm;
763 uint16_t * d  = (uint16_t *) mes->data;
764 int64_t * d64 = ( int64_t *) mes->data;
765 int64_t * d64ptr;
766 int i, h, k;
767 char * str;
768 size_t needed;
769 int test, bits;
770
771 ROAR_DBG("req_on_get_stream_para(client=%i, mes=%p{.stream=%i, .datalen=%i,...}, data=%p, flags=%p) = ?", client, mes, (int)mes->stream, (int)mes->datalen, data, flags);
772
773 if ( mes->datalen < 4 )
774  return -1;
775
776 for (i = 0; i < 2; i++) {
777  d[i] = ROAR_NET2HOST16(d[i]);
778 }
779
780 if ( d[0] != 0 ) {
781  ROAR_WARN("req_on_get_stream_para(*): unsupported command version: %i, %i", (int)d[0], (int)d[1]);
782  return -1;
783 }
784
785 switch (d[1]) {
786  case ROAR_STREAM_PARA_INFO:
787    if ( streams_get(mes->stream, &ss) == -1 ) {
788     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
789     return -1;
790    }
791
792    if ( streams_calc_delay(mes->stream) == -1 ) {
793     ROAR_WARN("req_on_get_stream_para(*): can not calc delay for stream %i", mes->stream);
794    }
795
796    s = ROAR_STREAM(ss);
797
798    audio_info = &(s->info);
799
800    mes->datalen = 2*12;
801
802    d[ 2] = ROAR_OUTPUT_CALC_OUTBUFSIZE(audio_info);
803    d[ 3] = ss->pre_underruns;
804    d[ 4] = ss->post_underruns;
805    d[ 5] = ss->codec_orgi;
806    d[ 6] = (ss->flags & 0xFFFF) | (ss->primary ? ROAR_FLAG_PRIMARY : 0) | (ss->driver_id != -1 ? ROAR_FLAG_OUTPUT : 0);
807    d[ 7] = ss->delay/1000;
808    d[ 8] = ss->state;
809    d[ 9] = (ss->flags & 0xFFFF0000) >> 16;
810    d[10] = ss->mixer_stream;
811    d[11] = ss->role;
812
813    ROAR_DBG("req_on_get_stream_para(*): ss->driver_id=%i", ss->driver_id);
814
815    ROAR_DBG("req_on_get_stream_para(*): delay=%i, send delay=%i", ss->delay, d[7]);
816
817    for (i = 0; i < mes->datalen/2; i++) {
818     d[i] = ROAR_HOST2NET16(d[i]);
819    }
820
821    mes->pos = s->pos;
822   break;
823
824  case ROAR_STREAM_PARA_NAME:
825   str = streams_get_name(mes->stream);
826
827   if ( str == NULL )
828    return -1;
829
830    mes->datalen = 4 + strlen(str);
831
832    if ( mes->datalen > LIBROAR_BUFFER_MSGDATA )
833     return -1;
834
835    strncpy(((char*)&(mes->data))+4, str, mes->datalen);
836
837    d[0] = ROAR_HOST2NET16(d[0]);
838    d[1] = ROAR_HOST2NET16(d[1]);
839   break;
840
841  case ROAR_STREAM_PARA_CHANMAP:
842    if ( streams_get(mes->stream, &ss) == -1 ) {
843     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
844     return -1;
845    }
846
847    s = ROAR_STREAM(ss);
848
849    memcpy(&(mes->data[4]), ss->chanmap.in, s->info.channels);
850    mes->datalen = 2*2 + s->info.channels;
851
852    d[0] = ROAR_HOST2NET16(d[0]);
853    d[1] = ROAR_HOST2NET16(d[1]);
854   break;
855
856  case ROAR_STREAM_PARA_LTM:
857    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request...", client);
858
859    if ( mes->datalen < (6 * 2) ) {
860     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: message too short", client);
861     return -1;
862    }
863
864    for (i = 2; i < mes->datalen/2; i++) {
865     d[i] = ROAR_NET2HOST16(d[i]);
866    }
867
868    if ( d[2] != ROAR_LTM_SST_GET_RAW ) {
869     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: unknown LTM subtype: %i", client, (int)d[2]);
870     return -1;
871    }
872
873    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request of type GET_RAW", client);
874
875    test = d[5];
876    bits = 0;
877    while (test) {
878     if ( test & 0x1 )
879      bits++;
880
881     test >>= 1;
882    }
883
884    needed = 0;
885
886    if ( mes->stream == -1 ) {
887     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM multi-stream request...", client);
888
889     for (i = 6; i < mes->datalen/2; i++) {
890      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
891       return -1;
892
893      needed += ltm->channels;
894     }
895    } else {
896     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM single-stream request for stream %i...", client, mes->stream);
897     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
898      return -1;
899
900     needed = ltm->channels;
901    }
902
903    needed *= bits;
904
905    needed += mes->stream == -1 ? (mes->datalen/2) - 6 : 1;
906
907    ROAR_DBG("req_on_get_stream_para(client=%i, ...): data size for answer is %i 64 bit sub-packets", client, (int)needed);
908
909    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
910    d64 = _dataspace(mes, data, flags, needed * 8);
911    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
912
913    if ( (d = roar_mm_malloc(mes->datalen)) == NULL )
914     return -1;
915
916    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d=%p, data=%p{%p}", client, d, data, *data);
917
918
919    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
920    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
921    memcpy(d, mes->data, mes->datalen);
922    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
923
924    d64ptr = d64;
925
926    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
927    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
928
929    if ( mes->stream == -1 ) {
930     for (i = 6; i < mes->datalen/2; i++) {
931      ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
932
933      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
934       return -1;
935
936      *d64ptr = ltm->channels & 0xFFFF;
937       d64ptr++;
938
939      for (h = 0; h < ltm->channels; h++) {
940       for (k = 0; k < ROAR_LTM_MTBITS; k++) {
941        if ( d[5] & (1<<k) ) {
942         switch (1<<k) {
943          case ROAR_LTM_MT_RMS:
944            *d64ptr = ltm->cur[h].rms;
945           break;
946          default:
947            ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
948         }
949         d64ptr++;
950        }
951       }
952      }
953     }
954    } else {
955     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
956      return -1;
957
958     *d64ptr = ltm->channels & 0xFFFF;
959      d64ptr++;
960
961     for (h = 0; h < ltm->channels; h++) {
962      for (k = 0; k < ROAR_LTM_MTBITS; k++) {
963       if ( d[5] & (1<<k) ) {
964        switch (1<<k) {
965         case ROAR_LTM_MT_RMS:
966           *d64ptr = ltm->cur[h].rms;
967           ROAR_DBG("req_on_get_stream_para(client=%i, ...): rms=%lli to %p", client, (long long int)*d64ptr, d64ptr);
968          break;
969         default:
970           ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
971        }
972        d64ptr++;
973       }
974      }
975     }
976    }
977
978    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
979
980    roar_mm_free(d);
981
982    for (i = 0; i < needed; i++) {
983     d64[i] = ROAR_HOST2NET64(d64[i]);
984    }
985
986    mes->datalen = needed * 8;
987    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM d64=%p, d64ptr=%p", client, d64, d64ptr);
988    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM final message has %i byte of data", client, (int)mes->datalen);
989    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
990    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM GET_RAW request: OK. returning...", client);
991   break;
992
993  default:
994    ROAR_WARN("req_on_get_stream_para(*): unsupported command: %i", d[1]);
995    return -1;
996 }
997
998 ROAR_DBG("req_on_get_stream_para(client=%i, mes=%p{.stream=%i, .datalen=%i,...}, data=%p, flags=%p) = 0 // returning OK", client, mes, (int)mes->stream, (int)mes->datalen, data, flags);
999 mes->cmd = ROAR_CMD_OK;
1000 return 0;
1001}
1002
1003int req_on_set_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1004 uint16_t * d = (uint16_t *) mes->data;
1005 int i;
1006
1007 if ( mes->datalen < 2*2 )
1008  return -1;
1009
1010 for (i = 0; i < 2; i++) {
1011  d[i] = ROAR_NET2HOST16(d[i]);
1012 }
1013
1014 if ( d[0] != 0 )
1015  return -1;
1016
1017 switch (d[1]) {
1018  case ROAR_STREAM_PARA_FLAGS:
1019    if ( mes->datalen != 2*4 )
1020     return -1;
1021
1022    d[2] = ROAR_NET2HOST16(d[2]);
1023    d[3] = ROAR_NET2HOST16(d[3]);
1024
1025    ROAR_DBG("req_on_set_stream_para(*): request seems to be valid");
1026
1027    if ( d[2] == ROAR_RESET_FLAG ) {
1028     if ( streams_reset_flag(mes->stream, d[3]) == -1 )
1029      return -1;
1030    } else {
1031     if ( streams_set_flag(mes->stream, d[3]) == -1 )
1032      return -1;
1033    }
1034   break;
1035  case ROAR_STREAM_PARA_CHANMAP:
1036    if ( streams_set_map(mes->stream, &(mes->data[4]), mes->datalen - 4) == -1 )
1037     return -1;
1038   break;
1039  case ROAR_STREAM_PARA_ROLE:
1040    if ( mes->datalen != 2*3 )
1041     return -1;
1042
1043    d[2] = ROAR_NET2HOST16(d[2]);
1044
1045    if ( streams_set_role(mes->stream, d[2]) == -1 )
1046     return -1;
1047   break;
1048  case ROAR_STREAM_PARA_LTM:
1049    if ( mes->datalen < (6 * 2) )
1050     return -1;
1051
1052    for (i = 2; i < mes->datalen/2; i++) {
1053     d[i] = ROAR_NET2HOST16(d[i]);
1054    }
1055
1056    if ( mes->stream == -1 ) {
1057     for (i = 6; i < mes->datalen/2; i++)
1058      if ( streams_ltm_ctl(d[i], d[5], d[3], d[2]) == -1 )
1059       return -1;
1060    } else {
1061     if ( streams_ltm_ctl(mes->stream, d[5], d[3], d[2]) == -1 )
1062      return -1;
1063    }
1064   break;
1065  default:
1066    ROAR_WARN("req_on_set_stream_para(*): unsupported command version: %i, %i", d[0], d[1]);
1067    return -1;
1068   break;
1069 }
1070
1071 mes->cmd     = ROAR_CMD_OK;
1072 mes->datalen = 0;
1073
1074 return 0;
1075}
1076
1077int req_on_kick (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1078 struct roar_stream_server * ss;
1079 uint16_t * info = (uint16_t *) mes->data;
1080 int is_stream = 0;
1081
1082 if ( mes->datalen != 4 )
1083  return -1;
1084
1085 info[0] = ROAR_NET2HOST16(info[0]);
1086 info[1] = ROAR_NET2HOST16(info[1]);
1087
1088 switch (info[0]) {
1089  case ROAR_OT_CLIENT:
1090    clients_delete(info[1]);
1091   break;
1092  case ROAR_OT_STREAM:
1093    is_stream = 1;
1094   break;
1095  case ROAR_OT_SOURCE:
1096    if ( streams_get_flag(info[1], ROAR_FLAG_SOURCE) != 1 )
1097     return -1;
1098    is_stream = 1;
1099   break;
1100  case ROAR_OT_OUTPUT:
1101    if ( streams_get(info[1], &ss) == -1 )
1102     return -1;
1103
1104    if ( ss->driver_id == -1 )
1105     return -1;
1106
1107    is_stream = 1;
1108   break;
1109  case ROAR_OT_MIXER:
1110    if ( streams_get(info[1], &ss) == -1 )
1111     return -1;
1112
1113    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_MIXING )
1114     return -1;
1115
1116    is_stream = 1;
1117   break;
1118  case ROAR_OT_BRIDGE:
1119    if ( streams_get(info[1], &ss) == -1 )
1120     return -1;
1121
1122    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_BRIDGE )
1123     return -1;
1124
1125    is_stream = 1;
1126   break;
1127  default:
1128/* TODO: those types should be handled, too:
1129#define ROAR_OT_SAMPLE    4
1130#define ROAR_OT_LISTEN    8
1131#define ROAR_OT_ACTION    9
1132#define ROAR_OT_MSGQUEUE 10
1133#define ROAR_OT_MSGBUS   11
1134*/
1135    return -1;
1136   break;
1137 }
1138
1139 if ( is_stream ) {
1140  if ( streams_get_flag(info[1], ROAR_FLAG_IMMUTABLE) == 1 )
1141   return -1;
1142
1143  streams_delete(info[1]);
1144 }
1145
1146 mes->cmd     = ROAR_CMD_OK;
1147 mes->datalen = 0;
1148
1149 return 0;
1150}
1151
1152int req_on_attach      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1153 uint16_t * info = (uint16_t *) mes->data;
1154
1155 if ( mes->datalen < 6 )
1156  return -1;
1157
1158 info[0] = ROAR_NET2HOST16(info[0]);
1159 info[1] = ROAR_NET2HOST16(info[1]);
1160 info[2] = ROAR_NET2HOST16(info[2]);
1161
1162 if ( info[0] != 0 )
1163  return -1;
1164
1165 if ( info[1] == ROAR_ATTACH_SIMPLE ) {
1166  if ( client_stream_move(info[2], mes->stream) == -1 )
1167   return -1;
1168 } else {
1169  return -1;
1170 }
1171
1172 mes->cmd     = ROAR_CMD_OK;
1173 mes->datalen = 0;
1174
1175 return 0;
1176}
1177
1178int req_on_set_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1179 struct roar_stream_server * s;
1180 uint16_t * info = (uint16_t *) mes->data;
1181 uint16_t   version;
1182 uint16_t   scale = 65535;
1183 int stream;
1184 int i;
1185 int chans;
1186
1187 ROAR_DBG("req_on_set_vol(*) = ?");
1188 ROAR_DBG("req_on_set_vol(*): mes->datalen=%i", mes->datalen);
1189
1190 if ( mes->datalen < (4*2) )
1191  return -1;
1192
1193 version = ROAR_NET2HOST16(info[0]);
1194 ROAR_DBG("req_on_set_vol(*): version=%i", (int)version);
1195
1196 switch (version) {
1197  case 0:
1198    stream = ROAR_NET2HOST16(info[1]);
1199   break;
1200  case 1:
1201    stream = mes->stream;
1202    scale  = ROAR_NET2HOST16(info[1]);
1203   break;
1204  default:
1205    return -1;
1206   break;
1207 }
1208 ROAR_DBG("req_on_set_vol(*): stream=%i", stream);
1209
1210 if ( scale == 0 )
1211  return -1;
1212
1213 // TODO: change this code.
1214 //       we should not directly change the stream object but use some stream_*()-func
1215 //       for that job.
1216
1217 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1218  return -1;
1219
1220 s = g_streams[stream];
1221
1222 if ( s == NULL )
1223  return -1;
1224
1225 ROAR_DBG("req_on_set_vol(*): s=%p", s);
1226
1227 info[2] = ROAR_NET2HOST16(info[2]);
1228
1229 if ( info[2] == ROAR_SET_VOL_ALL ) {
1230  chans = (mes->datalen/2) - 3;
1231  ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ALL, channes=%i", chans);
1232
1233  if ( chans >= ROAR_MAX_CHANNELS )
1234   return -1;
1235
1236  ROAR_DBG("req_on_set_vol(*): mixer at %p", s->mixer.mixer);
1237
1238  for (i = 0; i < chans; i++) {
1239   s->mixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
1240   ROAR_DBG("req_on_set_vol(*): channel %i: %i", i, ROAR_NET2HOST16(info[i+3]));
1241  }
1242
1243  s->mixer.scale = scale;
1244
1245  ROAR_DBG("req_on_set_vol(*): mixer changed!");
1246
1247 } else if ( info[2] == ROAR_SET_VOL_ONE ) {
1248  ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ONE");
1249  if ( ROAR_NET2HOST16(info[3]) >= ROAR_MAX_CHANNELS )
1250   return -1;
1251
1252  s->mixer.mixer[ROAR_NET2HOST16(info[3])] = ROAR_NET2HOST16(info[4]);
1253
1254  s->mixer.scale = scale;
1255 } else {
1256  return -1;
1257 }
1258
1259 if ( streams_set_mixer(stream) == -1 )
1260  return -1;
1261
1262 mes->cmd     = ROAR_CMD_OK;
1263 mes->datalen = 0;
1264
1265 return 0;
1266}
1267
1268int req_on_get_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1269 uint16_t * info = (uint16_t *) mes->data;
1270 uint16_t   version = -1;
1271 int stream;
1272 struct roar_stream_server * s;
1273 int i;
1274 int chans;
1275
1276 ROAR_DBG("req_on_get_vol(*) = ?");
1277 ROAR_DBG("req_on_get_vol(*): mes->datalen=%i", mes->datalen);
1278
1279 if ( mes->datalen < 2 ) {
1280  return -1;
1281 }
1282
1283 version = ROAR_NET2HOST16(info[0]);
1284
1285 switch (version) {
1286  case 0:
1287    if ( mes->datalen < (2*2) )
1288     return -1;
1289
1290    stream = ROAR_NET2HOST16(info[1]);
1291   break;
1292  case 1:
1293    stream = mes->stream;
1294   break;
1295  default:
1296    return -1;
1297   break;
1298 }
1299
1300 ROAR_DBG("req_on_get_vol(*): stream=%i", stream);
1301
1302 // TODO: change this code.
1303 //       we should not directly change the stream object but use some stream_*()-func
1304 //       for that job.
1305
1306 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1307  return -1;
1308
1309 s = g_streams[stream];
1310
1311 if ( s == NULL )
1312  return -1;
1313
1314 ROAR_DBG("req_on_get_vol(*): s=%p", s);
1315
1316 // ok, we have everything
1317
1318 info[0] = ROAR_HOST2NET16(version);
1319
1320 switch (version) {
1321  case 0:
1322    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1323
1324    for (i = 0; i < chans; i++)
1325     info[2+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1326
1327     mes->datalen = (2 + chans)*2;
1328   break;
1329  case 1:
1330    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1331    info[2] = ROAR_HOST2NET16(s->mixer.scale);
1332    info[3] = ROAR_HOST2NET16(s->mixer.rpg_mul);
1333    info[4] = ROAR_HOST2NET16(s->mixer.rpg_div);
1334
1335    for (i = 0; i < chans; i++)
1336     info[5+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1337
1338     mes->datalen = (5 + chans)*2;
1339   break;
1340  default:
1341    return -1;
1342   break;
1343 }
1344
1345 mes->cmd = ROAR_CMD_OK;
1346
1347 return 0;
1348}
1349
1350int req_on_add_data (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1351 struct roar_buffer * b;
1352 char               * buf;
1353
1354 if ( roar_buffer_new_data(&b, mes->datalen, (void **)&buf) == -1 ) {
1355  ROAR_ERR("req_on_add_data(*): Can not alloc buffer space!");
1356  ROAR_DBG("req_on_add_data(*) = -1");
1357  return -1;
1358 }
1359
1360 if ( data == NULL ) {
1361  memcpy(buf, mes->data, mes->datalen);
1362 } else {
1363  memcpy(buf, *data, mes->datalen);
1364 }
1365
1366 if ( stream_add_buffer(mes->stream, b) == -1 ) {
1367  roar_buffer_free(b);
1368  return -1;
1369 }
1370
1371 mes->cmd     = ROAR_CMD_OK_STOP;
1372 mes->datalen = 0;
1373
1374 return 0;
1375}
1376
1377int req_on_beep        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1378 struct roar_beep bs;
1379 int16_t * info = (int16_t*)mes->data;
1380 int stream;
1381
1382 memset(&bs, 0, sizeof(bs));
1383
1384 if ( mes->datalen > 0 ) {
1385  if ( mes->datalen < 2 )
1386   return -1;
1387
1388  if ( ROAR_NET2HOST16(info[0]) != 0 ) /* version */
1389   return -1;
1390
1391  if ( mes->datalen != 8*2 )
1392   return -1;
1393
1394  bs.vol  = ROAR_NET2HOST16(info[1]);
1395  bs.time = ROAR_NET2HOST16(info[2]);
1396  bs.freq = ROAR_NET2HOST16(info[3]);
1397  bs.type = ROAR_NET2HOST16(info[4]);
1398  bs.x    = ROAR_NET2HOST16(info[5]);
1399  bs.y    = ROAR_NET2HOST16(info[6]);
1400  bs.z    = ROAR_NET2HOST16(info[7]);
1401 }
1402
1403 if ( (stream = beep_start(client, &bs)) == -1 )
1404  return -1;
1405
1406 mes->stream  = stream;
1407 mes->cmd     = ROAR_CMD_OK_STOP;
1408 mes->datalen = 0;
1409
1410 return 0;
1411}
1412
1413int req_on_wait        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1414 uint16_t * u16 = (uint16_t*)mes->data;
1415 struct roar_event events[4];
1416 size_t left, tmp;
1417 size_t num = 0;
1418 void * vp = mes->data;
1419
1420 vp += 4;
1421
1422 // check for complet header...
1423 if ( mes->datalen < 4 )
1424  return -1;
1425
1426 u16[0] = ROAR_NET2HOST16(u16[0]);
1427 u16[1] = ROAR_NET2HOST16(u16[1]);
1428
1429 // do we support version and flags?
1430 if ( u16[0] != 0 || u16[1] != 0 )
1431  return -1;
1432
1433 memset(events, 0, sizeof(events));
1434
1435 left = mes->datalen - 4;
1436
1437 while (left) {
1438  tmp = left;
1439  if ( roar_event_from_blob(&(events[num]), vp, &tmp) == -1 )
1440   return -1;
1441
1442  vp   += tmp;
1443  left -= tmp;
1444  num++;
1445 }
1446
1447 if ( clients_wait(client, events, num) == -1 )
1448  return -1;
1449
1450 flags[1] |= COMMAND_FLAG_OUT_NOSEND;
1451
1452 return 0;
1453}
1454
1455//ll
Note: See TracBrowser for help on using the repository browser.