source: roaraudio/roard/req.c @ 1223:29f5a58d63ce

Last change on this file since 1223:29f5a58d63ce was 1223:29f5a58d63ce, checked in by phi, 15 years ago

typo in 'streams_calc_delay' and added cf ctl, prototype for a stream ctl...

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