source: roaraudio/roard/req.c @ 4923:eb6f9e17661a

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

use new target syntax of ckport

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