source: roaraudio/roard/req.c @ 4948:29b5b41a1ca2

Last change on this file since 4948:29b5b41a1ca2 was 4948:29b5b41a1ca2, checked in by phi, 13 years ago

a first (not yet fully working) patch for non-stream execs (see #32)

File size: 42.7 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 if ( mes->datalen < 4*2 )
371  return -1;
372
373 for (i = 0; i < 4; i++) {
374  d[i] = ROAR_NET2HOST16(d[i]);
375 }
376
377 if ( d[0] != 0 ) // version
378  return -1;
379
380 if ( d[1] != 0 ) // flags
381  return -1;
382
383 memset(&m, 0, sizeof(m));
384
385 m.cmd = ROAR_CMD_OK;
386
387 flags[1] |= COMMAND_FLAG_OUT_NOSEND;
388
389 c = ROAR_CLIENT(g_clients[client]);
390
391 sock = c->fh;
392
393 if ( sock == -1 )
394  return -1;
395
396 roar_connect_fh(&con, sock);
397
398 roar_send_message(&con, &m, NULL);
399
400 clients_set_fh(client, -1);
401 clients_delete(client);
402
403 clients_new_from_fh(sock, d[2], d[3], 1);
404
405 return 0;
406}
407
408int req_on_con_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
409 char   host[80] = {0};
410 int    port = 0;
411 int    type;
412 int    fh;
413 int    len;
414
415 if ( mes->datalen < 4 )
416  return -1;
417
418 if ( *(mes->data) != 0 )
419  return -1;
420
421 if ( mes->datalen > 80 ) // we do not support long messages here
422  return -1;
423
424 type = (unsigned)mes->data[1];
425 port = ROAR_NET2HOST16(((uint16_t*)mes->data)[1]);
426
427 len = mes->datalen - 4;
428
429 strncpy(host, &(mes->data[4]), len);
430 host[len] = 0;
431
432 if ( type > ROAR_SOCKET_TYPE_MAX )
433  return -1;
434
435 if ( type == ROAR_SOCKET_TYPE_FILE ) // disabled because of security resons
436  return -1;
437
438 if ( type == ROAR_SOCKET_TYPE_FORK ) // why should we connect to ourself?
439  return -1;
440
441 ROAR_DBG("req_on_con_stream(*): CONNECT(type=%i, host='%s', port=%i)", type, host, port);
442
443 if ( (fh = roar_socket_open(ROAR_SOCKET_MODE_CONNECT, type, host, port)) == -1 )
444  return -1;
445
446 if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
447  close(fh);
448  return 1;
449 }
450
451 mes->datalen = 0;
452 mes->cmd     = ROAR_CMD_OK;
453
454 return 0;
455}
456
457int req_on_passfh      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
458 int sock = clients_get_fh(client);
459 int16_t * d = (int16_t*)mes->data;
460 struct roard_listen * lsock;
461 int listening;
462 int fh;
463 int i;
464
465 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...) = ?", client, mes->stream);
466
467 if ( (fh = roar_socket_recv_fh(sock, NULL, NULL)) == -1 ) {
468  ROAR_WARN("req_on_passfh(client=%i, mes={stream=%i,...},...): was unabled to get filehandle from remote end. bad.", client, mes->stream);
469  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (ERROR)...", client, mes->stream);
470  return -1;
471 }
472
473 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): fh=%i", client, mes->stream, fh);
474
475 if ( mes->stream != -1 ) { // stream pass:
476  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): This is a stream passfh", client, mes->stream);
477
478  if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
479   close(fh);
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,...},...): returning (OK)...", client, mes->stream);
485
486  mes->datalen = 0;
487  mes->cmd     = ROAR_CMD_OK;
488
489  return 0;
490 }
491
492// non-stream pass:
493
494 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): This is a client passfh", client, mes->stream);
495
496/*
497 0: Version,   16
498 1: Flags,     16
499 2: Protocol,  16
500 3: Byteorder, 16
501 Options...
502*/
503
504 if ( mes->datalen < 4*2 )
505  return -1;
506
507 for (i = 0; i < 4; i++) {
508  d[i] = ROAR_NET2HOST16(d[i]);
509 }
510
511 if ( d[0] != 0 ) // version
512  return -1;
513
514 listening = d[1] & ROAR_CLIENTPASS_FLAG_LISTEN;
515
516 if ( listening )
517  d[1] -= ROAR_CLIENTPASS_FLAG_LISTEN;
518
519 if ( d[1] != 0 ) // flags
520  return -1;
521
522 if ( listening ) {
523  if ( get_listen(&lsock, NULL) == -1 ) {
524   close(fh);
525   return -1;
526  }
527
528  roar_vio_open_fh_socket(&(lsock->sock), fh);
529  lsock->used   = 1;
530  lsock->proto  = d[2];
531 } else {
532  if ( clients_new_from_fh(fh, d[2], d[3], 1) == -1 )
533   return -1;
534 }
535
536 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (OK)...", client, mes->stream);
537
538 mes->datalen = 0;
539 mes->cmd     = ROAR_CMD_OK;
540
541 return 0;
542}
543
544#ifdef ROAR_SUPPORT_META
545int req_on_set_meta    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
546 int type;
547 int mode;
548 int namelen, vallen;
549 char   val[255+1];
550 char   name[ROAR_META_MAX_NAMELEN+1];
551
552 if ( mes->datalen < 3 )
553  return -1;
554
555 if ( mes->data[0] != 0 ) // version
556  return -1;
557
558 mode = (unsigned) mes->data[1];
559 type = (unsigned) mes->data[2];
560
561 ROAR_DBG("req_on_set_meta(*): mode=%i, type=%i", mode, type);
562
563 if ( mode == ROAR_META_MODE_CLEAR ) {
564  stream_meta_clear(mes->stream);
565  mes->datalen = 0;
566  mes->cmd     = ROAR_CMD_OK;
567  return 0;
568 } else if ( mode == ROAR_META_MODE_DELETE ) { // unsuppoerted at the moment
569  return -1;
570 } else if ( mode == ROAR_META_MODE_FINALIZE ) {
571  stream_meta_finalize(mes->stream);
572  mes->datalen = 0;
573  mes->cmd     = ROAR_CMD_OK;
574  return 0;
575 } else if ( mode == ROAR_META_MODE_SET || mode == ROAR_META_MODE_ADD ) {
576  if ( mes->datalen < 5 )
577   return -1;
578
579  namelen = (unsigned) mes->data[3];
580  vallen  = (unsigned) mes->data[4];
581
582  ROAR_DBG("req_on_set_meta(*): namelen=%i, vallen=%i", namelen, vallen);
583
584  if ( mes->datalen < (5 + namelen + vallen) )
585   return -1;
586
587  if ( namelen > ROAR_META_MAX_NAMELEN )
588   return -1;
589
590  strncpy(name, &(mes->data[5]), namelen);
591  name[namelen] = 0;
592
593  if ( vallen > 255 )
594   return -1;
595
596  strncpy(val, &(mes->data[5+namelen]), vallen);
597  val[vallen] = 0;
598
599  if ( mode == ROAR_META_MODE_SET ) {
600   if ( stream_meta_set(mes->stream, type, name, val) == -1 )
601    return -1;
602  } else {
603   if ( stream_meta_add(mes->stream, type, name, val) == -1 )
604    return -1;
605  }
606
607  mes->datalen = 0;
608  mes->cmd     = ROAR_CMD_OK;
609  return 0;
610 } else { // unknown mode!
611  return -1;
612 }
613
614 return -1;
615}
616
617int req_on_get_meta    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
618 int vallen;
619 int type;
620 char val[LIBROAR_BUFFER_MSGDATA-1];
621
622 if ( mes->datalen != 2 )
623  return -1;
624
625 if ( mes->data[0] != 0 ) // version
626  return -1;
627
628 type = (unsigned) mes->data[1];
629
630 if ( stream_meta_get(mes->stream, type, NULL, val, LIBROAR_BUFFER_MSGDATA-2) == -1 )
631  return -1;
632
633 vallen = strlen(val);
634
635 mes->cmd     = ROAR_CMD_OK;
636 mes->datalen = 2 + vallen;
637
638 mes->data[0] = 0;
639 mes->data[1] = (unsigned char) vallen;
640
641 val[vallen] = 0;
642
643 strncpy(&(mes->data[2]), val, vallen+1);
644
645 return 0;
646}
647
648int req_on_list_meta   (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
649 int i;
650 int len = 0;
651 int types[ROAR_META_MAX_PER_STREAM];
652
653 if ( mes->datalen != 1 )
654  return -1;
655
656 if ( mes->data[0] != 0 ) // version
657  return -1;
658
659 if ( (len = stream_meta_list(mes->stream, types, ROAR_META_MAX_PER_STREAM)) == -1 )
660  return -1;
661
662 mes->cmd     = ROAR_CMD_OK;
663 mes->datalen = 1 + len;
664 mes->data[0] = 0;
665
666 for (i = 0; i < len; i++)
667  mes->data[i+1] = types[i];
668
669 return 0;
670}
671#endif
672
673int req_on_server_info (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
674#ifdef ROAR_HAVE_UNAME
675 struct utsname utsname;
676#endif
677#ifdef ROAR_HAVE_GETVERSIONEX
678 OSVERSIONINFO osinfo;
679 char buf_release[80];
680#endif
681 struct roar_server_info info;
682 uint16_t * d16;
683
684 if ( mes->datalen != 4 )
685  return -1;
686
687 d16 = (uint16_t*)mes->data;
688
689 // check version.
690 if ( ROAR_NET2HOST16(d16[0]) != 0 )
691  return -1;
692
693 switch (ROAR_NET2HOST16(d16[1])) {
694  case ROAR_IT_SERVER:
695   memset(&info, 0, sizeof(info));
696
697   // the following if is optimized out by compiler.
698   if ( DISTRIBUTION_VERSION_STRING[0] == 0 ) {
699    info.version = "roard/" PACKAGE_VERSION " <" DEVICE_VENDOR_STRING ">";
700   } else {
701    info.version = "roard/" PACKAGE_VERSION " <" DEVICE_VENDOR_STRING "> (" DISTRIBUTION_VERSION_STRING ")";
702   }
703
704   if ( !!strcmp(g_config->location, CONF_DEF_STRING) )
705    info.location = g_config->location;
706
707   if ( !!strcmp(g_config->description, CONF_DEF_STRING) )
708   info.description = g_config->description;
709
710#ifdef ROAR_HAVE_UNAME
711   if ( uname(&utsname) == 0 ) {
712    info.un.sysname  = utsname.sysname;
713    info.un.release  = utsname.release;
714    info.un.nodename = utsname.nodename;
715    info.un.machine  = utsname.machine;
716   }
717#endif
718#ifdef ROAR_HAVE_GETVERSIONEX
719   osinfo.dwOSVersionInfoSize = sizeof(osinfo);
720   if ( GetVersionEx(&osinfo) ) {
721    info.un.sysname = "Windows";
722    snprintf(buf_release, sizeof(buf_release), "%i.%i.%i",
723               (int)osinfo.dwMajorVersion, (int)osinfo.dwMinorVersion, (int)osinfo.dwBuildNumber);
724    buf_release[sizeof(buf_release)-1] = 0;
725    info.un.release = buf_release;
726   }
727#endif
728
729   *data = NULL;
730
731   if ( roar_server_info_to_mes(mes, &info, (void**)data) == -1 )
732    return -1;
733
734   if ( *data != NULL )
735    flags[1] |= COMMAND_FLAG_OUT_LONGDATA;
736  break;
737  default: /* unknown request */
738    return -1;
739   break;
740 }
741
742 mes->cmd = ROAR_CMD_OK;
743
744 return 0;
745}
746
747int req_on_server_oinfo    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
748 struct roar_stream s;
749 int dir = ROAR_DIR_PLAY;
750 int subsys;
751//ROAR_DIR_OUTPUT
752
753 if ( mes->datalen != 0 ) {
754  if ( mes->datalen != 2 )
755   return -1;
756
757  if ( mes->data[0] != 0 )
758   return -1;
759
760  dir = mes->data[1];
761 }
762
763 subsys = streams_dir2subsys(dir);
764
765 memset(&s, 0, sizeof(struct roar_stream));
766
767 s.dir           = ROAR_DIR_MIXING;
768 s.pos_rel_id    = -1;
769
770 switch (subsys) {
771  case ROAR_SUBSYS_WAVEFORM:
772    s.info.rate     = g_sa->rate;
773    s.info.bits     = g_sa->bits;
774    s.info.channels = g_sa->channels;
775    s.info.codec    = g_sa->codec;
776    s.pos           = g_pos;
777   break;
778#ifndef ROAR_WITHOUT_DCOMP_MIDI
779  case ROAR_SUBSYS_MIDI:
780   break;
781#endif
782#ifndef ROAR_WITHOUT_DCOMP_LIGHT
783  case ROAR_SUBSYS_LIGHT:
784    s.info.rate     = ROAR_OUTPUT_CFREQ;
785    s.info.bits     = ROAR_LIGHT_BITS;
786    s.info.channels = g_light_state.channels;
787   break;
788#endif
789#ifndef ROAR_WITHOUT_DCOMP_RAW
790  case ROAR_SUBSYS_RAW:
791    // no need to set anything here.
792   break;
793#endif
794#ifndef ROAR_WITHOUT_DCOMP_RDTCS
795  case ROAR_SUBSYS_RDTCS:
796    s.info.rate     = ROAR_OUTPUT_CFREQ;
797    s.info.bits     = ROAR_RDTCS_BITS;
798    s.info.channels = ROAR_RDTCS_CHANNELS;
799    s.info.codec    = ROAR_RDTCS_CODEC;
800   break;
801#endif
802  default:
803    return -1;
804   break;
805 }
806
807 if ( roar_stream_s2m(&s, mes) == -1 )
808  return -1;
809
810 mes->cmd = ROAR_CMD_OK;
811
812 return 0;
813}
814
815int req_on_caps        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
816 struct roar_caps caps;
817 struct roar_stds * stds;
818 size_t i;
819
820 if ( roar_caps_from_msg(&caps, mes, *data) == -1 )
821  return -1;
822
823 // handle the data from the caps command here...
824
825 if ( !(caps.flags & ROAR_CF_REQUEST) ) {
826  mes->cmd = ROAR_CMD_OK;
827  mes->datalen = 0;
828  return 0;
829 }
830
831 mes->datalen = 0;
832
833 switch (caps.type) {
834  case ROAR_CT_STANDARDS:
835    if ( (stds = roar_stds_new(g_caps_stds.stds_len)) == NULL )
836     return -1;
837
838    for ( i = 0; i < stds->stds_len; i++) {
839     stds->stds[i] = ROAR_HOST2NET32(g_caps_stds.stds[i]);
840    }
841
842    caps.data = stds->stds;
843    caps.len  = stds->stds_len * 4;
844    // TODO: add support for **data.
845    if ( roar_caps_to_msg(mes, &caps, NULL) == -1 ) {
846     roar_stds_free(stds);
847     return -1;
848    }
849    roar_stds_free(stds);
850   break;
851  default:
852    return -1;
853   break;
854 }
855
856 mes->cmd = ROAR_CMD_OK;
857
858 return 0;
859}
860
861int req_on_get_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
862 mes->cmd     = ROAR_CMD_OK;
863 mes->pos     = g_pos;
864 mes->datalen = 2;
865
866 *((uint16_t*)mes->data) = ROAR_HOST2NET16((unsigned) g_standby);
867
868 return 0;
869}
870
871int req_on_set_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
872 if ( mes->datalen != 2 )
873  return -1;
874
875 g_standby = ROAR_NET2HOST16(*((uint16_t*)mes->data));
876
877 mes->cmd     = ROAR_CMD_OK;
878 mes->pos     = g_pos;
879 mes->datalen = 0;
880
881 return 0;
882}
883
884int req_on_exit      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
885 int term = 0;
886
887 if ( mes->datalen == 1 )
888  term = mes->data[0];
889
890 mes->cmd     = ROAR_CMD_OK;
891 mes->pos     = g_pos;
892 mes->datalen = 0;
893
894 ROAR_DBG("req_on_exit(*): term=%i", term);
895
896 if ( term ) {
897  cleanup_listen_socket(1);
898 } else {
899  alive = 0;
900 }
901
902 return 0;
903}
904
905int req_on_list_clients(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
906 unsigned char filter, cmp;
907 uint32_t id;
908 int clients[ROAR_CLIENTS_MAX];
909 int i, c = 0;
910
911 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
912  return -1;
913
914 // TODO: add code to support filter
915 if ( filter != ROAR_CTL_FILTER_ANY )
916  return -1;
917
918 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
919  if ( g_clients[i] != NULL ) {
920   clients[c++] = i;
921  }
922 }
923
924 roar_ctl_ia2m(mes, clients, c);
925
926 mes->cmd = ROAR_CMD_OK;
927
928 return 0;
929}
930int req_on_list_streams(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
931 unsigned char filter, cmp;
932 uint32_t id;
933 int streams[ROAR_STREAMS_MAX];
934 int i, c = 0;
935 int match;
936
937 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
938  return -1;
939
940 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
941  if ( g_streams[i] == NULL )
942   continue;
943
944  match = 0;
945
946  switch (filter) {
947   case ROAR_CTL_FILTER_ANY:
948     match = 1;
949    break;
950   case ROAR_CTL_FILTER_DIR:
951     match = roar_filter_match(cmp, id, ROAR_STREAM(g_streams[i])->dir);
952    break;
953   default: // unsupported filter...
954     return -1;
955    break;
956  }
957
958  if ( match )
959   streams[c++] = i;
960 }
961
962 roar_ctl_ia2m(mes, streams, c);
963
964 mes->cmd = ROAR_CMD_OK;
965
966 return 0;
967}
968
969int req_on_get_client  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
970 struct roar_client * c;
971
972 if ( mes->datalen != 1 )
973  return -1;
974
975 if ( clients_get(mes->data[0], &c) == -1 )
976  return -1;
977
978 mes->cmd = ROAR_CMD_OK;
979
980 return roar_ctl_c2m(mes, c);
981}
982
983int req_on_get_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
984 struct roar_stream_server * s;
985
986 if ( mes->datalen != 1 )
987  return -1;
988
989 if ( streams_get(mes->data[0], &s) == -1 )
990  return -1;
991
992 mes->cmd = ROAR_CMD_OK;
993 mes->stream = mes->data[0];
994
995 return roar_stream_s2m(ROAR_STREAM(s), mes);
996}
997
998int req_on_get_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
999 struct roar_stream * s;
1000 struct roar_stream_server * ss;
1001 struct roar_audio_info * audio_info;
1002 struct roar_stream_ltm * ltm;
1003 uint16_t * d  = (uint16_t *) mes->data;
1004 int64_t * d64 = ( int64_t *) mes->data;
1005 int64_t * d64ptr;
1006 int i, h, k;
1007 char * str;
1008 size_t needed;
1009 int test, bits;
1010
1011 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);
1012
1013 if ( mes->datalen < 4 )
1014  return -1;
1015
1016 for (i = 0; i < 2; i++) {
1017  d[i] = ROAR_NET2HOST16(d[i]);
1018 }
1019
1020 if ( d[0] != 0 ) {
1021  ROAR_WARN("req_on_get_stream_para(*): unsupported command version: %i, %i", (int)d[0], (int)d[1]);
1022  return -1;
1023 }
1024
1025 switch (d[1]) {
1026  case ROAR_STREAM_PARA_INFO:
1027    if ( streams_get(mes->stream, &ss) == -1 ) {
1028     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
1029     return -1;
1030    }
1031
1032    if ( streams_calc_delay(mes->stream) == -1 ) {
1033     ROAR_WARN("req_on_get_stream_para(*): can not calc delay for stream %i", mes->stream);
1034    }
1035
1036    s = ROAR_STREAM(ss);
1037
1038    audio_info = &(s->info);
1039
1040    mes->datalen = 2*12;
1041
1042    d[ 2] = ROAR_OUTPUT_CALC_OUTBUFSIZE(audio_info);
1043    d[ 3] = ss->pre_underruns;
1044    d[ 4] = ss->post_underruns;
1045    d[ 5] = ss->codec_orgi;
1046    d[ 6] = (ss->flags & 0xFFFF) | (ss->primary ? ROAR_FLAG_PRIMARY : 0) | (ss->driver_id != -1 ? ROAR_FLAG_OUTPUT : 0);
1047    d[ 7] = ss->delay/1000;
1048    d[ 8] = ss->state;
1049    d[ 9] = (ss->flags & 0xFFFF0000) >> 16;
1050    d[10] = ss->mixer_stream;
1051    d[11] = ss->role;
1052
1053    ROAR_DBG("req_on_get_stream_para(*): ss->driver_id=%i", ss->driver_id);
1054
1055    ROAR_DBG("req_on_get_stream_para(*): delay=%i, send delay=%i", ss->delay, d[7]);
1056
1057    for (i = 0; i < mes->datalen/2; i++) {
1058     d[i] = ROAR_HOST2NET16(d[i]);
1059    }
1060
1061    mes->pos = s->pos;
1062   break;
1063
1064  case ROAR_STREAM_PARA_NAME:
1065   str = streams_get_name(mes->stream);
1066
1067   if ( str == NULL )
1068    return -1;
1069
1070    mes->datalen = 4 + strlen(str);
1071
1072    if ( mes->datalen > LIBROAR_BUFFER_MSGDATA )
1073     return -1;
1074
1075    strncpy(((char*)&(mes->data))+4, str, mes->datalen);
1076
1077    d[0] = ROAR_HOST2NET16(d[0]);
1078    d[1] = ROAR_HOST2NET16(d[1]);
1079   break;
1080
1081  case ROAR_STREAM_PARA_CHANMAP:
1082    if ( streams_get(mes->stream, &ss) == -1 ) {
1083     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
1084     return -1;
1085    }
1086
1087    s = ROAR_STREAM(ss);
1088
1089    memcpy(&(mes->data[4]), ss->chanmap.in, s->info.channels);
1090    mes->datalen = 2*2 + s->info.channels;
1091
1092    d[0] = ROAR_HOST2NET16(d[0]);
1093    d[1] = ROAR_HOST2NET16(d[1]);
1094   break;
1095
1096  case ROAR_STREAM_PARA_LTM:
1097    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request...", client);
1098
1099    if ( mes->datalen < (6 * 2) ) {
1100     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: message too short", client);
1101     return -1;
1102    }
1103
1104    for (i = 2; i < mes->datalen/2; i++) {
1105     d[i] = ROAR_NET2HOST16(d[i]);
1106    }
1107
1108    if ( d[2] != ROAR_LTM_SST_GET_RAW ) {
1109     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: unknown LTM subtype: %i", client, (int)d[2]);
1110     return -1;
1111    }
1112
1113    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request of type GET_RAW", client);
1114
1115    test = d[5];
1116    bits = 0;
1117    while (test) {
1118     if ( test & 0x1 )
1119      bits++;
1120
1121     test >>= 1;
1122    }
1123
1124    needed = 0;
1125
1126    if ( mes->stream == -1 ) {
1127     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM multi-stream request...", client);
1128
1129     for (i = 6; i < mes->datalen/2; i++) {
1130      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
1131       return -1;
1132
1133      needed += ltm->channels;
1134     }
1135    } else {
1136     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM single-stream request for stream %i...", client, mes->stream);
1137     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
1138      return -1;
1139
1140     needed = ltm->channels;
1141    }
1142
1143    needed *= bits;
1144
1145    needed += mes->stream == -1 ? (mes->datalen/2) - 6 : 1;
1146
1147    ROAR_DBG("req_on_get_stream_para(client=%i, ...): data size for answer is %i 64 bit sub-packets", client, (int)needed);
1148
1149    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1150    d64 = _dataspace(mes, data, flags, needed * 8);
1151    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1152
1153    if ( (d = roar_mm_malloc(mes->datalen)) == NULL )
1154     return -1;
1155
1156    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d=%p, data=%p{%p}", client, d, data, *data);
1157
1158
1159    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1160    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1161    memcpy(d, mes->data, mes->datalen);
1162    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1163
1164    d64ptr = d64;
1165
1166    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1167    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1168
1169    if ( mes->stream == -1 ) {
1170     for (i = 6; i < mes->datalen/2; i++) {
1171      ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1172
1173      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
1174       return -1;
1175
1176      *d64ptr = ltm->channels & 0xFFFF;
1177       d64ptr++;
1178
1179      for (h = 0; h < ltm->channels; h++) {
1180       for (k = 0; k < ROAR_LTM_MTBITS; k++) {
1181        if ( d[5] & (1<<k) ) {
1182         switch (1<<k) {
1183          case ROAR_LTM_MT_RMS:
1184            *d64ptr = ltm->cur[h].rms;
1185           break;
1186          default:
1187            ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
1188         }
1189         d64ptr++;
1190        }
1191       }
1192      }
1193     }
1194    } else {
1195     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
1196      return -1;
1197
1198     *d64ptr = ltm->channels & 0xFFFF;
1199      d64ptr++;
1200
1201     for (h = 0; h < ltm->channels; h++) {
1202      for (k = 0; k < ROAR_LTM_MTBITS; k++) {
1203       if ( d[5] & (1<<k) ) {
1204        switch (1<<k) {
1205         case ROAR_LTM_MT_RMS:
1206           *d64ptr = ltm->cur[h].rms;
1207           ROAR_DBG("req_on_get_stream_para(client=%i, ...): rms=%lli to %p", client, (long long int)*d64ptr, d64ptr);
1208          break;
1209         default:
1210           ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
1211        }
1212        d64ptr++;
1213       }
1214      }
1215     }
1216    }
1217
1218    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1219
1220    roar_mm_free(d);
1221
1222    for (i = 0; i < needed; i++) {
1223     d64[i] = ROAR_HOST2NET64(d64[i]);
1224    }
1225
1226    mes->datalen = needed * 8;
1227    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM d64=%p, d64ptr=%p", client, d64, d64ptr);
1228    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM final message has %i byte of data", client, (int)mes->datalen);
1229    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1230    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM GET_RAW request: OK. returning...", client);
1231   break;
1232
1233  default:
1234    ROAR_WARN("req_on_get_stream_para(*): unsupported command: %i", d[1]);
1235    return -1;
1236 }
1237
1238 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);
1239 mes->cmd = ROAR_CMD_OK;
1240 return 0;
1241}
1242
1243int req_on_set_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1244 struct roar_stream_server * ss;
1245 uint16_t * d = (uint16_t *) mes->data;
1246 uint32_t tmp, tmp2, flagstore;
1247 int protect = 0;
1248 int i;
1249
1250 if ( mes->datalen < 2*2 )
1251  return -1;
1252
1253 for (i = 0; i < 2; i++) {
1254  d[i] = ROAR_NET2HOST16(d[i]);
1255 }
1256
1257 if ( d[0] != 0 )
1258  return -1;
1259
1260 switch (d[1]) {
1261  case ROAR_STREAM_PARA_FLAGS:
1262    if ( mes->datalen != 2*4 && mes->datalen != 2*5 )
1263     return -1;
1264
1265    d[2] = ROAR_NET2HOST16(d[2]);
1266    d[3] = ROAR_NET2HOST16(d[3]);
1267
1268    ROAR_DBG("req_on_set_stream_para(*): request seems to be valid");
1269
1270    tmp = 0;
1271
1272    if ( mes->datalen == 2*5 ) {
1273     d[4] = ROAR_NET2HOST16(d[4]);
1274     tmp   = d[4];
1275     tmp <<= 16;
1276    }
1277
1278    tmp |= d[3];
1279
1280    if ( d[2] & ROAR_PROTECT_FLAG ) {
1281     protect = 1;
1282     d[2] -= ROAR_PROTECT_FLAG;
1283    }
1284
1285    switch (d[2]) {
1286     case ROAR_SET_FLAG:
1287       if ( streams_set_flag(mes->stream, tmp) == -1 )
1288        return -1;
1289      break;
1290     case ROAR_RESET_FLAG:
1291       if ( streams_reset_flag(mes->stream, tmp) == -1 )
1292        return -1;
1293      break;
1294     case ROAR_NOOP_FLAG:
1295      break;
1296     case ROAR_TOGGLE_FLAG:
1297       if ( streams_get(mes->stream, &ss) == -1 )
1298        return -1;
1299
1300       flagstore = ss->flags;
1301
1302       tmp2 = flagstore & tmp; // those are the flags we need to reset.
1303       ROAR_DBG("req_on_set_stream_para(*): tmp2=0x%.8lx", (long int)tmp2);
1304       if ( tmp2 )
1305        if ( streams_reset_flag(mes->stream, tmp2) == -1 )
1306         return -1;
1307
1308       tmp2 = (flagstore ^ tmp) & tmp; // those are the flags we need to set.
1309       ROAR_DBG("req_on_set_stream_para(*): tmp2=0x%.8lx", (long int)tmp2);
1310       if ( tmp2 )
1311        if ( streams_set_flag(mes->stream, tmp2) == -1 )
1312         return -1;
1313      break;
1314     default:
1315       return -1;
1316      break;
1317    }
1318
1319   ROAR_DBG("req_on_set_stream_para(*): protect=%i", protect);
1320   if ( protect )
1321    if ( streams_protect_flag(mes->stream, tmp) == -1 )
1322     return -1;
1323
1324   break;
1325  case ROAR_STREAM_PARA_CHANMAP:
1326    if ( streams_set_map(mes->stream, &(mes->data[4]), mes->datalen - 4) == -1 )
1327     return -1;
1328   break;
1329  case ROAR_STREAM_PARA_ROLE:
1330    if ( mes->datalen != 2*3 )
1331     return -1;
1332
1333    d[2] = ROAR_NET2HOST16(d[2]);
1334
1335    if ( streams_set_role(mes->stream, d[2]) == -1 )
1336     return -1;
1337   break;
1338  case ROAR_STREAM_PARA_LTM:
1339    if ( mes->datalen < (6 * 2) )
1340     return -1;
1341
1342    for (i = 2; i < mes->datalen/2; i++) {
1343     d[i] = ROAR_NET2HOST16(d[i]);
1344    }
1345
1346    if ( mes->stream == -1 ) {
1347     for (i = 6; i < mes->datalen/2; i++)
1348      if ( streams_ltm_ctl(d[i], d[5], d[3], d[2]) == -1 )
1349       return -1;
1350    } else {
1351     if ( streams_ltm_ctl(mes->stream, d[5], d[3], d[2]) == -1 )
1352      return -1;
1353    }
1354   break;
1355  default:
1356    ROAR_WARN("req_on_set_stream_para(*): unsupported command version: %i, %i", d[0], d[1]);
1357    return -1;
1358   break;
1359 }
1360
1361 mes->cmd     = ROAR_CMD_OK;
1362 mes->datalen = 0;
1363
1364 return 0;
1365}
1366
1367int req_on_kick (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1368 struct roar_stream_server * ss;
1369 uint16_t * info = (uint16_t *) mes->data;
1370 int is_stream = 0;
1371
1372 if ( mes->datalen != 4 )
1373  return -1;
1374
1375 info[0] = ROAR_NET2HOST16(info[0]);
1376 info[1] = ROAR_NET2HOST16(info[1]);
1377
1378 switch (info[0]) {
1379  case ROAR_OT_CLIENT:
1380    clients_delete(info[1]);
1381   break;
1382  case ROAR_OT_STREAM:
1383    is_stream = 1;
1384   break;
1385  case ROAR_OT_SOURCE:
1386    if ( streams_get_flag(info[1], ROAR_FLAG_SOURCE) != 1 )
1387     return -1;
1388    is_stream = 1;
1389   break;
1390  case ROAR_OT_OUTPUT:
1391    if ( streams_get(info[1], &ss) == -1 )
1392     return -1;
1393
1394    if ( ss->driver_id == -1 )
1395     return -1;
1396
1397    is_stream = 1;
1398   break;
1399  case ROAR_OT_MIXER:
1400    if ( streams_get(info[1], &ss) == -1 )
1401     return -1;
1402
1403    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_MIXING )
1404     return -1;
1405
1406    is_stream = 1;
1407   break;
1408  case ROAR_OT_BRIDGE:
1409    if ( streams_get(info[1], &ss) == -1 )
1410     return -1;
1411
1412    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_BRIDGE )
1413     return -1;
1414
1415    is_stream = 1;
1416   break;
1417  default:
1418/* TODO: those types should be handled, too:
1419#define ROAR_OT_SAMPLE    4
1420#define ROAR_OT_LISTEN    8
1421#define ROAR_OT_ACTION    9
1422#define ROAR_OT_MSGQUEUE 10
1423#define ROAR_OT_MSGBUS   11
1424*/
1425    return -1;
1426   break;
1427 }
1428
1429 if ( is_stream ) {
1430  if ( streams_get_flag(info[1], ROAR_FLAG_IMMUTABLE) == 1 )
1431   return -1;
1432
1433  streams_delete(info[1]);
1434 }
1435
1436 mes->cmd     = ROAR_CMD_OK;
1437 mes->datalen = 0;
1438
1439 return 0;
1440}
1441
1442int req_on_attach      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1443 uint16_t * info = (uint16_t *) mes->data;
1444
1445 if ( mes->datalen < 6 )
1446  return -1;
1447
1448 info[0] = ROAR_NET2HOST16(info[0]);
1449 info[1] = ROAR_NET2HOST16(info[1]);
1450 info[2] = ROAR_NET2HOST16(info[2]);
1451
1452 if ( info[0] != 0 )
1453  return -1;
1454
1455 if ( info[1] == ROAR_ATTACH_SIMPLE ) {
1456  if ( client_stream_move(info[2], mes->stream) == -1 )
1457   return -1;
1458 } else {
1459  return -1;
1460 }
1461
1462 mes->cmd     = ROAR_CMD_OK;
1463 mes->datalen = 0;
1464
1465 return 0;
1466}
1467
1468int req_on_set_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1469 struct roar_mixer_settings tmpmixer;
1470 struct roar_stream_server * s;
1471 uint16_t * info = (uint16_t *) mes->data;
1472 uint16_t   version;
1473 uint16_t   scale = 65535;
1474 int stream;
1475 int i;
1476 int chans;
1477
1478 ROAR_DBG("req_on_set_vol(*) = ?");
1479 ROAR_DBG("req_on_set_vol(*): mes->datalen=%i", mes->datalen);
1480
1481 if ( mes->datalen < (4*2) )
1482  return -1;
1483
1484 version = ROAR_NET2HOST16(info[0]);
1485 ROAR_DBG("req_on_set_vol(*): version=%i", (int)version);
1486
1487 switch (version) {
1488  case 0:
1489    stream = ROAR_NET2HOST16(info[1]);
1490   break;
1491  case 1:
1492    stream = mes->stream;
1493    scale  = ROAR_NET2HOST16(info[1]);
1494   break;
1495  default:
1496    return -1;
1497   break;
1498 }
1499 ROAR_DBG("req_on_set_vol(*): stream=%i", stream);
1500
1501 if ( scale == 0 )
1502  return -1;
1503
1504 // TODO: change this code.
1505 //       we should not directly change the stream object but use some stream_*()-func
1506 //       for that job.
1507
1508 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1509  return -1;
1510
1511 s = g_streams[stream];
1512
1513 if ( s == NULL )
1514  return -1;
1515
1516 ROAR_DBG("req_on_set_vol(*): s=%p", s);
1517
1518 info[2] = ROAR_NET2HOST16(info[2]);
1519
1520 switch (info[2]) {
1521  case ROAR_SET_VOL_ALL:
1522    chans = (mes->datalen/2) - 3;
1523    ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ALL, channes=%i", chans);
1524
1525    if ( chans >= ROAR_MAX_CHANNELS )
1526     return -1;
1527
1528    ROAR_DBG("req_on_set_vol(*): mixer at %p", s->mixer.mixer);
1529
1530    for (i = 0; i < chans; i++) {
1531     s->mixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
1532     ROAR_DBG("req_on_set_vol(*): channel %i: %i", i, ROAR_NET2HOST16(info[i+3]));
1533    }
1534
1535    s->mixer.scale = scale;
1536
1537    ROAR_DBG("req_on_set_vol(*): mixer changed!");
1538
1539   break;
1540  case ROAR_SET_VOL_ONE:
1541    ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ONE");
1542    if ( ROAR_NET2HOST16(info[3]) >= ROAR_MAX_CHANNELS )
1543     return -1;
1544
1545    s->mixer.mixer[ROAR_NET2HOST16(info[3])] = ROAR_NET2HOST16(info[4]);
1546
1547    s->mixer.scale = scale;
1548   break;
1549  case ROAR_SET_VOL_UNMAPPED:
1550    chans = (mes->datalen/2) - 3;
1551
1552    if ( chans >= ROAR_MAX_CHANNELS )
1553     return -1;
1554
1555    memcpy(&tmpmixer, &(s->mixer), sizeof(tmpmixer));
1556
1557    for (i = 0; i < chans; i++) {
1558     tmpmixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
1559    }
1560
1561    tmpmixer.scale = scale;
1562
1563    if ( roar_conv_volume(&(s->mixer), &tmpmixer, ROAR_STREAM(s)->info.channels, chans) == -1 )
1564     return -1;
1565
1566   break;
1567  case ROAR_SET_VOL_MS:
1568  default:
1569    return -1;
1570 }
1571
1572 if ( streams_set_mixer(stream) == -1 )
1573  return -1;
1574
1575 mes->cmd     = ROAR_CMD_OK;
1576 mes->datalen = 0;
1577
1578 return 0;
1579}
1580
1581int req_on_get_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1582 uint16_t * info = (uint16_t *) mes->data;
1583 uint16_t   version = -1;
1584 int stream;
1585 struct roar_stream_server * s;
1586 int i;
1587 int chans;
1588
1589 ROAR_DBG("req_on_get_vol(*) = ?");
1590 ROAR_DBG("req_on_get_vol(*): mes->datalen=%i", mes->datalen);
1591
1592 if ( mes->datalen < 2 ) {
1593  return -1;
1594 }
1595
1596 version = ROAR_NET2HOST16(info[0]);
1597
1598 switch (version) {
1599  case 0:
1600    if ( mes->datalen < (2*2) )
1601     return -1;
1602
1603    stream = ROAR_NET2HOST16(info[1]);
1604   break;
1605  case 1:
1606    stream = mes->stream;
1607   break;
1608  default:
1609    return -1;
1610   break;
1611 }
1612
1613 ROAR_DBG("req_on_get_vol(*): stream=%i", stream);
1614
1615 // TODO: change this code.
1616 //       we should not directly change the stream object but use some stream_*()-func
1617 //       for that job.
1618
1619 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1620  return -1;
1621
1622 s = g_streams[stream];
1623
1624 if ( s == NULL )
1625  return -1;
1626
1627 ROAR_DBG("req_on_get_vol(*): s=%p", s);
1628
1629 // ok, we have everything
1630
1631 info[0] = ROAR_HOST2NET16(version);
1632
1633 switch (version) {
1634  case 0:
1635    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1636
1637    for (i = 0; i < chans; i++)
1638     info[2+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1639
1640     mes->datalen = (2 + chans)*2;
1641   break;
1642  case 1:
1643    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1644    info[2] = ROAR_HOST2NET16(s->mixer.scale);
1645    info[3] = ROAR_HOST2NET16(s->mixer.rpg_mul);
1646    info[4] = ROAR_HOST2NET16(s->mixer.rpg_div);
1647
1648    for (i = 0; i < chans; i++)
1649     info[5+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1650
1651     mes->datalen = (5 + chans)*2;
1652   break;
1653  default:
1654    return -1;
1655   break;
1656 }
1657
1658 mes->cmd = ROAR_CMD_OK;
1659
1660 return 0;
1661}
1662
1663int req_on_add_data (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1664 struct roar_buffer * b;
1665 void               * buf;
1666
1667 if ( roar_buffer_new_data(&b, mes->datalen, &buf) == -1 ) {
1668  ROAR_ERR("req_on_add_data(*): Can not alloc buffer space!");
1669  ROAR_DBG("req_on_add_data(*) = -1");
1670  return -1;
1671 }
1672
1673 if ( data == NULL ) {
1674  memcpy(buf, mes->data, mes->datalen);
1675 } else {
1676  memcpy(buf, *data, mes->datalen);
1677 }
1678
1679 if ( stream_add_buffer(mes->stream, b) == -1 ) {
1680  roar_buffer_free(b);
1681  return -1;
1682 }
1683
1684 mes->cmd     = ROAR_CMD_OK_STOP;
1685 mes->datalen = 0;
1686
1687 return 0;
1688}
1689
1690int req_on_beep        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1691 struct roar_beep bs;
1692 int16_t * info = (int16_t*)mes->data;
1693 int stream;
1694
1695 memset(&bs, 0, sizeof(bs));
1696
1697 if ( mes->datalen > 0 ) {
1698  if ( mes->datalen < 2 )
1699   return -1;
1700
1701  if ( ROAR_NET2HOST16(info[0]) != 0 ) /* version */
1702   return -1;
1703
1704  if ( mes->datalen != 8*2 )
1705   return -1;
1706
1707  bs.vol  = ROAR_NET2HOST16(info[1]);
1708  bs.time = ROAR_NET2HOST16(info[2]);
1709  bs.freq = ROAR_NET2HOST16(info[3]);
1710  bs.type = ROAR_NET2HOST16(info[4]);
1711  bs.x    = ROAR_NET2HOST16(info[5]);
1712  bs.y    = ROAR_NET2HOST16(info[6]);
1713  bs.z    = ROAR_NET2HOST16(info[7]);
1714 }
1715
1716 if ( (stream = beep_start(client, &bs)) == -1 )
1717  return -1;
1718
1719 mes->stream  = stream;
1720 mes->cmd     = ROAR_CMD_OK_STOP;
1721 mes->datalen = 0;
1722
1723 return 0;
1724}
1725
1726int req_on_wait        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1727 uint16_t * u16 = (uint16_t*)mes->data;
1728 struct roar_event events[4];
1729 size_t left, tmp;
1730 size_t num = 0;
1731 void * vp = mes->data;
1732
1733 vp += 4;
1734
1735 // check for complet header...
1736 if ( mes->datalen < 4 )
1737  return -1;
1738
1739 u16[0] = ROAR_NET2HOST16(u16[0]);
1740 u16[1] = ROAR_NET2HOST16(u16[1]);
1741
1742 // do we support version and flags?
1743 if ( u16[0] != 0 || u16[1] != 0 )
1744  return -1;
1745
1746 memset(events, 0, sizeof(events));
1747
1748 left = mes->datalen - 4;
1749
1750 while (left) {
1751  tmp = left;
1752  if ( roar_event_from_blob(&(events[num]), vp, &tmp) == -1 )
1753   return -1;
1754
1755  vp   += tmp;
1756  left -= tmp;
1757  num++;
1758 }
1759
1760 if ( clients_wait(client, events, num) == -1 )
1761  return -1;
1762
1763 flags[1] |= COMMAND_FLAG_OUT_NOSEND;
1764
1765 return 0;
1766}
1767
1768//ll
Note: See TracBrowser for help on using the repository browser.