source: roaraudio/roard/req.c @ 5031:ebd6fe192503

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

Added support for ROAR_CMD_GETTIMEOFDAY

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