source: roaraudio/libroar/ctl.c @ 4332:e0b5649844a7

Last change on this file since 4332:e0b5649844a7 was 4332:e0b5649844a7, checked in by phi, 14 years ago

wrote a basic function for int matching from filters

File size: 14.3 KB
Line 
1//ctl.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2010
5 *
6 *  This file is part of libroar 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 *  libroar 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 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
38int roar_get_clientid  (struct roar_connection * con) {
39 struct roar_message mes;
40
41 memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
42
43 mes.cmd     = ROAR_CMD_WHOAMI;
44 mes.datalen = 0;
45
46 if ( roar_req(con, &mes, NULL) == -1 )
47  return -1;
48
49 if ( mes.cmd != ROAR_CMD_OK )
50  return -1;
51
52 if ( mes.datalen != 1 )
53  return -1;
54
55 return mes.data[0];
56}
57
58int roar_server_oinfo   (struct roar_connection * con, struct roar_stream * sa) {
59 struct roar_message mes;
60
61 memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
62
63 mes.cmd     = ROAR_CMD_SERVER_OINFO;
64 mes.datalen = 0;
65
66 if ( roar_req(con, &mes, NULL) == -1 )
67  return -1;
68
69 if ( mes.cmd != ROAR_CMD_OK )
70  return -1;
71
72 if ( roar_stream_m2s(sa, &mes) == -1 )
73  return -1;
74
75 return 0;
76}
77
78int roar_get_standby   (struct roar_connection * con) {
79 struct roar_message mes;
80
81 memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
82
83 mes.cmd = ROAR_CMD_GET_STANDBY;
84 mes.datalen = 0;
85
86 if ( roar_req(con, &mes, NULL) == -1 )
87  return -1;
88
89 if ( mes.cmd != ROAR_CMD_OK )
90  return -1;
91
92 return ROAR_NET2HOST16(*((uint16_t*)mes.data));
93}
94
95int roar_set_standby   (struct roar_connection * con, int state) {
96 struct roar_message mes;
97
98 memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
99
100 mes.cmd = ROAR_CMD_SET_STANDBY;
101 mes.datalen = 2;
102
103 *((uint16_t*)mes.data) = ROAR_HOST2NET16((unsigned) state);
104
105 if ( roar_req(con, &mes, NULL) == -1 )
106  return -1;
107
108 if ( mes.cmd != ROAR_CMD_OK )
109  return -1;
110
111 return 0;
112}
113
114int roar_exit   (struct roar_connection * con) {
115 return roar_terminate(con, 0);
116}
117
118int roar_terminate (struct roar_connection * con, int terminate) {
119 struct roar_message mes;
120
121 memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
122
123 mes.cmd     = ROAR_CMD_EXIT;
124 mes.datalen = 1;
125 mes.data[0] = terminate;
126
127 if ( roar_req(con, &mes, NULL) == -1 )
128  return -1;
129
130 if ( mes.cmd != ROAR_CMD_OK )
131  return -1;
132
133 return 0;
134}
135
136int roar_list         (struct roar_connection * con, int * items,   int max, int cmd) {
137 struct roar_message m;
138
139 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
140
141 roar_ctl_f2m_any(&m);
142 m.cmd = cmd;
143
144 if ( roar_req(con, &m, NULL) == -1 )
145  return -1;
146
147 return roar_ctl_m2ia(&m, items, max);
148}
149
150int roar_get_client   (struct roar_connection * con, struct roar_client * client, int id) {
151 struct roar_message m;
152
153 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
154
155 m.cmd     = ROAR_CMD_GET_CLIENT;
156 m.datalen = 1;
157 m.data[0] = id;
158
159 ROAR_DBG("roar_get_client(*): id = %i", id);
160
161 if ( roar_req(con, &m, NULL) == -1 )
162  return -1;
163
164 if ( m.cmd != ROAR_CMD_OK )
165  return -1;
166
167 ROAR_DBG("roar_get_client(*): got ok");
168
169 return roar_ctl_m2c(&m, client);
170}
171
172int roar_get_stream   (struct roar_connection * con, struct roar_stream * stream, int id) {
173 struct roar_message m;
174
175 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
176
177 m.cmd     = ROAR_CMD_GET_STREAM;
178 m.datalen = 1;
179 m.data[0] = id;
180
181 roar_errno = ROAR_ERROR_UNKNOWN;
182
183 if ( roar_req(con, &m, NULL) == -1 ) {
184  roar_errno = ROAR_ERROR_PROTO;
185  return -1;
186 }
187
188 if ( m.cmd != ROAR_CMD_OK )
189  return -1;
190
191 return roar_stream_m2s(stream, &m);
192}
193
194int roar_kick         (struct roar_connection * con, int type, int id) {
195 struct roar_message m;
196 uint16_t * info = (uint16_t *) m.data;
197
198 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
199
200 m.cmd     = ROAR_CMD_KICK;
201 m.datalen = 4;
202 info[0] = ROAR_HOST2NET16(type);
203 info[1] = ROAR_HOST2NET16(id);
204
205 if ( roar_req(con, &m, NULL) == -1 )
206  return -1;
207
208 if ( m.cmd != ROAR_CMD_OK )
209  return -1;
210
211 return 0;
212}
213
214int roar_set_vol      (struct roar_connection * con, int id, struct roar_mixer_settings * mixer, int channels) {
215 struct roar_message m;
216 uint16_t * info = (uint16_t *) m.data;
217 int i;
218
219 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
220
221 m.cmd     = ROAR_CMD_SET_VOL;
222 m.datalen = (3 + channels) * 2;
223 m.stream  = id;
224 info[0] = ROAR_HOST2NET16(1);
225 info[1] = ROAR_HOST2NET16(mixer->scale);
226 info[2] = ROAR_HOST2NET16(ROAR_SET_VOL_ALL);
227
228 for (i = 0; i < channels; i++)
229  info[i+3] = ROAR_HOST2NET16(mixer->mixer[i]);
230
231 if ( roar_req(con, &m, NULL) == -1 )
232  return -1;
233
234 if ( m.cmd != ROAR_CMD_OK )
235  return -1;
236
237 return 0;
238}
239
240int roar_get_vol      (struct roar_connection * con, int id, struct roar_mixer_settings * mixer, int * channels) {
241 struct roar_message m;
242 uint16_t * info = (uint16_t *) m.data;
243 int i;
244
245 memset(&m, 0, sizeof(struct roar_message)); // make valgrind happy!
246
247 m.cmd     = ROAR_CMD_GET_VOL;
248 m.datalen = 2*2;
249 m.stream  = id;
250
251 info[0]   = ROAR_HOST2NET16(1);
252
253 if ( roar_req(con, &m, NULL) == -1 )
254  return -1;
255
256 if ( m.cmd != ROAR_CMD_OK )
257  return -1;
258
259 if ( ROAR_NET2HOST16(info[0]) != 1 )
260  return -1;
261
262 info[1] = ROAR_NET2HOST16(info[1]);
263
264 if ( channels != NULL )
265  *channels = info[1];
266
267 if ( info[1] > ROAR_MAX_CHANNELS )
268  return -1;
269
270 mixer->scale   = ROAR_NET2HOST16(info[2]);
271 mixer->rpg_mul = ROAR_NET2HOST16(info[3]);
272 mixer->rpg_div = ROAR_NET2HOST16(info[4]);
273
274 for (i = 0; i < info[1]; i++)
275  mixer->mixer[i] = ROAR_NET2HOST16(info[i+5]);
276
277 return 0;
278}
279
280// converts: *_m2*, *_*2m
281
282int roar_ctl_f2m      (struct roar_message * m, unsigned char   filter, unsigned char   cmp, uint32_t   id) {
283
284 m->datalen = 7;
285
286 m->data[0] = 0;
287 m->data[1] = filter;
288 m->data[2] = cmp;
289 *((uint32_t*)&(m->data[3])) = ROAR_HOST2NET32(id);
290
291 return 0;
292}
293int roar_ctl_m2f      (struct roar_message * m, unsigned char * filter, unsigned char * cmp, uint32_t * id) {
294
295 if ( m->datalen != 7 )
296  return -1;
297
298 if ( m->data[0] != 0 ) {
299  ROAR_ERR("roar_ctl_m2f(*): version %i not supported!", (int)m->data[0]);
300  return -1;
301 }
302
303 *filter = m->data[1];
304 *cmp    = m->data[2];
305
306 *id = ROAR_NET2HOST32(*((uint32_t*)&(m->data[3])));
307
308 return 0;
309}
310
311int roar_filter_match (const unsigned cmp, const uint32_t a, const uint32_t b) {
312 switch (cmd) {
313  case ROAR_CTL_CMP_ANY:
314    return 1;
315   break;
316  case ROAR_CTL_CMP_EQ:
317    return a == b;
318   break;
319  case ROAR_CTL_CMP_NE:
320    return a != b;
321   break;
322  default:
323    return -1;
324 }
325}
326
327int roar_ctl_ia2m     (struct roar_message * m, int * data, int len) {
328 int i;
329
330 if ( len > LIBROAR_BUFFER_MSGDATA )
331  return -1;
332
333 m->datalen = len;
334
335 for (i = 0; i < len; i++)
336  m->data[i] = data[i];
337
338 return 0;
339}
340int roar_ctl_m2ia     (struct roar_message * m, int * data, int len) {
341 int i;
342
343 if ( m->datalen > len )
344  return -1;
345
346 for (i = 0; i < m->datalen; i++)
347  data[i] = m->data[i];
348
349 return m->datalen;
350}
351
352int roar_ctl_c2m      (struct roar_message * m, struct roar_client * c) {
353 int cur = 0;
354 int h;
355 int i;
356 int max_len;
357 uint32_t pid;
358 size_t len_rest;
359
360 if ( c == NULL )
361  return -1;
362
363 m->data[cur++] = 0;                       // 0: Version
364 m->data[cur++] = c->execed;               // 1: execed
365
366 h = 0;
367 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
368  if ( c->streams[i] != -1 )
369   m->data[cur+1+h++] = c->streams[i];
370 }
371
372 m->data[cur++] = h;                       // 2: num of streams
373 cur += h;
374
375 max_len = strlen(c->name);
376
377 // TODO: add some code to check if this fits in the pkg
378 // NOTE: add this code after we are sure how long this pkg will be
379 //       and fully decieded about this function.
380
381 m->data[cur++] = max_len;
382
383 strncpy((m->data)+cur, c->name, max_len);
384
385 cur += max_len;
386
387 pid = ROAR_HOST2NET32(c->pid);
388 memcpy(&(m->data[cur]), &pid, 4);
389 cur += 4;
390
391 pid = ROAR_HOST2NET32(c->uid);
392 memcpy(&(m->data[cur]), &pid, 4);
393 cur += 4;
394
395 pid = ROAR_HOST2NET32(c->gid);
396 memcpy(&(m->data[cur]), &pid, 4);
397 cur += 4;
398
399 pid = ROAR_HOST2NET32(c->proto);
400 memcpy(&(m->data[cur]), &pid, 4);
401 cur += 4;
402
403 pid = ROAR_HOST2NET32(c->byteorder);
404 memcpy(&(m->data[cur]), &pid, 4);
405 cur += 4;
406
407 len_rest = sizeof(m->data) - cur;
408 if ( roar_nnode_to_blob(&(c->nnode), &(m->data[cur]), &len_rest) == 0 ) {
409  cur += len_rest;
410 }
411
412 m->datalen = cur;
413
414 return 0;
415}
416
417int roar_ctl_m2c      (struct roar_message * m, struct roar_client * c) {
418 int i;
419 int cur;
420 uint32_t pid;
421 size_t len;
422
423 if ( m == NULL || c == NULL )
424  return -1;
425
426 if ( m->datalen == 0 )
427  return -1;
428
429 ROAR_DBG("roar_ctl_m2c(*): got data!, len = %i", m->datalen);
430
431 if ( m->data[0] != 0 ) {
432  ROAR_DBG("roar_ctl_m2c(*): wrong version!");
433  return -1;
434 }
435
436 if ( m->datalen < 3 )
437  return -1;
438
439 ROAR_DBG("roar_ctl_m2c(*): have usable data!");
440
441 c->execed = m->data[1];
442
443 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++)
444  c->streams[i] = -1;
445
446 for (i = 0; i < m->data[2]; i++)
447  c->streams[i] = m->data[3+i];
448
449 cur = 3 + m->data[2];
450
451 strncpy(c->name, (m->data)+cur+1, m->data[cur]);
452 c->name[(int)m->data[cur]] = 0;
453
454 cur += m->data[cur] + 1;
455
456 memcpy(&pid, &(m->data[cur]), 4);
457 c->pid = ROAR_NET2HOST32(pid);
458 cur += 4;
459
460 memcpy(&pid, &(m->data[cur]), 4);
461 c->uid = ROAR_NET2HOST32(pid);
462 cur += 4;
463
464 memcpy(&pid, &(m->data[cur]), 4);
465 c->gid = ROAR_NET2HOST32(pid);
466 cur += 4;
467
468 if ( m->datalen >= cur+4 ) {
469  memcpy(&pid, &(m->data[cur]), 4);
470  c->proto = ROAR_NET2HOST32(pid);
471  cur += 4;
472 } else {
473  c->proto = ROAR_PROTO_NONE;
474 }
475
476 if ( m->datalen >= cur+4 ) {
477  memcpy(&pid, &(m->data[cur]), 4);
478  c->byteorder = ROAR_NET2HOST32(pid);
479  cur += 4;
480 } else {
481  c->byteorder = ROAR_BYTEORDER_UNKNOWN;
482 }
483
484 if ( m->datalen > cur ) {
485  len = m->datalen - cur;
486  if ( roar_nnode_from_blob(&(c->nnode), &(m->data[cur]), &len) == 0 ) {
487   cur += len;
488  } else {
489   if ( roar_nnode_new(&(c->nnode), ROAR_SOCKET_TYPE_UNKNOWN) == -1 )
490    return -1;
491  }
492 } else {
493  if ( roar_nnode_new(&(c->nnode), ROAR_SOCKET_TYPE_UNKNOWN) == -1 )
494   return -1;
495 }
496
497 return 0;
498}
499
500int    roar_str2proto (char * proto) {
501 if ( !strcasecmp(proto, "roar") ) {
502  return ROAR_PROTO_ROARAUDIO;
503 } else if ( !strcasecmp(proto, "roaraudio") ) {
504  return ROAR_PROTO_ROARAUDIO;
505 } else if ( !strcasecmp(proto, "esd") ) {
506  return ROAR_PROTO_ESOUND;
507 } else if ( !strcasecmp(proto, "esound") ) {
508  return ROAR_PROTO_ESOUND;
509 } else if ( !strcasecmp(proto, "auto") ) {
510  return ROAR_PROTO_AUTO;
511 } else if ( !strcasecmp(proto, "(auto)") ) {
512  return ROAR_PROTO_AUTO;
513 } else if ( !strcasecmp(proto, "http") ) {
514  return ROAR_PROTO_HTTP;
515 } else if ( !strcasecmp(proto, "gopher") ) {
516  return ROAR_PROTO_GOPHER;
517 } else if ( !strcasecmp(proto, "icy") ) {
518  return ROAR_PROTO_ICY;
519 } else if ( !strcasecmp(proto, "simple") ) {
520  return ROAR_PROTO_SIMPLE;
521 } else if ( !strcasecmp(proto, "rsound") ) {
522  return ROAR_PROTO_RSOUND;
523 } else if ( !strcasecmp(proto, "rplay") ) {
524  return ROAR_PROTO_RPLAY;
525 }
526
527 return -1;
528}
529
530char * roar_proto2str (int    proto) {
531 switch (proto) {
532  case ROAR_PROTO_ROARAUDIO: return "RoarAudio"; break;
533  case ROAR_PROTO_ESOUND:    return "EsounD";    break;
534  case ROAR_PROTO_AUTO:      return "(auto)";    break;
535  case ROAR_PROTO_HTTP:      return "http";      break;
536  case ROAR_PROTO_GOPHER:    return "gopher";    break;
537  case ROAR_PROTO_ICY:       return "ICY";       break;
538  case ROAR_PROTO_SIMPLE:    return "Simple";    break;
539  case ROAR_PROTO_RSOUND:    return "RSound";    break;
540  case ROAR_PROTO_RPLAY:     return "RPlay";     break;
541  default:
542    return "(unknown)";
543 }
544}
545
546int    roar_str2byteorder (char * byteorder) {
547 if (        !strcasecmp(byteorder, "le")            || !strcasecmp(byteorder, "little") ||
548             !strcasecmp(byteorder, "little endian") || !strcasecmp(byteorder, "1234")   ) {
549  return ROAR_BYTEORDER_LE;
550 } else if ( !strcasecmp(byteorder, "be")            || !strcasecmp(byteorder, "big")    ||
551             !strcasecmp(byteorder, "big endian")    || !strcasecmp(byteorder, "4321")   ) {
552  return ROAR_BYTEORDER_BE;
553 } else if ( !strcasecmp(byteorder, "pdp")           ||
554             !strcasecmp(byteorder, "pdp endian") ) {
555  return ROAR_BYTEORDER_PDP;
556 } else if ( !strcasecmp(byteorder, "network")       ||
557             !strcasecmp(byteorder, "network byteorder") ) {
558  return ROAR_BYTEORDER_NETWORK;
559 }
560
561 return -1;
562}
563
564char * roar_byteorder2str (int    byteorder) {
565 switch (byteorder) {
566  case ROAR_BYTEORDER_LE:      return "little endian"; break;
567  case ROAR_BYTEORDER_BE:      return "big endian";    break;
568  case ROAR_BYTEORDER_PDP:     return "pdp endian";    break;
569//  case ROAR_BYTEORDER_NETWORK: return "network";       break;
570  default:
571    return "(unknown)";
572 }
573}
574
575// grep '^#define ROAR_OT_' roaraudio/proto.h | cut -d' ' -f2 | sed 's/^\(ROAR_OT_\)\(.*\)$/ {\1\2, "\2"},/'
576static struct {
577 const int ot;
578 const char * name;
579} _libroar_ot[] = {
580 {ROAR_OT_CLIENT,   "client"},
581 {ROAR_OT_STREAM,   "stream"},
582 {ROAR_OT_SOURCE,   "source"},
583 {ROAR_OT_SAMPLE,   "sample"},
584 {ROAR_OT_OUTPUT,   "output"},
585 {ROAR_OT_MIXER,    "mixer"},
586 {ROAR_OT_BRIDGE,   "bridge"},
587 {ROAR_OT_LISTEN,   "listen"},
588 {ROAR_OT_ACTION,   "action"},
589 {ROAR_OT_MSGQUEUE, "msgqueue"},
590 {ROAR_OT_MSGBUS,   "msgbus"},
591 {-1, NULL}
592};
593
594int    roar_str2ot        (const char * ot) {
595 int i;
596
597 for (i = 0; _libroar_ot[i].ot != -1; i++)
598  if ( !strcasecmp(ot, _libroar_ot[i].name) )
599   return _libroar_ot[i].ot;
600
601 return -1;
602}
603
604const char * roar_ot2str  (const int    ot) {
605 int i;
606
607 for (i = 0; _libroar_ot[i].ot != -1; i++)
608  if ( _libroar_ot[i].ot == ot )
609   return _libroar_ot[i].name;
610
611 return NULL;
612}
613
614//ll
Note: See TracBrowser for help on using the repository browser.