source: roaraudio/roard/req.c @ 4652:bca0fa4eabf1

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

added support for distri version string part

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