source: roaraudio/roard/req.c @ 4708:c9d40761088a

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

updated copyright statements

File size: 39.8 KB
Line 
1//req.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2011
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#ifdef ROAR_HAVE_GETVERSIONEX
582 OSVERSIONINFO osinfo;
583 char buf_release[80];
584#endif
585 struct roar_server_info info;
586 uint16_t * d16;
587
588 if ( mes->datalen != 4 )
589  return -1;
590
591 d16 = (uint16_t*)mes->data;
592
593 // check version.
594 if ( ROAR_NET2HOST16(d16[0]) != 0 )
595  return -1;
596
597 switch (ROAR_NET2HOST16(d16[1])) {
598  case ROAR_IT_SERVER:
599   memset(&info, 0, sizeof(info));
600
601   // the following if is optimized out by compiler.
602   if ( DISTRIBUTION_VERSION_STRING[0] == 0 ) {
603    info.version = "roard/" PACKAGE_VERSION " <" DEVICE_VENDOR_STRING ">";
604   } else {
605    info.version = "roard/" PACKAGE_VERSION " <" DEVICE_VENDOR_STRING "> (" DISTRIBUTION_VERSION_STRING ")";
606   }
607
608   if ( !!strcmp(g_config->location, CONF_DEF_STRING) )
609    info.location = g_config->location;
610
611   if ( !!strcmp(g_config->description, CONF_DEF_STRING) )
612   info.description = g_config->description;
613
614#ifdef ROAR_HAVE_UNAME
615   if ( uname(&utsname) == 0 ) {
616    info.un.sysname  = utsname.sysname;
617    info.un.release  = utsname.release;
618    info.un.nodename = utsname.nodename;
619    info.un.machine  = utsname.machine;
620   }
621#endif
622#ifdef ROAR_HAVE_GETVERSIONEX
623   osinfo.dwOSVersionInfoSize = sizeof(osinfo);
624   if ( GetVersionEx(&osinfo) ) {
625    info.un.sysname = "Windows";
626    snprintf(buf_release, sizeof(buf_release), "%i.%i.%i",
627               osinfo.dwMajorVersion, osinfo.dwMinorVersion, osinfo.dwBuildNumber);
628    buf_release[sizeof(buf_release)-1] = 0;
629    info.un.release = buf_release;
630   }
631#endif
632
633   *data = NULL;
634
635   if ( roar_server_info_to_mes(mes, &info, (void**)data) == -1 )
636    return -1;
637
638   if ( *data != NULL )
639    flags[1] |= COMMAND_FLAG_OUT_LONGDATA;
640  break;
641  default: /* unknown request */
642    return -1;
643   break;
644 }
645
646 mes->cmd = ROAR_CMD_OK;
647
648 return 0;
649}
650
651int req_on_server_oinfo    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
652 struct roar_stream s;
653 int dir = ROAR_DIR_PLAY;
654 int subsys;
655//ROAR_DIR_OUTPUT
656
657 if ( mes->datalen != 0 ) {
658  if ( mes->datalen != 2 )
659   return -1;
660
661  if ( mes->data[0] != 0 )
662   return -1;
663
664  dir = mes->data[1];
665 }
666
667 subsys = streams_dir2subsys(dir);
668
669 memset(&s, 0, sizeof(struct roar_stream));
670
671 s.dir           = ROAR_DIR_MIXING;
672 s.pos_rel_id    = -1;
673
674 switch (subsys) {
675  case ROAR_SUBSYS_WAVEFORM:
676    s.info.rate     = g_sa->rate;
677    s.info.bits     = g_sa->bits;
678    s.info.channels = g_sa->channels;
679    s.info.codec    = g_sa->codec;
680    s.pos           = g_pos;
681   break;
682#ifndef ROAR_WITHOUT_DCOMP_MIDI
683  case ROAR_SUBSYS_MIDI:
684   break;
685#endif
686#ifndef ROAR_WITHOUT_DCOMP_LIGHT
687  case ROAR_SUBSYS_LIGHT:
688    s.info.rate     = ROAR_OUTPUT_CFREQ;
689    s.info.bits     = ROAR_LIGHT_BITS;
690    s.info.channels = g_light_state.channels;
691   break;
692#endif
693#ifndef ROAR_WITHOUT_DCOMP_RAW
694  case ROAR_SUBSYS_RAW:
695    // no need to set anything here.
696   break;
697#endif
698#ifndef ROAR_WITHOUT_DCOMP_RDTCS
699  case ROAR_SUBSYS_RDTCS:
700    s.info.rate     = ROAR_OUTPUT_CFREQ;
701    s.info.bits     = ROAR_RDTCS_BITS;
702    s.info.channels = ROAR_RDTCS_CHANNELS;
703    s.info.codec    = ROAR_RDTCS_CODEC;
704   break;
705#endif
706  default:
707    return -1;
708   break;
709 }
710
711 if ( roar_stream_s2m(&s, mes) == -1 )
712  return -1;
713
714 mes->cmd = ROAR_CMD_OK;
715
716 return 0;
717}
718
719int req_on_caps        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
720 struct roar_caps caps;
721 struct roar_stds * stds;
722 size_t i;
723
724 if ( roar_caps_from_msg(&caps, mes, *data) == -1 )
725  return -1;
726
727 // handle the data from the caps command here...
728
729 if ( !(caps.flags & ROAR_CF_REQUEST) ) {
730  mes->cmd = ROAR_CMD_OK;
731  mes->datalen = 0;
732  return 0;
733 }
734
735 mes->datalen = 0;
736
737 switch (caps.type) {
738  case ROAR_CT_STANDARDS:
739    if ( (stds = roar_stds_new(g_caps_stds.stds_len)) == NULL )
740     return -1;
741
742    for ( i = 0; i < stds->stds_len; i++) {
743     stds->stds[i] = ROAR_HOST2NET32(g_caps_stds.stds[i]);
744    }
745
746    caps.data = stds->stds;
747    caps.len  = stds->stds_len * 4;
748    // TODO: add support for **data.
749    if ( roar_caps_to_msg(mes, &caps, NULL) == -1 ) {
750     roar_stds_free(stds);
751     return -1;
752    }
753    roar_stds_free(stds);
754   break;
755  default:
756    return -1;
757   break;
758 }
759
760 mes->cmd = ROAR_CMD_OK;
761
762 return 0;
763}
764
765int req_on_get_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
766 mes->cmd     = ROAR_CMD_OK;
767 mes->pos     = g_pos;
768 mes->datalen = 2;
769
770 *((uint16_t*)mes->data) = ROAR_HOST2NET16((unsigned) g_standby);
771
772 return 0;
773}
774
775int req_on_set_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
776 if ( mes->datalen != 2 )
777  return -1;
778
779 g_standby = ROAR_NET2HOST16(*((uint16_t*)mes->data));
780
781 mes->cmd     = ROAR_CMD_OK;
782 mes->pos     = g_pos;
783 mes->datalen = 0;
784
785 return 0;
786}
787
788int req_on_exit      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
789 int term = 0;
790
791 if ( mes->datalen == 1 )
792  term = mes->data[0];
793
794 mes->cmd     = ROAR_CMD_OK;
795 mes->pos     = g_pos;
796 mes->datalen = 0;
797
798 ROAR_DBG("req_on_exit(*): term=%i", term);
799
800 if ( term ) {
801  cleanup_listen_socket(1);
802 } else {
803  alive = 0;
804 }
805
806 return 0;
807}
808
809int req_on_list_clients(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
810 unsigned char filter, cmp;
811 uint32_t id;
812 int clients[ROAR_CLIENTS_MAX];
813 int i, c = 0;
814
815 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
816  return -1;
817
818 // TODO: add code to support filter
819 if ( filter != ROAR_CTL_FILTER_ANY )
820  return -1;
821
822 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
823  if ( g_clients[i] != NULL ) {
824   clients[c++] = i;
825  }
826 }
827
828 roar_ctl_ia2m(mes, clients, c);
829
830 mes->cmd = ROAR_CMD_OK;
831
832 return 0;
833}
834int req_on_list_streams(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
835 unsigned char filter, cmp;
836 uint32_t id;
837 int streams[ROAR_STREAMS_MAX];
838 int i, c = 0;
839 int match;
840
841 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
842  return -1;
843
844 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
845  if ( g_streams[i] == NULL )
846   continue;
847
848  match = 0;
849
850  switch (filter) {
851   case ROAR_CTL_FILTER_ANY:
852     match = 1;
853    break;
854   case ROAR_CTL_FILTER_DIR:
855     match = roar_filter_match(cmp, id, ROAR_STREAM(g_streams[i])->dir);
856    break;
857   default: // unsupported filter...
858     return -1;
859    break;
860  }
861
862  if ( match )
863   streams[c++] = i;
864 }
865
866 roar_ctl_ia2m(mes, streams, c);
867
868 mes->cmd = ROAR_CMD_OK;
869
870 return 0;
871}
872
873int req_on_get_client  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
874 struct roar_client * c;
875
876 if ( mes->datalen != 1 )
877  return -1;
878
879 if ( clients_get(mes->data[0], &c) == -1 )
880  return -1;
881
882 mes->cmd = ROAR_CMD_OK;
883
884 return roar_ctl_c2m(mes, c);
885}
886
887int req_on_get_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
888 struct roar_stream_server * s;
889
890 if ( mes->datalen != 1 )
891  return -1;
892
893 if ( streams_get(mes->data[0], &s) == -1 )
894  return -1;
895
896 mes->cmd = ROAR_CMD_OK;
897 mes->stream = mes->data[0];
898
899 return roar_stream_s2m(ROAR_STREAM(s), mes);
900}
901
902int req_on_get_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
903 struct roar_stream * s;
904 struct roar_stream_server * ss;
905 struct roar_audio_info * audio_info;
906 struct roar_stream_ltm * ltm;
907 uint16_t * d  = (uint16_t *) mes->data;
908 int64_t * d64 = ( int64_t *) mes->data;
909 int64_t * d64ptr;
910 int i, h, k;
911 char * str;
912 size_t needed;
913 int test, bits;
914
915 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);
916
917 if ( mes->datalen < 4 )
918  return -1;
919
920 for (i = 0; i < 2; i++) {
921  d[i] = ROAR_NET2HOST16(d[i]);
922 }
923
924 if ( d[0] != 0 ) {
925  ROAR_WARN("req_on_get_stream_para(*): unsupported command version: %i, %i", (int)d[0], (int)d[1]);
926  return -1;
927 }
928
929 switch (d[1]) {
930  case ROAR_STREAM_PARA_INFO:
931    if ( streams_get(mes->stream, &ss) == -1 ) {
932     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
933     return -1;
934    }
935
936    if ( streams_calc_delay(mes->stream) == -1 ) {
937     ROAR_WARN("req_on_get_stream_para(*): can not calc delay for stream %i", mes->stream);
938    }
939
940    s = ROAR_STREAM(ss);
941
942    audio_info = &(s->info);
943
944    mes->datalen = 2*12;
945
946    d[ 2] = ROAR_OUTPUT_CALC_OUTBUFSIZE(audio_info);
947    d[ 3] = ss->pre_underruns;
948    d[ 4] = ss->post_underruns;
949    d[ 5] = ss->codec_orgi;
950    d[ 6] = (ss->flags & 0xFFFF) | (ss->primary ? ROAR_FLAG_PRIMARY : 0) | (ss->driver_id != -1 ? ROAR_FLAG_OUTPUT : 0);
951    d[ 7] = ss->delay/1000;
952    d[ 8] = ss->state;
953    d[ 9] = (ss->flags & 0xFFFF0000) >> 16;
954    d[10] = ss->mixer_stream;
955    d[11] = ss->role;
956
957    ROAR_DBG("req_on_get_stream_para(*): ss->driver_id=%i", ss->driver_id);
958
959    ROAR_DBG("req_on_get_stream_para(*): delay=%i, send delay=%i", ss->delay, d[7]);
960
961    for (i = 0; i < mes->datalen/2; i++) {
962     d[i] = ROAR_HOST2NET16(d[i]);
963    }
964
965    mes->pos = s->pos;
966   break;
967
968  case ROAR_STREAM_PARA_NAME:
969   str = streams_get_name(mes->stream);
970
971   if ( str == NULL )
972    return -1;
973
974    mes->datalen = 4 + strlen(str);
975
976    if ( mes->datalen > LIBROAR_BUFFER_MSGDATA )
977     return -1;
978
979    strncpy(((char*)&(mes->data))+4, str, mes->datalen);
980
981    d[0] = ROAR_HOST2NET16(d[0]);
982    d[1] = ROAR_HOST2NET16(d[1]);
983   break;
984
985  case ROAR_STREAM_PARA_CHANMAP:
986    if ( streams_get(mes->stream, &ss) == -1 ) {
987     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
988     return -1;
989    }
990
991    s = ROAR_STREAM(ss);
992
993    memcpy(&(mes->data[4]), ss->chanmap.in, s->info.channels);
994    mes->datalen = 2*2 + s->info.channels;
995
996    d[0] = ROAR_HOST2NET16(d[0]);
997    d[1] = ROAR_HOST2NET16(d[1]);
998   break;
999
1000  case ROAR_STREAM_PARA_LTM:
1001    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request...", client);
1002
1003    if ( mes->datalen < (6 * 2) ) {
1004     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: message too short", client);
1005     return -1;
1006    }
1007
1008    for (i = 2; i < mes->datalen/2; i++) {
1009     d[i] = ROAR_NET2HOST16(d[i]);
1010    }
1011
1012    if ( d[2] != ROAR_LTM_SST_GET_RAW ) {
1013     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: unknown LTM subtype: %i", client, (int)d[2]);
1014     return -1;
1015    }
1016
1017    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request of type GET_RAW", client);
1018
1019    test = d[5];
1020    bits = 0;
1021    while (test) {
1022     if ( test & 0x1 )
1023      bits++;
1024
1025     test >>= 1;
1026    }
1027
1028    needed = 0;
1029
1030    if ( mes->stream == -1 ) {
1031     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM multi-stream request...", client);
1032
1033     for (i = 6; i < mes->datalen/2; i++) {
1034      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
1035       return -1;
1036
1037      needed += ltm->channels;
1038     }
1039    } else {
1040     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM single-stream request for stream %i...", client, mes->stream);
1041     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
1042      return -1;
1043
1044     needed = ltm->channels;
1045    }
1046
1047    needed *= bits;
1048
1049    needed += mes->stream == -1 ? (mes->datalen/2) - 6 : 1;
1050
1051    ROAR_DBG("req_on_get_stream_para(client=%i, ...): data size for answer is %i 64 bit sub-packets", client, (int)needed);
1052
1053    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1054    d64 = _dataspace(mes, data, flags, needed * 8);
1055    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1056
1057    if ( (d = roar_mm_malloc(mes->datalen)) == NULL )
1058     return -1;
1059
1060    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d=%p, data=%p{%p}", client, d, data, *data);
1061
1062
1063    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1064    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1065    memcpy(d, mes->data, mes->datalen);
1066    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1067
1068    d64ptr = d64;
1069
1070    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1071    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1072
1073    if ( mes->stream == -1 ) {
1074     for (i = 6; i < mes->datalen/2; i++) {
1075      ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1076
1077      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
1078       return -1;
1079
1080      *d64ptr = ltm->channels & 0xFFFF;
1081       d64ptr++;
1082
1083      for (h = 0; h < ltm->channels; h++) {
1084       for (k = 0; k < ROAR_LTM_MTBITS; k++) {
1085        if ( d[5] & (1<<k) ) {
1086         switch (1<<k) {
1087          case ROAR_LTM_MT_RMS:
1088            *d64ptr = ltm->cur[h].rms;
1089           break;
1090          default:
1091            ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
1092         }
1093         d64ptr++;
1094        }
1095       }
1096      }
1097     }
1098    } else {
1099     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
1100      return -1;
1101
1102     *d64ptr = ltm->channels & 0xFFFF;
1103      d64ptr++;
1104
1105     for (h = 0; h < ltm->channels; h++) {
1106      for (k = 0; k < ROAR_LTM_MTBITS; k++) {
1107       if ( d[5] & (1<<k) ) {
1108        switch (1<<k) {
1109         case ROAR_LTM_MT_RMS:
1110           *d64ptr = ltm->cur[h].rms;
1111           ROAR_DBG("req_on_get_stream_para(client=%i, ...): rms=%lli to %p", client, (long long int)*d64ptr, d64ptr);
1112          break;
1113         default:
1114           ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
1115        }
1116        d64ptr++;
1117       }
1118      }
1119     }
1120    }
1121
1122    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1123
1124    roar_mm_free(d);
1125
1126    for (i = 0; i < needed; i++) {
1127     d64[i] = ROAR_HOST2NET64(d64[i]);
1128    }
1129
1130    mes->datalen = needed * 8;
1131    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM d64=%p, d64ptr=%p", client, d64, d64ptr);
1132    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM final message has %i byte of data", client, (int)mes->datalen);
1133    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1134    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM GET_RAW request: OK. returning...", client);
1135   break;
1136
1137  default:
1138    ROAR_WARN("req_on_get_stream_para(*): unsupported command: %i", d[1]);
1139    return -1;
1140 }
1141
1142 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);
1143 mes->cmd = ROAR_CMD_OK;
1144 return 0;
1145}
1146
1147int req_on_set_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1148 struct roar_stream_server * ss;
1149 uint16_t * d = (uint16_t *) mes->data;
1150 uint32_t tmp, tmp2, flagstore;
1151 int protect = 0;
1152 int i;
1153
1154 if ( mes->datalen < 2*2 )
1155  return -1;
1156
1157 for (i = 0; i < 2; i++) {
1158  d[i] = ROAR_NET2HOST16(d[i]);
1159 }
1160
1161 if ( d[0] != 0 )
1162  return -1;
1163
1164 switch (d[1]) {
1165  case ROAR_STREAM_PARA_FLAGS:
1166    if ( mes->datalen != 2*4 && mes->datalen != 2*5 )
1167     return -1;
1168
1169    d[2] = ROAR_NET2HOST16(d[2]);
1170    d[3] = ROAR_NET2HOST16(d[3]);
1171
1172    ROAR_DBG("req_on_set_stream_para(*): request seems to be valid");
1173
1174    tmp = 0;
1175
1176    if ( mes->datalen == 2*5 ) {
1177     d[4] = ROAR_NET2HOST16(d[4]);
1178     tmp   = d[4];
1179     tmp <<= 16;
1180    }
1181
1182    tmp |= d[3];
1183
1184    if ( d[2] & ROAR_PROTECT_FLAG ) {
1185     protect = 1;
1186     d[2] -= ROAR_PROTECT_FLAG;
1187    }
1188
1189    switch (d[2]) {
1190     case ROAR_SET_FLAG:
1191       if ( streams_set_flag(mes->stream, tmp) == -1 )
1192        return -1;
1193      break;
1194     case ROAR_RESET_FLAG:
1195       if ( streams_reset_flag(mes->stream, tmp) == -1 )
1196        return -1;
1197      break;
1198     case ROAR_NOOP_FLAG:
1199      break;
1200     case ROAR_TOGGLE_FLAG:
1201       if ( streams_get(mes->stream, &ss) == -1 )
1202        return -1;
1203
1204       flagstore = ss->flags;
1205
1206       tmp2 = flagstore & tmp; // those are the flags we need to reset.
1207       ROAR_DBG("req_on_set_stream_para(*): tmp2=0x%.8lx", (long int)tmp2);
1208       if ( tmp2 )
1209        if ( streams_reset_flag(mes->stream, tmp2) == -1 )
1210         return -1;
1211
1212       tmp2 = (flagstore ^ tmp) & tmp; // those are the flags we need to set.
1213       ROAR_DBG("req_on_set_stream_para(*): tmp2=0x%.8lx", (long int)tmp2);
1214       if ( tmp2 )
1215        if ( streams_set_flag(mes->stream, tmp2) == -1 )
1216         return -1;
1217      break;
1218     default:
1219       return -1;
1220      break;
1221    }
1222
1223   ROAR_DBG("req_on_set_stream_para(*): protect=%i", protect);
1224   if ( protect )
1225    if ( streams_protect_flag(mes->stream, tmp) == -1 )
1226     return -1;
1227
1228   break;
1229  case ROAR_STREAM_PARA_CHANMAP:
1230    if ( streams_set_map(mes->stream, &(mes->data[4]), mes->datalen - 4) == -1 )
1231     return -1;
1232   break;
1233  case ROAR_STREAM_PARA_ROLE:
1234    if ( mes->datalen != 2*3 )
1235     return -1;
1236
1237    d[2] = ROAR_NET2HOST16(d[2]);
1238
1239    if ( streams_set_role(mes->stream, d[2]) == -1 )
1240     return -1;
1241   break;
1242  case ROAR_STREAM_PARA_LTM:
1243    if ( mes->datalen < (6 * 2) )
1244     return -1;
1245
1246    for (i = 2; i < mes->datalen/2; i++) {
1247     d[i] = ROAR_NET2HOST16(d[i]);
1248    }
1249
1250    if ( mes->stream == -1 ) {
1251     for (i = 6; i < mes->datalen/2; i++)
1252      if ( streams_ltm_ctl(d[i], d[5], d[3], d[2]) == -1 )
1253       return -1;
1254    } else {
1255     if ( streams_ltm_ctl(mes->stream, d[5], d[3], d[2]) == -1 )
1256      return -1;
1257    }
1258   break;
1259  default:
1260    ROAR_WARN("req_on_set_stream_para(*): unsupported command version: %i, %i", d[0], d[1]);
1261    return -1;
1262   break;
1263 }
1264
1265 mes->cmd     = ROAR_CMD_OK;
1266 mes->datalen = 0;
1267
1268 return 0;
1269}
1270
1271int req_on_kick (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1272 struct roar_stream_server * ss;
1273 uint16_t * info = (uint16_t *) mes->data;
1274 int is_stream = 0;
1275
1276 if ( mes->datalen != 4 )
1277  return -1;
1278
1279 info[0] = ROAR_NET2HOST16(info[0]);
1280 info[1] = ROAR_NET2HOST16(info[1]);
1281
1282 switch (info[0]) {
1283  case ROAR_OT_CLIENT:
1284    clients_delete(info[1]);
1285   break;
1286  case ROAR_OT_STREAM:
1287    is_stream = 1;
1288   break;
1289  case ROAR_OT_SOURCE:
1290    if ( streams_get_flag(info[1], ROAR_FLAG_SOURCE) != 1 )
1291     return -1;
1292    is_stream = 1;
1293   break;
1294  case ROAR_OT_OUTPUT:
1295    if ( streams_get(info[1], &ss) == -1 )
1296     return -1;
1297
1298    if ( ss->driver_id == -1 )
1299     return -1;
1300
1301    is_stream = 1;
1302   break;
1303  case ROAR_OT_MIXER:
1304    if ( streams_get(info[1], &ss) == -1 )
1305     return -1;
1306
1307    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_MIXING )
1308     return -1;
1309
1310    is_stream = 1;
1311   break;
1312  case ROAR_OT_BRIDGE:
1313    if ( streams_get(info[1], &ss) == -1 )
1314     return -1;
1315
1316    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_BRIDGE )
1317     return -1;
1318
1319    is_stream = 1;
1320   break;
1321  default:
1322/* TODO: those types should be handled, too:
1323#define ROAR_OT_SAMPLE    4
1324#define ROAR_OT_LISTEN    8
1325#define ROAR_OT_ACTION    9
1326#define ROAR_OT_MSGQUEUE 10
1327#define ROAR_OT_MSGBUS   11
1328*/
1329    return -1;
1330   break;
1331 }
1332
1333 if ( is_stream ) {
1334  if ( streams_get_flag(info[1], ROAR_FLAG_IMMUTABLE) == 1 )
1335   return -1;
1336
1337  streams_delete(info[1]);
1338 }
1339
1340 mes->cmd     = ROAR_CMD_OK;
1341 mes->datalen = 0;
1342
1343 return 0;
1344}
1345
1346int req_on_attach      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1347 uint16_t * info = (uint16_t *) mes->data;
1348
1349 if ( mes->datalen < 6 )
1350  return -1;
1351
1352 info[0] = ROAR_NET2HOST16(info[0]);
1353 info[1] = ROAR_NET2HOST16(info[1]);
1354 info[2] = ROAR_NET2HOST16(info[2]);
1355
1356 if ( info[0] != 0 )
1357  return -1;
1358
1359 if ( info[1] == ROAR_ATTACH_SIMPLE ) {
1360  if ( client_stream_move(info[2], mes->stream) == -1 )
1361   return -1;
1362 } else {
1363  return -1;
1364 }
1365
1366 mes->cmd     = ROAR_CMD_OK;
1367 mes->datalen = 0;
1368
1369 return 0;
1370}
1371
1372int req_on_set_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1373 struct roar_stream_server * s;
1374 uint16_t * info = (uint16_t *) mes->data;
1375 uint16_t   version;
1376 uint16_t   scale = 65535;
1377 int stream;
1378 int i;
1379 int chans;
1380
1381 ROAR_DBG("req_on_set_vol(*) = ?");
1382 ROAR_DBG("req_on_set_vol(*): mes->datalen=%i", mes->datalen);
1383
1384 if ( mes->datalen < (4*2) )
1385  return -1;
1386
1387 version = ROAR_NET2HOST16(info[0]);
1388 ROAR_DBG("req_on_set_vol(*): version=%i", (int)version);
1389
1390 switch (version) {
1391  case 0:
1392    stream = ROAR_NET2HOST16(info[1]);
1393   break;
1394  case 1:
1395    stream = mes->stream;
1396    scale  = ROAR_NET2HOST16(info[1]);
1397   break;
1398  default:
1399    return -1;
1400   break;
1401 }
1402 ROAR_DBG("req_on_set_vol(*): stream=%i", stream);
1403
1404 if ( scale == 0 )
1405  return -1;
1406
1407 // TODO: change this code.
1408 //       we should not directly change the stream object but use some stream_*()-func
1409 //       for that job.
1410
1411 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1412  return -1;
1413
1414 s = g_streams[stream];
1415
1416 if ( s == NULL )
1417  return -1;
1418
1419 ROAR_DBG("req_on_set_vol(*): s=%p", s);
1420
1421 info[2] = ROAR_NET2HOST16(info[2]);
1422
1423 if ( info[2] == ROAR_SET_VOL_ALL ) {
1424  chans = (mes->datalen/2) - 3;
1425  ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ALL, channes=%i", chans);
1426
1427  if ( chans >= ROAR_MAX_CHANNELS )
1428   return -1;
1429
1430  ROAR_DBG("req_on_set_vol(*): mixer at %p", s->mixer.mixer);
1431
1432  for (i = 0; i < chans; i++) {
1433   s->mixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
1434   ROAR_DBG("req_on_set_vol(*): channel %i: %i", i, ROAR_NET2HOST16(info[i+3]));
1435  }
1436
1437  s->mixer.scale = scale;
1438
1439  ROAR_DBG("req_on_set_vol(*): mixer changed!");
1440
1441 } else if ( info[2] == ROAR_SET_VOL_ONE ) {
1442  ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ONE");
1443  if ( ROAR_NET2HOST16(info[3]) >= ROAR_MAX_CHANNELS )
1444   return -1;
1445
1446  s->mixer.mixer[ROAR_NET2HOST16(info[3])] = ROAR_NET2HOST16(info[4]);
1447
1448  s->mixer.scale = scale;
1449 } else {
1450  return -1;
1451 }
1452
1453 if ( streams_set_mixer(stream) == -1 )
1454  return -1;
1455
1456 mes->cmd     = ROAR_CMD_OK;
1457 mes->datalen = 0;
1458
1459 return 0;
1460}
1461
1462int req_on_get_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1463 uint16_t * info = (uint16_t *) mes->data;
1464 uint16_t   version = -1;
1465 int stream;
1466 struct roar_stream_server * s;
1467 int i;
1468 int chans;
1469
1470 ROAR_DBG("req_on_get_vol(*) = ?");
1471 ROAR_DBG("req_on_get_vol(*): mes->datalen=%i", mes->datalen);
1472
1473 if ( mes->datalen < 2 ) {
1474  return -1;
1475 }
1476
1477 version = ROAR_NET2HOST16(info[0]);
1478
1479 switch (version) {
1480  case 0:
1481    if ( mes->datalen < (2*2) )
1482     return -1;
1483
1484    stream = ROAR_NET2HOST16(info[1]);
1485   break;
1486  case 1:
1487    stream = mes->stream;
1488   break;
1489  default:
1490    return -1;
1491   break;
1492 }
1493
1494 ROAR_DBG("req_on_get_vol(*): stream=%i", stream);
1495
1496 // TODO: change this code.
1497 //       we should not directly change the stream object but use some stream_*()-func
1498 //       for that job.
1499
1500 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1501  return -1;
1502
1503 s = g_streams[stream];
1504
1505 if ( s == NULL )
1506  return -1;
1507
1508 ROAR_DBG("req_on_get_vol(*): s=%p", s);
1509
1510 // ok, we have everything
1511
1512 info[0] = ROAR_HOST2NET16(version);
1513
1514 switch (version) {
1515  case 0:
1516    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1517
1518    for (i = 0; i < chans; i++)
1519     info[2+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1520
1521     mes->datalen = (2 + chans)*2;
1522   break;
1523  case 1:
1524    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1525    info[2] = ROAR_HOST2NET16(s->mixer.scale);
1526    info[3] = ROAR_HOST2NET16(s->mixer.rpg_mul);
1527    info[4] = ROAR_HOST2NET16(s->mixer.rpg_div);
1528
1529    for (i = 0; i < chans; i++)
1530     info[5+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1531
1532     mes->datalen = (5 + chans)*2;
1533   break;
1534  default:
1535    return -1;
1536   break;
1537 }
1538
1539 mes->cmd = ROAR_CMD_OK;
1540
1541 return 0;
1542}
1543
1544int req_on_add_data (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1545 struct roar_buffer * b;
1546 void               * buf;
1547
1548 if ( roar_buffer_new_data(&b, mes->datalen, &buf) == -1 ) {
1549  ROAR_ERR("req_on_add_data(*): Can not alloc buffer space!");
1550  ROAR_DBG("req_on_add_data(*) = -1");
1551  return -1;
1552 }
1553
1554 if ( data == NULL ) {
1555  memcpy(buf, mes->data, mes->datalen);
1556 } else {
1557  memcpy(buf, *data, mes->datalen);
1558 }
1559
1560 if ( stream_add_buffer(mes->stream, b) == -1 ) {
1561  roar_buffer_free(b);
1562  return -1;
1563 }
1564
1565 mes->cmd     = ROAR_CMD_OK_STOP;
1566 mes->datalen = 0;
1567
1568 return 0;
1569}
1570
1571int req_on_beep        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1572 struct roar_beep bs;
1573 int16_t * info = (int16_t*)mes->data;
1574 int stream;
1575
1576 memset(&bs, 0, sizeof(bs));
1577
1578 if ( mes->datalen > 0 ) {
1579  if ( mes->datalen < 2 )
1580   return -1;
1581
1582  if ( ROAR_NET2HOST16(info[0]) != 0 ) /* version */
1583   return -1;
1584
1585  if ( mes->datalen != 8*2 )
1586   return -1;
1587
1588  bs.vol  = ROAR_NET2HOST16(info[1]);
1589  bs.time = ROAR_NET2HOST16(info[2]);
1590  bs.freq = ROAR_NET2HOST16(info[3]);
1591  bs.type = ROAR_NET2HOST16(info[4]);
1592  bs.x    = ROAR_NET2HOST16(info[5]);
1593  bs.y    = ROAR_NET2HOST16(info[6]);
1594  bs.z    = ROAR_NET2HOST16(info[7]);
1595 }
1596
1597 if ( (stream = beep_start(client, &bs)) == -1 )
1598  return -1;
1599
1600 mes->stream  = stream;
1601 mes->cmd     = ROAR_CMD_OK_STOP;
1602 mes->datalen = 0;
1603
1604 return 0;
1605}
1606
1607int req_on_wait        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1608 uint16_t * u16 = (uint16_t*)mes->data;
1609 struct roar_event events[4];
1610 size_t left, tmp;
1611 size_t num = 0;
1612 void * vp = mes->data;
1613
1614 vp += 4;
1615
1616 // check for complet header...
1617 if ( mes->datalen < 4 )
1618  return -1;
1619
1620 u16[0] = ROAR_NET2HOST16(u16[0]);
1621 u16[1] = ROAR_NET2HOST16(u16[1]);
1622
1623 // do we support version and flags?
1624 if ( u16[0] != 0 || u16[1] != 0 )
1625  return -1;
1626
1627 memset(events, 0, sizeof(events));
1628
1629 left = mes->datalen - 4;
1630
1631 while (left) {
1632  tmp = left;
1633  if ( roar_event_from_blob(&(events[num]), vp, &tmp) == -1 )
1634   return -1;
1635
1636  vp   += tmp;
1637  left -= tmp;
1638  num++;
1639 }
1640
1641 if ( clients_wait(client, events, num) == -1 )
1642  return -1;
1643
1644 flags[1] |= COMMAND_FLAG_OUT_NOSEND;
1645
1646 return 0;
1647}
1648
1649//ll
Note: See TracBrowser for help on using the repository browser.