source: roaraudio/plugins/roard/protocol-esound.c @ 2529:eba7f2ff0163

Last change on this file since 2529:eba7f2ff0163 was 2529:eba7f2ff0163, checked in by phi, 15 years ago

got basic streaming working

File size: 8.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, 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
39struct emul_esd_command g_emul_esd_commands[] = {
40 {ESD_PROTO_CONNECT,      ESD_KEY_LEN  +     _INTSIZE, _NAME("CONNECT"),      emul_esd_on_connect},
41 {ESD_PROTO_LOCK,         ESD_KEY_LEN  +     _INTSIZE, _NAME("LOCK"),         NULL},
42 {ESD_PROTO_UNLOCK,       ESD_KEY_LEN  +     _INTSIZE, _NAME("UNLOCK"),       NULL},
43 {ESD_PROTO_STREAM_PLAY,  ESD_NAME_MAX + 2 * _INTSIZE, _NAME("STREAM_PLAY"),  emul_esd_on_stream},
44 {ESD_PROTO_STREAM_REC,   ESD_NAME_MAX + 2 * _INTSIZE, _NAME("STREAM_REC"),   emul_esd_on_stream},
45 {ESD_PROTO_STREAM_MON,   ESD_NAME_MAX + 2 * _INTSIZE, _NAME("STREAM_MON"),   emul_esd_on_stream},
46 {ESD_PROTO_SAMPLE_CACHE, ESD_NAME_MAX + 3 * _INTSIZE, _NAME("SAMPLE_CACHE"), NULL},
47 {ESD_PROTO_SAMPLE_FREE,                     _INTSIZE, _NAME("SAMPLE_FREE"),  NULL},
48 {ESD_PROTO_SAMPLE_PLAY,                     _INTSIZE, _NAME("SAMPLE_PLAY"),  NULL},
49 {ESD_PROTO_SAMPLE_LOOP,                     _INTSIZE, _NAME("SAMPLE_LOOP"),  NULL},
50 {ESD_PROTO_SAMPLE_STOP,                     _INTSIZE, _NAME("SAMPLE_STOP"),  NULL},
51 {ESD_PROTO_SAMPLE_KILL,  0                          , _NAME("SAMPLE_KILL"),  NULL},
52 {ESD_PROTO_STANDBY,      ESD_KEY_LEN +      _INTSIZE, _NAME("STANDBY"),      NULL},
53 {ESD_PROTO_RESUME,       ESD_KEY_LEN +      _INTSIZE, _NAME("RESUME"),       NULL},
54 {ESD_PROTO_SAMPLE_GETID, ESD_NAME_MAX               , _NAME("SAMPLE_GETID"), NULL},
55 {ESD_PROTO_STREAM_FILT,  ESD_NAME_MAX + 2 * _INTSIZE, _NAME("STREAM_FILT"),  emul_esd_on_stream},
56 {ESD_PROTO_SERVER_INFO,                     _INTSIZE, _NAME("SERVER_INFO"),  NULL},
57 {ESD_PROTO_ALL_INFO,                        _INTSIZE, _NAME("ALL_INFO"),     NULL},
58 {ESD_PROTO_SUBSCRIBE,    0                          , _NAME("SUBSCRIBE"),    NULL},
59 {ESD_PROTO_UNSUBSCRIBE,  0                          , _NAME("UNSUBSCRIBE"),  NULL},
60 {ESD_PROTO_STREAM_PAN,                  3 * _INTSIZE, _NAME("STREAM_PAN"),   NULL},
61 {ESD_PROTO_SAMPLE_PAN,                  3 * _INTSIZE, _NAME("SAMPLE_PAN"),   NULL},
62 {ESD_PROTO_STANDBY_MODE,                    _INTSIZE, _NAME("STANDBY_MODE"), NULL},
63 {ESD_PROTO_LATENCY,      0                          , _NAME("LATENCY"),      NULL},
64 {ESD_PROTO_MAX,          0                          , _NAME("MAX"),          NULL},
65 {-1, 0, _NAME("END OF LIST"), NULL}
66};
67
68// command handling:
69int emul_esd_exec_command(int client, int cmd, struct roar_vio_calls * vio) {
70 struct emul_esd_command * cur;
71 void * data = NULL;
72 int r;
73 int i;
74
75 if ( client == -1 || cmd < ESD_PROTO_CONNECT || cmd > ESD_PROTO_MAX || vio == NULL )
76  return -1;
77
78 for (i = 0; (cur = &(g_emul_esd_commands[i]))->cmd != -1; i++) {
79  if ( cur->cmd == cmd ) {
80   if ( cur->datalen > 0 ) {
81    if ( (data = malloc(cur->datalen)) == NULL ) {
82     // we will do a protocol error in case we do not drop the client
83     clients_delete(client);
84     return -1;
85    }
86
87    if ( roar_vio_read(vio, data, cur->datalen) != cur->datalen ) {
88     free(data);
89     clients_delete(client);
90     return -1;
91    }
92   }
93
94   if ( cur->handler == NULL ) {
95    ROAR_WARN("emul_esd_exec_command(client=%i, cmd=%s(%i), vio=%p): client uses unimplemted command",
96               client, cur->name, cmd, vio
97             );
98    r = -1;
99   } else {
100    r = cur->handler(client, cur, data, vio);
101   }
102
103   if ( data != NULL )
104    free(data);
105
106   return r;
107  }
108 }
109
110 return -1;
111}
112
113int emul_esd_check_client(int client, struct roar_vio_calls * vio) {
114 struct roar_vio_calls calls;
115 _cmd_t cmd;
116
117 if ( client == -1 )
118  return -1;
119
120 if ( vio == NULL ) {
121  vio = &calls;
122  if ( roar_vio_open_fh(vio, clients_get_fh(client)) == -1 )
123   return -1;
124 }
125
126 if ( roar_vio_read(vio, &cmd, _INTSIZE) != _INTSIZE ) {
127  // really bad protocol error
128  clients_delete(client);
129  return -1;
130 }
131
132 return emul_esd_exec_command(client, cmd, vio);
133}
134
135// porto lib:
136int emul_esd_int_read_buf  (int client, int * data, void * buf) {
137 _cmd_t d;
138
139 if ( data == NULL || buf == NULL )
140  return -1;
141
142 d = *(_cmd_t*)buf;
143
144 *data = d;
145
146 return 0;
147}
148int emul_esd_int_read      (int client, int * data, struct roar_vio_calls * vio) {
149 _cmd_t d;
150
151 if ( data == NULL )
152  return -1;
153
154 if ( roar_vio_read(vio, &d, _INTSIZE) != _INTSIZE )
155  return -1;
156
157 *data = d;
158
159 return 0;
160}
161
162int emul_esd_int_write     (int client, int   data, struct roar_vio_calls * vio) {
163 _cmd_t d = data;
164
165 return roar_vio_write(vio, &d, _INTSIZE) == _INTSIZE ? 0 : -1;
166}
167
168int emul_esd_test_auth     (int client, void * data, struct roar_vio_calls * vio) {
169 // accept all clients for the moment.
170 return emul_esd_int_write(client, 1, vio);
171}
172
173int emul_esd_test_byteorder(int client, void * data) {
174 // TODO: do a real test
175 return 0;
176}
177
178// handler:
179int emul_esd_on_connect    (int client, struct emul_esd_command * cmd, void * data, struct roar_vio_calls * vio) {
180
181 ROAR_DBG("emul_esd_on_connect(client=%i, cmd=%p, data=%p, vio=%p) = ?", client, cmd, data, vio);
182
183 if ( client == -1 || data == NULL || vio == NULL )
184  return -1;
185
186 ROAR_DBG("emul_esd_on_connect(client=%i, cmd=%p, data=%p, vio=%p) = ?", client, cmd, data, vio);
187
188 if ( emul_esd_test_auth(client, data, vio) == -1 )
189  return -1;
190
191 ROAR_DBG("emul_esd_on_connect(client=%i, cmd=%p, data=%p, vio=%p) = ?", client, cmd, data, vio);
192
193 if ( emul_esd_test_byteorder(client, data+ESD_KEY_LEN) == -1 )
194  return -1;
195
196 ROAR_DBG("emul_esd_on_connect(client=%i, cmd=%p, data=%p, vio=%p) = ?", client, cmd, data, vio);
197
198 return 0;
199}
200
201int emul_esd_on_stream     (int client, struct emul_esd_command * cmd, void * data, struct roar_vio_calls * vio) {
202 struct roar_stream_server * ss;
203 struct roar_stream        *  s;
204 int stream;
205 int dir = -1;
206 int esdformat;
207 int rate;
208
209 if ( client == -1 || cmd == NULL || data == NULL || vio == NULL )
210  return -1;
211
212 switch (cmd->cmd) {
213  case ESD_PROTO_STREAM_PLAY: dir = ROAR_DIR_PLAY;    break;
214  case ESD_PROTO_STREAM_REC:  dir = ROAR_DIR_RECORD;  break;
215  case ESD_PROTO_STREAM_MON:  dir = ROAR_DIR_MONITOR; break;
216  case ESD_PROTO_STREAM_FILT: dir = ROAR_DIR_FILTER;  break;
217  default:
218    clients_delete(client);
219    return -1;
220 }
221
222 ROAR_DBG("emul_esd_on_stream(client=%i, ...): creating stream...", client);
223 if ((stream = streams_new()) == -1 ) {
224  clients_delete(client);
225  return -1;
226 }
227
228 ROAR_DBG("emul_esd_on_stream(client=%i, ...): getting stream...", client);
229 if ( streams_get(stream, &ss) == -1 ) {
230  streams_delete(stream);
231  clients_delete(client);
232  return -1;
233 }
234
235 s = ROAR_STREAM(ss);
236
237 ROAR_DBG("emul_esd_on_stream(client=%i, ...): set client of stream...", client);
238 if ( client_stream_add(client, stream) == -1 ) {
239  streams_delete(stream);
240  clients_delete(client);
241  return -1;
242 }
243
244 emul_esd_int_read_buf(client, &esdformat, data);
245 emul_esd_int_read_buf(client, &rate,      data+_INTSIZE);
246
247 ROAR_DBG("emul_esd_on_stream(*): esdformat=0x%.8X, rate=%i", esdformat, rate);
248
249 s->info.rate = rate;
250
251 switch (esdformat & ESD_MASK_BITS) {
252  case ESD_BITS8:  s->info.bits =  8; s->info.codec = ROAR_CODEC_PCM_U_LE; break;
253  case ESD_BITS16: s->info.bits = 16; s->info.codec = ROAR_CODEC_DEFAULT;  break;
254  default:
255    streams_delete(stream);
256    clients_delete(client);
257    return -1;
258 }
259
260 switch (esdformat & ESD_MASK_CHAN) {
261  case ESD_MONO:   s->info.channels = 1; break;
262  case ESD_STEREO: s->info.channels = 2; break;
263  default:
264    streams_delete(stream);
265    clients_delete(client);
266    return -1;
267 }
268
269 ss->codec_orgi = s->info.codec;
270
271 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);
272
273 if ( streams_set_dir(stream, dir, 1) == -1 ) {
274  clients_delete(client);
275  return -1;
276 }
277
278 if ( client_stream_exec(client, stream) == -1 ) {
279  clients_delete(client);
280  return -1;
281 }
282
283 return 0;
284}
285
286#endif
287#endif
288
289//ll
Note: See TracBrowser for help on using the repository browser.