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)
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.
31 #if defined HAVE_DLFCN_H && defined HAVE_DLOPEN
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; }
41 #include <sys/types.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"
55 #ifndef SHARED_LIB_EXT
56 #define SHARED_LIB_EXT ".so"
59 /* --- Other constants --- */
60 #define DEF_SWAP_BUF_SIZE 1024
62 /* --- Driver Table --- */
64 typedef struct driver_list
{
65 ao_functions
*functions
;
67 struct driver_list
*next
;
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
;
79 extern ao_functions ao_wmm
;
81 static ao_functions
*static_drivers
[] = {
82 &ao_null
, /* Must have at least one static driver! */
86 #ifdef HAVE_SYS_AUDIO_H
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
117 static driver_list
*_get_plugin(char *plugin_file
)
122 handle
= dlopen(plugin_file
, DLOPEN_FLAG
/* See ao_private.h */);
125 dt
= (driver_list
*)malloc(sizeof(driver_list
));
126 if (!dt
) return NULL
;
130 dt
->functions
= (ao_functions
*)malloc(sizeof(ao_functions
));
131 if (!(dt
->functions
)) {
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
;
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
)
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. */
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 */
203 driver
= driver
->next
;
212 /* Convert the static drivers table into a linked list of drivers. */
213 static driver_list
* _load_static_drivers(driver_list
**end
)
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
;
227 while (static_drivers
[i
] != NULL
) {
228 driver
->next
= malloc(sizeof(driver_list
));
229 if (driver
->next
== NULL
)
232 driver
->next
->functions
= static_drivers
[i
];
233 driver
->next
->handle
= NULL
;
234 driver
->next
->next
= NULL
;
236 driver
= driver
->next
;
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
)
253 struct dirent
*plugin_dirent
;
256 char fullpath
[PATH_MAX
];
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
);
273 driver
->next
= plugin
;
275 driver
= driver
->next
;
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
),
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
)
304 driver_list
**drivers_table
;
311 while (list
!= NULL
) {
317 /* Sort driver_list */
318 drivers_table
= (driver_list
**) calloc(i
, sizeof(driver_list
*));
319 if (drivers_table
== NULL
)
320 return (ao_info
**) NULL
;
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
;
335 table
= (ao_info
**) calloc(i
, sizeof(ao_info
*));
337 for (i
= 0; i
< *driver_count
; i
++)
338 table
[i
] = drivers_table
[i
]->functions
->driver_info();
347 /* Return the driver struct corresponding to particular driver id
349 static driver_list
*_get_driver(int driver_id
) {
351 driver_list
*driver
= driver_head
;
353 if (driver_id
< 0) return NULL
;
355 while (driver
&& (i
< driver_id
)) {
357 driver
= driver
->next
;
367 /* Check if driver_id is a valid id number */
368 static int _check_driver_id(int driver_id
)
371 driver_list
*driver
= driver_head
;
373 if (driver_id
< 0) return 0;
375 while (driver
&& (i
<= driver_id
)) {
376 driver
= driver
->next
;
380 if (i
== (driver_id
+ 1))
387 /* helper function to convert a byte_format of AO_FMT_NATIVE to the
388 actual byte format of the machine, otherwise just return
390 static int _real_byte_format(int byte_format
)
392 if (byte_format
== AO_FMT_NATIVE
) {
393 if (ao_is_big_endian())
396 return AO_FMT_LITTLE
;
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
)
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
;
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
;
428 /* Expand the swap buffer in this device if it is smaller than
430 static int _realloc_swap_buffer(ao_device
*device
, int min_size
)
434 if (min_size
> device
->swap_buffer_size
) {
435 temp
= realloc(device
->swap_buffer
, min_size
);
437 device
->swap_buffer
= temp
;
438 device
->swap_buffer_size
= min_size
;
439 return 1; /* Success, realloc worked */
441 return 0; /* Fail to realloc */
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
,
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
)
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 */
480 funcs
->driver_info()->type
!= AO_TYPE_LIVE
) {
484 } else if (file
!= NULL
&&
485 funcs
->driver_info()->type
!= AO_TYPE_FILE
) {
491 /* Make a new device structure */
492 if ( (device
= _create_device(driver_id
, driver
,
493 format
, file
)) == NULL
) {
495 return NULL
; /* Couldn't alloc device */
498 /* Initialize the device memory */
499 if (!funcs
->device_init(device
)) {
502 return NULL
; /* Couldn't init internal memory */
506 while (options
!= NULL
) {
507 if (!funcs
->set_option(device
, options
->key
, options
->value
)) {
508 /* Problem setting options */
510 errno
= AO_EOPENDEVICE
;
514 options
= options
->next
;
517 /* Open the device */
518 result
= funcs
->open(device
, format
);
520 funcs
->device_clear(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
) {
535 "n\n\n\n-------------------------\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
);
546 device
->funcs
->close(device
);
547 device
->funcs
->device_clear(device
);
550 return NULL
; /* Couldn't alloc swap buffer */
554 /* If we made it this far, everything is OK. */
559 /* ---------- Public Functions ---------- */
561 /* -- Library Setup/Teardown -- */
563 void ao_initialize(void)
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 */
589 if (driver
->handle
) {
591 dlclose(driver
->handle
);
592 free(driver
->functions
); /* DON'T FREE STATIC FUNC TABLES */
594 next_driver
= driver
->next
;
596 driver
= next_driver
;
600 /* NULL out driver_head or ao_initialize() won't work */
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
);
618 if ((list
= *options
) != NULL
) {
620 while (list
->next
!= NULL
) list
= list
->next
;
631 void ao_free_options(ao_option
*options
)
635 while (options
!= NULL
) {
636 rest
= options
->next
;
638 free(options
->value
);
645 ao_device
*ao_open_live (int driver_id
, ao_sample_format
*format
,
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
)
658 if (strcmp("-", filename
) == 0)
663 /* Test for file existence */
664 file
= fopen(filename
, "r");
667 errno
= AO_EFILEEXISTS
;
673 file
= fopen(filename
, "w");
678 errno
= AO_EOPENFILE
;
682 device
= _open_device(driver_id
, format
, options
, file
);
684 if (device
== NULL
) {
686 /* errno already set by _open_device() */
694 int ao_play(ao_device
*device
, char* output_samples
, uint_32 num_bytes
)
696 char *playback_buffer
;
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
;
708 return 0; /* Could not expand swap buffer */
711 playback_buffer
= output_samples
;
713 return device
->funcs
->play(device
, playback_buffer
, num_bytes
);
717 int ao_close(ao_device
*device
)
724 result
= device
->funcs
->close(device
);
725 device
->funcs
->device_clear(device
);
728 fclose(device
->file
);
732 if (device
->swap_buffer
!= NULL
)
733 free(device
->swap_buffer
);
742 /* -- Driver Information -- */
744 int ao_driver_id(const char *short_name
)
747 driver_list
*driver
= driver_head
;
751 if (strcmp(short_name
,
752 driver
->functions
->driver_info()->short_name
) == 0)
754 driver
= driver
->next
;
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
)
774 if ( (driver
= _get_driver(driver_id
)) )
775 return driver
->functions
->driver_info();
781 ao_info
**ao_driver_info_list(int *count
)
783 *count
= driver_count
;
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;