source: roaraudio/roard/req.c @ 4745:1e974ec321bd

Last change on this file since 4745:1e974ec321bd was 4745:1e974ec321bd, checked in by phi, 13 years ago

Better auth type oder support (Closes: #6)

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