source: roaraudio/plugins/roard/protocol-esound.c @ 2537:f9ad29f742c0

Last change on this file since 2537:f9ad29f742c0 was 2537:f9ad29f742c0, checked in by phi, 13 years ago

use symbolic names for diffrent cases of NULL impls.

File size: 10.4 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, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25#include "roard.h"
26
27#ifndef ROAR_WITHOUT_DCOMP_EMUL_ESD
28#ifdef ROAR_HAVE_ESD
29
30#if !defined(ROAR_TARGET_MICROCONTROLLER) && !defined(ROAR_MINIMAL)
31#define _NAME(x) (x)
32#else
33#define _NAME(x) ((char*)NULL)
34#endif
35
36#define _cmd_t   int
37#define _INTSIZE sizeof(_cmd_t)
38
39#define _NOT_TO_IMPLEMENT    NULL
40#define _UNIMPLEMNTED_IN_ESD NULL
41#define _NEED_SAMPLE_SUPPORT NULL
42
43struct emul_esd_command g_emul_esd_commands[] = {
44 {ESD_PROTO_CONNECT,      ESD_KEY_LEN  +     _INTSIZE, _NAME("CONNECT"),      emul_esd_on_connect},
45 {ESD_PROTO_LOCK,         ESD_KEY_LEN  +     _INTSIZE, _NAME("LOCK"),         NULL},
46 {ESD_PROTO_UNLOCK,       ESD_KEY_LEN  +     _INTSIZE, _NAME("UNLOCK"),       NULL},
47 {ESD_PROTO_STREAM_PLAY,  ESD_NAME_MAX + 2 * _INTSIZE, _NAME("STREAM_PLAY"),  emul_esd_on_stream},
48 {ESD_PROTO_STREAM_REC,   ESD_NAME_MAX + 2 * _INTSIZE, _NAME("STREAM_REC"),   emul_esd_on_stream},
49 {ESD_PROTO_STREAM_MON,   ESD_NAME_MAX + 2 * _INTSIZE, _NAME("STREAM_MON"),   emul_esd_on_stream},
50 {ESD_PROTO_SAMPLE_CACHE, ESD_NAME_MAX + 3 * _INTSIZE, _NAME("SAMPLE_CACHE"), _NEED_SAMPLE_SUPPORT},
51 {ESD_PROTO_SAMPLE_FREE,                     _INTSIZE, _NAME("SAMPLE_FREE"),  _NEED_SAMPLE_SUPPORT},
52 {ESD_PROTO_SAMPLE_PLAY,                     _INTSIZE, _NAME("SAMPLE_PLAY"),  _NEED_SAMPLE_SUPPORT},
53 {ESD_PROTO_SAMPLE_LOOP,                     _INTSIZE, _NAME("SAMPLE_LOOP"),  _NEED_SAMPLE_SUPPORT},
54 {ESD_PROTO_SAMPLE_STOP,                     _INTSIZE, _NAME("SAMPLE_STOP"),  _NEED_SAMPLE_SUPPORT},
55 {ESD_PROTO_SAMPLE_KILL,  0                          , _NAME("SAMPLE_KILL"),  _NEED_SAMPLE_SUPPORT},
56 {ESD_PROTO_STANDBY,      ESD_KEY_LEN +      _INTSIZE, _NAME("STANDBY"),      emul_esd_on_standby},
57 {ESD_PROTO_RESUME,       ESD_KEY_LEN +      _INTSIZE, _NAME("RESUME"),       emul_esd_on_standby},
58 {ESD_PROTO_SAMPLE_GETID, ESD_NAME_MAX               , _NAME("SAMPLE_GETID"), _NEED_SAMPLE_SUPPORT},
59 {ESD_PROTO_STREAM_FILT,  ESD_NAME_MAX + 2 * _INTSIZE, _NAME("STREAM_FILT"),  emul_esd_on_stream},
60 {ESD_PROTO_SERVER_INFO,                     _INTSIZE, _NAME("SERVER_INFO"),  NULL},
61 {ESD_PROTO_ALL_INFO,                        _INTSIZE, _NAME("ALL_INFO"),     NULL},
62 {ESD_PROTO_SUBSCRIBE,    0                          , _NAME("SUBSCRIBE"),    _UNIMPLEMNTED_IN_ESD},
63 {ESD_PROTO_UNSUBSCRIBE,  0                          , _NAME("UNSUBSCRIBE"),  _UNIMPLEMNTED_IN_ESD},
64 {ESD_PROTO_STREAM_PAN,                  3 * _INTSIZE, _NAME("STREAM_PAN"),   NULL},
65 {ESD_PROTO_SAMPLE_PAN,                  3 * _INTSIZE, _NAME("SAMPLE_PAN"),   _NEED_SAMPLE_SUPPORT},
66 {ESD_PROTO_STANDBY_MODE,                    _INTSIZE, _NAME("STANDBY_MODE"), emul_esd_on_standbymode},
67 {ESD_PROTO_LATENCY,      0                          , _NAME("LATENCY"),      emul_esd_on_latency},
68 {ESD_PROTO_MAX,          0                          , _NAME("MAX"),          _NOT_TO_IMPLEMENT},
69 {-1, 0, _NAME("END OF LIST"), _NOT_TO_IMPLEMENT}
70};
71
72// command handling:
73int emul_esd_exec_command(int client, int cmd, struct roar_vio_calls * vio) {
74 struct emul_esd_command * cur;
75 void * data = NULL;
76 ssize_t ret;
77 size_t  done = 0;
78 int r;
79 int i;
80
81 ROAR_DBG("emul_esd_exec_command(*) = ?");
82
83 if ( client == -1 || cmd < ESD_PROTO_CONNECT || cmd > ESD_PROTO_MAX || vio == NULL )
84  return -1;
85
86 ROAR_DBG("emul_esd_exec_command(*) = ?");
87
88 for (i = 0; (cur = &(g_emul_esd_commands[i]))->cmd != -1; i++) {
89  if ( cur->cmd == cmd ) {
90   if ( cur->datalen > 0 ) {
91    if ( (data = malloc(cur->datalen)) == NULL ) {
92     // we will do a protocol error in case we do not drop the client
93     clients_delete(client);
94     return -1;
95    }
96
97    while ( done < cur->datalen ) {
98     ret = roar_vio_read(vio, data+done, cur->datalen-done);
99
100     if ( ret < 1 ) {
101      free(data);
102      clients_delete(client);
103      return -1;
104     } else {
105      done += ret;
106     }
107    }
108   }
109
110   if ( cur->handler == NULL ) {
111    ROAR_WARN("emul_esd_exec_command(client=%i, cmd=%s(%i), vio=%p): client uses unimplemted command",
112               client, cur->name, cmd, vio
113             );
114    clients_delete(client);
115    r = -1;
116   } else {
117    r = cur->handler(client, cur, data, vio);
118   }
119
120   if ( data != NULL )
121    free(data);
122
123   return r;
124  }
125 }
126
127 return -1;
128}
129
130int emul_esd_check_client(int client, struct roar_vio_calls * vio) {
131 struct roar_vio_calls calls;
132 _cmd_t cmd;
133
134 if ( client == -1 )
135  return -1;
136
137 if ( vio == NULL ) {
138  vio = &calls;
139  if ( roar_vio_open_fh(vio, clients_get_fh(client)) == -1 )
140   return -1;
141 }
142
143 if ( roar_vio_read(vio, &cmd, _INTSIZE) != _INTSIZE ) {
144  // really bad protocol error
145  clients_delete(client);
146  return -1;
147 }
148
149 return emul_esd_exec_command(client, cmd, vio);
150}
151
152// porto lib:
153int emul_esd_int_read_buf  (int client, int * data, void * buf) {
154 _cmd_t d;
155
156 if ( data == NULL || buf == NULL )
157  return -1;
158
159 d = *(_cmd_t*)buf;
160
161 *data = d;
162
163 return 0;
164}
165int emul_esd_int_read      (int client, int * data, struct roar_vio_calls * vio) {
166 _cmd_t d;
167
168 if ( data == NULL )
169  return -1;
170
171 if ( roar_vio_read(vio, &d, _INTSIZE) != _INTSIZE )
172  return -1;
173
174 *data = d;
175
176 return 0;
177}
178
179int emul_esd_int_write     (int client, int   data, struct roar_vio_calls * vio) {
180 _cmd_t d = data;
181
182 return roar_vio_write(vio, &d, _INTSIZE) == _INTSIZE ? 0 : -1;
183}
184
185int emul_esd_test_auth     (int client, void * data, struct roar_vio_calls * vio) {
186 // accept all clients for the moment.
187 return emul_esd_int_write(client, 1, vio);
188}
189
190int emul_esd_test_byteorder(int client, void * data) {
191 // TODO: do a real test
192 return 0;
193}
194
195// handler:
196int emul_esd_on_connect    (int client, struct emul_esd_command * cmd, void * data, struct roar_vio_calls * vio) {
197
198 ROAR_DBG("emul_esd_on_connect(client=%i, cmd=%p, data=%p, vio=%p) = ?", client, cmd, data, vio);
199
200 if ( client == -1 || data == NULL || vio == NULL )
201  return -1;
202
203 ROAR_DBG("emul_esd_on_connect(client=%i, cmd=%p, data=%p, vio=%p) = ?", client, cmd, data, vio);
204
205 if ( emul_esd_test_auth(client, data, vio) == -1 )
206  return -1;
207
208 ROAR_DBG("emul_esd_on_connect(client=%i, cmd=%p, data=%p, vio=%p) = ?", client, cmd, data, vio);
209
210 if ( emul_esd_test_byteorder(client, data+ESD_KEY_LEN) == -1 )
211  return -1;
212
213 ROAR_DBG("emul_esd_on_connect(client=%i, cmd=%p, data=%p, vio=%p) = ?", client, cmd, data, vio);
214
215 return 0;
216}
217
218int emul_esd_on_stream     (int client, struct emul_esd_command * cmd, void * data, struct roar_vio_calls * vio) {
219 struct roar_stream_server * ss;
220 struct roar_stream        *  s;
221 struct roar_client        *  c;
222 int stream;
223 int dir = -1;
224 int esdformat;
225 int rate;
226
227 if ( client == -1 || cmd == NULL || data == NULL || vio == NULL )
228  return -1;
229
230 switch (cmd->cmd) {
231  case ESD_PROTO_STREAM_PLAY: dir = ROAR_DIR_PLAY;    break;
232  case ESD_PROTO_STREAM_REC:  dir = ROAR_DIR_RECORD;  break;
233  case ESD_PROTO_STREAM_MON:  dir = ROAR_DIR_MONITOR; break;
234  case ESD_PROTO_STREAM_FILT: dir = ROAR_DIR_FILTER;  break;
235  default:
236    clients_delete(client);
237    return -1;
238 }
239
240 if ( clients_get(client, &c) == -1 ) {
241  return -1;
242 }
243
244 ROAR_DBG("emul_esd_on_stream(client=%i, ...): creating stream...", client);
245 if ((stream = streams_new()) == -1 ) {
246  clients_delete(client);
247  return -1;
248 }
249
250 ROAR_DBG("emul_esd_on_stream(client=%i, ...): getting stream...", client);
251 if ( streams_get(stream, &ss) == -1 ) {
252  streams_delete(stream);
253  clients_delete(client);
254  return -1;
255 }
256
257 s = ROAR_STREAM(ss);
258
259 ROAR_DBG("emul_esd_on_stream(client=%i, ...): set client of stream...", client);
260 if ( client_stream_add(client, stream) == -1 ) {
261  streams_delete(stream);
262  clients_delete(client);
263  return -1;
264 }
265
266 emul_esd_int_read_buf(client, &esdformat, data);
267 emul_esd_int_read_buf(client, &rate,      data+_INTSIZE);
268
269 strncpy(c->name, data + 2*_INTSIZE, ROAR_BUFFER_NAME > ESD_NAME_MAX ? ESD_NAME_MAX : ROAR_BUFFER_NAME);
270 c->name[ROAR_BUFFER_NAME-1] = 0;
271
272 ROAR_DBG("emul_esd_on_stream(*): esdformat=0x%.8X, rate=%i", esdformat, rate);
273
274 s->info.rate = rate;
275
276 switch (esdformat & ESD_MASK_BITS) {
277  case ESD_BITS8:  s->info.bits =  8; s->info.codec = ROAR_CODEC_PCM_U_LE; break;
278  case ESD_BITS16: s->info.bits = 16; s->info.codec = ROAR_CODEC_DEFAULT;  break;
279  default:
280    streams_delete(stream);
281    clients_delete(client);
282    return -1;
283 }
284
285 switch (esdformat & ESD_MASK_CHAN) {
286  case ESD_MONO:   s->info.channels = 1; break;
287  case ESD_STEREO: s->info.channels = 2; break;
288  default:
289    streams_delete(stream);
290    clients_delete(client);
291    return -1;
292 }
293
294 ss->codec_orgi = s->info.codec;
295
296 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);
297
298 if ( streams_set_dir(stream, dir, 1) == -1 ) {
299  clients_delete(client);
300  return -1;
301 }
302
303 if ( client_stream_exec(client, stream) == -1 ) {
304  clients_delete(client);
305  return -1;
306 }
307
308 return 0;
309}
310
311int emul_esd_on_latency    (int client, struct emul_esd_command * cmd, void * data, struct roar_vio_calls * vio) {
312 int lag = ROAR_OUTPUT_CFREQ;
313
314 lag *= 2.0 * 44100.0 / (float)g_sa->rate;
315 
316 return emul_esd_int_write(client, lag, vio);
317}
318
319int emul_esd_on_standby    (int client, struct emul_esd_command * cmd, void * data, struct roar_vio_calls * vio) {
320 int ok = 0;
321
322 if ( emul_esd_test_auth(client, data, vio) == -1 ) {
323  return emul_esd_int_write(client, ok, vio);
324 }
325
326 ok = 1;
327
328 if (cmd->cmd == ESD_PROTO_STANDBY) {
329  g_standby = 1;
330 } else {
331  g_standby = 0;
332 }
333
334
335 return emul_esd_int_write(client, ok, vio);
336}
337
338int emul_esd_on_standbymode(int client, struct emul_esd_command * cmd, void * data, struct roar_vio_calls * vio) {
339 int mode = ESM_ERROR;
340
341 if ( g_standby ) {
342  if ( g_autostandby ) {
343   mode = ESM_ON_AUTOSTANDBY;
344  } else {
345   mode = ESM_ON_STANDBY;
346  }
347 } else {
348  mode = ESM_RUNNING;
349 }
350
351 return emul_esd_int_write(client, mode, vio);
352}
353
354#endif
355#endif
356
357//ll
Note: See TracBrowser for help on using the repository browser.