From a68df043bfbc7f8f38332143577877846631eca4 Mon Sep 17 00:00:00 2001 From: Michał Cichoń Date: Tue, 25 Aug 2015 19:58:37 +0200 Subject: Update build environment - remove faad2 - remove mad - remove polarssl - remove pthreads - add libcurl - add vtparse with UTF8 support - update project to use Visual Studio 2015 --- libao/src/src/audio_out.c | 1514 --------------------------------------------- 1 file changed, 1514 deletions(-) delete mode 100644 libao/src/src/audio_out.c (limited to 'libao/src/src/audio_out.c') diff --git a/libao/src/src/audio_out.c b/libao/src/src/audio_out.c deleted file mode 100644 index f83199d..0000000 --- a/libao/src/src/audio_out.c +++ /dev/null @@ -1,1514 +0,0 @@ -/* - * - * audio_out.c - * - * Original Copyright (C) Aaron Holtzman - May 1999 - * Modifications Copyright (C) Stan Seibert - July 2000 - * - * This file is part of libao, a cross-platform audio output library. See - * README for a history of this source code. - * - * libao is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * libao is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Make; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - ******************************************************************** - - last mod: $Id: audio_out.c 17008 2010-03-24 03:12:16Z xiphmont $ - - ********************************************************************/ - -#define STRIP_PLUGINS - -#define HAVE_WMM - -#include -#include -#include -#include -#include -#ifndef STRIP_PLUGINS -#if defined HAVE_DLFCN_H && defined HAVE_DLOPEN -# include -#else -static void *dlopen(const char *filename, int flag) {return 0;} -static char *dlerror(void) { return "dlopen: unsupported"; } -static void *dlsym(void *handle, const char *symbol) { return 0; } -static int dlclose(void *handle) { return 0; } -#undef DLOPEN_FLAG -#define DLOPEN_FLAG 0 -#endif -#endif -#include -#include -#ifndef _MSC_VER -# include -#endif -//#include - -#include "ao/ao.h" -#include "ao/ao_private.h" - -/* These should have been set by the Makefile */ -#ifndef AO_PLUGIN_PATH -#define AO_PLUGIN_PATH "/usr/local/lib/ao" -#endif -#ifndef SHARED_LIB_EXT -#define SHARED_LIB_EXT ".so" -#endif - -/* --- Other constants --- */ -#define DEF_SWAP_BUF_SIZE 1024 - -/* --- Driver Table --- */ - -typedef struct driver_list { - ao_functions *functions; - void *handle; - struct driver_list *next; -} driver_list; - - -extern ao_functions ao_null; -//extern ao_functions ao_wav; -//extern ao_functions ao_raw; -//extern ao_functions ao_au; -#ifdef HAVE_SYS_AUDIO_H -extern ao_functions ao_aixs; -#endif -#ifdef HAVE_WMM -extern ao_functions ao_wmm; -#endif -static ao_functions *static_drivers[] = { - &ao_null, /* Must have at least one static driver! */ - //&ao_wav, - //&ao_raw, - //&ao_au, -#ifdef HAVE_SYS_AUDIO_H - &ao_aixs, -#endif -#ifdef HAVE_WMM - &ao_wmm, -#endif - - NULL /* End of list */ -}; - -static driver_list *driver_head = NULL; -static ao_config config = { - NULL /* default_driver */ -}; - -static ao_info **info_table = NULL; -static int driver_count = 0; - -/* uses the device messaging and option infrastructure */ -static ao_device *ao_global_dummy; -static ao_device ao_global_dummy_storage; -static ao_option *ao_global_options=NULL; - -/* ---------- Helper functions ---------- */ - -/* Clear out all of the library configuration options and set them to - defaults. The defaults should match the initializer above. */ -static void _clear_config() -{ - memset(ao_global_dummy,0,sizeof(*ao_global_dummy)); - ao_global_dummy = NULL; - ao_free_options(ao_global_options); - ao_global_options = NULL; - - free(config.default_driver); - config.default_driver = NULL; -} - - -#ifndef STRIP_PLUGINS -/* Load a plugin from disk and put the function table into a driver_list - struct. */ -static driver_list *_get_plugin(char *plugin_file) -{ - ao_device *device = ao_global_dummy; - driver_list *dt; - void *handle; - char *prompt=""; - - handle = dlopen(plugin_file, DLOPEN_FLAG /* See ao_private.h */); - - if (handle) { - prompt="calloc() failed"; - dt = (driver_list *)calloc(1,sizeof(driver_list)); - if (!dt) return NULL; - - dt->handle = handle; - - dt->functions = (ao_functions *)calloc(1,sizeof(ao_functions)); - if (!(dt->functions)) { - free(dt); - return NULL; - } - - prompt="ao_plugin_test() missing"; - dt->functions->test = dlsym(dt->handle, "ao_plugin_test"); - if (!(dt->functions->test)) goto failed; - - prompt="ao_plugin_driver_info() missing"; - dt->functions->driver_info = - dlsym(dt->handle, "ao_plugin_driver_info"); - if (!(dt->functions->driver_info)) goto failed; - - prompt="ao_plugin_device_list() missing"; - dt->functions->device_init = - dlsym(dt->handle, "ao_plugin_device_init"); - if (!(dt->functions->device_init )) goto failed; - - prompt="ao_plugin_set_option() missing"; - dt->functions->set_option = - dlsym(dt->handle, "ao_plugin_set_option"); - if (!(dt->functions->set_option)) goto failed; - - prompt="ao_plugin_open() missing"; - dt->functions->open = dlsym(dt->handle, "ao_plugin_open"); - if (!(dt->functions->open)) goto failed; - - prompt="ao_plugin_play() missing"; - dt->functions->play = dlsym(dt->handle, "ao_plugin_play"); - if (!(dt->functions->play)) goto failed; - - prompt="ao_plugin_close() missing"; - dt->functions->close = dlsym(dt->handle, "ao_plugin_close"); - if (!(dt->functions->close)) goto failed; - - prompt="ao_plugin_clear() missing"; - dt->functions->device_clear = - dlsym(dt->handle, "ao_plugin_device_clear"); - if (!(dt->functions->device_clear)) goto failed; - - - } else { - aerror("Failed to load plugin %s => dlopen() failed\n",plugin_file); - return NULL; - } - - adebug("Loaded driver %s\n",dt->functions->driver_info()->short_name); - return dt; - - failed: - aerror("Failed to load plugin %s => %s\n",plugin_file,prompt); - free(dt->functions); - free(dt); - return NULL; -} -#endif - - -/* If *name is a valid driver name, return its driver number. - Otherwise, test all of available live drivers until one works. */ -static int _find_default_driver_id (const char *name) -{ - int def_id; - int id; - ao_info *info; - driver_list *dl = driver_head; - ao_device *device = ao_global_dummy; - - adebug("Testing drivers to find playback default...\n"); - if ( name == NULL || (def_id = ao_driver_id(name)) < 0 ) { - /* No default specified. Find one among available drivers. */ - def_id = -1; - - id = 0; - while (dl != NULL) { - - info = dl->functions->driver_info(); - adebug("...testing %s\n",info->short_name); - if ( info->type == AO_TYPE_LIVE && - info->priority > 0 && /* Skip static drivers */ - dl->functions->test() ) { - def_id = id; /* Found a usable driver */ - adebug("OK, using driver %s\n",info->short_name); - break; - } - - dl = dl->next; - id++; - } - } - - return def_id; -} - - -/* Convert the static drivers table into a linked list of drivers. */ -static driver_list* _load_static_drivers(driver_list **end) -{ - ao_device *device = ao_global_dummy; - driver_list *head; - driver_list *driver; - int i; - - /* insert first driver */ - head = driver = calloc(1,sizeof(driver_list)); - if (driver != NULL) { - driver->functions = static_drivers[0]; - driver->handle = NULL; - driver->next = NULL; - adebug("Loaded driver %s (built-in)\n",driver->functions->driver_info()->short_name); - - i = 1; - while (static_drivers[i] != NULL) { - driver->next = calloc(1,sizeof(driver_list)); - if (driver->next == NULL) - break; - - driver->next->functions = static_drivers[i]; - driver->next->handle = NULL; - driver->next->next = NULL; - - driver = driver->next; - adebug("Loaded driver %s (built-in)\n",driver->functions->driver_info()->short_name); - i++; - } - } - - if (end != NULL) - *end = driver; - - return head; -} - - -/* Load the dynamic drivers from disk and append them to end of the - driver list. end points the driver_list node to append to. */ -static void _append_dynamic_drivers(driver_list *end) -{ -#ifdef HAVE_DLOPEN - struct dirent *plugin_dirent; - char *ext; - struct stat statbuf; - DIR *plugindir; - driver_list *plugin; - driver_list *driver = end; - ao_device *device = ao_global_dummy; - - /* now insert any plugins we find */ - plugindir = opendir(AO_PLUGIN_PATH); - adebug("Loading driver plugins from %s...\n",AO_PLUGIN_PATH); - if (plugindir != NULL) { - while ((plugin_dirent = readdir(plugindir)) != NULL) { - char fullpath[strlen(AO_PLUGIN_PATH) + 1 + strlen(plugin_dirent->d_name) + 1]; - snprintf(fullpath, sizeof(fullpath), "%s/%s", - AO_PLUGIN_PATH, plugin_dirent->d_name); - if (!stat(fullpath, &statbuf) && - S_ISREG(statbuf.st_mode) && - (ext = strrchr(plugin_dirent->d_name, '.')) != NULL) { - if (strcmp(ext, SHARED_LIB_EXT) == 0) { - plugin = _get_plugin(fullpath); - if (plugin) { - driver->next = plugin; - plugin->next = NULL; - driver = driver->next; - } - } - } - } - - closedir(plugindir); - } -#endif -} - - -/* Compare two drivers based on priority - Used as compar function for qsort() in _make_info_table() */ -static int _compar_driver_priority (const driver_list **a, - const driver_list **b) -{ - return memcmp(&((*b)->functions->driver_info()->priority), - &((*a)->functions->driver_info()->priority), - sizeof(int)); -} - - -/* Make a table of driver info structures for ao_driver_info_list(). */ -static ao_info ** _make_info_table (driver_list **head, int *driver_count) -{ - driver_list *list; - int i; - ao_info **table; - driver_list **drivers_table; - - *driver_count = 0; - - /* Count drivers */ - list = *head; - i = 0; - while (list != NULL) { - i++; - list = list->next; - } - - - /* Sort driver_list */ - drivers_table = (driver_list **) calloc(i, sizeof(driver_list *)); - if (drivers_table == NULL) - return (ao_info **) NULL; - list = *head; - *driver_count = i; - for (i = 0; i < *driver_count; i++, list = list->next) - drivers_table[i] = list; - qsort(drivers_table, i, sizeof(driver_list *), - (int(*)(const void *, const void *)) - _compar_driver_priority); - *head = drivers_table[0]; - for (i = 1; i < *driver_count; i++) - drivers_table[i-1]->next = drivers_table[i]; - drivers_table[i-1]->next = NULL; - - - /* Alloc table */ - table = (ao_info **) calloc(i, sizeof(ao_info *)); - if (table != NULL) { - for (i = 0; i < *driver_count; i++) - table[i] = drivers_table[i]->functions->driver_info(); - } - - free(drivers_table); - - return table; -} - - -/* Return the driver struct corresponding to particular driver id - number. */ -static driver_list *_get_driver(int driver_id) { - int i = 0; - driver_list *driver = driver_head; - - if (driver_id < 0) return NULL; - - while (driver && (i < driver_id)) { - i++; - driver = driver->next; - } - - if (i == driver_id) - return driver; - - return NULL; -} - - -#ifndef STRIP_PLUGINS -/* Check if driver_id is a valid id number */ -static int _check_driver_id(int driver_id) -{ - int i = 0; - driver_list *driver = driver_head; - - if (driver_id < 0) return 0; - - while (driver && (i <= driver_id)) { - driver = driver->next; - i++; - } - - if (i == (driver_id + 1)) - return 1; - - return 0; -} -#endif - - -/* helper function to convert a byte_format of AO_FMT_NATIVE to the - actual byte format of the machine, otherwise just return - byte_format */ -static int _real_byte_format(int byte_format) -{ - if (byte_format == AO_FMT_NATIVE) { - if (ao_is_big_endian()) - return AO_FMT_BIG; - else - return AO_FMT_LITTLE; - } else - return byte_format; -} - - -/* Create a new ao_device structure and populate it with data */ -static ao_device* _create_device(int driver_id, driver_list *driver, - ao_sample_format *format, FILE *file) -{ - ao_device *device; - - device = calloc(1,sizeof(ao_device)); - - if (device != NULL) { - device->type = driver->functions->driver_info()->type; - device->driver_id = driver_id; - device->funcs = driver->functions; - device->file = file; - device->machine_byte_format = - ao_is_big_endian() ? AO_FMT_BIG : AO_FMT_LITTLE; - device->client_byte_format = - _real_byte_format(format->byte_format); - device->swap_buffer = NULL; - device->swap_buffer_size = 0; - device->internal = NULL; - device->output_channels = format->channels; - device->inter_permute = NULL; - device->output_matrix = NULL; - } - - return device; -} - - -/* Expand the swap buffer in this device if it is smaller than - min_size. */ -static int _realloc_swap_buffer(ao_device *device, int min_size) -{ - void *temp; - - if (min_size > device->swap_buffer_size) { - temp = realloc(device->swap_buffer, min_size); - if (temp != NULL) { - device->swap_buffer = temp; - device->swap_buffer_size = min_size; - return 1; /* Success, realloc worked */ - } else - return 0; /* Fail to realloc */ - } else - return 1; /* Success, no need to realloc */ -} - - -static void _buffer_zero(char *target,int och,int bytewidth,int ochannels,int bytes){ - int i = och*bytewidth; - int stride = bytewidth*ochannels; - switch(bytewidth){ - case 1: - while(ip && isspace(*(t-1)))t--; - - while(mnemonics[m]){ - if(t-p && !strncmp(mnemonics[m],p,t-p) && - strlen(mnemonics[m])==t-p){ - if(count)strcat(ret,","); - strcat(ret,mnemonics[m]); - break; - } - m++; - } - if(!mnemonics[m]){ - /* unrecognized channel mnemonic */ - { - int i; - aerror("Unrecognized channel name \""); - for(i=0;ip && isspace(*(t-1)))t--; - - count++; - if(!*h)break; - p=h+1; - } - - ret = calloc(count+1,sizeof(*ret)); - - p=matrix; - count=0; - while(1){ - char *h,*t; - - /* trim leading space */ - while(*p && isspace(*p))p++; - - /* search for seperator */ - h=p; - while(*h && *h!=',')h++; - - /* trim trailing space */ - t=h; - while(t>p && isspace(*(t-1)))t--; - - ret[count] = calloc(t-p+1,1); - memcpy(ret[count],p,t-p); - count++; - if(!*h)break; - p=h+1; - } - - return ret; - -} - -static void _free_map(char **m){ - char **in=m; - while(m && *m){ - free(*m); - m++; - } - if(in)free(in); -} - -static unsigned int _matrix_to_channelmask(int ch, char *matrix, char *premap, int **mout){ - unsigned int ret=0; - char *p=matrix; - int *perm=(*mout=malloc(ch*sizeof(*mout))); - int i; - char **map = _tokenize_matrix(premap); - - for(i=0;ikey,"debug")){ - ao_global_dummy->verbose=2; - }else if(!strcmp(options->key,"verbose")){ - if(ao_global_dummy->verbose<1)ao_global_dummy->verbose=1; - }else if(!strcmp(options->key,"quiet")){ - ao_global_dummy->verbose=-1; - } - - options = options->next; - } - - return 0; - -} - -static int ao_device_load_options(ao_device *device, ao_option *options){ - - while (options != NULL) { - if(!strcmp(options->key,"matrix")){ - /* If a driver has a static channel mapping mechanism - (physically constant channel mapping, or at least an - unvarying set of constants for mapping channels), the - output_matrix is already set. An app/user specified - output mapping trumps. */ - if(device->output_matrix) - free(device->output_matrix); - /* explicitly set the output matrix to the requested - string; devices must not override. */ - device->output_matrix = _sanitize_matrix(32, options->value, device); - if(!device->output_matrix){ - aerror("Empty or inavlid output matrix\n"); - return AO_EBADOPTION; - } - adebug("Sanitized device output matrix: %s\n",device->output_matrix); - }else if(!strcmp(options->key,"debug")){ - device->verbose=2; - }else if(!strcmp(options->key,"verbose")){ - if(device->verbose<1)device->verbose=1; - }else if(!strcmp(options->key,"quiet")){ - device->verbose=-1; - }else{ - if (!device->funcs->set_option(device, options->key, options->value)) { - /* Problem setting options */ - return AO_EOPENDEVICE; - } - } - - options = options->next; - } - - return 0; -} - -/* Open a device. If this is a live device, file == NULL. */ -static ao_device* _open_device(int driver_id, ao_sample_format *format, - ao_option *options, FILE *file) -{ - ao_functions *funcs; - driver_list *driver; - ao_device *device=NULL; - int result; - ao_sample_format sformat=*format; - sformat.matrix=NULL; - - /* Get driver id */ - if ( (driver = _get_driver(driver_id)) == NULL ) { - errno = AO_ENODRIVER; - goto error; - } - - funcs = driver->functions; - - /* Check the driver type */ - if (file == NULL && - funcs->driver_info()->type != AO_TYPE_LIVE) { - - errno = AO_ENOTLIVE; - goto error; - } else if (file != NULL && - funcs->driver_info()->type != AO_TYPE_FILE) { - - errno = AO_ENOTFILE; - goto error; - } - - /* Make a new device structure */ - if ( (device = _create_device(driver_id, driver, - format, file)) == NULL ) { - errno = AO_EFAIL; - goto error; - } - - /* Initialize the device memory; get static channel mapping */ - if (!funcs->device_init(device)) { - errno = AO_EFAIL; - goto error; - } - - /* Load options */ - errno = ao_device_load_options(device,ao_global_options); - if(errno) goto error; - errno = ao_device_load_options(device,options); - if(errno) goto error; - - /* also sanitize the format input channel matrix */ - if(format->matrix){ - sformat.matrix = _sanitize_matrix(format->channels, format->matrix, device); - if(!sformat.matrix) - awarn("Input channel matrix invalid; ignoring.\n"); - - /* special-case handling of 'M'. */ - if(sformat.channels==1 && sformat.matrix && !strcmp(sformat.matrix,"M")){ - free(sformat.matrix); - sformat.matrix=NULL; - } - } - - /* If device init was able to declare a static channel mapping - mechanism, reconcile it to the input now. Odd drivers that - need to communicate with a backend device to determine - channel mapping strategy can still bypass this mechanism - entirely. Also, drivers like ALSA may need to adjust - strategy depending on what device is successfully opened, - etc, but this still saves work later. */ - - if(device->output_matrix && sformat.matrix){ - switch(device->output_matrix_order){ - case AO_OUTPUT_MATRIX_FIXED: - /* Backend channel ordering is immutable and unused - channels must still be sent. Look for the highest - channel number we are able to map from the input - matrix. */ - { - unsigned int mask = _matrix_to_channelmask(sformat.channels,sformat.matrix, - device->output_matrix, - &device->input_map); - int max = _channelmask_maxbit(mask); - if(max<0){ - aerror("Unable to map any channels from input matrix to output"); - errno = AO_EBADFORMAT; - goto error; - } - device->output_channels = max+1; - device->output_mask = mask; - device->inter_matrix = _strdup(device->output_matrix); - } - break; - - case AO_OUTPUT_MATRIX_COLLAPSIBLE: - /* the ordering of channels submitted to the backend is - fixed, but only the channels in use should be present - in the audio stream */ - { - unsigned int mask = _matrix_to_channelmask(sformat.channels,sformat.matrix, - device->output_matrix, - &device->input_map); - int channels = _channelmask_bits(mask); - if(channels<0){ - aerror("Unable to map any channels from input matrix to output"); - errno = AO_EBADFORMAT; - goto error; - } - device->output_channels = channels; - device->output_mask = mask; - device->inter_matrix = _channelmask_to_matrix(mask,device->output_matrix); - } - break; - - case AO_OUTPUT_MATRIX_PERMUTABLE: - /* The ordering of channels is freeform. Only the - channels in use should be sent, and they may be sent in - any order. If possible, leave the input ordering - unchanged */ - { - unsigned int mask = _matrix_to_channelmask(sformat.channels,sformat.matrix, - device->output_matrix, - &device->input_map); - int channels = _channelmask_bits(mask); - if(channels<0){ - aerror("Unable to map any channels from input matrix to output"); - errno = AO_EBADFORMAT; - goto error; - } - device->output_channels = channels; - device->output_mask = mask; - device->inter_matrix = _matrix_intersect(sformat.matrix,device->output_matrix); - } - break; - - default: - aerror("Driver backend failed to set output ordering.\n"); - errno = AO_EFAIL; - goto error; - } - - }else{ - device->output_channels = sformat.channels; - } - - /* other housekeeping */ - device->input_channels = sformat.channels; - device->bytewidth = (sformat.bits+7)>>3; - device->rate = sformat.rate; - - /* Open the device */ - result = funcs->open(device, &sformat); - if (!result) { - errno = AO_EOPENDEVICE; - goto error; - } - - /* set up permutation based on finalized inter_matrix mapping */ - /* The only way device->output_channels could be zero here is - if the driver has opted to ouput no channels (eg, the null - driver). */ - if(sformat.matrix){ - if(!device->inter_matrix){ - awarn("Driver %s does not support automatic channel mapping;\n" - "\tRouting only L/R channels to output.\n\n", - info_table[device->driver_id]->short_name); - device->inter_matrix=_strdup("L,R"); - } - { - - /* walk thorugh the inter matrix, match channels */ - char *op=device->inter_matrix; - int count=0; - device->inter_permute = calloc(device->output_channels,sizeof(int)); - - adebug("\n"); - - while(countoutput_channels){ - int m=0,mm; - char *h=op; - - if(*op){ - /* find mnemonic offset of inter channel */ - while(*h && *h!=',')h++; - while(mnemonics[m]){ - if(!strncmp(mnemonics[m],op,h-op)) - break; - m++; - } - mm=m; - - /* find match in input if any */ - device->inter_permute[count] = _find_channel(m,sformat.matrix); - if(device->inter_permute[count] == -1 && sformat.channels == 1){ - device->inter_permute[count] = _find_channel(1,sformat.matrix); - mm=1; - } - }else - device->inter_permute[count] = -1; - - /* display resulting mapping for now */ - if(device->inter_permute[count]>=0){ - adebug("input %d (%s)\t -> backend %d (%s)\n", - device->inter_permute[count], mnemonics[mm], - count,mnemonics[m]); - }else{ - adebug(" \t backend %d (%s)\n", - count,mnemonics[m]); - } - count++; - op=h; - if(*h)op++; - } - { - char **inch = _tokenize_matrix(sformat.matrix); - int i,j; - int unflag=0; - for(j=0;joutput_channels;i++) - if(device->inter_permute[i]==j)break; - if(i==device->output_channels){ - adebug("input %d (%s)\t -> none\n", - j,inch[j]); - unflag=1; - } - } - _free_map(inch); - if(unflag) - awarn("Some input channels are unmapped and will not be used.\n"); - } - averbose("\n"); - - } - } - - /* if there's no actual permutation to do, release the permutation vector */ - if(device->inter_permute && device->output_channels == device->input_channels){ - int i; - for(i=0;ioutput_channels;i++) - if(device->inter_permute[i]!=i)break; - if(i==device->output_channels){ - free(device->inter_permute); - device->inter_permute=NULL; - } - } - - /* Resolve actual driver byte format */ - device->driver_byte_format = - _real_byte_format(device->driver_byte_format); - - /* Only create swap buffer if needed */ - if (device->bytewidth>1 && - device->client_byte_format != device->driver_byte_format){ - adebug("swap buffer required:\n"); - adebug(" machine endianness: %d\n",ao_is_big_endian()); - adebug(" device->client_byte_format:%d\n",device->client_byte_format); - adebug(" device->driver_byte_format:%d\n",device->driver_byte_format); - } - - if ( (device->bytewidth>1 && - device->client_byte_format != device->driver_byte_format) || - device->inter_permute){ - - result = _realloc_swap_buffer(device, DEF_SWAP_BUF_SIZE); - - if (!result) { - - if(sformat.matrix)free(sformat.matrix); - device->funcs->close(device); - device->funcs->device_clear(device); - free(device); - errno = AO_EFAIL; - return NULL; /* Couldn't alloc swap buffer */ - } - } - - /* If we made it this far, everything is OK. */ - if(sformat.matrix)free(sformat.matrix); - return device; - - error: - { - int errtemp = errno; - if(sformat.matrix) - free(sformat.matrix); - ao_close(device); - errno=errtemp; - } - return NULL; -} - - -/* ---------- Public Functions ---------- */ - -/* -- Library Setup/Teardown -- */ - -static ao_info ao_dummy_info= - { 0,0,0,0,0,0,0,0,0 }; -static ao_info *ao_dummy_driver_info(void){ - return &ao_dummy_info; -} -static ao_functions ao_dummy_funcs= - { 0, &ao_dummy_driver_info, 0,0,0,0,0,0,0}; - -void ao_initialize(void) -{ - driver_list *end; - ao_global_dummy = &ao_global_dummy_storage; - ao_global_dummy->funcs = &ao_dummy_funcs; - - /* Read config files */ - ao_read_config_files(&config); - ao_global_load_options(ao_global_options); - - if (driver_head == NULL) { - driver_head = _load_static_drivers(&end); - _append_dynamic_drivers(end); - } - - /* Create the table of driver info structs */ - info_table = _make_info_table(&driver_head, &driver_count); -} - -void ao_shutdown(void) -{ - driver_list *driver = driver_head; - driver_list *next_driver; - - if (!driver_head) return; - - /* unload and free all the drivers */ - while (driver) { - if (driver->handle) { -#ifndef STRIP_PLUGINS - dlclose(driver->handle); -#endif - free(driver->functions); /* DON'T FREE STATIC FUNC TABLES */ - } - next_driver = driver->next; - free(driver); - driver = next_driver; - } - - free(info_table); - - _clear_config(); - /* NULL out driver_head or ao_initialize() won't work */ - driver_head = NULL; -} - - -/* -- Device Setup/Playback/Teardown -- */ -int ao_append_option(ao_option **options, const char *key, const char *value) -{ - ao_option *op, *list; - - op = calloc(1,sizeof(ao_option)); - if (op == NULL) return 0; - - op->key = _strdup(key); - op->value = _strdup(value?value:""); - op->next = NULL; - - if ((list = *options) != NULL) { - list = *options; - while (list->next != NULL) list = list->next; - list->next = op; - } else { - *options = op; - } - - - return 1; -} - -int ao_append_global_option(const char *key, const char *value) -{ - return ao_append_option(&ao_global_options,key,value); -} - -void ao_free_options(ao_option *options) -{ - ao_option *rest; - - while (options != NULL) { - rest = options->next; - free(options->key); - free(options->value); - free(options); - options = rest; - } -} - - -ao_device *ao_open_live (int driver_id, ao_sample_format *format, - ao_option *options) -{ - return _open_device(driver_id, format, options, NULL); -} - - -ao_device *ao_open_file (int driver_id, const char *filename, int overwrite, - ao_sample_format *format, ao_option *options) -{ - FILE *file; - ao_device *device; - - if (strcmp("-", filename) == 0) - file = stdout; - else { - - if (!overwrite) { - /* Test for file existence */ - file = fopen(filename, "r"); - if (file != NULL) { - fclose(file); - errno = AO_EFILEEXISTS; - return NULL; - } - } - - - file = fopen(filename, "w"); - } - - - if (file == NULL) { - errno = AO_EOPENFILE; - return NULL; - } - - device = _open_device(driver_id, format, options, file); - - if (device == NULL) { - fclose(file); - /* errno already set by _open_device() */ - return NULL; - } - - return device; -} - - -int ao_play(ao_device *device, char* output_samples, uint_32 num_bytes) -{ - char *playback_buffer; - - if (device == NULL) - return 0; - - if (device->swap_buffer != NULL) { - int out_bytes = num_bytes*device->output_channels/device->input_channels; - if (_realloc_swap_buffer(device, out_bytes)) { - int i; - int swap = (device->bytewidth>1 && - device->client_byte_format != device->driver_byte_format); - for(i=0;ioutput_channels;i++){ - int ic = device->inter_permute ? device->inter_permute[i] : i; - if(ic==-1){ - _buffer_zero(device->swap_buffer,i,device->bytewidth,device->output_channels, - out_bytes); - }else if(swap){ - _buffer_permute_swap(device->swap_buffer,i,device->bytewidth,device->output_channels, - out_bytes, output_samples, ic, device->input_channels); - }else{ - _buffer_permute(device->swap_buffer,i,device->bytewidth,device->output_channels, - out_bytes, output_samples, ic, device->input_channels); - } - } - playback_buffer = device->swap_buffer; - num_bytes = out_bytes; - } else - return 0; /* Could not expand swap buffer */ - } else - playback_buffer = output_samples; - - return device->funcs->play(device, playback_buffer, num_bytes); -} - - -int ao_close(ao_device *device) -{ - int result; - - if (device == NULL) - result = 0; - else { - result = device->funcs->close(device); - device->funcs->device_clear(device); - - if (device->file) { - fclose(device->file); - device->file = NULL; - } - - if (device->swap_buffer != NULL) - free(device->swap_buffer); - if (device->output_matrix != NULL) - free(device->output_matrix); - if (device->input_map != NULL) - free(device->input_map); - if (device->inter_matrix != NULL) - free(device->inter_matrix); - if (device->inter_permute != NULL) - free(device->inter_permute); - free(device); - } - - return result; -} - - -/* -- Driver Information -- */ - -int ao_driver_id(const char *short_name) -{ - int i; - driver_list *driver = driver_head; - - i = 0; - while (driver) { - if (strcmp(short_name, - driver->functions->driver_info()->short_name) == 0) - return i; - driver = driver->next; - i++; - } - - return -1; /* No driver by that name */ -} - - -int ao_default_driver_id (void) -{ - /* Find the default driver in the list of loaded drivers */ - - return _find_default_driver_id(config.default_driver); -} - - -ao_info *ao_driver_info(int driver_id) -{ - driver_list *driver; - - if ( (driver = _get_driver(driver_id)) ) - return driver->functions->driver_info(); - else - return NULL; -} - - -ao_info **ao_driver_info_list(int *count) -{ - *count = driver_count; - return info_table; -} - - -/* -- Miscellaneous -- */ - -/* Stolen from Vorbis' lib/vorbisfile.c */ -int ao_is_big_endian(void) -{ - static uint_16 pattern = 0xbabe; - return 0[(volatile unsigned char *)&pattern] == 0xba; -} -- cgit v1.2.3