Recognizes if input is ogg or not.
[xiph.git] / ao / src / audio_out.c
blob88660c05af115eded21d54a950d1e2474acbc35e
1 /*
3 * audio_out.c
5 * Original Copyright (C) Aaron Holtzman - May 1999
6 * Modifications Copyright (C) Stan Seibert - July 2000
8 * This file is part of libao, a cross-platform audio output library. See
9 * README for a history of this source code.
11 * libao is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
16 * libao is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with GNU Make; see the file COPYING. If not, write to
23 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <limits.h>
31 #if defined HAVE_DLFCN_H && defined HAVE_DLOPEN
32 # include <dlfcn.h>
33 #else
34 static void *dlopen(const char *filename, int flag) {return 0;}
35 static char *dlerror(void) { return "dlopen: unsupported"; }
36 static void *dlsym(void *handle, const char *symbol) { return 0; }
37 static int dlclose(void *handle) { return 0; }
38 #undef DLOPEN_FLAG
39 #define DLOPEN_FLAG 0
40 #endif
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #ifndef _MSC_VER
44 # include <unistd.h>
45 #endif
46 #include <dirent.h>
48 #include "ao/ao.h"
49 #include "ao_private.h"
51 /* These should have been set by the Makefile */
52 #ifndef AO_PLUGIN_PATH
53 #define AO_PLUGIN_PATH "/usr/local/lib/ao"
54 #endif
55 #ifndef SHARED_LIB_EXT
56 #define SHARED_LIB_EXT ".so"
57 #endif
59 /* --- Other constants --- */
60 #define DEF_SWAP_BUF_SIZE 1024
62 /* --- Driver Table --- */
64 typedef struct driver_list {
65 ao_functions *functions;
66 void *handle;
67 struct driver_list *next;
68 } driver_list;
71 extern ao_functions ao_null;
72 extern ao_functions ao_wav;
73 extern ao_functions ao_raw;
74 extern ao_functions ao_au;
75 #ifdef HAVE_SYS_AUDIO_H
76 extern ao_functions ao_aixs;
77 #endif
78 #ifdef HAVE_WMM
79 extern ao_functions ao_wmm;
80 #endif
81 static ao_functions *static_drivers[] = {
82 &ao_null, /* Must have at least one static driver! */
83 &ao_wav,
84 &ao_raw,
85 &ao_au,
86 #ifdef HAVE_SYS_AUDIO_H
87 &ao_aixs,
88 #endif
89 #ifdef HAVE_WMM
90 &ao_wmm,
91 #endif
93 NULL /* End of list */
96 static driver_list *driver_head = NULL;
97 static ao_config config = {
98 NULL /* default_driver */
101 static ao_info **info_table = NULL;
102 static int driver_count = 0;
104 /* ---------- Helper functions ---------- */
106 /* Clear out all of the library configuration options and set them to
107 defaults. The defaults should match the initializer above. */
108 static void _clear_config()
110 free(config.default_driver);
111 config.default_driver = NULL;
115 /* Load a plugin from disk and put the function table into a driver_list
116 struct. */
117 static driver_list *_get_plugin(char *plugin_file)
119 driver_list *dt;
120 void *handle;
122 handle = dlopen(plugin_file, DLOPEN_FLAG /* See ao_private.h */);
124 if (handle) {
125 dt = (driver_list *)malloc(sizeof(driver_list));
126 if (!dt) return NULL;
128 dt->handle = handle;
130 dt->functions = (ao_functions *)malloc(sizeof(ao_functions));
131 if (!(dt->functions)) {
132 free(dt);
133 return NULL;
136 dt->functions->test = dlsym(dt->handle, "ao_plugin_test");
137 if (!(dt->functions->test)) goto failed;
139 dt->functions->driver_info =
140 dlsym(dt->handle, "ao_plugin_driver_info");
141 if (!(dt->functions->driver_info)) goto failed;
143 dt->functions->device_init =
144 dlsym(dt->handle, "ao_plugin_device_init");
145 if (!(dt->functions->device_init )) goto failed;
147 dt->functions->set_option =
148 dlsym(dt->handle, "ao_plugin_set_option");
149 if (!(dt->functions->set_option)) goto failed;
151 dt->functions->open = dlsym(dt->handle, "ao_plugin_open");
152 if (!(dt->functions->open)) goto failed;
154 dt->functions->play = dlsym(dt->handle, "ao_plugin_play");
155 if (!(dt->functions->play)) goto failed;
157 dt->functions->close = dlsym(dt->handle, "ao_plugin_close");
158 if (!(dt->functions->close)) goto failed;
160 dt->functions->device_clear =
161 dlsym(dt->handle, "ao_plugin_device_clear");
162 if (!(dt->functions->device_clear)) goto failed;
165 } else {
166 return NULL;
169 return dt;
171 failed:
172 free(dt->functions);
173 free(dt);
174 return NULL;
178 /* If *name is a valid driver name, return its driver number.
179 Otherwise, test all of available live drivers until one works. */
180 static int _find_default_driver_id (const char *name)
182 int def_id;
183 int id;
184 ao_info *info;
185 driver_list *driver = driver_head;
187 if ( name == NULL || (def_id = ao_driver_id(name)) < 0 ) {
188 /* No default specified. Find one among available drivers. */
189 def_id = -1;
191 id = 0;
192 while (driver != NULL) {
194 info = driver->functions->driver_info();
196 if ( info->type == AO_TYPE_LIVE &&
197 info->priority > 0 && /* Skip static drivers */
198 driver->functions->test() ) {
199 def_id = id; /* Found a usable driver */
200 break;
203 driver = driver->next;
204 id++;
208 return def_id;
212 /* Convert the static drivers table into a linked list of drivers. */
213 static driver_list* _load_static_drivers(driver_list **end)
215 driver_list *head;
216 driver_list *driver;
217 int i;
219 /* insert first driver */
220 head = driver = malloc(sizeof(driver_list));
221 if (driver != NULL) {
222 driver->functions = static_drivers[0];
223 driver->handle = NULL;
224 driver->next = NULL;
226 i = 1;
227 while (static_drivers[i] != NULL) {
228 driver->next = malloc(sizeof(driver_list));
229 if (driver->next == NULL)
230 break;
232 driver->next->functions = static_drivers[i];
233 driver->next->handle = NULL;
234 driver->next->next = NULL;
236 driver = driver->next;
237 i++;
241 if (end != NULL)
242 *end = driver;
244 return head;
248 /* Load the dynamic drivers from disk and append them to end of the
249 driver list. end points the driver_list node to append to. */
250 static void _append_dynamic_drivers(driver_list *end)
252 #ifdef HAVE_DLOPEN
253 struct dirent *plugin_dirent;
254 char *ext;
255 struct stat statbuf;
256 char fullpath[PATH_MAX];
257 DIR *plugindir;
258 driver_list *plugin;
259 driver_list *driver = end;
261 /* now insert any plugins we find */
262 plugindir = opendir(AO_PLUGIN_PATH);
263 if (plugindir != NULL) {
264 while ((plugin_dirent = readdir(plugindir)) != NULL) {
265 snprintf(fullpath, PATH_MAX, "%s/%s",
266 AO_PLUGIN_PATH, plugin_dirent->d_name);
267 if (!stat(fullpath, &statbuf) &&
268 S_ISREG(statbuf.st_mode) &&
269 (ext = strrchr(plugin_dirent->d_name, '.')) != NULL) {
270 if (strcmp(ext, SHARED_LIB_EXT) == 0) {
271 plugin = _get_plugin(fullpath);
272 if (plugin) {
273 driver->next = plugin;
274 plugin->next = NULL;
275 driver = driver->next;
281 closedir(plugindir);
283 #endif
287 /* Compare two drivers based on priority
288 Used as compar function for qsort() in _make_info_table() */
289 static int _compar_driver_priority (const driver_list **a,
290 const driver_list **b)
292 return memcmp(&((*b)->functions->driver_info()->priority),
293 &((*a)->functions->driver_info()->priority),
294 sizeof(int));
298 /* Make a table of driver info structures for ao_driver_info_list(). */
299 static ao_info ** _make_info_table (driver_list **head, int *driver_count)
301 driver_list *list;
302 int i;
303 ao_info **table;
304 driver_list **drivers_table;
306 *driver_count = 0;
308 /* Count drivers */
309 list = *head;
310 i = 0;
311 while (list != NULL) {
312 i++;
313 list = list->next;
317 /* Sort driver_list */
318 drivers_table = (driver_list **) calloc(i, sizeof(driver_list *));
319 if (drivers_table == NULL)
320 return (ao_info **) NULL;
321 list = *head;
322 *driver_count = i;
323 for (i = 0; i < *driver_count; i++, list = list->next)
324 drivers_table[i] = list;
325 qsort(drivers_table, i, sizeof(driver_list *),
326 (int(*)(const void *, const void *))
327 _compar_driver_priority);
328 *head = drivers_table[0];
329 for (i = 1; i < *driver_count; i++)
330 drivers_table[i-1]->next = drivers_table[i];
331 drivers_table[i-1]->next = NULL;
334 /* Alloc table */
335 table = (ao_info **) calloc(i, sizeof(ao_info *));
336 if (table != NULL) {
337 for (i = 0; i < *driver_count; i++)
338 table[i] = drivers_table[i]->functions->driver_info();
341 free(drivers_table);
343 return table;
347 /* Return the driver struct corresponding to particular driver id
348 number. */
349 static driver_list *_get_driver(int driver_id) {
350 int i = 0;
351 driver_list *driver = driver_head;
353 if (driver_id < 0) return NULL;
355 while (driver && (i < driver_id)) {
356 i++;
357 driver = driver->next;
360 if (i == driver_id)
361 return driver;
363 return NULL;
367 /* Check if driver_id is a valid id number */
368 static int _check_driver_id(int driver_id)
370 int i = 0;
371 driver_list *driver = driver_head;
373 if (driver_id < 0) return 0;
375 while (driver && (i <= driver_id)) {
376 driver = driver->next;
377 i++;
380 if (i == (driver_id + 1))
381 return 1;
383 return 0;
387 /* helper function to convert a byte_format of AO_FMT_NATIVE to the
388 actual byte format of the machine, otherwise just return
389 byte_format */
390 static int _real_byte_format(int byte_format)
392 if (byte_format == AO_FMT_NATIVE) {
393 if (ao_is_big_endian())
394 return AO_FMT_BIG;
395 else
396 return AO_FMT_LITTLE;
397 } else
398 return byte_format;
402 /* Create a new ao_device structure and populate it with data */
403 static ao_device* _create_device(int driver_id, driver_list *driver,
404 ao_sample_format *format, FILE *file)
406 ao_device *device;
408 device = malloc(sizeof(ao_device));
410 if (device != NULL) {
411 device->type = driver->functions->driver_info()->type;
412 device->driver_id = driver_id;
413 device->funcs = driver->functions;
414 device->file = file;
415 device->machine_byte_format =
416 ao_is_big_endian() ? AO_FMT_BIG : AO_FMT_LITTLE;
417 device->client_byte_format =
418 _real_byte_format(format->byte_format);
419 device->swap_buffer = NULL;
420 device->swap_buffer_size = 0;
421 device->internal = NULL;
424 return device;
428 /* Expand the swap buffer in this device if it is smaller than
429 min_size. */
430 static int _realloc_swap_buffer(ao_device *device, int min_size)
432 void *temp;
434 if (min_size > device->swap_buffer_size) {
435 temp = realloc(device->swap_buffer, min_size);
436 if (temp != NULL) {
437 device->swap_buffer = temp;
438 device->swap_buffer_size = min_size;
439 return 1; /* Success, realloc worked */
440 } else
441 return 0; /* Fail to realloc */
442 } else
443 return 1; /* Success, no need to realloc */
447 /* Swap and copy the byte order of samples from the source buffer to
448 the target buffer. */
449 static void _swap_samples(char *target_buffer, char* source_buffer,
450 uint_32 num_bytes)
452 uint_32 i;
454 for (i = 0; i < num_bytes; i += 2) {
455 target_buffer[i] = source_buffer[i+1];
456 target_buffer[i+1] = source_buffer[i];
461 /* Open a device. If this is a live device, file == NULL. */
462 static ao_device* _open_device(int driver_id, ao_sample_format *format,
463 ao_option *options, FILE *file)
465 ao_functions *funcs;
466 driver_list *driver;
467 ao_device *device;
468 int result;
470 /* Get driver id */
471 if ( (driver = _get_driver(driver_id)) == NULL ) {
472 errno = AO_ENODRIVER;
473 return NULL; /* No driver exists */
476 funcs = driver->functions;
478 /* Check the driver type */
479 if (file == NULL &&
480 funcs->driver_info()->type != AO_TYPE_LIVE) {
482 errno = AO_ENOTLIVE;
483 return NULL;
484 } else if (file != NULL &&
485 funcs->driver_info()->type != AO_TYPE_FILE) {
487 errno = AO_ENOTFILE;
488 return NULL;
491 /* Make a new device structure */
492 if ( (device = _create_device(driver_id, driver,
493 format, file)) == NULL ) {
494 errno = AO_EFAIL;
495 return NULL; /* Couldn't alloc device */
498 /* Initialize the device memory */
499 if (!funcs->device_init(device)) {
500 free(device);
501 errno = AO_EFAIL;
502 return NULL; /* Couldn't init internal memory */
505 /* Load options */
506 while (options != NULL) {
507 if (!funcs->set_option(device, options->key, options->value)) {
508 /* Problem setting options */
509 free(device);
510 errno = AO_EOPENDEVICE;
511 return NULL;
514 options = options->next;
517 /* Open the device */
518 result = funcs->open(device, format);
519 if (!result) {
520 funcs->device_clear(device);
521 free(device);
522 errno = AO_EOPENDEVICE;
523 return NULL; /* Couldn't open device */
526 /* Resolve actual driver byte format */
527 device->driver_byte_format =
528 _real_byte_format(device->driver_byte_format);
530 /* Only create swap buffer for 16 bit samples if needed */
531 if (format->bits == 16 &&
532 device->client_byte_format != device->driver_byte_format) {
534 fprintf(stderr,
535 "n\n\n\n-------------------------\n"
536 "big : %d\n"
537 "device->client_byte_format:%d\n"
538 "device->driver_byte_format:%d\n"
539 "--------------------------\n",
540 ao_is_big_endian(),device->client_byte_format,device->driver_byte_format);
542 result = _realloc_swap_buffer(device, DEF_SWAP_BUF_SIZE);
544 if (!result) {
546 device->funcs->close(device);
547 device->funcs->device_clear(device);
548 free(device);
549 errno = AO_EFAIL;
550 return NULL; /* Couldn't alloc swap buffer */
554 /* If we made it this far, everything is OK. */
555 return device;
559 /* ---------- Public Functions ---------- */
561 /* -- Library Setup/Teardown -- */
563 void ao_initialize(void)
565 driver_list *end;
567 /* Read config files */
568 read_config_files(&config);
570 if (driver_head == NULL) {
571 driver_head = _load_static_drivers(&end);
572 _append_dynamic_drivers(end);
575 /* Create the table of driver info structs */
576 info_table = _make_info_table(&driver_head, &driver_count);
580 void ao_shutdown(void)
582 driver_list *driver = driver_head;
583 driver_list *next_driver;
585 if (!driver_head) return;
587 /* unload and free all the drivers */
588 while (driver) {
589 if (driver->handle) {
591 dlclose(driver->handle);
592 free(driver->functions); /* DON'T FREE STATIC FUNC TABLES */
594 next_driver = driver->next;
595 free(driver);
596 driver = next_driver;
599 _clear_config();
600 /* NULL out driver_head or ao_initialize() won't work */
601 driver_head = NULL;
605 /* -- Device Setup/Playback/Teardown -- */
607 int ao_append_option(ao_option **options, const char *key, const char *value)
609 ao_option *op, *list;
611 op = malloc(sizeof(ao_option));
612 if (op == NULL) return 0;
614 op->key = strdup(key);
615 op->value = strdup(value);
616 op->next = NULL;
618 if ((list = *options) != NULL) {
619 list = *options;
620 while (list->next != NULL) list = list->next;
621 list->next = op;
622 } else {
623 *options = op;
627 return 1;
631 void ao_free_options(ao_option *options)
633 ao_option *rest;
635 while (options != NULL) {
636 rest = options->next;
637 free(options->key);
638 free(options->value);
639 free(options);
640 options = rest;
645 ao_device *ao_open_live (int driver_id, ao_sample_format *format,
646 ao_option *options)
648 return _open_device(driver_id, format, options, NULL);
652 ao_device *ao_open_file (int driver_id, const char *filename, int overwrite,
653 ao_sample_format *format, ao_option *options)
655 FILE *file;
656 ao_device *device;
658 if (strcmp("-", filename) == 0)
659 file = stdout;
660 else {
662 if (!overwrite) {
663 /* Test for file existence */
664 file = fopen(filename, "r");
665 if (file != NULL) {
666 fclose(file);
667 errno = AO_EFILEEXISTS;
668 return NULL;
673 file = fopen(filename, "w");
677 if (file == NULL) {
678 errno = AO_EOPENFILE;
679 return NULL;
682 device = _open_device(driver_id, format, options, file);
684 if (device == NULL) {
685 fclose(file);
686 /* errno already set by _open_device() */
687 return NULL;
690 return device;
694 int ao_play(ao_device *device, char* output_samples, uint_32 num_bytes)
696 char *playback_buffer;
698 if (device == NULL)
699 return 0;
701 #if 1
702 if (device->swap_buffer != NULL) {
703 if (_realloc_swap_buffer(device, num_bytes)) {
704 _swap_samples(device->swap_buffer,
705 output_samples, num_bytes);
706 playback_buffer = device->swap_buffer;
707 } else
708 return 0; /* Could not expand swap buffer */
709 } else
710 #endif
711 playback_buffer = output_samples;
713 return device->funcs->play(device, playback_buffer, num_bytes);
717 int ao_close(ao_device *device)
719 int result;
721 if (device == NULL)
722 result = 0;
723 else {
724 result = device->funcs->close(device);
725 device->funcs->device_clear(device);
727 if (device->file) {
728 fclose(device->file);
729 device->file = NULL;
732 if (device->swap_buffer != NULL)
733 free(device->swap_buffer);
735 free(device);
738 return result;
742 /* -- Driver Information -- */
744 int ao_driver_id(const char *short_name)
746 int i;
747 driver_list *driver = driver_head;
749 i = 0;
750 while (driver) {
751 if (strcmp(short_name,
752 driver->functions->driver_info()->short_name) == 0)
753 return i;
754 driver = driver->next;
755 i++;
758 return -1; /* No driver by that name */
762 int ao_default_driver_id (void)
764 /* Find the default driver in the list of loaded drivers */
766 return _find_default_driver_id(config.default_driver);
770 ao_info *ao_driver_info(int driver_id)
772 driver_list *driver;
774 if ( (driver = _get_driver(driver_id)) )
775 return driver->functions->driver_info();
776 else
777 return NULL;
781 ao_info **ao_driver_info_list(int *count)
783 *count = driver_count;
784 return info_table;
788 /* -- Miscellaneous -- */
790 /* Stolen from Vorbis' lib/vorbisfile.c */
791 int ao_is_big_endian(void)
793 static uint_16 pattern = 0xbabe;
794 return 0[(volatile unsigned char *)&pattern] == 0xba;