source: roaraudio/roard/req.c @ 4614:3b1ab4d465e8

Last change on this file since 4614:3b1ab4d465e8 was 4614:3b1ab4d465e8, checked in by phi, 13 years ago

Support dir parameter in OINFO command (Closes: #31)

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