1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * ESD sound driver.
12 *
13 * By Michael Bukin.
14 *
15 * Bug fixes by Peter Wang and Eduard Bloch.
16 *
17 * See readme.txt for copyright information.
18 */
19
20
21 #include "allegro.h"
22
23 #if (defined ALLEGRO_WITH_ESDDIGI) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE))
24
25 #include "allegro/internal/aintern.h"
26 #include "allegro/platform/aintunix.h"
27
28 #include <sys/time.h>
29 #include <sys/types.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <esd.h>
33
34 static int _al_esd_fd;
35 static int _al_esd_bufsize;
36 static unsigned char *_al_esd_bufdata;
37 static int _al_esd_bits, _al_esd_signed, _al_esd_rate, _al_esd_stereo;
38 static esd_format_t _al_esd_format;
39
40 static int _al_esd_detect(int input);
41 static int _al_esd_init(int input, int voices);
42 static void _al_esd_exit(int input);
43 static int _al_esd_set_mixer_volume(int volume);
44 static int _al_esd_buffer_size(void);
45
46 static char _al_esd_desc[256] = EMPTY_STRING;
47
48 DIGI_DRIVER digi_esd =
49 {
50 DIGI_ESD,
51 empty_string,
52 empty_string,
53 "Enlightened Sound Daemon",
54 0,
55 0,
56 MIXER_MAX_SFX,
57 MIXER_DEF_SFX,
58
59 _al_esd_detect,
60 _al_esd_init,
61 _al_esd_exit,
62 _al_esd_set_mixer_volume,
63 NULL,
64
65 NULL,
66 NULL,
67 _al_esd_buffer_size,
68 _mixer_init_voice,
69 _mixer_release_voice,
70 _mixer_start_voice,
71 _mixer_stop_voice,
72 _mixer_loop_voice,
73
74 _mixer_get_position,
75 _mixer_set_position,
76
77 _mixer_get_volume,
78 _mixer_set_volume,
79 _mixer_ramp_volume,
80 _mixer_stop_volume_ramp,
81
82 _mixer_get_frequency,
83 _mixer_set_frequency,
84 _mixer_sweep_frequency,
85 _mixer_stop_frequency_sweep,
86
87 _mixer_get_pan,
88 _mixer_set_pan,
89 _mixer_sweep_pan,
90 _mixer_stop_pan_sweep,
91
92 _mixer_set_echo,
93 _mixer_set_tremolo,
94 _mixer_set_vibrato,
95 0, 0,
96 0,
97 0,
98 0,
99 0,
100 0,
101 0
102 };
103
104
105
106 /* _al_esd_buffer_size:
107 * Returns the current DMA buffer size, for use by the audiostream code.
108 */
_al_esd_buffer_size(void)109 static int _al_esd_buffer_size(void)
110 {
111 return _al_esd_bufsize / (_al_esd_bits / 8) / (_al_esd_stereo ? 2 : 1);
112 }
113
114
115
116 /* _al_esd_update:
117 * Update data.
118 */
_al_esd_update(int threaded)119 static void _al_esd_update(int threaded)
120 {
121 fd_set wfds;
122 struct timeval timeout;
123
124 FD_ZERO(&wfds);
125 FD_SET(_al_esd_fd, &wfds);
126 timeout.tv_sec = 0;
127 timeout.tv_usec = 0;
128
129 if (select(_al_esd_fd+1, NULL, &wfds, NULL, &timeout) > 0) {
130 write(_al_esd_fd, _al_esd_bufdata, _al_esd_bufsize);
131 _mix_some_samples((uintptr_t) _al_esd_bufdata, 0, _al_esd_signed);
132 }
133 }
134
135
136
137 /* _al_esd_detect:
138 * Detect driver presence.
139 */
_al_esd_detect(int input)140 static int _al_esd_detect(int input)
141 {
142 int fd;
143 AL_CONST char *server;
144 char tmp1[128], tmp2[128], tmp3[16];
145 char s[256];
146
147 if (input) {
148 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
149 return FALSE;
150 }
151
152 /* We don't want esdlib to spawn ESD while we are detecting it. */
153 putenv("ESD_NO_SPAWN=1");
154
155 /* Get ESD server name. */
156 server = get_config_string(uconvert_ascii("sound", tmp1),
157 uconvert_ascii("esd_server", tmp2),
158 uconvert_ascii("", tmp3));
159
160 /* Try to open ESD server. */
161 fd = esd_open_sound(uconvert_toascii(server, s));
162 if (fd < 0) {
163 uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("%s: can not open"),
164 (ugetc(server) ? server : get_config_text("No server")));
165 return FALSE;
166 }
167
168 esd_close(fd);
169 return TRUE;
170 }
171
172
173
174 /* _al_esd_init:
175 * ESD init routine.
176 */
_al_esd_init(int input,int voices)177 static int _al_esd_init(int input, int voices)
178 {
179 AL_CONST char *server;
180 char tmp1[128], tmp2[128], tmp3[16];
181 char s[256];
182
183 if (input) {
184 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
185 return -1;
186 }
187
188 server = get_config_string(uconvert_ascii("sound", tmp1),
189 uconvert_ascii("esd_server", tmp2),
190 uconvert_ascii("", tmp3));
191
192 _al_esd_bits = (_sound_bits == 8) ? 8 : 16;
193 _al_esd_stereo = (_sound_stereo) ? 1 : 0;
194 _al_esd_rate = (_sound_freq > 0) ? _sound_freq : ESD_DEFAULT_RATE;
195 _al_esd_signed = 1;
196
197 _al_esd_format = (((_al_esd_bits == 16) ? ESD_BITS16 : ESD_BITS8)
198 | (_al_esd_stereo ? ESD_STEREO : ESD_MONO)
199 | ESD_STREAM | ESD_PLAY);
200
201 _al_esd_fd = esd_play_stream_fallback(_al_esd_format, _al_esd_rate,
202 uconvert_toascii(server, s), NULL);
203 if (_al_esd_fd < 0) {
204 uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("%s: can not open"),
205 (ugetc(server) ? server : get_config_text("No server")));
206 return -1;
207 }
208
209 _al_esd_bufsize = ESD_BUF_SIZE;
210 _al_esd_bufdata = _AL_MALLOC_ATOMIC(_al_esd_bufsize);
211 if (_al_esd_bufdata == 0) {
212 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not allocate audio buffer"));
213 close(_al_esd_fd);
214 return -1;
215 }
216
217 digi_esd.voices = voices;
218
219 if (_mixer_init(_al_esd_bufsize / (_al_esd_bits / 8), _al_esd_rate,
220 _al_esd_stereo, ((_al_esd_bits == 16) ? 1 : 0),
221 &digi_esd.voices) != 0) {
222 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not init software mixer"));
223 _AL_FREE(_al_esd_bufdata);
224 _al_esd_bufdata = 0;
225 close(_al_esd_fd);
226 return -1;
227 }
228
229 _mix_some_samples((uintptr_t) _al_esd_bufdata, 0, _al_esd_signed);
230
231 /* Add audio interrupt. */
232 _unix_bg_man->register_func(_al_esd_update);
233
234 uszprintf(_al_esd_desc, sizeof(_al_esd_desc), get_config_text("%s: %d bits, %s, %d bps, %s"),
235 server, _al_esd_bits,
236 uconvert_ascii((_al_esd_signed ? "signed" : "unsigned"), tmp1), _al_esd_rate,
237 uconvert_ascii((_al_esd_stereo ? "stereo" : "mono"), tmp2));
238
239 digi_driver->desc = _al_esd_desc;
240
241 return 0;
242 }
243
244
245
246 /* _al_esd_exit:
247 * Shutdown ESD driver.
248 */
_al_esd_exit(int input)249 static void _al_esd_exit(int input)
250 {
251 if (input) {
252 return;
253 }
254
255 _unix_bg_man->unregister_func(_al_esd_update);
256
257 _AL_FREE(_al_esd_bufdata);
258 _al_esd_bufdata = 0;
259
260 _mixer_exit();
261
262 close(_al_esd_fd);
263 }
264
265
266
267 /* _al_esd_set_mixer_volume:
268 * Set mixer volume.
269 */
_al_esd_set_mixer_volume(int volume)270 static int _al_esd_set_mixer_volume(int volume)
271 {
272 return 0;
273 }
274
275
276
277 #ifdef ALLEGRO_MODULE
278
279 /* _module_init:
280 * Called when loaded as a dynamically linked module.
281 */
_module_init(int system_driver)282 void _module_init(int system_driver)
283 {
284 _unix_register_digi_driver(DIGI_ESD, &digi_esd, TRUE, TRUE);
285 }
286
287 #endif
288
289 #endif
290
291