source: roaraudio/roard/req.c @ 1143:252903e35adc

Last change on this file since 1143:252903e35adc was 1142:f940ed8ab4f0, checked in by phi, 15 years ago

added parameter for stream delay

File size: 15.8 KB
RevLine 
[668]1//req.c:
[486]2
[668]3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008
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, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
[0]24
25#include "roard.h"
26
27int req_on_noop        (int client, struct roar_message * mes, char * data) {
28 mes->cmd     = ROAR_CMD_OK;
29 mes->datalen = 0;
30 return 0;
31}
32
33int req_on_identify    (int client, struct roar_message * mes, char * data) {
34 struct roar_client * c;
35 int max_len;
36
37 if ( mes->datalen < 1 )
38  return -1;
39
40 clients_get(client, &c);
41
42 if ( mes->data[0] == 1 ) {
[436]43  if ( c->pid == -1 ) {
44   c->pid       = ROAR_NET2HOST32(*(uint32_t*)((mes->data)+1));
[443]45   ROAR_DBG("req_on_identify(): new PID: c->pid = %i", c->pid);
[436]46  }
[0]47
[443]48  ROAR_DBG("req_on_identify(): final PID: c->pid = %i", c->pid);
49
[0]50  max_len = (mes->datalen - 5) < (ROAR_BUFFER_NAME-1) ? (mes->datalen - 5) : (ROAR_BUFFER_NAME-1);
51
52  strncpy(c->name, mes->data + 5, max_len);
53  c->name[max_len] = 0;
54
55  mes->cmd     = ROAR_CMD_OK;
56  mes->datalen = 0;
57
58  ROAR_DBG("req_on_identify(*): client=%i, pid=%i", client, c->pid);
59  ROAR_DBG("req_on_identify(*) = 0");
60  return 0;
61 }
62
63 return -1;
64}
65
66int req_on_auth        (int client, struct roar_message * mes, char * data) {
67 // TODO: add code to support some auth.
68 mes->cmd     = ROAR_CMD_OK;
69 mes->datalen = 0;
70 return 0;
71}
72
73
74int req_on_new_stream  (int client, struct roar_message * mes, char * data) {
75 int stream;
76 struct roar_stream * s;
77
78 if ((stream = streams_new()) == -1 )
79  return -1;
80
81 if ( streams_get(stream, (struct roar_stream_server **)&s) == -1 ) {
82  streams_delete(stream);
83  return -1;
84 }
85
86 if ( client_stream_add(client, stream) == -1 ) {
87  streams_delete(stream);
88  return -1;
89 }
90
91 if ( roar_stream_m2s(s, mes) == -1 ) {
92  streams_delete(stream);
93  return -1;
94 }
95
[486]96 ROAR_STREAM(s)->id = stream; // roar_stream_m2s() resets this
[539]97 ROAR_STREAM_SERVER(s)->codec_orgi = ROAR_STREAM(s)->info.codec;
[486]98
[0]99 mes->cmd     = ROAR_CMD_OK;
100 mes->stream  = stream;
101 mes->datalen = 0;
102
103 return 0;
104}
105
106int req_on_exec_stream (int client, struct roar_message * mes, char * data) {
107 int r;
108
109 if ( (r = client_stream_exec(client, mes->stream)) == -1 )
110  return -1;
111
112 mes->cmd     = ROAR_CMD_OK;
113 mes->datalen = 0;
114
115 return 0;
116}
117
[77]118int req_on_con_stream  (int client, struct roar_message * mes, char * data) {
119 char   host[80] = {0};
120 int    port = 0;
121 int    type;
122 int    fh;
123 int    len;
124
125 if ( mes->datalen < 4 )
126  return -1;
127
128 if ( *(mes->data) != 0 )
129  return -1;
130
[80]131 if ( mes->datalen > 80 ) // we do not support long messages here
132  return -1;
133
[77]134 type = (unsigned)mes->data[1];
[79]135 port = ROAR_NET2HOST16(((uint16_t*)mes->data)[1]);
[77]136
[80]137 len = mes->datalen - 4;
[77]138
[84]139 strncpy(host, &(mes->data[4]), len);
[77]140 host[len] = 0;
141
142 if ( type > ROAR_SOCKET_TYPE_MAX )
143  return -1;
144
145 if ( type == ROAR_SOCKET_TYPE_FILE ) // disabled because of security resons
146  return -1;
147
148 if ( type == ROAR_SOCKET_TYPE_FORK ) // why should we connect to ourself?
149  return -1;
150
[525]151 ROAR_DBG("req_on_con_stream(*): CONNECT(type=%i, host='%s', port=%i)", type, host, port);
152
[77]153 if ( (fh = roar_socket_open(ROAR_SOCKET_MODE_CONNECT, type, host, port)) == -1 )
154  return -1;
155
[78]156 if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
157  close(fh);
158  return 1;
159 }
160
[757]161 mes->datalen = 0;
162 mes->cmd     = ROAR_CMD_OK;
163
[78]164 return 0;
[757]165}
166
167int req_on_passfh      (int client, struct roar_message * mes, char * data) {
168 int fh;
169 int sock = clients_get_fh(client);
170
171 if ( (fh = roar_socket_recv_fh(sock, NULL, NULL)) == -1 )
172  return -1;
173
174 if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
175  close(fh);
176  return 1;
177 }
178
[78]179
180 mes->datalen = 0;
181 mes->cmd     = ROAR_CMD_OK;
[757]182
183 return 0;
[77]184}
185
[0]186int req_on_set_meta    (int client, struct roar_message * mes, char * data) {
[92]187 int type;
188 int mode;
189 int namelen, vallen;
[99]190 char   val[255+1];
[92]191 char   name[ROAR_META_MAX_NAMELEN+1];
192
193 if ( mes->datalen < 3 )
194  return -1;
195
196 if ( mes->data[0] != 0 ) // version
197  return -1;
198
199 mode = (unsigned) mes->data[1];
200 type = (unsigned) mes->data[2];
201
[99]202 ROAR_DBG("req_on_set_meta(*): mode=%i, type=%i", mode, type);
203
[92]204 if ( mode == ROAR_META_MODE_CLEAR ) {
205  stream_meta_clear(mes->stream);
206  mes->datalen = 0;
207  mes->cmd     = ROAR_CMD_OK;
208  return 0;
209 } else if ( mode == ROAR_META_MODE_DELETE ) { // unsuppoerted at the moment
[1038]210  return -1;
211 } else if ( mode == ROAR_META_MODE_FINALIZE ) {
212  stream_meta_finalize(mes->stream);
213  mes->datalen = 0;
214  mes->cmd     = ROAR_CMD_OK;
215  return 0;
[92]216 } else if ( mode == ROAR_META_MODE_SET || mode == ROAR_META_MODE_ADD ) {
217  if ( mes->datalen < 5 )
218   return -1;
219
220  namelen = (unsigned) mes->data[3];
221  vallen  = (unsigned) mes->data[4];
222
[99]223  ROAR_DBG("req_on_set_meta(*): namelen=%i, vallen=%i", namelen, vallen);
224
[92]225  if ( mes->datalen < (5 + namelen + vallen) )
226   return -1;
227
228  if ( namelen > ROAR_META_MAX_NAMELEN )
229   return -1;
230
231  strncpy(name, &(mes->data[5]), namelen);
232  name[namelen] = 0;
233
[99]234  if ( vallen > 255 )
[92]235   return -1;
236
237  strncpy(val, &(mes->data[5+namelen]), vallen);
238  val[vallen] = 0;
239
240  if ( mode == ROAR_META_MODE_SET ) {
241   if ( stream_meta_set(mes->stream, type, name, val) == -1 )
242    return -1;
243  } else {
244   if ( stream_meta_add(mes->stream, type, name, val) == -1 )
245    return -1;
246  }
247
248  mes->datalen = 0;
249  mes->cmd     = ROAR_CMD_OK;
250  return 0;
251 } else { // unknown mode!
252  return -1;
253 }
254
[0]255 return -1;
256}
257
[100]258int req_on_get_meta    (int client, struct roar_message * mes, char * data) {
[101]259 int vallen;
260 int type;
[107]261 char val[LIBROAR_BUFFER_MSGDATA-1];
[101]262
263 if ( mes->datalen != 2 )
264  return -1;
265
266 if ( mes->data[0] != 0 ) // version
267  return -1;
268
269 type = (unsigned) mes->data[1];
270
271 if ( stream_meta_get(mes->stream, type, NULL, val, LIBROAR_BUFFER_MSGDATA-2) == -1 )
272  return -1;
273
274 vallen = strlen(val);
275
276 mes->cmd     = ROAR_CMD_OK;
277 mes->datalen = 2 + vallen;
278
279 mes->data[0] = 0;
280 mes->data[1] = (unsigned char) vallen;
281
[107]282 val[vallen] = 0;
283
284 strncpy(&(mes->data[2]), val, vallen+1);
[101]285
286 return 0;
[100]287}
[0]288
[113]289int req_on_list_meta   (int client, struct roar_message * mes, char * data) {
290 int i;
291 int len = 0;
292 int types[ROAR_META_MAX_PER_STREAM];
293
294 if ( mes->datalen != 1 )
295  return -1;
296
297 if ( mes->data[0] != 0 ) // version
298  return -1;
299
300 if ( (len = stream_meta_list(mes->stream, types, ROAR_META_MAX_PER_STREAM)) == -1 )
301  return -1;
302
303 mes->cmd     = ROAR_CMD_OK;
304 mes->datalen = 1 + len;
305 mes->data[0] = 0;
306
307 for (i = 0; i < len; i++)
308  mes->data[i+1] = types[i];
309
310 return 0;
311}
312
[0]313int req_on_server_oinfo    (int client, struct roar_message * mes, char * data) {
314 struct roar_stream s;
315//ROAR_DIR_OUTPUT
316
[966]317 memset(&s, 0, sizeof(struct roar_stream));
[964]318
[977]319 s.dir           = ROAR_DIR_MIXING;
[0]320 s.pos_rel_id    = -1;
321 s.info.rate     = g_sa->rate;
322 s.info.bits     = g_sa->bits;
323 s.info.channels = g_sa->channels;
324 s.info.codec    = g_sa->codec;
[977]325 s.pos           = g_pos;
[0]326
327 if ( roar_stream_s2m(&s, mes) == -1 )
328  return -1;
329
330 mes->cmd = ROAR_CMD_OK;
331
332 return 0;
333}
334
335
336int req_on_get_standby (int client, struct roar_message * mes, char * data) {
337 mes->cmd = ROAR_CMD_OK;
338 mes->datalen = 2;
339
340 *((uint16_t*)mes->data) = ROAR_HOST2NET16((unsigned) g_standby);
341
342 return 0;
343}
344
345int req_on_set_standby (int client, struct roar_message * mes, char * data) {
346 if ( mes->datalen != 2 )
347  return -1;
348
349 g_standby = ROAR_NET2HOST16(*((uint16_t*)mes->data));
350
351 mes->cmd     = ROAR_CMD_OK;
352 mes->datalen = 0;
353
354 return 0;
355}
356
357int req_on_exit      (int client, struct roar_message * mes, char * data) {
[575]358 int term = 0;
359
360 if ( mes->datalen == 1 )
361  term = mes->data[0];
362
[0]363 mes->cmd     = ROAR_CMD_OK;
364 mes->datalen = 0;
365
[576]366 ROAR_DBG("req_on_exit(*): term=%i", term);
367
[575]368 if ( term ) {
369  cleanup_listen_socket(1);
370 } else {
371  alive = 0;
372 }
[0]373
374 return 0;
375}
376
377int req_on_list_clients(int client, struct roar_message * mes, char * data) {
378 unsigned char filter, cmp;
379 uint32_t id;
380 int clients[ROAR_CLIENTS_MAX];
381 int i, c = 0;
382
383 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
384  return -1;
385
386 // TODO: add code to support filter
387 if ( filter != ROAR_CTL_FILTER_ANY )
388  return -1;
389
390 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
391  if ( g_clients[i] != NULL ) {
392   clients[c++] = i;
393  }
394 }
395
396 roar_ctl_ia2m(mes, clients, c);
397
398 mes->cmd = ROAR_CMD_OK;
399
400 return 0;
401}
402int req_on_list_streams(int client, struct roar_message * mes, char * data) {
403 unsigned char filter, cmp;
404 uint32_t id;
405 int streams[ROAR_STREAMS_MAX];
406 int i, c = 0;
407
408 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
409  return -1;
410
411 // TODO: add code to support filter
412 if ( filter != ROAR_CTL_FILTER_ANY )
413  return -1;
414
415 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
416  if ( g_streams[i] != NULL ) {
417   streams[c++] = i;
418  }
419 }
420
421 roar_ctl_ia2m(mes, streams, c);
422
423 mes->cmd = ROAR_CMD_OK;
424
425 return 0;
426}
427
428int req_on_get_client  (int client, struct roar_message * mes, char * data) {
429 struct roar_client * c;
430
431 if ( mes->datalen != 1 )
432  return -1;
433
434 if ( clients_get(mes->data[0], &c) == -1 )
435  return -1;
436
437 mes->cmd = ROAR_CMD_OK;
438
439 return roar_ctl_c2m(mes, c);
440}
441
442int req_on_get_stream  (int client, struct roar_message * mes, char * data) {
443 struct roar_stream_server * s;
444
445 if ( mes->datalen != 1 )
446  return -1;
447
448 if ( streams_get(mes->data[0], &s) == -1 )
449  return -1;
450
451 mes->cmd = ROAR_CMD_OK;
[465]452 mes->stream = mes->data[0];
[0]453
454 return roar_stream_s2m(ROAR_STREAM(s), mes);
455}
456
[465]457int req_on_get_stream_para (int client, struct roar_message * mes, char * data) {
458 struct roar_stream * s;
[963]459 struct roar_stream_server * ss;
[465]460 struct roar_audio_info * audio_info;
461 uint16_t * d = (uint16_t *) mes->data;
462 int i;
463
464 if ( mes->datalen != 4 )
465  return -1;
466
467 for (i = 0; i < mes->datalen/2; i++) {
468  d[i] = ROAR_NET2HOST16(d[i]);
469 }
470
[963]471 if ( streams_get(mes->stream, &ss) == -1 ) {
[465]472  ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
473  return -1;
474 }
475
[1142]476 if ( sreams_calc_delay(mes->stream) == -1 ) {
477  ROAR_WARN("req_on_get_stream_para(*): can not calc delay for stream %i", mes->stream);
478 }
479
[963]480 s = ROAR_STREAM(ss);
481
[465]482 audio_info = &(s->info);
483
484 if ( d[0] != 0 || d[1] != 1 ) {
485  ROAR_WARN("req_on_get_stream_para(*): unsupported command version: %i, %i", d[0], d[1]);
486  return -1;
487 }
488
[1137]489 mes->datalen = 2*8;
[465]490
491 d[2] = ROAR_OUTPUT_CALC_OUTBUFSIZE(audio_info);
[963]492 d[3] = ss->pre_underruns;
493 d[4] = ss->post_underruns;
494 d[5] = ss->codec_orgi;
[1030]495 d[6] = ss->flags | (ss->primary ? ROAR_FLAG_PRIMARY : 0) | (ss->driver_id != -1 ? ROAR_FLAG_OUTPUT : 0);
[1137]496 d[7] = ss->delay/1000;
[465]497
498 for (i = 0; i < mes->datalen/2; i++) {
499  d[i] = ROAR_HOST2NET16(d[i]);
500 }
501
[964]502 mes->pos = s->pos;
503
[465]504 mes->cmd = ROAR_CMD_OK;
505 return 0;
506}
507
[1043]508int req_on_set_stream_para (int client, struct roar_message * mes, char * data) {
509 uint16_t * d = (uint16_t *) mes->data;
510 int i;
511
512 if ( mes->datalen != 8 )
513  return -1;
514
515 for (i = 0; i < mes->datalen/2; i++) {
516  d[i] = ROAR_NET2HOST16(d[i]);
517 }
518
519 if ( d[0] != 0 || d[1] != 2 ) {
520  ROAR_WARN("req_on_set_stream_para(*): unsupported command version: %i, %i", d[0], d[1]);
521  return -1;
522 }
523
524 mes->cmd     = ROAR_CMD_OK;
525 mes->datalen = 0;
526
[1044]527 ROAR_DBG("req_on_set_stream_para(*): request seems to be valid");
[1043]528
529 if ( d[2] == ROAR_RESET_FLAG ) {
530  return streams_reset_flag(mes->stream, d[3]);
531 } else {
532  return streams_set_flag(mes->stream, d[3]);
533 }
534
535 return -1;
536}
537
[0]538int req_on_kick (int client, struct roar_message * mes, char * data) {
[17]539 uint16_t * info = (uint16_t *) mes->data;
[0]540
541 if ( mes->datalen != 4 )
542  return -1;
543
[251]544 info[0] = ROAR_NET2HOST16(info[0]);
545 info[1] = ROAR_NET2HOST16(info[1]);
546
[0]547 if ( info[0] == ROAR_OT_CLIENT ) {
548  clients_delete(info[1]);
549 } else if ( info[0] == ROAR_OT_STREAM ) {
550  streams_delete(info[1]);
[1111]551 } else if ( info[0] == ROAR_OT_SOURCE ) {
552  if ( streams_get_flag(info[1], ROAR_FLAG_SOURCE) == 1 ) {
553   streams_delete(info[1]);
554  } else {
555   return -1;
556  }
[0]557 } else {
558  return -1;
559 }
560
561 mes->cmd     = ROAR_CMD_OK;
562 mes->datalen = 0;
563
564 return 0;
565}
566
[768]567int req_on_attach      (int client, struct roar_message * mes, char * data) {
[769]568 uint16_t * info = (uint16_t *) mes->data;
569
570 if ( mes->datalen < 6 )
571  return -1;
572
573 info[0] = ROAR_NET2HOST16(info[0]);
574 info[1] = ROAR_NET2HOST16(info[1]);
575 info[2] = ROAR_NET2HOST16(info[2]);
576
577 if ( info[0] != 0 )
578  return -1;
579
580 if ( info[1] == ROAR_ATTACH_SIMPLE ) {
581  if ( client_stream_move(info[2], mes->stream) == -1 )
582   return -1;
583 } else {
584  return -1;
585 }
586
587 mes->cmd     = ROAR_CMD_OK;
588 mes->datalen = 0;
589
590 return 0;
[768]591}
592
[17]593int req_on_set_vol (int client, struct roar_message * mes, char * data) {
594 uint16_t * info = (uint16_t *) mes->data;
595 int stream;
596 struct roar_stream_server * s;
597 int i;
598 int chans;
599
600 ROAR_DBG("req_on_set_vol(*) = ?");
601 ROAR_DBG("req_on_set_vol(*): mes->datalen=%i", mes->datalen);
602
603 if ( mes->datalen < (4*2) )
604  return -1;
605
606 if ( info[0] != 0 ) // version
607  return -1;
608
[252]609 stream = ROAR_NET2HOST16(info[1]);
[17]610 ROAR_DBG("req_on_set_vol(*): stream=%i", stream);
611
612 // TODO: change this code.
613 //       we should not directly change the stream object but use some stream_*()-func
614 //       for that job.
615
616 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
617  return -1;
618
619 s = g_streams[stream];
620
621 if ( s == NULL )
622  return -1;
623
624 ROAR_DBG("req_on_set_vol(*): s=%p", s);
625
[252]626 info[2] = ROAR_NET2HOST16(info[2]);
627
[17]628 if ( info[2] == ROAR_SET_VOL_ALL ) {
629  chans = (mes->datalen/2) - 3;
630  ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ALL, channes=%i", chans);
631
632  if ( chans >= ROAR_MAX_CHANNELS )
633   return -1;
634
[18]635  ROAR_DBG("req_on_set_vol(*): mixer at %p", s->mixer.mixer);
636
[17]637  for (i = 0; i < chans; i++) {
[252]638   s->mixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
639   ROAR_DBG("req_on_set_vol(*): channel %i: %i", i, ROAR_NET2HOST16(info[i+3]));
[17]640  }
641
642  ROAR_DBG("req_on_set_vol(*): mixer changed!");
643
644 } else if ( info[2] == ROAR_SET_VOL_ONE ) {
645  ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ONE");
[252]646  if ( ROAR_NET2HOST16(info[3]) >= ROAR_MAX_CHANNELS )
[17]647   return -1;
648
[252]649  s->mixer.mixer[ROAR_NET2HOST16(info[3])] = ROAR_NET2HOST16(info[4]);
[17]650 } else {
651  return -1;
652 }
653
654 mes->cmd     = ROAR_CMD_OK;
655 mes->datalen = 0;
656
657 return 0;
658}
[0]659
[23]660int req_on_get_vol (int client, struct roar_message * mes, char * data) {
661 uint16_t * info = (uint16_t *) mes->data;
662 int stream;
663 struct roar_stream_server * s;
664 int i;
665 int chans;
666
667 ROAR_DBG("req_on_get_vol(*) = ?");
668 ROAR_DBG("req_on_get_vol(*): mes->datalen=%i", mes->datalen);
669
670 if ( mes->datalen < (2*2) )
671  return -1;
672
673 if ( info[0] != 0 ) // version
674  return -1;
675
[252]676 stream = ROAR_NET2HOST16(info[1]);
[23]677 ROAR_DBG("req_on_get_vol(*): stream=%i", stream);
678
679 // TODO: change this code.
680 //       we should not directly change the stream object but use some stream_*()-func
681 //       for that job.
682
683 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
684  return -1;
685
686 s = g_streams[stream];
687
688 if ( s == NULL )
689  return -1;
690
691 ROAR_DBG("req_on_get_vol(*): s=%p", s);
692
693 // ok, we have everything
694
695 info[0] = 0;
[252]696 info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
[23]697
698 for (i = 0; i < chans; i++)
[252]699  info[2+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
[23]700
701 mes->datalen = (2 + chans)*2;
702 mes->cmd = ROAR_CMD_OK;
703
704 return 0;
705}
706
[0]707int req_on_add_data (int client, struct roar_message * mes, char * data) {
708 struct roar_buffer * b;
709 char               * buf;
710
711 if ( roar_buffer_new(&b, mes->datalen) == -1 ) {
712  ROAR_ERR("req_on_add_data(*): Can not alloc buffer space!");
713  ROAR_DBG("req_on_add_data(*) = -1");
714  return -1;
715 }
716
717 roar_buffer_get_data(b, (void **)&buf);
718
719 if ( data == NULL ) {
720  memcpy(buf, mes->data, mes->datalen);
721 } else {
722  memcpy(buf, data, mes->datalen);
723 }
724
725 if ( stream_add_buffer(mes->stream, b) == -1 ) {
726  roar_buffer_free(b);
727  return -1;
728 }
729
[498]730 mes->cmd     = ROAR_CMD_OK_STOP;
[0]731 mes->datalen = 0;
732
733 return 0;
734}
735
736//ll
Note: See TracBrowser for help on using the repository browser.