source: roaraudio/roard/req.c @ 4468:f8d2cccafc74

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

do very basic auth stuff

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