1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * Jack sound driver.
12 *
13 * By Elias Pschernig.
14 *
15 * See readme.txt for copyright information.
16 */
17
18
19 #include "allegro.h"
20
21 #if (defined ALLEGRO_WITH_JACKDIGI) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE))
22
23 #include "allegro/internal/aintern.h"
24 #include "allegro/platform/aintunix.h"
25
26 #ifndef SCAN_DEPEND
27 #include <jack/jack.h>
28 #endif
29
30 /* This still uses Allegro's mixer, and mixes into an intermediate buffer, which
31 * then is transferred to Jack. Another possibility would be to completely
32 * circumvent Allegro's mixer and send each single voice to jack, letting Jack
33 * take care of the mixing. I didn't care about some things in the Jack docs,
34 * like the possibility of buffer sizes changing, or that no mutex_lock function
35 * should be called (inside mix_some_samples).
36 */
37 #define JACK_DEFAULT_BUFFER_SIZE -1
38 #define JACK_DEFAULT_CLIENT_NAME "allegro"
39 #define AMP16 ((sample_t) 32768)
40 #define AMP8 ((sample_t) 128)
41
42 #define PREFIX_I "al-jack INFO: "
43 #define PREFIX_W "al-jack WARNING: "
44 #define PREFIX_E "al-jack ERROR: "
45
46 typedef jack_default_audio_sample_t sample_t;
47
48 static int jack_bufsize = JACK_DEFAULT_BUFFER_SIZE;
49 static char const *jack_client_name = JACK_DEFAULT_CLIENT_NAME;
50 static int jack_16bit;
51 static int jack_stereo;
52 static int jack_signed;
53 static jack_nframes_t jack_rate;
54 static char jack_desc[256] = EMPTY_STRING;
55 static jack_client_t *jack_client = NULL;
56 static jack_port_t *output_left, *output_right;
57 static void *jack_buffer;
58
59 static int jack_detect(int input);
60 static int jack_init(int input, int voices);
61 static void jack_exit(int input);
62 static int jack_buffer_size(void);
63 static int jack_set_mixer_volume(int volume);
64
65 DIGI_DRIVER digi_jack =
66 {
67 DIGI_JACK,
68 empty_string,
69 empty_string,
70 "JACK",
71 0,
72 0,
73 MIXER_MAX_SFX,
74 MIXER_DEF_SFX,
75
76 jack_detect,
77 jack_init,
78 jack_exit,
79 jack_set_mixer_volume,
80 NULL,
81
82 NULL,
83 NULL,
84 jack_buffer_size,
85 _mixer_init_voice,
86 _mixer_release_voice,
87 _mixer_start_voice,
88 _mixer_stop_voice,
89 _mixer_loop_voice,
90
91 _mixer_get_position,
92 _mixer_set_position,
93
94 _mixer_get_volume,
95 _mixer_set_volume,
96 _mixer_ramp_volume,
97 _mixer_stop_volume_ramp,
98
99 _mixer_get_frequency,
100 _mixer_set_frequency,
101 _mixer_sweep_frequency,
102 _mixer_stop_frequency_sweep,
103
104 _mixer_get_pan,
105 _mixer_set_pan,
106 _mixer_sweep_pan,
107 _mixer_stop_pan_sweep,
108
109 _mixer_set_echo,
110 _mixer_set_tremolo,
111 _mixer_set_vibrato,
112 0, 0,
113 0,
114 0,
115 0,
116 0,
117 0,
118 0
119 };
120
121
122
123 /* jack_buffer_size:
124 * Returns the current buffer size, for use by the audiostream code.
125 */
jack_buffer_size(void)126 static int jack_buffer_size(void)
127 {
128 return jack_bufsize;
129 }
130
131
132
133 /* jack_process:
134 * The JACK processing functions.
135 */
jack_process(jack_nframes_t nframes,void * arg)136 static int jack_process (jack_nframes_t nframes, void *arg)
137 {
138 jack_nframes_t i;
139 /* TODO: Should be uint16_t and uint8_t? Endianess? */
140 unsigned short *buffer16 = jack_buffer;
141 unsigned char *buffer8 = jack_buffer;
142 jack_default_audio_sample_t *out_left;
143
144 _mix_some_samples((uintptr_t) jack_buffer, 0, jack_signed);
145
146 out_left = (jack_default_audio_sample_t *)
147 jack_port_get_buffer (output_left, nframes);
148
149 if (jack_stereo) {
150 jack_default_audio_sample_t *out_right = (jack_default_audio_sample_t *)
151 jack_port_get_buffer (output_right, nframes);
152
153 if (jack_16bit) {
154 for (i = 0; i < nframes; i++) {
155 out_left[i] = ((sample_t) buffer16[i * 2] - AMP16) / AMP16;
156 out_right[i] = ((sample_t) buffer16[i * 2 + 1] - AMP16) / AMP16;
157 }
158 }
159 else {
160 for (i = 0; i < nframes; i++) {
161 out_left[i] = ((sample_t) buffer8[i * 2] - AMP8) / (sample_t) AMP8;
162 out_right[i] = ((sample_t) buffer8[i * 2 + 1] - AMP8) / (sample_t) AMP8;
163 }
164 }
165 }
166 else
167 {
168 if (jack_16bit) {
169 for (i = 0; i < nframes; i++) {
170 out_left[i] = ((sample_t) buffer16[i] - AMP16) / AMP16;
171 }
172 }
173 else {
174 for (i = 0; i < nframes; i++) {
175 out_left[i] = ((sample_t) buffer8[i] - AMP8) / AMP8;
176 }
177 }
178 }
179
180 return 0;
181 }
182
183
184
185 /* jack_detect:
186 * Detects driver presence.
187 */
jack_detect(int input)188 static int jack_detect(int input)
189 {
190 if (input) {
191 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(
192 "Input is not supported"));
193 return FALSE;
194 }
195
196 if (!jack_client)
197 {
198 jack_client_name = get_config_string("sound", "jack_client_name",
199 jack_client_name);
200 jack_client = jack_client_new(jack_client_name);
201 if (!jack_client)
202 return FALSE;
203 }
204 return TRUE;
205 }
206
207
208
209 /* jack_init:
210 * JACK init routine.
211 */
jack_init(int input,int voices)212 static int jack_init(int input, int voices)
213 {
214 const char **ports;
215 char tmp[128];
216
217 if (!jack_detect(input))
218 return -1;
219
220 jack_bufsize = get_config_int("sound", "jack_buffer_size",
221 jack_bufsize);
222
223 if (jack_bufsize == -1)
224 jack_bufsize = jack_get_buffer_size (jack_client);
225
226 /* Those are already read in from the config file by Allegro. */
227 jack_16bit = (_sound_bits == 16 ? 1 : 0);
228 jack_stereo = (_sound_stereo ? 1 : 0);
229
230 /* Let Allegro mix in its native unsigned format. */
231 jack_signed = 0;
232
233 jack_set_process_callback (jack_client, jack_process, NULL);
234
235 output_left = jack_port_register (jack_client, jack_stereo ? "left" : "mono",
236 JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
237
238 if (jack_stereo)
239 output_right = jack_port_register (jack_client, "right",
240 JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
241
242 jack_rate = jack_get_sample_rate (jack_client);
243
244 jack_buffer = _AL_MALLOC_ATOMIC(jack_bufsize * (1 + jack_16bit) * (1 + jack_stereo));
245 if (!jack_buffer) {
246 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(
247 "Cannot allocate audio buffer"));
248 jack_exit (input);
249 return -1;
250 }
251
252 digi_jack.voices = voices;
253
254 if (_mixer_init(jack_bufsize * (1 + jack_stereo), jack_rate,
255 jack_stereo, jack_16bit, &digi_jack.voices)) {
256 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(
257 "Cannot init software mixer"));
258 jack_exit (input);
259 return -1;
260 }
261
262 _mix_some_samples((uintptr_t) jack_buffer, 0, jack_signed);
263
264 if (jack_activate (jack_client)) {
265 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(
266 "Cannot activate Jack client"));
267 jack_exit (input);
268 return 1;
269 }
270
271 /* Try to connect the ports. Failure to connect is not critical, since with
272 * JACK, users may connect/disconnect ports anytime, without Allegro caring.
273 */
274 if ((ports = jack_get_ports (jack_client, NULL, NULL,
275 JackPortIsPhysical|JackPortIsInput)) == NULL) {
276 TRACE (PREFIX_I "Cannot find any physical playback ports");
277 }
278
279 if (ports) {
280 if (ports[0]) {
281 if (jack_connect (jack_client, jack_port_name (output_left), ports[0]) == 0)
282 TRACE (PREFIX_I "Connected left playback port to %s", ports[0]);
283 }
284 if (jack_stereo && ports[1]) {
285 if (jack_connect (jack_client, jack_port_name (output_right), ports[1]) == 0)
286 TRACE (PREFIX_I "Connected right playback port to %s", ports[1]);
287 }
288 _AL_FREE (ports);
289 }
290
291 uszprintf(jack_desc, sizeof(jack_desc),
292 get_config_text ("Jack, client '%s': %d bits, %s, %d bps, %s"),
293 jack_client_name, jack_16bit ? 16 : 8,
294 uconvert_ascii((jack_signed ? "signed" : "unsigned"), tmp),
295 jack_rate, uconvert_ascii((jack_stereo ? "stereo" : "mono"), tmp));
296
297 return 0;
298 }
299
300
301
302 /* jack_exit:
303 * Shuts down the JACK driver.
304 */
jack_exit(int input)305 static void jack_exit(int input)
306 {
307 jack_client_close (jack_client);
308 jack_client = NULL;
309 }
310
311
312
313 /* jack_set_mixer_volume:
314 * Set mixer volume (0-255)
315 */
jack_set_mixer_volume(int volume)316 static int jack_set_mixer_volume(int volume)
317 {
318 /* Not implemented */
319 return 0;
320 }
321
322
323
324 #ifdef ALLEGRO_MODULE
325
326 /* _module_init:
327 * Called when loaded as a dynamically linked module.
328 */
_module_init(int system_driver)329 void _module_init(int system_driver)
330 {
331 _unix_register_digi_driver(DIGI_JACK, &digi_jack, TRUE, TRUE);
332 }
333
334 #endif
335
336 #endif
337