source: roaraudio/plugins/roard/protocol-esound.c @ 3517:1a3218a3fc5b

Last change on this file since 3517:1a3218a3fc5b was 3517:1a3218a3fc5b, checked in by phi, 14 years ago

updated license headers, FSF moved office

File size: 14.7 KB
Line 
1//emul_esd.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009
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, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include "roard.h"
27
28#ifndef ROAR_WITHOUT_DCOMP_EMUL_ESD
29#ifdef ROAR_HAVE_H_ESD
30
31#if !defined(ROAR_TARGET_MICROCONTROLLER) && !defined(ROAR_MINIMAL)
32#define _NAME(x) (x)
33#else
34#define _NAME(x) ((char*)NULL)
35#endif
36
37#define _cmd_t   int
38#define _INTSIZE sizeof(_cmd_t)
39
40#define _NOT_TO_IMPLEMENT    NULL
41#define _UNIMPLEMNTED_IN_ESD NULL
42#define _NEED_SAMPLE_SUPPORT NULL
43
44#define _ROAR2ESD(x) ((x)+1)
45#define _ESD2ROAR(x) ((x)-1)
46
47struct emul_esd_command g_emul_esd_commands[] = {
48 {ESD_PROTO_CONNECT,      ESD_KEY_LEN  +     _INTSIZE, _NAME("CONNECT"),      emul_esd_on_connect},
49 {ESD_PROTO_LOCK,         ESD_KEY_LEN  +     _INTSIZE, _NAME("LOCK"),         NULL},
50 {ESD_PROTO_UNLOCK,       ESD_KEY_LEN  +     _INTSIZE, _NAME("UNLOCK"),       NULL},
51 {ESD_PROTO_STREAM_PLAY,  ESD_NAME_MAX + 2 * _INTSIZE, _NAME("STREAM_PLAY"),  emul_esd_on_stream},
52 {ESD_PROTO_STREAM_REC,   ESD_NAME_MAX + 2 * _INTSIZE, _NAME("STREAM_REC"),   emul_esd_on_stream},
53 {ESD_PROTO_STREAM_MON,   ESD_NAME_MAX + 2 * _INTSIZE, _NAME("STREAM_MON"),   emul_esd_on_stream},
54 {ESD_PROTO_SAMPLE_CACHE, ESD_NAME_MAX + 3 * _INTSIZE, _NAME("SAMPLE_CACHE"), _NEED_SAMPLE_SUPPORT},
55 {ESD_PROTO_SAMPLE_FREE,                     _INTSIZE, _NAME("SAMPLE_FREE"),  _NEED_SAMPLE_SUPPORT},
56 {ESD_PROTO_SAMPLE_PLAY,                     _INTSIZE, _NAME("SAMPLE_PLAY"),  _NEED_SAMPLE_SUPPORT},
57 {ESD_PROTO_SAMPLE_LOOP,                     _INTSIZE, _NAME("SAMPLE_LOOP"),  _NEED_SAMPLE_SUPPORT},
58 {ESD_PROTO_SAMPLE_STOP,                     _INTSIZE, _NAME("SAMPLE_STOP"),  _NEED_SAMPLE_SUPPORT},
59 {ESD_PROTO_SAMPLE_KILL,  0                          , _NAME("SAMPLE_KILL"),  _NEED_SAMPLE_SUPPORT},
60 {ESD_PROTO_STANDBY,      ESD_KEY_LEN +      _INTSIZE, _NAME("STANDBY"),      emul_esd_on_standby},
61 {ESD_PROTO_RESUME,       ESD_KEY_LEN +      _INTSIZE, _NAME("RESUME"),       emul_esd_on_standby},
62 {ESD_PROTO_SAMPLE_GETID, ESD_NAME_MAX               , _NAME("SAMPLE_GETID"), _NEED_SAMPLE_SUPPORT},
63 {ESD_PROTO_STREAM_FILT,  ESD_NAME_MAX + 2 * _INTSIZE, _NAME("STREAM_FILT"),  emul_esd_on_stream},
64 {ESD_PROTO_SERVER_INFO,                     _INTSIZE, _NAME("SERVER_INFO"),  emul_esd_on_server_info},
65 {ESD_PROTO_ALL_INFO,                        _INTSIZE, _NAME("ALL_INFO"),     emul_esd_on_all_info},
66 {ESD_PROTO_SUBSCRIBE,    0                          , _NAME("SUBSCRIBE"),    _UNIMPLEMNTED_IN_ESD},
67 {ESD_PROTO_UNSUBSCRIBE,  0                          , _NAME("UNSUBSCRIBE"),  _UNIMPLEMNTED_IN_ESD},
68 {ESD_PROTO_STREAM_PAN,                  3 * _INTSIZE, _NAME("STREAM_PAN"),   emul_esd_on_stream_pan},
69 {ESD_PROTO_SAMPLE_PAN,                  3 * _INTSIZE, _NAME("SAMPLE_PAN"),   _NEED_SAMPLE_SUPPORT},
70 {ESD_PROTO_STANDBY_MODE,                    _INTSIZE, _NAME("STANDBY_MODE"), emul_esd_on_standbymode},
71 {ESD_PROTO_LATENCY,      0                          , _NAME("LATENCY"),      emul_esd_on_latency},
72 {ESD_PROTO_MAX,          0                          , _NAME("MAX"),          _NOT_TO_IMPLEMENT},
73 {-1, 0, _NAME("END OF LIST"), _NOT_TO_IMPLEMENT}
74};
75
76// command handling:
77int emul_esd_exec_command(int client, int cmd, struct roar_vio_calls * vio) {
78 struct emul_esd_command * cur;
79 void * data = NULL;
80 ssize_t ret;
81 size_t  done = 0;
82 int r;
83 int i;
84
85 ROAR_DBG("emul_esd_exec_command(*) = ?");
86
87 if ( client == -1 || cmd < ESD_PROTO_CONNECT || cmd > ESD_PROTO_MAX || vio == NULL )
88  return -1;
89
90 ROAR_DBG("emul_esd_exec_command(*) = ?");
91
92 for (i = 0; (cur = &(g_emul_esd_commands[i]))->cmd != -1; i++) {
93  if ( cur->cmd == cmd ) {
94   if ( cur->datalen > 0 ) {
95    if ( (data = malloc(cur->datalen)) == NULL ) {
96     // we will do a protocol error in case we do not drop the client
97     clients_delete(client);
98     return -1;
99    }
100
101    while ( done < cur->datalen ) {
102     ret = roar_vio_read(vio, data+done, cur->datalen-done);
103
104     if ( ret < 1 ) {
105      free(data);
106      clients_delete(client);
107      return -1;
108     } else {
109      done += ret;
110     }
111    }
112   }
113
114   if ( cur->handler == NULL ) {
115    ROAR_WARN("emul_esd_exec_command(client=%i, cmd=%s(%i), vio=%p): client uses unimplemted command",
116               client, cur->name, cmd, vio
117             );
118    clients_delete(client);
119    r = -1;
120   } else {
121    r = cur->handler(client, cur, data, vio);
122   }
123
124   if ( data != NULL )
125    free(data);
126
127   return r;
128  }
129 }
130
131 return -1;
132}
133
134int emul_esd_check_client(int client, struct roar_vio_calls * vio) {
135 struct roar_vio_calls calls;
136 _cmd_t cmd;
137
138 if ( client == -1 )
139  return -1;
140
141 if ( vio == NULL ) {
142  vio = &calls;
143  if ( roar_vio_open_fh_socket(vio, clients_get_fh(client)) == -1 )
144   return -1;
145 }
146
147 if ( roar_vio_read(vio, &cmd, _INTSIZE) != _INTSIZE ) {
148  // really bad protocol error
149  clients_delete(client);
150  return -1;
151 }
152
153 return emul_esd_exec_command(client, cmd, vio);
154}
155
156// porto lib:
157int emul_esd_int_read_buf  (int client, int * data, void * buf) {
158 _cmd_t d;
159
160 if ( data == NULL || buf == NULL )
161  return -1;
162
163 d = *(_cmd_t*)buf;
164
165 *data = d;
166
167 return 0;
168}
169int emul_esd_int_read      (int client, int * data, struct roar_vio_calls * vio) {
170 _cmd_t d;
171
172 if ( data == NULL )
173  return -1;
174
175 if ( roar_vio_read(vio, &d, _INTSIZE) != _INTSIZE )
176  return -1;
177
178 *data = d;
179
180 return 0;
181}
182
183int emul_esd_int_write     (int client, int   data, struct roar_vio_calls * vio) {
184 _cmd_t d = data;
185
186 return roar_vio_write(vio, &d, _INTSIZE) == _INTSIZE ? 0 : -1;
187}
188
189int emul_esd_test_auth     (int client, void * data, struct roar_vio_calls * vio) {
190 // accept all clients for the moment.
191 return emul_esd_int_write(client, 1, vio);
192}
193
194int emul_esd_test_byteorder(int client, void * data) {
195 struct roar_client * c;
196
197 if ( clients_get(client, &c) == -1 )
198  return -1;
199
200// "NDNE";
201
202 if ( !memcmp(data, "NDNE", 4) ) {
203  c->byteorder = ROAR_BYTEORDER_LE;
204 } else if ( !memcmp(data, "ENDE", 4) ) {
205  c->byteorder = ROAR_BYTEORDER_BE;
206 } else if ( !memcmp(data, "NEED", 4) ) {
207  c->byteorder = ROAR_BYTEORDER_PDP;
208 } else {
209  return -1;
210 }
211
212 return 0;
213}
214
215// handler:
216int emul_esd_on_connect    (int client, struct emul_esd_command * cmd, void * data, struct roar_vio_calls * vio) {
217
218 ROAR_DBG("emul_esd_on_connect(client=%i, cmd=%p, data=%p, vio=%p) = ?", client, cmd, data, vio);
219
220 if ( client == -1 || data == NULL || vio == NULL )
221  return -1;
222
223 ROAR_DBG("emul_esd_on_connect(client=%i, cmd=%p, data=%p, vio=%p) = ?", client, cmd, data, vio);
224
225 if ( emul_esd_test_auth(client, data, vio) == -1 )
226  return -1;
227
228 ROAR_DBG("emul_esd_on_connect(client=%i, cmd=%p, data=%p, vio=%p) = ?", client, cmd, data, vio);
229
230 if ( emul_esd_test_byteorder(client, data+ESD_KEY_LEN) == -1 )
231  return -1;
232
233 ROAR_DBG("emul_esd_on_connect(client=%i, cmd=%p, data=%p, vio=%p) = ?", client, cmd, data, vio);
234
235 return 0;
236}
237
238int emul_esd_on_stream     (int client, struct emul_esd_command * cmd, void * data, struct roar_vio_calls * vio) {
239 struct roar_stream_server * ss;
240 struct roar_stream        *  s;
241 struct roar_client        *  c;
242 int stream;
243 int dir = -1;
244 int esdformat;
245 int rate = 0;
246
247 if ( client == -1 || cmd == NULL || data == NULL || vio == NULL )
248  return -1;
249
250 switch (cmd->cmd) {
251  case ESD_PROTO_STREAM_PLAY: dir = ROAR_DIR_PLAY;    break;
252  case ESD_PROTO_STREAM_REC:  dir = ROAR_DIR_RECORD;  break;
253  case ESD_PROTO_STREAM_MON:  dir = ROAR_DIR_MONITOR; break;
254  case ESD_PROTO_STREAM_FILT: dir = ROAR_DIR_FILTER;  break;
255  default:
256    clients_delete(client);
257    return -1;
258 }
259
260 if ( clients_get(client, &c) == -1 ) {
261  return -1;
262 }
263
264 ROAR_DBG("emul_esd_on_stream(client=%i, ...): creating stream...", client);
265 if ((stream = streams_new()) == -1 ) {
266  clients_delete(client);
267  return -1;
268 }
269
270 ROAR_DBG("emul_esd_on_stream(client=%i, ...): getting stream...", client);
271 if ( streams_get(stream, &ss) == -1 ) {
272  streams_delete(stream);
273  clients_delete(client);
274  return -1;
275 }
276
277 s = ROAR_STREAM(ss);
278
279 ROAR_DBG("emul_esd_on_stream(client=%i, ...): set client of stream...", client);
280 if ( client_stream_add(client, stream) == -1 ) {
281  streams_delete(stream);
282  clients_delete(client);
283  return -1;
284 }
285
286 emul_esd_int_read_buf(client, &esdformat, data);
287 emul_esd_int_read_buf(client, &rate,      data+_INTSIZE);
288
289 strncpy(c->name, data + 2*_INTSIZE, ROAR_BUFFER_NAME > ESD_NAME_MAX ? ESD_NAME_MAX : ROAR_BUFFER_NAME);
290 c->name[ROAR_BUFFER_NAME-1] = 0;
291
292 ROAR_DBG("emul_esd_on_stream(*): esdformat=0x%.8X, rate=%i", esdformat, rate);
293
294 s->info.rate = rate;
295
296 switch (esdformat & ESD_MASK_BITS) {
297  case ESD_BITS8:  s->info.bits =  8; s->info.codec = ROAR_CODEC_PCM_U_LE; break;
298  case ESD_BITS16: s->info.bits = 16; s->info.codec = ROAR_CODEC_DEFAULT;  break;
299  default:
300    streams_delete(stream);
301    clients_delete(client);
302    return -1;
303 }
304
305 switch (esdformat & ESD_MASK_CHAN) {
306  case ESD_MONO:   s->info.channels = 1; break;
307  case ESD_STEREO: s->info.channels = 2; break;
308  default:
309    streams_delete(stream);
310    clients_delete(client);
311    return -1;
312 }
313
314 ss->codec_orgi = s->info.codec;
315
316 ROAR_DBG("emul_esd_on_stream(*): s->info = {.rate=%i, .bits=%i, .channels=%i, .codec=%i}", s->info.rate, s->info.bits, s->info.channels, s->info.codec);
317
318 if ( streams_set_dir(stream, dir, 1) == -1 ) {
319  clients_delete(client);
320  return -1;
321 }
322
323 if ( client_stream_exec(client, stream) == -1 ) {
324  clients_delete(client);
325  return -1;
326 }
327
328 return 0;
329}
330
331int emul_esd_on_latency    (int client, struct emul_esd_command * cmd, void * data, struct roar_vio_calls * vio) {
332 int lag = ROAR_OUTPUT_CFREQ;
333
334 lag *= 2.0 * 44100.0 / (float)g_sa->rate;
335 
336 return emul_esd_int_write(client, lag, vio);
337}
338
339int emul_esd_on_standby    (int client, struct emul_esd_command * cmd, void * data, struct roar_vio_calls * vio) {
340 int ok = 0;
341
342 if ( emul_esd_test_auth(client, data, vio) == -1 ) {
343  return emul_esd_int_write(client, ok, vio);
344 }
345
346 ok = 1;
347
348 if (cmd->cmd == ESD_PROTO_STANDBY) {
349  g_standby = 1;
350 } else {
351  g_standby = 0;
352 }
353
354
355 return emul_esd_int_write(client, ok, vio);
356}
357
358int emul_esd_on_standbymode(int client, struct emul_esd_command * cmd, void * data, struct roar_vio_calls * vio) {
359 int mode = ESM_ERROR;
360
361 if ( g_standby ) {
362  if ( g_autostandby ) {
363   mode = ESM_ON_AUTOSTANDBY;
364  } else {
365   mode = ESM_ON_STANDBY;
366  }
367 } else {
368  mode = ESM_RUNNING;
369 }
370
371 return emul_esd_int_write(client, mode, vio);
372}
373
374int emul_esd_on_stream_pan (int client, struct emul_esd_command * cmd, void * data, struct roar_vio_calls * vio) {
375 struct roar_stream_server * ss;
376 int stream = -1;
377 int left = 256, right = 256;
378 int ok = 0;
379
380 emul_esd_int_read_buf(client, &stream, data + 0*_INTSIZE);
381 emul_esd_int_read_buf(client, &left,   data + 1*_INTSIZE);
382 emul_esd_int_read_buf(client, &right,  data + 2*_INTSIZE);
383
384 stream = _ESD2ROAR(stream);
385
386 if ( streams_get(stream, &ss) != -1 ) {
387  ss->mixer.mixer[0] = left  == 256 ? 65535 : left  * 256;
388  ss->mixer.mixer[1] = right == 256 ? 65535 : right * 256;
389  if ( streams_set_mixer(stream) != -1 )
390   ok = 1;
391 }
392
393 return emul_esd_int_write(client, ok, vio);
394}
395
396int emul_esd_on_server_info(int client, struct emul_esd_command * cmd, void * data, struct roar_vio_calls * vio) {
397 int version = 0;
398 int rate    = g_sa->rate;
399 int format  = 0;
400
401 switch (g_sa->bits) {
402  case  8: format |= ESD_BITS8;  break;
403  case 16: format |= ESD_BITS16; break;
404 }
405
406 switch (g_sa->channels) {
407  case  1: format |= ESD_MONO;   break;
408  case  2: format |= ESD_STEREO; break;
409 }
410
411 if ( emul_esd_int_write(client, version, vio) == -1 )
412  return -1;
413
414 if ( emul_esd_int_write(client, rate, vio) == -1 )
415  return -1;
416
417 if ( emul_esd_int_write(client, format, vio) == -1 )
418  return -1;
419
420 return 0;
421}
422
423int emul_esd_on_all_info   (int client, struct emul_esd_command * cmd, void * data, struct roar_vio_calls * vio) {
424 struct roar_stream_server *   ss;
425 struct roar_audio_info    * info;
426 struct roar_client        *    c;
427 char name[ESD_NAME_MAX];
428 char * sname;
429 int id, rate, left, right, format;
430 int i;
431
432 if ( emul_esd_on_server_info(client, cmd, data, vio) == -1 )
433  return -1;
434
435 for (i = 0; i < (ROAR_STREAMS_MAX+2); i++) {
436  memset(name, 0, sizeof(name));
437
438  id   = rate  = format = 0;
439  left = right = 0;
440
441  if ( i >= ROAR_STREAMS_MAX ) {
442   id = -1;
443  } else {
444   if ( streams_get(i, &ss) == -1 )
445    continue;
446
447   switch (streams_get_dir(i)) {
448    case ROAR_DIR_PLAY:    format |= ESD_PLAY;    break;
449    case ROAR_DIR_MONITOR: format |= ESD_MONITOR; break;
450    case ROAR_DIR_RECORD:  format |= ESD_RECORD;  break;
451    default:               continue;              break;
452   }
453
454   info = &(ROAR_STREAM(ss)->info);
455
456   id = i;
457   rate = info->rate;
458
459   switch (info->bits) {
460    case  8: format |= ESD_BITS8;  break;
461    case 16: format |= ESD_BITS16; break;
462   }
463
464   switch (info->channels) {
465    case  1:
466      if ( ss->mixer.mixer[0] == ss->mixer.scale ) {
467       left = right = 256;
468      } else {
469       left = right = ss->mixer.mixer[0] / 256;
470      }
471      format |= ESD_MONO;
472     break;
473    case  2:
474      if ( ss->mixer.mixer[0] == ss->mixer.scale ) {
475       left = 256;
476      } else {
477       left = ss->mixer.mixer[0] / 256;
478      }
479
480      if ( ss->mixer.mixer[1] == ss->mixer.scale ) {
481       right = 256;
482      } else {
483       right = ss->mixer.mixer[1] / 256;
484      }
485
486      format |= ESD_STEREO;
487     break;
488    default:
489      left = right = 0;
490   }
491
492   sname = streams_get_name(id);
493
494   if ( sname == NULL || sname[0] == 0 ) {
495    if ( clients_get(streams_get_client(id), &c) != -1 ) {
496     sname = c->name;
497    }
498   }
499
500   if ( sname == NULL || sname[0] == 0 )
501    sname = "(unknown)";
502
503   strncpy(name, sname, sizeof(name) > ROAR_BUFFER_NAME ? ROAR_BUFFER_NAME : sizeof(name));
504   name[sizeof(name)-1] = 0;
505
506  }
507
508  id = _ROAR2ESD(id);
509
510  if ( emul_esd_int_write(client, id, vio) == -1 )
511   return -1;
512  if ( roar_vio_write(vio, name, sizeof(name)) != sizeof(name) )
513   return -1;
514  if ( emul_esd_int_write(client, rate, vio) == -1 )
515   return -1;
516  if ( emul_esd_int_write(client, left, vio) == -1 )
517   return -1;
518  if ( emul_esd_int_write(client, right, vio) == -1 )
519   return -1;
520  if ( emul_esd_int_write(client, format, vio) == -1 )
521   return -1;
522
523  if ( i == ROAR_STREAMS_MAX+1) {
524   // write 'length'...
525   if ( emul_esd_int_write(client, id, vio) == -1 )
526    return -1;
527  }
528 }
529
530 return 0;
531}
532
533#endif
534#endif
535
536//ll
Note: See TracBrowser for help on using the repository browser.