source: roaraudio/roard/req.c @ 5065:18cdc8c3a1ab

Last change on this file since 5065:18cdc8c3a1ab was 5065:18cdc8c3a1ab, checked in by phi, 13 years ago

added roar_clock_gettime()

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