source: roaraudio/libroar/ctl.c @ 3251:bdabdeacf725

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

added consts and string handling for ROAR_PROTO_SIMPLE

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