1/* FluidSynth - A Software Synthesizer
2 *
3 * Copyright (C) 2003  Peter Hanappe and others.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public License
7 * as published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 * 02111-1307, USA
19 */
20
21#include "fluid_adriver.h"
22#include "fluid_settings.h"
23
24/*
25 * fluid_adriver_definition_t
26 */
27
28typedef struct _fluid_audriver_definition_t
29{
30  char* name;
31  fluid_audio_driver_t* (*new)(fluid_settings_t* settings, fluid_synth_t* synth);
32  fluid_audio_driver_t* (*new2)(fluid_settings_t* settings,
33				fluid_audio_func_t func,
34				void* data);
35  int (*free)(fluid_audio_driver_t* driver);
36  void (*settings)(fluid_settings_t* settings);
37} fluid_audriver_definition_t;
38
39
40#if PULSE_SUPPORT
41fluid_audio_driver_t* new_fluid_pulse_audio_driver(fluid_settings_t* settings,
42						   fluid_synth_t* synth);
43fluid_audio_driver_t* new_fluid_pulse_audio_driver2(fluid_settings_t* settings,
44						    fluid_audio_func_t func, void* data);
45int delete_fluid_pulse_audio_driver(fluid_audio_driver_t* p);
46void fluid_pulse_audio_driver_settings(fluid_settings_t* settings);
47#endif
48
49#if ALSA_SUPPORT
50fluid_audio_driver_t* new_fluid_alsa_audio_driver(fluid_settings_t* settings,
51						  fluid_synth_t* synth);
52fluid_audio_driver_t* new_fluid_alsa_audio_driver2(fluid_settings_t* settings,
53						 fluid_audio_func_t func, void* data);
54int delete_fluid_alsa_audio_driver(fluid_audio_driver_t* p);
55void fluid_alsa_audio_driver_settings(fluid_settings_t* settings);
56#endif
57
58#if OSS_SUPPORT
59fluid_audio_driver_t* new_fluid_oss_audio_driver(fluid_settings_t* settings,
60						 fluid_synth_t* synth);
61fluid_audio_driver_t* new_fluid_oss_audio_driver2(fluid_settings_t* settings,
62						fluid_audio_func_t func, void* data);
63int delete_fluid_oss_audio_driver(fluid_audio_driver_t* p);
64void fluid_oss_audio_driver_settings(fluid_settings_t* settings);
65#endif
66
67#if COREAUDIO_SUPPORT
68fluid_audio_driver_t* new_fluid_core_audio_driver(fluid_settings_t* settings,
69						  fluid_synth_t* synth);
70fluid_audio_driver_t* new_fluid_core_audio_driver2(fluid_settings_t* settings,
71						      fluid_audio_func_t func,
72						      void* data);
73int delete_fluid_core_audio_driver(fluid_audio_driver_t* p);
74void fluid_core_audio_driver_settings(fluid_settings_t* settings);
75#endif
76
77#if DSOUND_SUPPORT
78fluid_audio_driver_t* new_fluid_dsound_audio_driver(fluid_settings_t* settings,
79						  fluid_synth_t* synth);
80int delete_fluid_dsound_audio_driver(fluid_audio_driver_t* p);
81void fluid_dsound_audio_driver_settings(fluid_settings_t* settings);
82#endif
83
84#if PORTAUDIO_SUPPORT
85void fluid_portaudio_driver_settings (fluid_settings_t *settings);
86fluid_audio_driver_t* new_fluid_portaudio_driver(fluid_settings_t* settings,
87						 fluid_synth_t* synth);
88int delete_fluid_portaudio_driver(fluid_audio_driver_t* p);
89#endif
90
91#if JACK_SUPPORT
92fluid_audio_driver_t* new_fluid_jack_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth);
93fluid_audio_driver_t* new_fluid_jack_audio_driver2(fluid_settings_t* settings,
94						 fluid_audio_func_t func, void* data);
95int delete_fluid_jack_audio_driver(fluid_audio_driver_t* p);
96void fluid_jack_audio_driver_settings(fluid_settings_t* settings);
97#endif
98
99#if SNDMAN_SUPPORT
100fluid_audio_driver_t* new_fluid_sndmgr_audio_driver(fluid_settings_t* settings,
101						  fluid_synth_t* synth);
102fluid_audio_driver_t* new_fluid_sndmgr_audio_driver2(fluid_settings_t* settings,
103						   fluid_audio_func_t func,
104						   void* data);
105int delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t* p);
106#endif
107
108#if DART_SUPPORT
109fluid_audio_driver_t* new_fluid_dart_audio_driver(fluid_settings_t* settings,
110                          fluid_synth_t* synth);
111int delete_fluid_dart_audio_driver(fluid_audio_driver_t* p);
112void fluid_dart_audio_driver_settings(fluid_settings_t* settings);
113#endif
114
115#define AUFILE_SUPPORT 1
116#if AUFILE_SUPPORT
117fluid_audio_driver_t* new_fluid_file_audio_driver(fluid_settings_t* settings,
118						  fluid_synth_t* synth);
119int delete_fluid_file_audio_driver(fluid_audio_driver_t* p);
120void fluid_file_audio_driver_settings(fluid_settings_t* settings);
121#endif
122
123/* Available audio drivers, listed in order of preference */
124fluid_audriver_definition_t fluid_audio_drivers[] = {
125#if JACK_SUPPORT
126  { "jack",
127    new_fluid_jack_audio_driver,
128    new_fluid_jack_audio_driver2,
129    delete_fluid_jack_audio_driver,
130    fluid_jack_audio_driver_settings },
131#endif
132#if ALSA_SUPPORT
133  { "alsa",
134    new_fluid_alsa_audio_driver,
135    new_fluid_alsa_audio_driver2,
136    delete_fluid_alsa_audio_driver,
137    fluid_alsa_audio_driver_settings },
138#endif
139#if OSS_SUPPORT
140  { "oss",
141    new_fluid_oss_audio_driver,
142    new_fluid_oss_audio_driver2,
143    delete_fluid_oss_audio_driver,
144    fluid_oss_audio_driver_settings },
145#endif
146#if PULSE_SUPPORT
147  { "pulseaudio",
148    new_fluid_pulse_audio_driver,
149    new_fluid_pulse_audio_driver2,
150    delete_fluid_pulse_audio_driver,
151    fluid_pulse_audio_driver_settings },
152#endif
153#if COREAUDIO_SUPPORT
154  { "coreaudio",
155    new_fluid_core_audio_driver,
156    new_fluid_core_audio_driver2,
157    delete_fluid_core_audio_driver,
158    fluid_core_audio_driver_settings },
159#endif
160#if DSOUND_SUPPORT
161  { "dsound",
162    new_fluid_dsound_audio_driver,
163    NULL,
164    delete_fluid_dsound_audio_driver,
165    fluid_dsound_audio_driver_settings },
166#endif
167#if PORTAUDIO_SUPPORT
168  { "portaudio",
169    new_fluid_portaudio_driver,
170    NULL,
171    delete_fluid_portaudio_driver,
172    fluid_portaudio_driver_settings },
173#endif
174#if SNDMAN_SUPPORT
175  { "sndman",
176    new_fluid_sndmgr_audio_driver,
177    new_fluid_sndmgr_audio_driver2,
178    delete_fluid_sndmgr_audio_driver,
179    NULL },
180#endif
181#if DART_SUPPORT
182  { "dart",
183    new_fluid_dart_audio_driver,
184    NULL,
185    delete_fluid_dart_audio_driver,
186    fluid_dart_audio_driver_settings },
187#endif
188#if AUFILE_SUPPORT
189  { "file",
190    new_fluid_file_audio_driver,
191    NULL,
192    delete_fluid_file_audio_driver,
193    fluid_file_audio_driver_settings },
194#endif
195  { NULL, NULL, NULL, NULL, NULL }
196};
197
198
199
200
201void fluid_audio_driver_settings(fluid_settings_t* settings)
202{
203  int i;
204
205  fluid_settings_register_str(settings, "audio.sample-format", "16bits", 0, NULL, NULL);
206  fluid_settings_add_option(settings, "audio.sample-format", "16bits");
207  fluid_settings_add_option(settings, "audio.sample-format", "float");
208
209  fluid_settings_register_int(settings, "audio.output-channels", 2, 2, 32, 0, NULL, NULL);
210  fluid_settings_register_int(settings, "audio.input-channels", 0, 0, 2, 0, NULL, NULL);
211
212
213#if defined(WIN32)
214  fluid_settings_register_int(settings, "audio.period-size", 512, 64, 8192, 0, NULL, NULL);
215  fluid_settings_register_int(settings, "audio.periods", 8, 2, 64, 0, NULL, NULL);
216#elif defined(MACOS9)
217  fluid_settings_register_int(settings, "audio.period-size", 64, 64, 8192, 0, NULL, NULL);
218  fluid_settings_register_int(settings, "audio.periods", 8, 2, 64, 0, NULL, NULL);
219#else
220  fluid_settings_register_int(settings, "audio.period-size", 64, 64, 8192, 0, NULL, NULL);
221  fluid_settings_register_int(settings, "audio.periods", 16, 2, 64, 0, NULL, NULL);
222#endif
223
224  /* Set the default driver */
225#if JACK_SUPPORT
226  fluid_settings_register_str(settings, "audio.driver", "jack", 0, NULL, NULL);
227#elif ALSA_SUPPORT
228  fluid_settings_register_str(settings, "audio.driver", "alsa", 0, NULL, NULL);
229#elif PULSE_SUPPORT
230  fluid_settings_register_str(settings, "audio.driver", "pulseaudio", 0, NULL, NULL);
231#elif OSS_SUPPORT
232  fluid_settings_register_str(settings, "audio.driver", "oss", 0, NULL, NULL);
233#elif COREAUDIO_SUPPORT
234  fluid_settings_register_str(settings, "audio.driver", "coreaudio", 0, NULL, NULL);
235#elif DSOUND_SUPPORT
236  fluid_settings_register_str(settings, "audio.driver", "dsound", 0, NULL, NULL);
237#elif SNDMAN_SUPPORT
238  fluid_settings_register_str(settings, "audio.driver", "sndman", 0, NULL, NULL);
239#elif PORTAUDIO_SUPPORT
240  fluid_settings_register_str(settings, "audio.driver", "portaudio", 0, NULL, NULL);
241#elif DART_SUPPORT
242  fluid_settings_register_str(settings, "audio.driver", "dart", 0, NULL, NULL);
243#elif AUFILE_SUPPORT
244  fluid_settings_register_str(settings, "audio.driver", "file", 0, NULL, NULL);
245#else
246  fluid_settings_register_str(settings, "audio.driver", "", 0, NULL, NULL);
247#endif
248
249  /* Add all drivers to the list of options */
250#if PULSE_SUPPORT
251  fluid_settings_add_option(settings, "audio.driver", "pulseaudio");
252#endif
253#if ALSA_SUPPORT
254  fluid_settings_add_option(settings, "audio.driver", "alsa");
255#endif
256#if OSS_SUPPORT
257  fluid_settings_add_option(settings, "audio.driver", "oss");
258#endif
259#if COREAUDIO_SUPPORT
260  fluid_settings_add_option(settings, "audio.driver", "coreaudio");
261#endif
262#if DSOUND_SUPPORT
263  fluid_settings_add_option(settings, "audio.driver", "dsound");
264#endif
265#if SNDMAN_SUPPORT
266  fluid_settings_add_option(settings, "audio.driver", "sndman");
267#endif
268#if PORTAUDIO_SUPPORT
269  fluid_settings_add_option(settings, "audio.driver", "portaudio");
270#endif
271#if JACK_SUPPORT
272  fluid_settings_add_option(settings, "audio.driver", "jack");
273#endif
274#if DART_SUPPORT
275  fluid_settings_add_option(settings, "audio.driver", "dart");
276#endif
277#if AUFILE_SUPPORT
278  fluid_settings_add_option(settings, "audio.driver", "file");
279#endif
280
281  for (i = 0; fluid_audio_drivers[i].name != NULL; i++) {
282    if (fluid_audio_drivers[i].settings != NULL) {
283      fluid_audio_drivers[i].settings(settings);
284    }
285  }
286}
287
288
289/**
290 * Create a new audio driver.
291 * @param settings Configuration settings used to select and create the audio
292 *   driver.
293 * @param synth Synthesizer instance for which the audio driver is created for.
294 * @return The new audio driver instance.
295 *
296 * Creates a new audio driver for a given 'synth' instance with a defined set
297 * of configuration 'settings'.
298 */
299fluid_audio_driver_t*
300new_fluid_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
301{
302  int i;
303  fluid_audio_driver_t* driver = NULL;
304  char* name;
305
306  fluid_settings_getstr(settings, "audio.driver", &name);
307
308  for (i = 0; fluid_audio_drivers[i].name != NULL; i++) {
309    if (fluid_settings_str_equal(settings, "audio.driver", fluid_audio_drivers[i].name)) {
310      FLUID_LOG(FLUID_DBG, "Using '%s' audio driver", fluid_audio_drivers[i].name);
311      driver = (*fluid_audio_drivers[i].new)(settings, synth);
312      if (driver) {
313	driver->name = fluid_audio_drivers[i].name;
314      }
315      return driver;
316    }
317  }
318
319  FLUID_LOG(FLUID_ERR, "Couldn't find the requested audio driver: %s", name);
320  return NULL;
321}
322
323/**
324 * Create a new audio driver.
325 * @param settings Configuration settings used to select and create the audio
326 *   driver.
327 * @param func Function called to fill audio buffers for audio playback
328 * @param data User defined data pointer to pass to 'func'
329 * @return The new audio driver instance.
330 *
331 * Like new_fluid_audio_driver() but allows for custom audio processing before
332 * audio is sent to audio driver.  It is the responsibility of the callback
333 * 'func' to render the audio into the buffers.
334 * NOTE: Not as efficient as new_fluid_audio_driver().
335 */
336fluid_audio_driver_t*
337new_fluid_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data)
338{
339  int i;
340  fluid_audio_driver_t* driver = NULL;
341  char* name;
342
343  fluid_settings_getstr(settings, "audio.driver", &name);
344
345  for (i = 0; fluid_audio_drivers[i].name != NULL; i++) {
346    if (fluid_settings_str_equal(settings, "audio.driver", fluid_audio_drivers[i].name) &&
347	(fluid_audio_drivers[i].new2 != NULL)) {
348      FLUID_LOG(FLUID_DBG, "Using '%s' audio driver", fluid_audio_drivers[i].name);
349      driver = (*fluid_audio_drivers[i].new2)(settings, func, data);
350      if (driver) {
351	driver->name = fluid_audio_drivers[i].name;
352      }
353      return driver;
354    }
355  }
356
357  FLUID_LOG(FLUID_ERR, "Couldn't find the requested audio driver: %s", name);
358  return NULL;
359}
360
361/**
362 * Deletes an audio driver instance.
363 * @param driver Audio driver instance to delete
364 *
365 * Shuts down an audio driver and deletes its instance.
366 */
367void
368delete_fluid_audio_driver(fluid_audio_driver_t* driver)
369{
370  int i;
371
372  for (i = 0; fluid_audio_drivers[i].name != NULL; i++) {
373    if (fluid_audio_drivers[i].name == driver->name) {
374      fluid_audio_drivers[i].free(driver);
375      return;
376    }
377  }
378}
379