source: roaraudio/roard/req.c @ 4438:cd8f86bcbadc

Last change on this file since 4438:cd8f86bcbadc was 4438:cd8f86bcbadc, checked in by phi, 14 years ago

use vars from configure, implement support for uname

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