source: roaraudio/roard/req.c @ 964:0a0e4e32d700

Last change on this file since 964:0a0e4e32d700 was 964:0a0e4e32d700, checked in by phi, 15 years ago

added support for roarctl to show position info

File size: 14.6 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_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
96 ROAR_STREAM(s)->id = stream; // roar_stream_m2s() resets this
97 ROAR_STREAM_SERVER(s)->codec_orgi = ROAR_STREAM(s)->info.codec;
98
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
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
131 if ( mes->datalen > 80 ) // we do not support long messages here
132  return -1;
133
134 type = (unsigned)mes->data[1];
135 port = ROAR_NET2HOST16(((uint16_t*)mes->data)[1]);
136
137 len = mes->datalen - 4;
138
139 strncpy(host, &(mes->data[4]), len);
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
151 ROAR_DBG("req_on_con_stream(*): CONNECT(type=%i, host='%s', port=%i)", type, host, port);
152
153 if ( (fh = roar_socket_open(ROAR_SOCKET_MODE_CONNECT, type, host, port)) == -1 )
154  return -1;
155
156 if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
157  close(fh);
158  return 1;
159 }
160
161 mes->datalen = 0;
162 mes->cmd     = ROAR_CMD_OK;
163
164 return 0;
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
179
180 mes->datalen = 0;
181 mes->cmd     = ROAR_CMD_OK;
182
183 return 0;
184}
185
186int req_on_set_meta    (int client, struct roar_message * mes, char * data) {
187 int type;
188 int mode;
189 int namelen, vallen;
190 char   val[255+1];
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
202 ROAR_DBG("req_on_set_meta(*): mode=%i, type=%i", mode, type);
203
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
210 } else if ( mode == ROAR_META_MODE_SET || mode == ROAR_META_MODE_ADD ) {
211  if ( mes->datalen < 5 )
212   return -1;
213
214  namelen = (unsigned) mes->data[3];
215  vallen  = (unsigned) mes->data[4];
216
217  ROAR_DBG("req_on_set_meta(*): namelen=%i, vallen=%i", namelen, vallen);
218
219  if ( mes->datalen < (5 + namelen + vallen) )
220   return -1;
221
222  if ( namelen > ROAR_META_MAX_NAMELEN )
223   return -1;
224
225  strncpy(name, &(mes->data[5]), namelen);
226  name[namelen] = 0;
227
228  if ( vallen > 255 )
229   return -1;
230
231  strncpy(val, &(mes->data[5+namelen]), vallen);
232  val[vallen] = 0;
233
234  if ( mode == ROAR_META_MODE_SET ) {
235   if ( stream_meta_set(mes->stream, type, name, val) == -1 )
236    return -1;
237  } else {
238   if ( stream_meta_add(mes->stream, type, name, val) == -1 )
239    return -1;
240  }
241
242  mes->datalen = 0;
243  mes->cmd     = ROAR_CMD_OK;
244  return 0;
245 } else { // unknown mode!
246  return -1;
247 }
248
249 return -1;
250}
251
252int req_on_get_meta    (int client, struct roar_message * mes, char * data) {
253 int vallen;
254 int type;
255 char val[LIBROAR_BUFFER_MSGDATA-1];
256
257 if ( mes->datalen != 2 )
258  return -1;
259
260 if ( mes->data[0] != 0 ) // version
261  return -1;
262
263 type = (unsigned) mes->data[1];
264
265 if ( stream_meta_get(mes->stream, type, NULL, val, LIBROAR_BUFFER_MSGDATA-2) == -1 )
266  return -1;
267
268 vallen = strlen(val);
269
270 mes->cmd     = ROAR_CMD_OK;
271 mes->datalen = 2 + vallen;
272
273 mes->data[0] = 0;
274 mes->data[1] = (unsigned char) vallen;
275
276 val[vallen] = 0;
277
278 strncpy(&(mes->data[2]), val, vallen+1);
279
280 return 0;
281}
282
283int req_on_list_meta   (int client, struct roar_message * mes, char * data) {
284 int i;
285 int len = 0;
286 int types[ROAR_META_MAX_PER_STREAM];
287
288 if ( mes->datalen != 1 )
289  return -1;
290
291 if ( mes->data[0] != 0 ) // version
292  return -1;
293
294 if ( (len = stream_meta_list(mes->stream, types, ROAR_META_MAX_PER_STREAM)) == -1 )
295  return -1;
296
297 mes->cmd     = ROAR_CMD_OK;
298 mes->datalen = 1 + len;
299 mes->data[0] = 0;
300
301 for (i = 0; i < len; i++)
302  mes->data[i+1] = types[i];
303
304 return 0;
305}
306
307int req_on_server_oinfo    (int client, struct roar_message * mes, char * data) {
308 struct roar_stream s;
309//ROAR_DIR_OUTPUT
310
311 memset(s, 0, sizeof(struct roar_stream));
312
313 s.dir           = ROAR_DIR_OUTPUT;
314 s.pos_rel_id    = -1;
315 s.info.rate     = g_sa->rate;
316 s.info.bits     = g_sa->bits;
317 s.info.channels = g_sa->channels;
318 s.info.codec    = g_sa->codec;
319
320 if ( roar_stream_s2m(&s, mes) == -1 )
321  return -1;
322
323 mes->cmd = ROAR_CMD_OK;
324
325 return 0;
326}
327
328
329int req_on_get_standby (int client, struct roar_message * mes, char * data) {
330 mes->cmd = ROAR_CMD_OK;
331 mes->datalen = 2;
332
333 *((uint16_t*)mes->data) = ROAR_HOST2NET16((unsigned) g_standby);
334
335 return 0;
336}
337
338int req_on_set_standby (int client, struct roar_message * mes, char * data) {
339 if ( mes->datalen != 2 )
340  return -1;
341
342 g_standby = ROAR_NET2HOST16(*((uint16_t*)mes->data));
343
344 mes->cmd     = ROAR_CMD_OK;
345 mes->datalen = 0;
346
347 return 0;
348}
349
350int req_on_exit      (int client, struct roar_message * mes, char * data) {
351 int term = 0;
352
353 if ( mes->datalen == 1 )
354  term = mes->data[0];
355
356 mes->cmd     = ROAR_CMD_OK;
357 mes->datalen = 0;
358
359 ROAR_DBG("req_on_exit(*): term=%i", term);
360
361 if ( term ) {
362  cleanup_listen_socket(1);
363 } else {
364  alive = 0;
365 }
366
367 return 0;
368}
369
370int req_on_list_clients(int client, struct roar_message * mes, char * data) {
371 unsigned char filter, cmp;
372 uint32_t id;
373 int clients[ROAR_CLIENTS_MAX];
374 int i, c = 0;
375
376 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
377  return -1;
378
379 // TODO: add code to support filter
380 if ( filter != ROAR_CTL_FILTER_ANY )
381  return -1;
382
383 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
384  if ( g_clients[i] != NULL ) {
385   clients[c++] = i;
386  }
387 }
388
389 roar_ctl_ia2m(mes, clients, c);
390
391 mes->cmd = ROAR_CMD_OK;
392
393 return 0;
394}
395int req_on_list_streams(int client, struct roar_message * mes, char * data) {
396 unsigned char filter, cmp;
397 uint32_t id;
398 int streams[ROAR_STREAMS_MAX];
399 int i, c = 0;
400
401 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
402  return -1;
403
404 // TODO: add code to support filter
405 if ( filter != ROAR_CTL_FILTER_ANY )
406  return -1;
407
408 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
409  if ( g_streams[i] != NULL ) {
410   streams[c++] = i;
411  }
412 }
413
414 roar_ctl_ia2m(mes, streams, c);
415
416 mes->cmd = ROAR_CMD_OK;
417
418 return 0;
419}
420
421int req_on_get_client  (int client, struct roar_message * mes, char * data) {
422 struct roar_client * c;
423
424 if ( mes->datalen != 1 )
425  return -1;
426
427 if ( clients_get(mes->data[0], &c) == -1 )
428  return -1;
429
430 mes->cmd = ROAR_CMD_OK;
431
432 return roar_ctl_c2m(mes, c);
433}
434
435int req_on_get_stream  (int client, struct roar_message * mes, char * data) {
436 struct roar_stream_server * s;
437
438 if ( mes->datalen != 1 )
439  return -1;
440
441 if ( streams_get(mes->data[0], &s) == -1 )
442  return -1;
443
444 mes->cmd = ROAR_CMD_OK;
445 mes->stream = mes->data[0];
446
447 return roar_stream_s2m(ROAR_STREAM(s), mes);
448}
449
450int req_on_get_stream_para (int client, struct roar_message * mes, char * data) {
451 struct roar_stream * s;
452 struct roar_stream_server * ss;
453 struct roar_audio_info * audio_info;
454 uint16_t * d = (uint16_t *) mes->data;
455 int i;
456
457 if ( mes->datalen != 4 )
458  return -1;
459
460 for (i = 0; i < mes->datalen/2; i++) {
461  d[i] = ROAR_NET2HOST16(d[i]);
462 }
463
464 if ( streams_get(mes->stream, &ss) == -1 ) {
465  ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
466  return -1;
467 }
468
469 s = ROAR_STREAM(ss);
470
471 audio_info = &(s->info);
472
473 if ( d[0] != 0 || d[1] != 1 ) {
474  ROAR_WARN("req_on_get_stream_para(*): unsupported command version: %i, %i", d[0], d[1]);
475  return -1;
476 }
477
478 mes->datalen = 2*7;
479
480 d[2] = ROAR_OUTPUT_CALC_OUTBUFSIZE(audio_info);
481 d[3] = ss->pre_underruns;
482 d[4] = ss->post_underruns;
483 d[5] = ss->codec_orgi;
484 d[6] = ROAR_FLAG_NONE | (ss->primary ? ROAR_FLAG_PRIMARY : 0) | (ss->driver_id != -1 ? ROAR_FLAG_OUTPUT : 0);
485
486 for (i = 0; i < mes->datalen/2; i++) {
487  d[i] = ROAR_HOST2NET16(d[i]);
488 }
489
490 mes->pos = s->pos;
491
492 mes->cmd = ROAR_CMD_OK;
493 return 0;
494}
495
496int req_on_kick (int client, struct roar_message * mes, char * data) {
497 uint16_t * info = (uint16_t *) mes->data;
498
499 if ( mes->datalen != 4 )
500  return -1;
501
502 info[0] = ROAR_NET2HOST16(info[0]);
503 info[1] = ROAR_NET2HOST16(info[1]);
504
505 if ( info[0] == ROAR_OT_CLIENT ) {
506  clients_delete(info[1]);
507 } else if ( info[0] == ROAR_OT_STREAM ) {
508  streams_delete(info[1]);
509 } else {
510  return -1;
511 }
512
513 mes->cmd     = ROAR_CMD_OK;
514 mes->datalen = 0;
515
516 return 0;
517}
518
519int req_on_attach      (int client, struct roar_message * mes, char * data) {
520 uint16_t * info = (uint16_t *) mes->data;
521
522 if ( mes->datalen < 6 )
523  return -1;
524
525 info[0] = ROAR_NET2HOST16(info[0]);
526 info[1] = ROAR_NET2HOST16(info[1]);
527 info[2] = ROAR_NET2HOST16(info[2]);
528
529 if ( info[0] != 0 )
530  return -1;
531
532 if ( info[1] == ROAR_ATTACH_SIMPLE ) {
533  if ( client_stream_move(info[2], mes->stream) == -1 )
534   return -1;
535 } else {
536  return -1;
537 }
538
539 mes->cmd     = ROAR_CMD_OK;
540 mes->datalen = 0;
541
542 return 0;
543}
544
545int req_on_set_vol (int client, struct roar_message * mes, char * data) {
546 uint16_t * info = (uint16_t *) mes->data;
547 int stream;
548 struct roar_stream_server * s;
549 int i;
550 int chans;
551
552 ROAR_DBG("req_on_set_vol(*) = ?");
553 ROAR_DBG("req_on_set_vol(*): mes->datalen=%i", mes->datalen);
554
555 if ( mes->datalen < (4*2) )
556  return -1;
557
558 if ( info[0] != 0 ) // version
559  return -1;
560
561 stream = ROAR_NET2HOST16(info[1]);
562 ROAR_DBG("req_on_set_vol(*): stream=%i", stream);
563
564 // TODO: change this code.
565 //       we should not directly change the stream object but use some stream_*()-func
566 //       for that job.
567
568 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
569  return -1;
570
571 s = g_streams[stream];
572
573 if ( s == NULL )
574  return -1;
575
576 ROAR_DBG("req_on_set_vol(*): s=%p", s);
577
578 info[2] = ROAR_NET2HOST16(info[2]);
579
580 if ( info[2] == ROAR_SET_VOL_ALL ) {
581  chans = (mes->datalen/2) - 3;
582  ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ALL, channes=%i", chans);
583
584  if ( chans >= ROAR_MAX_CHANNELS )
585   return -1;
586
587  ROAR_DBG("req_on_set_vol(*): mixer at %p", s->mixer.mixer);
588
589  for (i = 0; i < chans; i++) {
590   s->mixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
591   ROAR_DBG("req_on_set_vol(*): channel %i: %i", i, ROAR_NET2HOST16(info[i+3]));
592  }
593
594  ROAR_DBG("req_on_set_vol(*): mixer changed!");
595
596 } else if ( info[2] == ROAR_SET_VOL_ONE ) {
597  ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ONE");
598  if ( ROAR_NET2HOST16(info[3]) >= ROAR_MAX_CHANNELS )
599   return -1;
600
601  s->mixer.mixer[ROAR_NET2HOST16(info[3])] = ROAR_NET2HOST16(info[4]);
602 } else {
603  return -1;
604 }
605
606 mes->cmd     = ROAR_CMD_OK;
607 mes->datalen = 0;
608
609 return 0;
610}
611
612int req_on_get_vol (int client, struct roar_message * mes, char * data) {
613 uint16_t * info = (uint16_t *) mes->data;
614 int stream;
615 struct roar_stream_server * s;
616 int i;
617 int chans;
618
619 ROAR_DBG("req_on_get_vol(*) = ?");
620 ROAR_DBG("req_on_get_vol(*): mes->datalen=%i", mes->datalen);
621
622 if ( mes->datalen < (2*2) )
623  return -1;
624
625 if ( info[0] != 0 ) // version
626  return -1;
627
628 stream = ROAR_NET2HOST16(info[1]);
629 ROAR_DBG("req_on_get_vol(*): stream=%i", stream);
630
631 // TODO: change this code.
632 //       we should not directly change the stream object but use some stream_*()-func
633 //       for that job.
634
635 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
636  return -1;
637
638 s = g_streams[stream];
639
640 if ( s == NULL )
641  return -1;
642
643 ROAR_DBG("req_on_get_vol(*): s=%p", s);
644
645 // ok, we have everything
646
647 info[0] = 0;
648 info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
649
650 for (i = 0; i < chans; i++)
651  info[2+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
652
653 mes->datalen = (2 + chans)*2;
654 mes->cmd = ROAR_CMD_OK;
655
656 return 0;
657}
658
659int req_on_add_data (int client, struct roar_message * mes, char * data) {
660 struct roar_buffer * b;
661 char               * buf;
662
663 if ( roar_buffer_new(&b, mes->datalen) == -1 ) {
664  ROAR_ERR("req_on_add_data(*): Can not alloc buffer space!");
665  ROAR_DBG("req_on_add_data(*) = -1");
666  return -1;
667 }
668
669 roar_buffer_get_data(b, (void **)&buf);
670
671 if ( data == NULL ) {
672  memcpy(buf, mes->data, mes->datalen);
673 } else {
674  memcpy(buf, data, mes->datalen);
675 }
676
677 if ( stream_add_buffer(mes->stream, b) == -1 ) {
678  roar_buffer_free(b);
679  return -1;
680 }
681
682 mes->cmd     = ROAR_CMD_OK_STOP;
683 mes->datalen = 0;
684
685 return 0;
686}
687
688//ll
Note: See TracBrowser for help on using the repository browser.