source: roaraudio/libroaresd/esdctl.c @ 5270:e25346c13638

Last change on this file since 5270:e25346c13638 was 5270:e25346c13638, checked in by phi, 12 years ago

fixed some gcc -Wextra warnings

File size: 10.7 KB
Line 
1//esdctl.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2011
5 *  The code (may) include prototypes and comments (and maybe
6 *  other code fragements) from EsounD.
7 *  They are mostly copyrighted by Eric B. Mitchell (aka 'Ricdude)
8 *  <ericmit@ix.netcom.com>. For more information see AUTHORS.esd.
9 *
10 *  This file is part of libroaresd a part of RoarAudio,
11 *  a cross-platform sound system for both, home and professional use.
12 *  See README for details.
13 *
14 *  This file is free software; you can redistribute it and/or modify
15 *  it under the terms of the GNU General Public License version 3
16 *  as published by the Free Software Foundation.
17 *
18 *  RoarAudio is distributed in the hope that it will be useful,
19 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 *  GNU General Public License for more details.
22 *
23 *  You should have received a copy of the GNU General Public License
24 *  along with this software; see the file COPYING.  If not, write to
25 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
26 *  Boston, MA 02110-1301, USA.
27 *
28 *  NOTE for everyone want's to change something and send patches:
29 *  read README and HACKING! There a addition information on
30 *  the license of this document you need to read before you send
31 *  any patches.
32 *
33 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
34 *  or libpulse*:
35 *  The libs libroaresd, libroararts and libroarpulse link this libroar
36 *  and are therefore GPL. Because of this it may be illigal to use
37 *  them with any software that uses libesd, libartsc or libpulse*.
38 */
39
40#include "libroaresd.h"
41
42/* lock/unlock will disable/enable foreign clients from connecting */
43
44// we do not have such a thing at the moment...
45// so always return -1
46int esd_lock( int esd ) {
47 (void)esd;
48 errno = ENOSYS;
49 return -1;
50}
51int esd_unlock( int esd ) {
52 (void)esd;
53 errno = ENOSYS;
54 return -1;
55}
56
57/* standby/resume will free/reclaim audio device so others may use it */
58int esd_standby( int esd ) {
59 struct roar_connection con;
60
61 roar_connect_fh(&con, esd);
62
63 return roar_set_standby(&con, ROAR_STANDBY_ACTIVE);
64}
65
66int esd_resume( int esd ) {
67 struct roar_connection con;
68
69 roar_connect_fh(&con, esd);
70
71 return roar_set_standby(&con, ROAR_STANDBY_INACTIVE);
72}
73
74static void _format2str(char * buf, size_t len, esd_format_t format) {
75
76 if ( (format & ESD_BITS16) == ESD_BITS16 ) {
77  roar_mm_strlcat(buf, "16 bit ", len);
78 } else {
79  roar_mm_strlcat(buf, "8 bit ", len);
80 }
81
82 if ( (format & ESD_STEREO) == ESD_STEREO ) {
83  roar_mm_strlcat(buf, "stereo ", len);
84 } else {
85  roar_mm_strlcat(buf, "mono ", len);
86 }
87}
88
89/* print server into to stdout */
90void esd_print_server_info(esd_server_info_t *server_info ) {
91 char buf[80] = "";
92
93 _format2str(buf, sizeof(buf), server_info->format);
94
95 printf("server version   = %i\n",        server_info->version);
96 printf("server format    = 0x%08x %s\n", server_info->format, buf);
97 printf("server rate      = %i\n",        server_info->rate);
98}
99
100void esd_print_player_info( esd_player_info_t *player_info ) {
101 char buf[80] = "";
102
103 _format2str(buf, sizeof(buf), player_info->format);
104
105 printf("player %i name    = %s\n",        player_info->source_id, player_info->name);
106 printf("player %i format  = 0x%08x %s\n", player_info->source_id, player_info->format, buf);
107 printf("player %i rate    = %i\n",        player_info->source_id, player_info->rate);
108 printf("player %i left    = %i\n",        player_info->source_id, player_info->left_vol_scale );
109 printf("player %i right   = %i\n",        player_info->source_id, player_info->right_vol_scale );
110}
111
112void esd_print_sample_info( esd_sample_info_t *sample_info ) {
113 char buf[80] = "";
114
115 _format2str(buf, sizeof(buf), sample_info->format);
116
117 printf("sample %i name    = %s\n",        sample_info->sample_id, sample_info->name);
118 printf("sample %i format  = 0x%08x %s\n", sample_info->sample_id, sample_info->format, buf);
119 printf("sample %i rate    = %i\n",        sample_info->sample_id, sample_info->rate);
120 printf("sample %i left    = %i\n",        sample_info->sample_id, sample_info->left_vol_scale);
121 printf("sample %i right   = %i\n",        sample_info->sample_id, sample_info->right_vol_scale);
122 printf("sample %i length  = %i\n",        sample_info->sample_id, sample_info->length);
123}
124
125/* print all info to stdout */
126void esd_print_all_info( esd_info_t *all_info ) {
127 esd_player_info_t *player;
128 esd_sample_info_t *sample;
129
130
131 esd_print_server_info(all_info->server);
132
133 player = all_info->player_list;
134
135 while (player) {
136  esd_print_player_info(player);
137  player = player->next;
138 }
139
140 sample = all_info->sample_list;
141
142 while (sample) {
143  esd_print_sample_info(sample);
144  sample = sample->next;
145 }
146
147}
148
149/* retrieve server properties (sample rate, format, version number) */
150esd_server_info_t *esd_get_server_info( int esd ) {
151 esd_server_info_t * r;
152 struct roar_stream     s;
153 struct roar_connection con;
154 struct roar_message    m;
155
156 r = roar_mm_malloc(sizeof(esd_server_info_t));
157
158 if ( r == NULL )
159  return NULL;
160
161 r->version = 0; // seems to be static
162
163 roar_connect_fh(&con, esd);
164
165 memset(&m, 0, sizeof(m));
166
167 m.cmd     = ROAR_CMD_SERVER_OINFO;
168 m.datalen = 0;
169
170 if ( roar_req(&con, &m, NULL) == -1 ) {
171  roar_mm_free(r);
172  return NULL;
173 }
174
175 if ( m.cmd != ROAR_CMD_OK ) {
176  roar_mm_free(r);
177  return NULL;
178 }
179
180 if ( roar_stream_m2s(&s, &m) == -1 ) {
181  roar_mm_free(r);
182  return NULL;
183 }
184
185 r->rate   = s.info.rate;
186 r->format = 0;
187
188 if ( s.info.channels  == 1 )
189  r->format |= ESD_MONO;
190 else
191  r->format |= ESD_STEREO;
192
193 if ( s.info.bits == 8 )
194  r->format |= ESD_BITS8;
195 else
196  r->format |= ESD_BITS16;
197
198 return r;
199}
200/* release all memory allocated for the server properties structure */
201void esd_free_server_info( esd_server_info_t *server_info ) {
202 if (server_info != NULL)
203  roar_mm_free(server_info);
204}
205
206/* retrieve all information from server */
207esd_info_t *esd_get_all_info( int esd ) {
208 esd_info_t * r;
209 int i;
210 int num;
211 int clients[ROAR_CLIENTS_MAX];
212 struct roar_client c;
213 struct roar_stream s;
214 struct roar_connection con[1];
215 struct roar_mixer_settings mixer;
216 int channels;
217 float fs;
218 esd_player_info_t * new_player, * cur = NULL; // = NULL to avoid gcc warning
219
220 roar_connect_fh(con, esd);
221
222 r = roar_mm_malloc(sizeof(esd_info_t));
223
224 if ( r == NULL )
225  return NULL;
226
227 r->server      = esd_get_server_info(esd);
228 r->player_list = NULL;
229 r->sample_list = NULL;
230
231 if ( (num = roar_list_clients(con, clients, ROAR_CLIENTS_MAX)) == -1 ) {
232  ROAR_ERR("esd_get_all_info(*): can not get client list");
233  num = 0;
234 }
235
236 for (i = 0; i < num; i++) {
237  if ( roar_get_client(con, &c, clients[i]) == -1 ) {
238   ROAR_ERR("esd_get_all_info(*): can not get client info");
239   continue;
240  }
241
242  if ( c.execed != -1 ) {
243   if ( roar_get_stream(con, &s, c.execed) == -1 ) {
244    ROAR_ERR("esd_get_all_info(*): can not get stream info");
245    continue;
246   }
247
248   if ( (new_player = roar_mm_malloc(sizeof(esd_player_info_t))) == NULL ) {
249    ROAR_ERR("esd_get_all_info(*): can not alloc memory for new player! BAD");
250    continue;
251   }
252
253   new_player->next = NULL;
254
255   new_player->source_id      = c.execed;
256   new_player->rate           = s.info.rate;
257
258   new_player->format         = ROAR_S2ESD(&s);
259//   sprintf(new_player->name, "roar stream %i", c.execed);
260   strncpy(new_player->name, c.name, ESD_NAME_MAX < ROAR_BUFFER_NAME ? ESD_NAME_MAX : ESD_NAME_MAX);
261
262   new_player->server         = r->server;
263
264   if ( roar_get_vol(con, c.execed, &mixer, &channels) == -1 ) {
265    ROAR_ERR("esd_get_all_info(*): can not get stream mixer info");
266    new_player->left_vol_scale = new_player->right_vol_scale = 256;
267   } else {
268    fs = mixer.scale / 257;
269    if ( channels == 1 ) {
270     new_player->left_vol_scale = new_player->right_vol_scale = mixer.mixer[0] == mixer.scale ? 256 : mixer.mixer[0] / fs;
271    } else {
272     if ( channels != 2 ) {
273      ROAR_ERR("esd_get_all_info(*): server seems to run in > 2 channel mode. ignoring any but the first two channels!");
274     }
275     new_player->left_vol_scale  = mixer.mixer[0] == mixer.scale ? 256 : mixer.mixer[0] / fs;
276     new_player->right_vol_scale = mixer.mixer[1] == mixer.scale ? 256 : mixer.mixer[1] / fs;
277    }
278   }
279
280
281   if ( r->player_list == NULL ) {
282     r->player_list = cur = new_player;
283   } else {
284     cur->next = new_player; // add to old player
285     cur       = new_player; // hop to next player
286   }
287
288  }
289 }
290
291 return r;
292}
293
294/* retrieve all information from server, and update until unsubsribed or closed */
295esd_info_t *esd_subscribe_all_info( int esd ) {
296 (void)esd;
297 errno = ENOSYS;
298 return NULL; // Not yet implemented in upstream esd
299}
300
301/* call to update the info structure with new information, and call callbacks */
302esd_info_t *esd_update_info( int esd, esd_info_t *info,
303                             esd_update_info_callbacks_t *callbacks ) {
304 (void)esd, (void)info, (void)callbacks;
305 errno = ENOSYS;
306 return NULL; // Not yet implemented in upstream esd
307}
308
309esd_info_t *esd_unsubscribe_info( int esd ) {
310 (void)esd;
311 errno = ENOSYS;
312 return NULL; // Not yet implemented in upstream esd
313}
314
315/* release all memory allocated for the esd info structure */
316void esd_free_all_info( esd_info_t *info ) {
317 esd_player_info_t *player, *oplayer;
318 esd_sample_info_t *sample, *osample;
319
320 if ( info != NULL ) {
321
322/*
323  if ( info->server )
324   free(info->server);
325*/
326  esd_free_server_info(info->server);
327
328
329/*
330  // TODO: do we need to free more?
331  if ( info->player_list )
332   free(info->player_list);
333
334  if ( info->sample_list )
335   free(info->sample_list);
336*/
337
338 player = info->player_list;
339
340 while (player != NULL) {
341  oplayer = player;
342  player  = player->next;
343
344  roar_mm_free(oplayer);
345 }
346
347 sample = info->sample_list;
348
349 while (sample) {
350  osample = sample;
351  sample  = sample->next;
352
353  roar_mm_free(osample);
354 }
355
356  roar_mm_free(info);
357 }
358}
359
360
361/* reset the volume panning for a stream */
362int esd_set_stream_pan( int esd, int stream_id,
363                        int left_scale, int right_scale ) {
364 struct roar_connection con;
365 struct roar_mixer_settings mixer;
366
367 roar_connect_fh(&con, esd);
368
369 mixer.scale    = 256;
370 mixer.mixer[0] = left_scale;
371 mixer.mixer[1] = right_scale;
372
373 ROAR_DBG("esd_set_stream_pan(esd=%i, stream_id=%i, left_scale=%i, right_scale=%i) = ?",
374                esd, stream_id, left_scale, right_scale);
375
376 return roar_set_vol(&con, stream_id, &mixer, 2, ROAR_SET_VOL_UNMAPPED);
377}
378
379/* reset the default volume panning for a sample */
380int esd_set_default_sample_pan( int esd, int sample_id,
381                                int left_scale, int right_scale ) {
382 // this is not yet implemented by the RA protocol.
383 (void)esd, (void)sample_id, (void)left_scale, (void)right_scale;
384 errno = ENOSYS;
385 return -1;
386}
387
388/* see if the server is in stnaby, autostandby, etc */
389esd_standby_mode_t esd_get_standby_mode( int esd ) {
390 struct roar_connection con;
391
392 if ( roar_connect_fh(&con, esd) == -1 )
393  return -1;
394
395 return roar_get_standby(&con);
396}
397
398//ll
Note: See TracBrowser for help on using the repository browser.