source: roaraudio/roard/req.c @ 4499:0f9cbe98ac0b

Last change on this file since 4499:0f9cbe98ac0b was 4474:bf3206323cae, checked in by phi, 14 years ago

got auth stuff basicly to work

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