# HG changeset patch # User Robert McIntyre # Date 1319573491 25200 # Node ID 82b9267a3e19c381d7c2c0a437560feec17d5315 # Parent c41d773a85fbfde41add87efe00f0b049c78bf98 removed all backends except for the send backend diff -r c41d773a85fb -r 82b9267a3e19 Alc/backends/alsa.c --- a/Alc/backends/alsa.c Tue Oct 25 13:03:35 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1138 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2007 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#include "config.h" - -#include -#include -#include - -#include "alMain.h" - -#include - - -static const ALCchar alsaDevice[] = "ALSA Default"; - - -static void *alsa_handle; -#ifdef HAVE_DYNLOAD -#define MAKE_FUNC(f) static typeof(f) * p##f -MAKE_FUNC(snd_strerror); -MAKE_FUNC(snd_pcm_open); -MAKE_FUNC(snd_pcm_close); -MAKE_FUNC(snd_pcm_nonblock); -MAKE_FUNC(snd_pcm_frames_to_bytes); -MAKE_FUNC(snd_pcm_bytes_to_frames); -MAKE_FUNC(snd_pcm_hw_params_malloc); -MAKE_FUNC(snd_pcm_hw_params_free); -MAKE_FUNC(snd_pcm_hw_params_any); -MAKE_FUNC(snd_pcm_hw_params_set_access); -MAKE_FUNC(snd_pcm_hw_params_set_format); -MAKE_FUNC(snd_pcm_hw_params_set_channels); -MAKE_FUNC(snd_pcm_hw_params_set_periods_near); -MAKE_FUNC(snd_pcm_hw_params_set_rate_near); -MAKE_FUNC(snd_pcm_hw_params_set_rate); -MAKE_FUNC(snd_pcm_hw_params_set_rate_resample); -MAKE_FUNC(snd_pcm_hw_params_set_buffer_time_near); -MAKE_FUNC(snd_pcm_hw_params_set_period_time_near); -MAKE_FUNC(snd_pcm_hw_params_set_buffer_size_near); -MAKE_FUNC(snd_pcm_hw_params_set_period_size_near); -MAKE_FUNC(snd_pcm_hw_params_set_buffer_size_min); -MAKE_FUNC(snd_pcm_hw_params_get_buffer_size); -MAKE_FUNC(snd_pcm_hw_params_get_period_size); -MAKE_FUNC(snd_pcm_hw_params_get_access); -MAKE_FUNC(snd_pcm_hw_params_get_periods); -MAKE_FUNC(snd_pcm_hw_params); -MAKE_FUNC(snd_pcm_sw_params_malloc); -MAKE_FUNC(snd_pcm_sw_params_current); -MAKE_FUNC(snd_pcm_sw_params_set_avail_min); -MAKE_FUNC(snd_pcm_sw_params); -MAKE_FUNC(snd_pcm_sw_params_free); -MAKE_FUNC(snd_pcm_prepare); -MAKE_FUNC(snd_pcm_start); -MAKE_FUNC(snd_pcm_resume); -MAKE_FUNC(snd_pcm_wait); -MAKE_FUNC(snd_pcm_state); -MAKE_FUNC(snd_pcm_avail_update); -MAKE_FUNC(snd_pcm_areas_silence); -MAKE_FUNC(snd_pcm_mmap_begin); -MAKE_FUNC(snd_pcm_mmap_commit); -MAKE_FUNC(snd_pcm_readi); -MAKE_FUNC(snd_pcm_writei); -MAKE_FUNC(snd_pcm_drain); -MAKE_FUNC(snd_pcm_recover); -MAKE_FUNC(snd_pcm_info_malloc); -MAKE_FUNC(snd_pcm_info_free); -MAKE_FUNC(snd_pcm_info_set_device); -MAKE_FUNC(snd_pcm_info_set_subdevice); -MAKE_FUNC(snd_pcm_info_set_stream); -MAKE_FUNC(snd_pcm_info_get_name); -MAKE_FUNC(snd_ctl_pcm_next_device); -MAKE_FUNC(snd_ctl_pcm_info); -MAKE_FUNC(snd_ctl_open); -MAKE_FUNC(snd_ctl_close); -MAKE_FUNC(snd_ctl_card_info_malloc); -MAKE_FUNC(snd_ctl_card_info_free); -MAKE_FUNC(snd_ctl_card_info); -MAKE_FUNC(snd_ctl_card_info_get_name); -MAKE_FUNC(snd_ctl_card_info_get_id); -MAKE_FUNC(snd_card_next); -#undef MAKE_FUNC - -#define snd_strerror psnd_strerror -#define snd_pcm_open psnd_pcm_open -#define snd_pcm_close psnd_pcm_close -#define snd_pcm_nonblock psnd_pcm_nonblock -#define snd_pcm_frames_to_bytes psnd_pcm_frames_to_bytes -#define snd_pcm_bytes_to_frames psnd_pcm_bytes_to_frames -#define snd_pcm_hw_params_malloc psnd_pcm_hw_params_malloc -#define snd_pcm_hw_params_free psnd_pcm_hw_params_free -#define snd_pcm_hw_params_any psnd_pcm_hw_params_any -#define snd_pcm_hw_params_set_access psnd_pcm_hw_params_set_access -#define snd_pcm_hw_params_set_format psnd_pcm_hw_params_set_format -#define snd_pcm_hw_params_set_channels psnd_pcm_hw_params_set_channels -#define snd_pcm_hw_params_set_periods_near psnd_pcm_hw_params_set_periods_near -#define snd_pcm_hw_params_set_rate_near psnd_pcm_hw_params_set_rate_near -#define snd_pcm_hw_params_set_rate psnd_pcm_hw_params_set_rate -#define snd_pcm_hw_params_set_rate_resample psnd_pcm_hw_params_set_rate_resample -#define snd_pcm_hw_params_set_buffer_time_near psnd_pcm_hw_params_set_buffer_time_near -#define snd_pcm_hw_params_set_period_time_near psnd_pcm_hw_params_set_period_time_near -#define snd_pcm_hw_params_set_buffer_size_near psnd_pcm_hw_params_set_buffer_size_near -#define snd_pcm_hw_params_set_period_size_near psnd_pcm_hw_params_set_period_size_near -#define snd_pcm_hw_params_set_buffer_size_min psnd_pcm_hw_params_set_buffer_size_min -#define snd_pcm_hw_params_get_buffer_size psnd_pcm_hw_params_get_buffer_size -#define snd_pcm_hw_params_get_period_size psnd_pcm_hw_params_get_period_size -#define snd_pcm_hw_params_get_access psnd_pcm_hw_params_get_access -#define snd_pcm_hw_params_get_periods psnd_pcm_hw_params_get_periods -#define snd_pcm_hw_params psnd_pcm_hw_params -#define snd_pcm_sw_params_malloc psnd_pcm_sw_params_malloc -#define snd_pcm_sw_params_current psnd_pcm_sw_params_current -#define snd_pcm_sw_params_set_avail_min psnd_pcm_sw_params_set_avail_min -#define snd_pcm_sw_params psnd_pcm_sw_params -#define snd_pcm_sw_params_free psnd_pcm_sw_params_free -#define snd_pcm_prepare psnd_pcm_prepare -#define snd_pcm_start psnd_pcm_start -#define snd_pcm_resume psnd_pcm_resume -#define snd_pcm_wait psnd_pcm_wait -#define snd_pcm_state psnd_pcm_state -#define snd_pcm_avail_update psnd_pcm_avail_update -#define snd_pcm_areas_silence psnd_pcm_areas_silence -#define snd_pcm_mmap_begin psnd_pcm_mmap_begin -#define snd_pcm_mmap_commit psnd_pcm_mmap_commit -#define snd_pcm_readi psnd_pcm_readi -#define snd_pcm_writei psnd_pcm_writei -#define snd_pcm_drain psnd_pcm_drain -#define snd_pcm_recover psnd_pcm_recover -#define snd_pcm_info_malloc psnd_pcm_info_malloc -#define snd_pcm_info_free psnd_pcm_info_free -#define snd_pcm_info_set_device psnd_pcm_info_set_device -#define snd_pcm_info_set_subdevice psnd_pcm_info_set_subdevice -#define snd_pcm_info_set_stream psnd_pcm_info_set_stream -#define snd_pcm_info_get_name psnd_pcm_info_get_name -#define snd_ctl_pcm_next_device psnd_ctl_pcm_next_device -#define snd_ctl_pcm_info psnd_ctl_pcm_info -#define snd_ctl_open psnd_ctl_open -#define snd_ctl_close psnd_ctl_close -#define snd_ctl_card_info_malloc psnd_ctl_card_info_malloc -#define snd_ctl_card_info_free psnd_ctl_card_info_free -#define snd_ctl_card_info psnd_ctl_card_info -#define snd_ctl_card_info_get_name psnd_ctl_card_info_get_name -#define snd_ctl_card_info_get_id psnd_ctl_card_info_get_id -#define snd_card_next psnd_card_next -#endif - - -static ALCboolean alsa_load(void) -{ - if(!alsa_handle) - { -#ifdef HAVE_DYNLOAD - alsa_handle = LoadLib("libasound.so.2"); - if(!alsa_handle) - return ALC_FALSE; - -#define LOAD_FUNC(f) do { \ - p##f = GetSymbol(alsa_handle, #f); \ - if(p##f == NULL) { \ - CloseLib(alsa_handle); \ - alsa_handle = NULL; \ - return ALC_FALSE; \ - } \ -} while(0) - LOAD_FUNC(snd_strerror); - LOAD_FUNC(snd_pcm_open); - LOAD_FUNC(snd_pcm_close); - LOAD_FUNC(snd_pcm_nonblock); - LOAD_FUNC(snd_pcm_frames_to_bytes); - LOAD_FUNC(snd_pcm_bytes_to_frames); - LOAD_FUNC(snd_pcm_hw_params_malloc); - LOAD_FUNC(snd_pcm_hw_params_free); - LOAD_FUNC(snd_pcm_hw_params_any); - LOAD_FUNC(snd_pcm_hw_params_set_access); - LOAD_FUNC(snd_pcm_hw_params_set_format); - LOAD_FUNC(snd_pcm_hw_params_set_channels); - LOAD_FUNC(snd_pcm_hw_params_set_periods_near); - LOAD_FUNC(snd_pcm_hw_params_set_rate_near); - LOAD_FUNC(snd_pcm_hw_params_set_rate); - LOAD_FUNC(snd_pcm_hw_params_set_rate_resample); - LOAD_FUNC(snd_pcm_hw_params_set_buffer_time_near); - LOAD_FUNC(snd_pcm_hw_params_set_period_time_near); - LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_near); - LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_min); - LOAD_FUNC(snd_pcm_hw_params_set_period_size_near); - LOAD_FUNC(snd_pcm_hw_params_get_buffer_size); - LOAD_FUNC(snd_pcm_hw_params_get_period_size); - LOAD_FUNC(snd_pcm_hw_params_get_access); - LOAD_FUNC(snd_pcm_hw_params_get_periods); - LOAD_FUNC(snd_pcm_hw_params); - LOAD_FUNC(snd_pcm_sw_params_malloc); - LOAD_FUNC(snd_pcm_sw_params_current); - LOAD_FUNC(snd_pcm_sw_params_set_avail_min); - LOAD_FUNC(snd_pcm_sw_params); - LOAD_FUNC(snd_pcm_sw_params_free); - LOAD_FUNC(snd_pcm_prepare); - LOAD_FUNC(snd_pcm_start); - LOAD_FUNC(snd_pcm_resume); - LOAD_FUNC(snd_pcm_wait); - LOAD_FUNC(snd_pcm_state); - LOAD_FUNC(snd_pcm_avail_update); - LOAD_FUNC(snd_pcm_areas_silence); - LOAD_FUNC(snd_pcm_mmap_begin); - LOAD_FUNC(snd_pcm_mmap_commit); - LOAD_FUNC(snd_pcm_readi); - LOAD_FUNC(snd_pcm_writei); - LOAD_FUNC(snd_pcm_drain); - LOAD_FUNC(snd_pcm_recover); - LOAD_FUNC(snd_pcm_info_malloc); - LOAD_FUNC(snd_pcm_info_free); - LOAD_FUNC(snd_pcm_info_set_device); - LOAD_FUNC(snd_pcm_info_set_subdevice); - LOAD_FUNC(snd_pcm_info_set_stream); - LOAD_FUNC(snd_pcm_info_get_name); - LOAD_FUNC(snd_ctl_pcm_next_device); - LOAD_FUNC(snd_ctl_pcm_info); - LOAD_FUNC(snd_ctl_open); - LOAD_FUNC(snd_ctl_close); - LOAD_FUNC(snd_ctl_card_info_malloc); - LOAD_FUNC(snd_ctl_card_info_free); - LOAD_FUNC(snd_ctl_card_info); - LOAD_FUNC(snd_ctl_card_info_get_name); - LOAD_FUNC(snd_ctl_card_info_get_id); - LOAD_FUNC(snd_card_next); -#undef LOAD_FUNC -#else - alsa_handle = (void*)0xDEADBEEF; -#endif - } - return ALC_TRUE; -} - - -typedef struct { - snd_pcm_t *pcmHandle; - - ALvoid *buffer; - ALsizei size; - - ALboolean doCapture; - RingBuffer *ring; - - volatile int killNow; - ALvoid *thread; -} alsa_data; - -typedef struct { - ALCchar *name; - char *card; - int dev; -} DevMap; - -static DevMap *allDevNameMap; -static ALuint numDevNames; -static DevMap *allCaptureDevNameMap; -static ALuint numCaptureDevNames; - -static const char *device_prefix; -static const char *capture_prefix; - - -static DevMap *probe_devices(snd_pcm_stream_t stream, ALuint *count) -{ - snd_ctl_t *handle; - int card, err, dev, idx; - snd_ctl_card_info_t *info; - snd_pcm_info_t *pcminfo; - DevMap *DevList; - char name[1024]; - - snd_ctl_card_info_malloc(&info); - snd_pcm_info_malloc(&pcminfo); - - card = -1; - if((err=snd_card_next(&card)) < 0) - ERR("Failed to find a card: %s\n", snd_strerror(err)); - - DevList = malloc(sizeof(DevMap) * 1); - DevList[0].name = strdup("ALSA Default"); - DevList[0].card = NULL; - DevList[0].dev = 0; - idx = 1; - while(card >= 0) - { - sprintf(name, "hw:%d", card); - if((err = snd_ctl_open(&handle, name, 0)) < 0) - { - ERR("control open (%i): %s\n", card, snd_strerror(err)); - goto next_card; - } - if((err = snd_ctl_card_info(handle, info)) < 0) - { - ERR("control hardware info (%i): %s\n", card, snd_strerror(err)); - snd_ctl_close(handle); - goto next_card; - } - - dev = -1; - while(1) - { - const char *cname, *dname, *cid; - void *temp; - - if(snd_ctl_pcm_next_device(handle, &dev) < 0) - ERR("snd_ctl_pcm_next_device failed\n"); - if(dev < 0) - break; - - snd_pcm_info_set_device(pcminfo, dev); - snd_pcm_info_set_subdevice(pcminfo, 0); - snd_pcm_info_set_stream(pcminfo, stream); - if((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) { - if(err != -ENOENT) - ERR("control digital audio info (%i): %s\n", card, snd_strerror(err)); - continue; - } - - temp = realloc(DevList, sizeof(DevMap) * (idx+1)); - if(temp) - { - DevList = temp; - cname = snd_ctl_card_info_get_name(info); - dname = snd_pcm_info_get_name(pcminfo); - cid = snd_ctl_card_info_get_id(info); - snprintf(name, sizeof(name), "%s, %s (CARD=%s,DEV=%d)", - cname, dname, cid, dev); - DevList[idx].name = strdup(name); - DevList[idx].card = strdup(cid); - DevList[idx].dev = dev; - idx++; - } - } - snd_ctl_close(handle); - next_card: - if(snd_card_next(&card) < 0) { - ERR("snd_card_next failed\n"); - break; - } - } - - snd_pcm_info_free(pcminfo); - snd_ctl_card_info_free(info); - - *count = idx; - return DevList; -} - - -static int xrun_recovery(snd_pcm_t *handle, int err) -{ - err = snd_pcm_recover(handle, err, 1); - if(err < 0) - ERR("recover failed: %s\n", snd_strerror(err)); - return err; -} - -static int verify_state(snd_pcm_t *handle) -{ - snd_pcm_state_t state = snd_pcm_state(handle); - if(state == SND_PCM_STATE_DISCONNECTED) - return -ENODEV; - if(state == SND_PCM_STATE_XRUN) - { - int err = xrun_recovery(handle, -EPIPE); - if(err < 0) return err; - } - else if(state == SND_PCM_STATE_SUSPENDED) - { - int err = xrun_recovery(handle, -ESTRPIPE); - if(err < 0) return err; - } - - return state; -} - - -static ALuint ALSAProc(ALvoid *ptr) -{ - ALCdevice *pDevice = (ALCdevice*)ptr; - alsa_data *data = (alsa_data*)pDevice->ExtraData; - const snd_pcm_channel_area_t *areas = NULL; - snd_pcm_sframes_t avail, commitres; - snd_pcm_uframes_t offset, frames; - char *WritePtr; - int err; - - SetRTPriority(); - - while(!data->killNow) - { - int state = verify_state(data->pcmHandle); - if(state < 0) - { - ERR("Invalid state detected: %s\n", snd_strerror(state)); - aluHandleDisconnect(pDevice); - break; - } - - avail = snd_pcm_avail_update(data->pcmHandle); - if(avail < 0) - { - ERR("available update failed: %s\n", snd_strerror(avail)); - continue; - } - - // make sure there's frames to process - if((snd_pcm_uframes_t)avail < pDevice->UpdateSize) - { - if(state != SND_PCM_STATE_RUNNING) - { - err = snd_pcm_start(data->pcmHandle); - if(err < 0) - { - ERR("start failed: %s\n", snd_strerror(err)); - continue; - } - } - if(snd_pcm_wait(data->pcmHandle, 1000) == 0) - ERR("Wait timeout... buffer size too low?\n"); - continue; - } - avail -= avail%pDevice->UpdateSize; - - // it is possible that contiguous areas are smaller, thus we use a loop - while(avail > 0) - { - frames = avail; - - err = snd_pcm_mmap_begin(data->pcmHandle, &areas, &offset, &frames); - if(err < 0) - { - ERR("mmap begin error: %s\n", snd_strerror(err)); - break; - } - - WritePtr = (char*)areas->addr + (offset * areas->step / 8); - aluMixData(pDevice, WritePtr, frames); - - commitres = snd_pcm_mmap_commit(data->pcmHandle, offset, frames); - if(commitres < 0 || (commitres-frames) != 0) - { - ERR("mmap commit error: %s\n", - snd_strerror(commitres >= 0 ? -EPIPE : commitres)); - break; - } - - avail -= frames; - } - } - - return 0; -} - -static ALuint ALSANoMMapProc(ALvoid *ptr) -{ - ALCdevice *pDevice = (ALCdevice*)ptr; - alsa_data *data = (alsa_data*)pDevice->ExtraData; - snd_pcm_sframes_t avail; - char *WritePtr; - - SetRTPriority(); - - while(!data->killNow) - { - int state = verify_state(data->pcmHandle); - if(state < 0) - { - ERR("Invalid state detected: %s\n", snd_strerror(state)); - aluHandleDisconnect(pDevice); - break; - } - - WritePtr = data->buffer; - avail = data->size / snd_pcm_frames_to_bytes(data->pcmHandle, 1); - aluMixData(pDevice, WritePtr, avail); - - while(avail > 0) - { - int ret = snd_pcm_writei(data->pcmHandle, WritePtr, avail); - switch (ret) - { - case -EAGAIN: - continue; - case -ESTRPIPE: - case -EPIPE: - case -EINTR: - ret = snd_pcm_recover(data->pcmHandle, ret, 1); - if(ret < 0) - avail = 0; - break; - default: - if (ret >= 0) - { - WritePtr += snd_pcm_frames_to_bytes(data->pcmHandle, ret); - avail -= ret; - } - break; - } - if (ret < 0) - { - ret = snd_pcm_prepare(data->pcmHandle); - if(ret < 0) - break; - } - } - } - - return 0; -} - -static ALCboolean alsa_open_playback(ALCdevice *device, const ALCchar *deviceName) -{ - alsa_data *data; - char driver[128]; - int i; - - strncpy(driver, GetConfigValue("alsa", "device", "default"), sizeof(driver)-1); - driver[sizeof(driver)-1] = 0; - - if(!deviceName) - deviceName = alsaDevice; - else if(strcmp(deviceName, alsaDevice) != 0) - { - size_t idx; - - if(!allDevNameMap) - allDevNameMap = probe_devices(SND_PCM_STREAM_PLAYBACK, &numDevNames); - - for(idx = 0;idx < numDevNames;idx++) - { - if(allDevNameMap[idx].name && - strcmp(deviceName, allDevNameMap[idx].name) == 0) - { - if(idx > 0) - snprintf(driver, sizeof(driver), "%sCARD=%s,DEV=%d", device_prefix, - allDevNameMap[idx].card, allDevNameMap[idx].dev); - break; - } - } - if(idx == numDevNames) - return ALC_FALSE; - } - - data = (alsa_data*)calloc(1, sizeof(alsa_data)); - - i = snd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); - if(i >= 0) - { - i = snd_pcm_nonblock(data->pcmHandle, 0); - if(i < 0) - snd_pcm_close(data->pcmHandle); - } - if(i < 0) - { - free(data); - ERR("Could not open playback device '%s': %s\n", driver, snd_strerror(i)); - return ALC_FALSE; - } - - device->szDeviceName = strdup(deviceName); - device->ExtraData = data; - return ALC_TRUE; -} - -static void alsa_close_playback(ALCdevice *device) -{ - alsa_data *data = (alsa_data*)device->ExtraData; - - snd_pcm_close(data->pcmHandle); - free(data); - device->ExtraData = NULL; -} - -static ALCboolean alsa_reset_playback(ALCdevice *device) -{ - alsa_data *data = (alsa_data*)device->ExtraData; - snd_pcm_uframes_t periodSizeInFrames; - unsigned int periodLen, bufferLen; - snd_pcm_sw_params_t *sp = NULL; - snd_pcm_hw_params_t *p = NULL; - snd_pcm_access_t access; - snd_pcm_format_t format; - unsigned int periods; - unsigned int rate; - int allowmmap; - char *err; - int i; - - - format = -1; - switch(device->FmtType) - { - case DevFmtByte: - format = SND_PCM_FORMAT_S8; - break; - case DevFmtUByte: - format = SND_PCM_FORMAT_U8; - break; - case DevFmtShort: - format = SND_PCM_FORMAT_S16; - break; - case DevFmtUShort: - format = SND_PCM_FORMAT_U16; - break; - case DevFmtFloat: - format = SND_PCM_FORMAT_FLOAT; - break; - } - - allowmmap = GetConfigValueBool("alsa", "mmap", 1); - periods = device->NumUpdates; - periodLen = (ALuint64)device->UpdateSize * 1000000 / device->Frequency; - bufferLen = periodLen * periods; - rate = device->Frequency; - - err = NULL; - snd_pcm_hw_params_malloc(&p); - - if((i=snd_pcm_hw_params_any(data->pcmHandle, p)) < 0) - err = "any"; - /* set interleaved access */ - if(i >= 0 && (!allowmmap || (i=snd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0)) - { - if(periods > 2) - { - periods--; - bufferLen = periodLen * periods; - } - if((i=snd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) - err = "set access"; - } - /* set format (implicitly sets sample bits) */ - if(i >= 0 && (i=snd_pcm_hw_params_set_format(data->pcmHandle, p, format)) < 0) - { - device->FmtType = DevFmtFloat; - if(format == SND_PCM_FORMAT_FLOAT || - (i=snd_pcm_hw_params_set_format(data->pcmHandle, p, SND_PCM_FORMAT_FLOAT)) < 0) - { - device->FmtType = DevFmtShort; - if(format == SND_PCM_FORMAT_S16 || - (i=snd_pcm_hw_params_set_format(data->pcmHandle, p, SND_PCM_FORMAT_S16)) < 0) - { - device->FmtType = DevFmtUByte; - if(format == SND_PCM_FORMAT_U8 || - (i=snd_pcm_hw_params_set_format(data->pcmHandle, p, SND_PCM_FORMAT_U8)) < 0) - err = "set format"; - } - } - } - /* set channels (implicitly sets frame bits) */ - if(i >= 0 && (i=snd_pcm_hw_params_set_channels(data->pcmHandle, p, ChannelsFromDevFmt(device->FmtChans))) < 0) - { - if((i=snd_pcm_hw_params_set_channels(data->pcmHandle, p, 2)) < 0) - { - if((i=snd_pcm_hw_params_set_channels(data->pcmHandle, p, 1)) < 0) - err = "set channels"; - else - { - if((device->Flags&DEVICE_CHANNELS_REQUEST)) - ERR("Failed to set %s, got Mono instead\n", DevFmtChannelsString(device->FmtChans)); - device->FmtChans = DevFmtMono; - } - } - else - { - if((device->Flags&DEVICE_CHANNELS_REQUEST)) - ERR("Failed to set %s, got Stereo instead\n", DevFmtChannelsString(device->FmtChans)); - device->FmtChans = DevFmtStereo; - } - device->Flags &= ~DEVICE_CHANNELS_REQUEST; - } - if(i >= 0 && (i=snd_pcm_hw_params_set_rate_resample(data->pcmHandle, p, 0)) < 0) - { - ERR("Failed to disable ALSA resampler\n"); - i = 0; - } - /* set rate (implicitly constrains period/buffer parameters) */ - if(i >= 0 && (i=snd_pcm_hw_params_set_rate_near(data->pcmHandle, p, &rate, NULL)) < 0) - err = "set rate near"; - /* set buffer time (implicitly constrains period/buffer parameters) */ - if(i >= 0 && (i=snd_pcm_hw_params_set_buffer_time_near(data->pcmHandle, p, &bufferLen, NULL)) < 0) - err = "set buffer time near"; - /* set period time in frame units (implicitly sets buffer size/bytes/time and period size/bytes) */ - if(i >= 0 && (i=snd_pcm_hw_params_set_period_time_near(data->pcmHandle, p, &periodLen, NULL)) < 0) - err = "set period time near"; - /* install and prepare hardware configuration */ - if(i >= 0 && (i=snd_pcm_hw_params(data->pcmHandle, p)) < 0) - err = "set params"; - if(i >= 0 && (i=snd_pcm_hw_params_get_access(p, &access)) < 0) - err = "get access"; - if(i >= 0 && (i=snd_pcm_hw_params_get_period_size(p, &periodSizeInFrames, NULL)) < 0) - err = "get period size"; - if(i >= 0 && (i=snd_pcm_hw_params_get_periods(p, &periods, NULL)) < 0) - err = "get periods"; - if(i < 0) - { - ERR("%s failed: %s\n", err, snd_strerror(i)); - snd_pcm_hw_params_free(p); - return ALC_FALSE; - } - - snd_pcm_hw_params_free(p); - - err = NULL; - snd_pcm_sw_params_malloc(&sp); - - if((i=snd_pcm_sw_params_current(data->pcmHandle, sp)) != 0) - err = "sw current"; - if(i == 0 && (i=snd_pcm_sw_params_set_avail_min(data->pcmHandle, sp, periodSizeInFrames)) != 0) - err = "sw set avail min"; - if(i == 0 && (i=snd_pcm_sw_params(data->pcmHandle, sp)) != 0) - err = "sw set params"; - if(i != 0) - { - ERR("%s failed: %s\n", err, snd_strerror(i)); - snd_pcm_sw_params_free(sp); - return ALC_FALSE; - } - - snd_pcm_sw_params_free(sp); - - if(device->Frequency != rate) - { - if((device->Flags&DEVICE_FREQUENCY_REQUEST)) - ERR("Failed to set %dhz, got %dhz instead\n", device->Frequency, rate); - device->Flags &= ~DEVICE_FREQUENCY_REQUEST; - device->Frequency = rate; - } - - SetDefaultChannelOrder(device); - - data->size = snd_pcm_frames_to_bytes(data->pcmHandle, periodSizeInFrames); - if(access == SND_PCM_ACCESS_RW_INTERLEAVED) - { - /* Increase periods by one, since the temp buffer counts as an extra - * period */ - periods++; - data->buffer = malloc(data->size); - if(!data->buffer) - { - ERR("buffer malloc failed\n"); - return ALC_FALSE; - } - device->UpdateSize = periodSizeInFrames; - device->NumUpdates = periods; - data->thread = StartThread(ALSANoMMapProc, device); - } - else - { - i = snd_pcm_prepare(data->pcmHandle); - if(i < 0) - { - ERR("prepare error: %s\n", snd_strerror(i)); - return ALC_FALSE; - } - device->UpdateSize = periodSizeInFrames; - device->NumUpdates = periods; - data->thread = StartThread(ALSAProc, device); - } - if(data->thread == NULL) - { - ERR("Could not create playback thread\n"); - free(data->buffer); - data->buffer = NULL; - return ALC_FALSE; - } - - return ALC_TRUE; -} - -static void alsa_stop_playback(ALCdevice *device) -{ - alsa_data *data = (alsa_data*)device->ExtraData; - - if(data->thread) - { - data->killNow = 1; - StopThread(data->thread); - data->thread = NULL; - } - data->killNow = 0; - free(data->buffer); - data->buffer = NULL; -} - - -static ALCboolean alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceName) -{ - snd_pcm_hw_params_t *p; - snd_pcm_uframes_t bufferSizeInFrames; - snd_pcm_format_t format; - ALuint frameSize; - alsa_data *data; - char driver[128]; - char *err; - int i; - - strncpy(driver, GetConfigValue("alsa", "capture", "default"), sizeof(driver)-1); - driver[sizeof(driver)-1] = 0; - - if(!allCaptureDevNameMap) - allCaptureDevNameMap = probe_devices(SND_PCM_STREAM_CAPTURE, &numCaptureDevNames); - - if(!deviceName) - deviceName = allCaptureDevNameMap[0].name; - else - { - size_t idx; - - for(idx = 0;idx < numCaptureDevNames;idx++) - { - if(allCaptureDevNameMap[idx].name && - strcmp(deviceName, allCaptureDevNameMap[idx].name) == 0) - { - if(idx > 0) - snprintf(driver, sizeof(driver), "%sCARD=%s,DEV=%d", capture_prefix, - allCaptureDevNameMap[idx].card, allCaptureDevNameMap[idx].dev); - break; - } - } - if(idx == numCaptureDevNames) - return ALC_FALSE; - } - - data = (alsa_data*)calloc(1, sizeof(alsa_data)); - - i = snd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK); - if(i < 0) - { - ERR("Could not open capture device '%s': %s\n", driver, snd_strerror(i)); - free(data); - return ALC_FALSE; - } - - format = -1; - switch(pDevice->FmtType) - { - case DevFmtByte: - format = SND_PCM_FORMAT_S8; - break; - case DevFmtUByte: - format = SND_PCM_FORMAT_U8; - break; - case DevFmtShort: - format = SND_PCM_FORMAT_S16; - break; - case DevFmtUShort: - format = SND_PCM_FORMAT_U16; - break; - case DevFmtFloat: - format = SND_PCM_FORMAT_FLOAT; - break; - } - - err = NULL; - bufferSizeInFrames = pDevice->UpdateSize * pDevice->NumUpdates; - snd_pcm_hw_params_malloc(&p); - - if((i=snd_pcm_hw_params_any(data->pcmHandle, p)) < 0) - err = "any"; - /* set interleaved access */ - if(i >= 0 && (i=snd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) - err = "set access"; - /* set format (implicitly sets sample bits) */ - if(i >= 0 && (i=snd_pcm_hw_params_set_format(data->pcmHandle, p, format)) < 0) - err = "set format"; - /* set channels (implicitly sets frame bits) */ - if(i >= 0 && (i=snd_pcm_hw_params_set_channels(data->pcmHandle, p, ChannelsFromDevFmt(pDevice->FmtChans))) < 0) - err = "set channels"; - /* set rate (implicitly constrains period/buffer parameters) */ - if(i >= 0 && (i=snd_pcm_hw_params_set_rate(data->pcmHandle, p, pDevice->Frequency, 0)) < 0) - err = "set rate near"; - /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */ - if(i >= 0 && (i=snd_pcm_hw_params_set_buffer_size_near(data->pcmHandle, p, &bufferSizeInFrames)) < 0) - err = "set buffer size near"; - /* install and prepare hardware configuration */ - if(i >= 0 && (i=snd_pcm_hw_params(data->pcmHandle, p)) < 0) - err = "set params"; - if(i < 0) - { - ERR("%s failed: %s\n", err, snd_strerror(i)); - snd_pcm_hw_params_free(p); - goto error; - } - - if((i=snd_pcm_hw_params_get_period_size(p, &bufferSizeInFrames, NULL)) < 0) - { - ERR("get size failed: %s\n", snd_strerror(i)); - snd_pcm_hw_params_free(p); - goto error; - } - - snd_pcm_hw_params_free(p); - - frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); - - data->ring = CreateRingBuffer(frameSize, pDevice->UpdateSize*pDevice->NumUpdates); - if(!data->ring) - { - ERR("ring buffer create failed\n"); - goto error; - } - - data->size = snd_pcm_frames_to_bytes(data->pcmHandle, bufferSizeInFrames); - data->buffer = malloc(data->size); - if(!data->buffer) - { - ERR("buffer malloc failed\n"); - goto error; - } - - pDevice->szDeviceName = strdup(deviceName); - - pDevice->ExtraData = data; - return ALC_TRUE; - -error: - free(data->buffer); - DestroyRingBuffer(data->ring); - snd_pcm_close(data->pcmHandle); - free(data); - - pDevice->ExtraData = NULL; - return ALC_FALSE; -} - -static void alsa_close_capture(ALCdevice *pDevice) -{ - alsa_data *data = (alsa_data*)pDevice->ExtraData; - - snd_pcm_close(data->pcmHandle); - DestroyRingBuffer(data->ring); - - free(data->buffer); - free(data); - pDevice->ExtraData = NULL; -} - -static void alsa_start_capture(ALCdevice *Device) -{ - alsa_data *data = (alsa_data*)Device->ExtraData; - int err; - - err = snd_pcm_start(data->pcmHandle); - if(err < 0) - { - ERR("start failed: %s\n", snd_strerror(err)); - aluHandleDisconnect(Device); - } - else - data->doCapture = AL_TRUE; -} - -static void alsa_stop_capture(ALCdevice *Device) -{ - alsa_data *data = (alsa_data*)Device->ExtraData; - snd_pcm_drain(data->pcmHandle); - data->doCapture = AL_FALSE; -} - -static ALCuint alsa_available_samples(ALCdevice *Device) -{ - alsa_data *data = (alsa_data*)Device->ExtraData; - snd_pcm_sframes_t avail; - - avail = (Device->Connected ? snd_pcm_avail_update(data->pcmHandle) : 0); - if(avail < 0) - { - ERR("avail update failed: %s\n", snd_strerror(avail)); - - if((avail=snd_pcm_recover(data->pcmHandle, avail, 1)) >= 0) - { - if(data->doCapture) - avail = snd_pcm_start(data->pcmHandle); - if(avail >= 0) - avail = snd_pcm_avail_update(data->pcmHandle); - } - if(avail < 0) - { - ERR("restore error: %s\n", snd_strerror(avail)); - aluHandleDisconnect(Device); - } - } - while(avail > 0) - { - snd_pcm_sframes_t amt; - - amt = snd_pcm_bytes_to_frames(data->pcmHandle, data->size); - if(avail < amt) amt = avail; - - amt = snd_pcm_readi(data->pcmHandle, data->buffer, amt); - if(amt < 0) - { - ERR("read error: %s\n", snd_strerror(amt)); - - if(amt == -EAGAIN) - continue; - if((amt=snd_pcm_recover(data->pcmHandle, amt, 1)) >= 0) - { - if(data->doCapture) - amt = snd_pcm_start(data->pcmHandle); - if(amt >= 0) - amt = snd_pcm_avail_update(data->pcmHandle); - } - if(amt < 0) - { - ERR("restore error: %s\n", snd_strerror(amt)); - aluHandleDisconnect(Device); - break; - } - avail = amt; - continue; - } - - WriteRingBuffer(data->ring, data->buffer, amt); - avail -= amt; - } - - return RingBufferSize(data->ring); -} - -static void alsa_capture_samples(ALCdevice *Device, ALCvoid *Buffer, ALCuint Samples) -{ - alsa_data *data = (alsa_data*)Device->ExtraData; - - if(Samples <= alsa_available_samples(Device)) - ReadRingBuffer(data->ring, Buffer, Samples); - else - alcSetError(Device, ALC_INVALID_VALUE); -} - - -static const BackendFuncs alsa_funcs = { - alsa_open_playback, - alsa_close_playback, - alsa_reset_playback, - alsa_stop_playback, - alsa_open_capture, - alsa_close_capture, - alsa_start_capture, - alsa_stop_capture, - alsa_capture_samples, - alsa_available_samples -}; - -ALCboolean alc_alsa_init(BackendFuncs *func_list) -{ - if(!alsa_load()) - return ALC_FALSE; - device_prefix = GetConfigValue("alsa", "device-prefix", "plughw:"); - capture_prefix = GetConfigValue("alsa", "capture-prefix", "plughw:"); - *func_list = alsa_funcs; - return ALC_TRUE; -} - -void alc_alsa_deinit(void) -{ - ALuint i; - - for(i = 0;i < numDevNames;++i) - { - free(allDevNameMap[i].name); - free(allDevNameMap[i].card); - } - free(allDevNameMap); - allDevNameMap = NULL; - numDevNames = 0; - - for(i = 0;i < numCaptureDevNames;++i) - { - free(allCaptureDevNameMap[i].name); - free(allCaptureDevNameMap[i].card); - } - free(allCaptureDevNameMap); - allCaptureDevNameMap = NULL; - numCaptureDevNames = 0; - -#ifdef HAVE_DYNLOAD - if(alsa_handle) - CloseLib(alsa_handle); - alsa_handle = NULL; -#endif -} - -void alc_alsa_probe(enum DevProbe type) -{ - ALuint i; - - switch(type) - { - case DEVICE_PROBE: - AppendDeviceList(alsaDevice); - break; - - case ALL_DEVICE_PROBE: - for(i = 0;i < numDevNames;++i) - { - free(allDevNameMap[i].name); - free(allDevNameMap[i].card); - } - - free(allDevNameMap); - allDevNameMap = probe_devices(SND_PCM_STREAM_PLAYBACK, &numDevNames); - - for(i = 0;i < numDevNames;++i) - AppendAllDeviceList(allDevNameMap[i].name); - break; - - case CAPTURE_DEVICE_PROBE: - for(i = 0;i < numCaptureDevNames;++i) - { - free(allCaptureDevNameMap[i].name); - free(allCaptureDevNameMap[i].card); - } - - free(allCaptureDevNameMap); - allCaptureDevNameMap = probe_devices(SND_PCM_STREAM_CAPTURE, &numCaptureDevNames); - - for(i = 0;i < numCaptureDevNames;++i) - AppendCaptureDeviceList(allCaptureDevNameMap[i].name); - break; - } -} diff -r c41d773a85fb -r 82b9267a3e19 Alc/backends/coreaudio.c --- a/Alc/backends/coreaudio.c Tue Oct 25 13:03:35 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,719 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2007 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#include "config.h" - -#include -#include -#include - -#include "alMain.h" -#include "AL/al.h" -#include "AL/alc.h" - -#include -#include -#include -#include - - -typedef struct { - AudioUnit audioUnit; - - ALuint frameSize; - ALdouble sampleRateRatio; // Ratio of hardware sample rate / requested sample rate - AudioStreamBasicDescription format; // This is the OpenAL format as a CoreAudio ASBD - - AudioConverterRef audioConverter; // Sample rate converter if needed - AudioBufferList *bufferList; // Buffer for data coming from the input device - ALCvoid *resampleBuffer; // Buffer for returned RingBuffer data when resampling - - RingBuffer *ring; -} ca_data; - -static const ALCchar ca_device[] = "CoreAudio Default"; - - -static void destroy_buffer_list(AudioBufferList* list) -{ - if(list) - { - UInt32 i; - for(i = 0;i < list->mNumberBuffers;i++) - free(list->mBuffers[i].mData); - free(list); - } -} - -static AudioBufferList* allocate_buffer_list(UInt32 channelCount, UInt32 byteSize) -{ - AudioBufferList *list; - - list = calloc(1, sizeof(AudioBufferList) + sizeof(AudioBuffer)); - if(list) - { - list->mNumberBuffers = 1; - - list->mBuffers[0].mNumberChannels = channelCount; - list->mBuffers[0].mDataByteSize = byteSize; - list->mBuffers[0].mData = malloc(byteSize); - if(list->mBuffers[0].mData == NULL) - { - free(list); - list = NULL; - } - } - return list; -} - -static OSStatus ca_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, - UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) -{ - ALCdevice *device = (ALCdevice*)inRefCon; - ca_data *data = (ca_data*)device->ExtraData; - - aluMixData(device, ioData->mBuffers[0].mData, - ioData->mBuffers[0].mDataByteSize / data->frameSize); - - return noErr; -} - -static OSStatus ca_capture_conversion_callback(AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets, - AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, void* inUserData) -{ - ALCdevice *device = (ALCdevice*)inUserData; - ca_data *data = (ca_data*)device->ExtraData; - - // Read from the ring buffer and store temporarily in a large buffer - ReadRingBuffer(data->ring, data->resampleBuffer, (ALsizei)(*ioNumberDataPackets)); - - // Set the input data - ioData->mNumberBuffers = 1; - ioData->mBuffers[0].mNumberChannels = data->format.mChannelsPerFrame; - ioData->mBuffers[0].mData = data->resampleBuffer; - ioData->mBuffers[0].mDataByteSize = (*ioNumberDataPackets) * data->format.mBytesPerFrame; - - return noErr; -} - -static OSStatus ca_capture_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, - UInt32 inNumberFrames, AudioBufferList *ioData) -{ - ALCdevice *device = (ALCdevice*)inRefCon; - ca_data *data = (ca_data*)device->ExtraData; - AudioUnitRenderActionFlags flags = 0; - OSStatus err; - - // fill the bufferList with data from the input device - err = AudioUnitRender(data->audioUnit, &flags, inTimeStamp, 1, inNumberFrames, data->bufferList); - if(err != noErr) - { - ERR("AudioUnitRender error: %d\n", err); - return err; - } - - WriteRingBuffer(data->ring, data->bufferList->mBuffers[0].mData, inNumberFrames); - - return noErr; -} - -static ALCboolean ca_open_playback(ALCdevice *device, const ALCchar *deviceName) -{ - ComponentDescription desc; - Component comp; - ca_data *data; - OSStatus err; - - if(!deviceName) - deviceName = ca_device; - else if(strcmp(deviceName, ca_device) != 0) - return ALC_FALSE; - - /* open the default output unit */ - desc.componentType = kAudioUnitType_Output; - desc.componentSubType = kAudioUnitSubType_DefaultOutput; - desc.componentManufacturer = kAudioUnitManufacturer_Apple; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; - - comp = FindNextComponent(NULL, &desc); - if(comp == NULL) - { - ERR("FindNextComponent failed\n"); - return ALC_FALSE; - } - - data = calloc(1, sizeof(*data)); - device->ExtraData = data; - - err = OpenAComponent(comp, &data->audioUnit); - if(err != noErr) - { - ERR("OpenAComponent failed\n"); - free(data); - device->ExtraData = NULL; - return ALC_FALSE; - } - - return ALC_TRUE; -} - -static void ca_close_playback(ALCdevice *device) -{ - ca_data *data = (ca_data*)device->ExtraData; - - CloseComponent(data->audioUnit); - - free(data); - device->ExtraData = NULL; -} - -static ALCboolean ca_reset_playback(ALCdevice *device) -{ - ca_data *data = (ca_data*)device->ExtraData; - AudioStreamBasicDescription streamFormat; - AURenderCallbackStruct input; - OSStatus err; - UInt32 size; - - /* init and start the default audio unit... */ - err = AudioUnitInitialize(data->audioUnit); - if(err != noErr) - { - ERR("AudioUnitInitialize failed\n"); - return ALC_FALSE; - } - - err = AudioOutputUnitStart(data->audioUnit); - if(err != noErr) - { - ERR("AudioOutputUnitStart failed\n"); - return ALC_FALSE; - } - - /* retrieve default output unit's properties (output side) */ - size = sizeof(AudioStreamBasicDescription); - err = AudioUnitGetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &streamFormat, &size); - if(err != noErr || size != sizeof(AudioStreamBasicDescription)) - { - ERR("AudioUnitGetProperty failed\n"); - return ALC_FALSE; - } - -#if 0 - TRACE("Output streamFormat of default output unit -\n"); - TRACE(" streamFormat.mFramesPerPacket = %d\n", streamFormat.mFramesPerPacket); - TRACE(" streamFormat.mChannelsPerFrame = %d\n", streamFormat.mChannelsPerFrame); - TRACE(" streamFormat.mBitsPerChannel = %d\n", streamFormat.mBitsPerChannel); - TRACE(" streamFormat.mBytesPerPacket = %d\n", streamFormat.mBytesPerPacket); - TRACE(" streamFormat.mBytesPerFrame = %d\n", streamFormat.mBytesPerFrame); - TRACE(" streamFormat.mSampleRate = %5.0f\n", streamFormat.mSampleRate); -#endif - - /* set default output unit's input side to match output side */ - err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, size); - if(err != noErr) - { - ERR("AudioUnitSetProperty failed\n"); - return ALC_FALSE; - } - - if(device->Frequency != streamFormat.mSampleRate) - { - if((device->Flags&DEVICE_FREQUENCY_REQUEST)) - ERR("CoreAudio does not support changing sample rates (wanted %dhz, got %dhz)\n", device->Frequency, streamFormat.mSampleRate); - device->Flags &= ~DEVICE_FREQUENCY_REQUEST; - - device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize * - streamFormat.mSampleRate / - device->Frequency); - device->Frequency = streamFormat.mSampleRate; - } - - /* FIXME: How to tell what channels are what in the output device, and how - * to specify what we're giving? eg, 6.0 vs 5.1 */ - switch(streamFormat.mChannelsPerFrame) - { - case 1: - if((device->Flags&DEVICE_CHANNELS_REQUEST) && - device->FmtChans != DevFmtMono) - { - ERR("Failed to set %s, got Mono instead\n", DevFmtChannelsString(device->FmtChans)); - device->Flags &= ~DEVICE_CHANNELS_REQUEST; - } - device->FmtChans = DevFmtMono; - break; - case 2: - if((device->Flags&DEVICE_CHANNELS_REQUEST) && - device->FmtChans != DevFmtStereo) - { - ERR("Failed to set %s, got Stereo instead\n", DevFmtChannelsString(device->FmtChans)); - device->Flags &= ~DEVICE_CHANNELS_REQUEST; - } - device->FmtChans = DevFmtStereo; - break; - case 4: - if((device->Flags&DEVICE_CHANNELS_REQUEST) && - device->FmtChans != DevFmtQuad) - { - ERR("Failed to set %s, got Quad instead\n", DevFmtChannelsString(device->FmtChans)); - device->Flags &= ~DEVICE_CHANNELS_REQUEST; - } - device->FmtChans = DevFmtQuad; - break; - case 6: - if((device->Flags&DEVICE_CHANNELS_REQUEST) && - device->FmtChans != DevFmtX51) - { - ERR("Failed to set %s, got 5.1 Surround instead\n", DevFmtChannelsString(device->FmtChans)); - device->Flags &= ~DEVICE_CHANNELS_REQUEST; - } - device->FmtChans = DevFmtX51; - break; - case 7: - if((device->Flags&DEVICE_CHANNELS_REQUEST) && - device->FmtChans != DevFmtX61) - { - ERR("Failed to set %s, got 6.1 Surround instead\n", DevFmtChannelsString(device->FmtChans)); - device->Flags &= ~DEVICE_CHANNELS_REQUEST; - } - device->FmtChans = DevFmtX61; - break; - case 8: - if((device->Flags&DEVICE_CHANNELS_REQUEST) && - device->FmtChans != DevFmtX71) - { - ERR("Failed to set %s, got 7.1 Surround instead\n", DevFmtChannelsString(device->FmtChans)); - device->Flags &= ~DEVICE_CHANNELS_REQUEST; - } - device->FmtChans = DevFmtX71; - break; - default: - ERR("Unhandled channel count (%d), using Stereo\n", streamFormat.mChannelsPerFrame); - device->Flags &= ~DEVICE_CHANNELS_REQUEST; - device->FmtChans = DevFmtStereo; - streamFormat.mChannelsPerFrame = 2; - break; - } - SetDefaultWFXChannelOrder(device); - - /* use channel count and sample rate from the default output unit's current - * parameters, but reset everything else */ - streamFormat.mFramesPerPacket = 1; - switch(device->FmtType) - { - case DevFmtUByte: - device->FmtType = DevFmtByte; - /* fall-through */ - case DevFmtByte: - streamFormat.mBitsPerChannel = 8; - streamFormat.mBytesPerPacket = streamFormat.mChannelsPerFrame; - streamFormat.mBytesPerFrame = streamFormat.mChannelsPerFrame; - break; - case DevFmtUShort: - case DevFmtFloat: - device->FmtType = DevFmtShort; - /* fall-through */ - case DevFmtShort: - streamFormat.mBitsPerChannel = 16; - streamFormat.mBytesPerPacket = 2 * streamFormat.mChannelsPerFrame; - streamFormat.mBytesPerFrame = 2 * streamFormat.mChannelsPerFrame; - break; - } - streamFormat.mFormatID = kAudioFormatLinearPCM; - streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | - kAudioFormatFlagsNativeEndian | - kLinearPCMFormatFlagIsPacked; - - err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, sizeof(AudioStreamBasicDescription)); - if(err != noErr) - { - ERR("AudioUnitSetProperty failed\n"); - return ALC_FALSE; - } - - /* setup callback */ - data->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); - input.inputProc = ca_callback; - input.inputProcRefCon = device; - - err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(AURenderCallbackStruct)); - if(err != noErr) - { - ERR("AudioUnitSetProperty failed\n"); - return ALC_FALSE; - } - - return ALC_TRUE; -} - -static void ca_stop_playback(ALCdevice *device) -{ - ca_data *data = (ca_data*)device->ExtraData; - OSStatus err; - - AudioOutputUnitStop(data->audioUnit); - err = AudioUnitUninitialize(data->audioUnit); - if(err != noErr) - ERR("-- AudioUnitUninitialize failed.\n"); -} - -static ALCboolean ca_open_capture(ALCdevice *device, const ALCchar *deviceName) -{ - AudioStreamBasicDescription requestedFormat; // The application requested format - AudioStreamBasicDescription hardwareFormat; // The hardware format - AudioStreamBasicDescription outputFormat; // The AudioUnit output format - AURenderCallbackStruct input; - ComponentDescription desc; - AudioDeviceID inputDevice; - UInt32 outputFrameCount; - UInt32 propertySize; - UInt32 enableIO; - Component comp; - ca_data *data; - OSStatus err; - - desc.componentType = kAudioUnitType_Output; - desc.componentSubType = kAudioUnitSubType_HALOutput; - desc.componentManufacturer = kAudioUnitManufacturer_Apple; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; - - // Search for component with given description - comp = FindNextComponent(NULL, &desc); - if(comp == NULL) - { - ERR("FindNextComponent failed\n"); - return ALC_FALSE; - } - - data = calloc(1, sizeof(*data)); - device->ExtraData = data; - - // Open the component - err = OpenAComponent(comp, &data->audioUnit); - if(err != noErr) - { - ERR("OpenAComponent failed\n"); - goto error; - } - - // Turn off AudioUnit output - enableIO = 0; - err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(ALuint)); - if(err != noErr) - { - ERR("AudioUnitSetProperty failed\n"); - goto error; - } - - // Turn on AudioUnit input - enableIO = 1; - err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(ALuint)); - if(err != noErr) - { - ERR("AudioUnitSetProperty failed\n"); - goto error; - } - - // Get the default input device - propertySize = sizeof(AudioDeviceID); - err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &propertySize, &inputDevice); - if(err != noErr) - { - ERR("AudioHardwareGetProperty failed\n"); - goto error; - } - - if(inputDevice == kAudioDeviceUnknown) - { - ERR("No input device found\n"); - goto error; - } - - // Track the input device - err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &inputDevice, sizeof(AudioDeviceID)); - if(err != noErr) - { - ERR("AudioUnitSetProperty failed\n"); - goto error; - } - - // set capture callback - input.inputProc = ca_capture_callback; - input.inputProcRefCon = device; - - err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &input, sizeof(AURenderCallbackStruct)); - if(err != noErr) - { - ERR("AudioUnitSetProperty failed\n"); - goto error; - } - - // Initialize the device - err = AudioUnitInitialize(data->audioUnit); - if(err != noErr) - { - ERR("AudioUnitInitialize failed\n"); - goto error; - } - - // Get the hardware format - propertySize = sizeof(AudioStreamBasicDescription); - err = AudioUnitGetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &hardwareFormat, &propertySize); - if(err != noErr || propertySize != sizeof(AudioStreamBasicDescription)) - { - ERR("AudioUnitGetProperty failed\n"); - goto error; - } - - // Set up the requested format description - switch(device->FmtType) - { - case DevFmtUByte: - requestedFormat.mBitsPerChannel = 8; - requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked; - break; - case DevFmtShort: - requestedFormat.mBitsPerChannel = 16; - requestedFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked; - break; - case DevFmtFloat: - requestedFormat.mBitsPerChannel = 32; - requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked; - break; - case DevFmtByte: - case DevFmtUShort: - ERR("%s samples not supported\n", DevFmtTypeString(device->FmtType)); - goto error; - } - - switch(device->FmtChans) - { - case DevFmtMono: - requestedFormat.mChannelsPerFrame = 1; - break; - case DevFmtStereo: - requestedFormat.mChannelsPerFrame = 2; - break; - - case DevFmtQuad: - case DevFmtX51: - case DevFmtX51Side: - case DevFmtX61: - case DevFmtX71: - ERR("%s not supported\n", DevFmtChannelsString(device->FmtChans)); - goto error; - } - - requestedFormat.mBytesPerFrame = requestedFormat.mChannelsPerFrame * requestedFormat.mBitsPerChannel / 8; - requestedFormat.mBytesPerPacket = requestedFormat.mBytesPerFrame; - requestedFormat.mSampleRate = device->Frequency; - requestedFormat.mFormatID = kAudioFormatLinearPCM; - requestedFormat.mReserved = 0; - requestedFormat.mFramesPerPacket = 1; - - // save requested format description for later use - data->format = requestedFormat; - data->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); - - // Use intermediate format for sample rate conversion (outputFormat) - // Set sample rate to the same as hardware for resampling later - outputFormat = requestedFormat; - outputFormat.mSampleRate = hardwareFormat.mSampleRate; - - // Determine sample rate ratio for resampling - data->sampleRateRatio = outputFormat.mSampleRate / device->Frequency; - - // The output format should be the requested format, but using the hardware sample rate - // This is because the AudioUnit will automatically scale other properties, except for sample rate - err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, (void *)&outputFormat, sizeof(outputFormat)); - if(err != noErr) - { - ERR("AudioUnitSetProperty failed\n"); - goto error; - } - - // Set the AudioUnit output format frame count - outputFrameCount = device->UpdateSize * data->sampleRateRatio; - err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Output, 0, &outputFrameCount, sizeof(outputFrameCount)); - if(err != noErr) - { - ERR("AudioUnitSetProperty failed: %d\n", err); - goto error; - } - - // Set up sample converter - err = AudioConverterNew(&outputFormat, &requestedFormat, &data->audioConverter); - if(err != noErr) - { - ERR("AudioConverterNew failed: %d\n", err); - goto error; - } - - // Create a buffer for use in the resample callback - data->resampleBuffer = malloc(device->UpdateSize * data->frameSize * data->sampleRateRatio); - - // Allocate buffer for the AudioUnit output - data->bufferList = allocate_buffer_list(outputFormat.mChannelsPerFrame, device->UpdateSize * data->frameSize * data->sampleRateRatio); - if(data->bufferList == NULL) - { - alcSetError(device, ALC_OUT_OF_MEMORY); - goto error; - } - - data->ring = CreateRingBuffer(data->frameSize, (device->UpdateSize * data->sampleRateRatio) * device->NumUpdates); - if(data->ring == NULL) - { - alcSetError(device, ALC_OUT_OF_MEMORY); - goto error; - } - - return ALC_TRUE; - -error: - DestroyRingBuffer(data->ring); - free(data->resampleBuffer); - destroy_buffer_list(data->bufferList); - - if(data->audioConverter) - AudioConverterDispose(data->audioConverter); - if(data->audioUnit) - CloseComponent(data->audioUnit); - - free(data); - device->ExtraData = NULL; - - return ALC_FALSE; -} - -static void ca_close_capture(ALCdevice *device) -{ - ca_data *data = (ca_data*)device->ExtraData; - - DestroyRingBuffer(data->ring); - free(data->resampleBuffer); - destroy_buffer_list(data->bufferList); - - AudioConverterDispose(data->audioConverter); - CloseComponent(data->audioUnit); - - free(data); - device->ExtraData = NULL; -} - -static void ca_start_capture(ALCdevice *device) -{ - ca_data *data = (ca_data*)device->ExtraData; - OSStatus err = AudioOutputUnitStart(data->audioUnit); - if(err != noErr) - ERR("AudioOutputUnitStart failed\n"); -} - -static void ca_stop_capture(ALCdevice *device) -{ - ca_data *data = (ca_data*)device->ExtraData; - OSStatus err = AudioOutputUnitStop(data->audioUnit); - if(err != noErr) - ERR("AudioOutputUnitStop failed\n"); -} - -static ALCuint ca_available_samples(ALCdevice *device) -{ - ca_data *data = device->ExtraData; - return RingBufferSize(data->ring) / data->sampleRateRatio; -} - -static void ca_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples) -{ - ca_data *data = (ca_data*)device->ExtraData; - - if(samples <= ca_available_samples(device)) - { - AudioBufferList *list; - UInt32 frameCount; - OSStatus err; - - // If no samples are requested, just return - if(samples == 0) - return; - - // Allocate a temporary AudioBufferList to use as the return resamples data - list = alloca(sizeof(AudioBufferList) + sizeof(AudioBuffer)); - - // Point the resampling buffer to the capture buffer - list->mNumberBuffers = 1; - list->mBuffers[0].mNumberChannels = data->format.mChannelsPerFrame; - list->mBuffers[0].mDataByteSize = samples * data->frameSize; - list->mBuffers[0].mData = buffer; - - // Resample into another AudioBufferList - frameCount = samples; - err = AudioConverterFillComplexBuffer(data->audioConverter, ca_capture_conversion_callback, device, - &frameCount, list, NULL); - if(err != noErr) - { - ERR("AudioConverterFillComplexBuffer error: %d\n", err); - alcSetError(device, ALC_INVALID_VALUE); - } - } - else - alcSetError(device, ALC_INVALID_VALUE); -} - -static const BackendFuncs ca_funcs = { - ca_open_playback, - ca_close_playback, - ca_reset_playback, - ca_stop_playback, - ca_open_capture, - ca_close_capture, - ca_start_capture, - ca_stop_capture, - ca_capture_samples, - ca_available_samples -}; - -ALCboolean alc_ca_init(BackendFuncs *func_list) -{ - *func_list = ca_funcs; - return ALC_TRUE; -} - -void alc_ca_deinit(void) -{ -} - -void alc_ca_probe(enum DevProbe type) -{ - switch(type) - { - case DEVICE_PROBE: - AppendDeviceList(ca_device); - break; - case ALL_DEVICE_PROBE: - AppendAllDeviceList(ca_device); - break; - case CAPTURE_DEVICE_PROBE: - AppendCaptureDeviceList(ca_device); - break; - } -} diff -r c41d773a85fb -r 82b9267a3e19 Alc/backends/dsound.c --- a/Alc/backends/dsound.c Tue Oct 25 13:03:35 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,614 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2007 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#include "config.h" - -#define _WIN32_WINNT 0x0500 -#include -#include -#include - -#include -#include -#include -#ifndef _WAVEFORMATEXTENSIBLE_ -#include -#include -#endif - -#include "alMain.h" -#include "AL/al.h" -#include "AL/alc.h" - -#ifndef DSSPEAKER_5POINT1 -#define DSSPEAKER_5POINT1 6 -#endif -#ifndef DSSPEAKER_7POINT1 -#define DSSPEAKER_7POINT1 7 -#endif - -DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); -DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); - - -static HMODULE ds_handle; -static HRESULT (WINAPI *pDirectSoundCreate)(LPCGUID pcGuidDevice, IDirectSound **ppDS, IUnknown *pUnkOuter); -static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA pDSEnumCallback, void *pContext); - -#define DirectSoundCreate pDirectSoundCreate -#define DirectSoundEnumerateA pDirectSoundEnumerateA - - -typedef struct { - // DirectSound Playback Device - IDirectSound *lpDS; - IDirectSoundBuffer *DSpbuffer; - IDirectSoundBuffer *DSsbuffer; - IDirectSoundNotify *DSnotify; - HANDLE hNotifyEvent; - - volatile int killNow; - ALvoid *thread; -} DSoundData; - - -typedef struct { - ALCchar *name; - GUID guid; -} DevMap; - -static const ALCchar dsDevice[] = "DirectSound Default"; -static DevMap *DeviceList; -static ALuint NumDevices; - -#define MAX_UPDATES 128 - -static ALCboolean DSoundLoad(void) -{ - ALCboolean ok = ALC_TRUE; - if(!ds_handle) - { - ds_handle = LoadLibraryA("dsound.dll"); - if(ds_handle == NULL) - { - ERR("Failed to load dsound.dll\n"); - return ALC_FALSE; - } - -#define LOAD_FUNC(x) do { \ - if((p##x = (void*)GetProcAddress(ds_handle, #x)) == NULL) { \ - ERR("Could not load %s from dsound.dll\n", #x); \ - ok = ALC_FALSE; \ - } \ -} while(0) - LOAD_FUNC(DirectSoundCreate); - LOAD_FUNC(DirectSoundEnumerateA); -#undef LOAD_FUNC - - if(!ok) - { - FreeLibrary(ds_handle); - ds_handle = NULL; - } - } - return ok; -} - - -static BOOL CALLBACK DSoundEnumDevices(LPGUID guid, LPCSTR desc, LPCSTR drvname, LPVOID data) -{ - char str[1024]; - void *temp; - int count; - ALuint i; - - (void)data; - (void)drvname; - - if(!guid) - return TRUE; - - count = 0; - do { - if(count == 0) - snprintf(str, sizeof(str), "%s", desc); - else - snprintf(str, sizeof(str), "%s #%d", desc, count+1); - count++; - - for(i = 0;i < NumDevices;i++) - { - if(strcmp(str, DeviceList[i].name) == 0) - break; - } - } while(i != NumDevices); - - temp = realloc(DeviceList, sizeof(DevMap) * (NumDevices+1)); - if(temp) - { - DeviceList = temp; - DeviceList[NumDevices].name = strdup(str); - DeviceList[NumDevices].guid = *guid; - NumDevices++; - } - - return TRUE; -} - - -static ALuint DSoundProc(ALvoid *ptr) -{ - ALCdevice *pDevice = (ALCdevice*)ptr; - DSoundData *pData = (DSoundData*)pDevice->ExtraData; - DSBCAPS DSBCaps; - DWORD LastCursor = 0; - DWORD PlayCursor; - VOID *WritePtr1, *WritePtr2; - DWORD WriteCnt1, WriteCnt2; - BOOL Playing = FALSE; - DWORD FrameSize; - DWORD FragSize; - DWORD avail; - HRESULT err; - - SetRTPriority(); - - memset(&DSBCaps, 0, sizeof(DSBCaps)); - DSBCaps.dwSize = sizeof(DSBCaps); - err = IDirectSoundBuffer_GetCaps(pData->DSsbuffer, &DSBCaps); - if(FAILED(err)) - { - ERR("Failed to get buffer caps: 0x%lx\n", err); - aluHandleDisconnect(pDevice); - return 1; - } - - FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); - FragSize = pDevice->UpdateSize * FrameSize; - - IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &LastCursor, NULL); - while(!pData->killNow) - { - // Get current play cursor - IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &PlayCursor, NULL); - avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes; - - if(avail < FragSize) - { - if(!Playing) - { - err = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING); - if(FAILED(err)) - { - ERR("Failed to play buffer: 0x%lx\n", err); - aluHandleDisconnect(pDevice); - return 1; - } - Playing = TRUE; - } - - avail = WaitForSingleObjectEx(pData->hNotifyEvent, 2000, FALSE); - if(avail != WAIT_OBJECT_0) - ERR("WaitForSingleObjectEx error: 0x%lx\n", avail); - continue; - } - avail -= avail%FragSize; - - // Lock output buffer - WriteCnt1 = 0; - WriteCnt2 = 0; - err = IDirectSoundBuffer_Lock(pData->DSsbuffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0); - - // If the buffer is lost, restore it and lock - if(err == DSERR_BUFFERLOST) - { - WARN("Buffer lost, restoring...\n"); - err = IDirectSoundBuffer_Restore(pData->DSsbuffer); - if(SUCCEEDED(err)) - { - Playing = FALSE; - LastCursor = 0; - err = IDirectSoundBuffer_Lock(pData->DSsbuffer, 0, DSBCaps.dwBufferBytes, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0); - } - } - - // Successfully locked the output buffer - if(SUCCEEDED(err)) - { - // If we have an active context, mix data directly into output buffer otherwise fill with silence - aluMixData(pDevice, WritePtr1, WriteCnt1/FrameSize); - aluMixData(pDevice, WritePtr2, WriteCnt2/FrameSize); - - // Unlock output buffer only when successfully locked - IDirectSoundBuffer_Unlock(pData->DSsbuffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2); - } - else - { - ERR("Buffer lock error: %#lx\n", err); - aluHandleDisconnect(pDevice); - return 1; - } - - // Update old write cursor location - LastCursor += WriteCnt1+WriteCnt2; - LastCursor %= DSBCaps.dwBufferBytes; - } - - return 0; -} - -static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName) -{ - DSoundData *pData = NULL; - LPGUID guid = NULL; - HRESULT hr; - - if(!deviceName) - deviceName = dsDevice; - else if(strcmp(deviceName, dsDevice) != 0) - { - ALuint i; - - if(!DeviceList) - { - hr = DirectSoundEnumerateA(DSoundEnumDevices, NULL); - if(FAILED(hr)) - ERR("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr); - } - - for(i = 0;i < NumDevices;i++) - { - if(strcmp(deviceName, DeviceList[i].name) == 0) - { - guid = &DeviceList[i].guid; - break; - } - } - if(i == NumDevices) - return ALC_FALSE; - } - - //Initialise requested device - pData = calloc(1, sizeof(DSoundData)); - if(!pData) - { - alcSetError(device, ALC_OUT_OF_MEMORY); - return ALC_FALSE; - } - - hr = DS_OK; - pData->hNotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if(pData->hNotifyEvent == NULL) - hr = E_FAIL; - - //DirectSound Init code - if(SUCCEEDED(hr)) - hr = DirectSoundCreate(guid, &pData->lpDS, NULL); - if(SUCCEEDED(hr)) - hr = IDirectSound_SetCooperativeLevel(pData->lpDS, GetForegroundWindow(), DSSCL_PRIORITY); - if(FAILED(hr)) - { - if(pData->lpDS) - IDirectSound_Release(pData->lpDS); - if(pData->hNotifyEvent) - CloseHandle(pData->hNotifyEvent); - free(pData); - ERR("Device init failed: 0x%08lx\n", hr); - return ALC_FALSE; - } - - device->szDeviceName = strdup(deviceName); - device->ExtraData = pData; - return ALC_TRUE; -} - -static void DSoundClosePlayback(ALCdevice *device) -{ - DSoundData *pData = device->ExtraData; - - IDirectSound_Release(pData->lpDS); - CloseHandle(pData->hNotifyEvent); - free(pData); - device->ExtraData = NULL; -} - -static ALCboolean DSoundResetPlayback(ALCdevice *device) -{ - DSoundData *pData = (DSoundData*)device->ExtraData; - DSBUFFERDESC DSBDescription; - WAVEFORMATEXTENSIBLE OutputType; - DWORD speakers; - HRESULT hr; - - memset(&OutputType, 0, sizeof(OutputType)); - - switch(device->FmtType) - { - case DevFmtByte: - device->FmtType = DevFmtUByte; - break; - case DevFmtUShort: - device->FmtType = DevFmtShort; - break; - case DevFmtUByte: - case DevFmtShort: - case DevFmtFloat: - break; - } - - hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers); - if(SUCCEEDED(hr)) - { - if(!(device->Flags&DEVICE_CHANNELS_REQUEST)) - { - speakers = DSSPEAKER_CONFIG(speakers); - if(speakers == DSSPEAKER_MONO) - device->FmtChans = DevFmtMono; - else if(speakers == DSSPEAKER_STEREO || speakers == DSSPEAKER_HEADPHONE) - device->FmtChans = DevFmtStereo; - else if(speakers == DSSPEAKER_QUAD) - device->FmtChans = DevFmtQuad; - else if(speakers == DSSPEAKER_5POINT1) - device->FmtChans = DevFmtX51; - else if(speakers == DSSPEAKER_7POINT1) - device->FmtChans = DevFmtX71; - else - ERR("Unknown system speaker config: 0x%lx\n", speakers); - } - - switch(device->FmtChans) - { - case DevFmtMono: - OutputType.dwChannelMask = SPEAKER_FRONT_CENTER; - break; - case DevFmtStereo: - OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | - SPEAKER_FRONT_RIGHT; - break; - case DevFmtQuad: - OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | - SPEAKER_FRONT_RIGHT | - SPEAKER_BACK_LEFT | - SPEAKER_BACK_RIGHT; - break; - case DevFmtX51: - OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | - SPEAKER_FRONT_RIGHT | - SPEAKER_FRONT_CENTER | - SPEAKER_LOW_FREQUENCY | - SPEAKER_BACK_LEFT | - SPEAKER_BACK_RIGHT; - break; - case DevFmtX51Side: - OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | - SPEAKER_FRONT_RIGHT | - SPEAKER_FRONT_CENTER | - SPEAKER_LOW_FREQUENCY | - SPEAKER_SIDE_LEFT | - SPEAKER_SIDE_RIGHT; - break; - case DevFmtX61: - OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | - SPEAKER_FRONT_RIGHT | - SPEAKER_FRONT_CENTER | - SPEAKER_LOW_FREQUENCY | - SPEAKER_BACK_CENTER | - SPEAKER_SIDE_LEFT | - SPEAKER_SIDE_RIGHT; - break; - case DevFmtX71: - OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | - SPEAKER_FRONT_RIGHT | - SPEAKER_FRONT_CENTER | - SPEAKER_LOW_FREQUENCY | - SPEAKER_BACK_LEFT | - SPEAKER_BACK_RIGHT | - SPEAKER_SIDE_LEFT | - SPEAKER_SIDE_RIGHT; - break; - } - - OutputType.Format.wFormatTag = WAVE_FORMAT_PCM; - OutputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans); - OutputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8; - OutputType.Format.nBlockAlign = OutputType.Format.nChannels*OutputType.Format.wBitsPerSample/8; - OutputType.Format.nSamplesPerSec = device->Frequency; - OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec*OutputType.Format.nBlockAlign; - OutputType.Format.cbSize = 0; - } - - if(OutputType.Format.nChannels > 2 || device->FmtType == DevFmtFloat) - { - OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; - OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; - OutputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); - if(device->FmtType == DevFmtFloat) - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; - else - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - } - else - { - if(SUCCEEDED(hr)) - { - memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); - DSBDescription.dwSize=sizeof(DSBUFFERDESC); - DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER; - hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSpbuffer, NULL); - } - if(SUCCEEDED(hr)) - hr = IDirectSoundBuffer_SetFormat(pData->DSpbuffer,&OutputType.Format); - } - - if(SUCCEEDED(hr)) - { - if(device->NumUpdates > MAX_UPDATES) - { - device->UpdateSize = (device->UpdateSize*device->NumUpdates + - MAX_UPDATES-1) / MAX_UPDATES; - device->NumUpdates = MAX_UPDATES; - } - - memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); - DSBDescription.dwSize=sizeof(DSBUFFERDESC); - DSBDescription.dwFlags=DSBCAPS_CTRLPOSITIONNOTIFY|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_GLOBALFOCUS; - DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates * - OutputType.Format.nBlockAlign; - DSBDescription.lpwfxFormat=&OutputType.Format; - hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL); - } - - if(SUCCEEDED(hr)) - { - hr = IDirectSoundBuffer_QueryInterface(pData->DSsbuffer, &IID_IDirectSoundNotify, (LPVOID *)&pData->DSnotify); - if(SUCCEEDED(hr)) - { - DSBPOSITIONNOTIFY notifies[MAX_UPDATES]; - ALuint i; - - for(i = 0;i < device->NumUpdates;++i) - { - notifies[i].dwOffset = i * device->UpdateSize * - OutputType.Format.nBlockAlign; - notifies[i].hEventNotify = pData->hNotifyEvent; - } - if(IDirectSoundNotify_SetNotificationPositions(pData->DSnotify, device->NumUpdates, notifies) != DS_OK) - hr = E_FAIL; - } - } - - if(SUCCEEDED(hr)) - { - ResetEvent(pData->hNotifyEvent); - SetDefaultWFXChannelOrder(device); - pData->thread = StartThread(DSoundProc, device); - if(pData->thread == NULL) - hr = E_FAIL; - } - - if(FAILED(hr)) - { - if(pData->DSnotify != NULL) - IDirectSoundNotify_Release(pData->DSnotify); - pData->DSnotify = NULL; - if(pData->DSsbuffer != NULL) - IDirectSoundBuffer_Release(pData->DSsbuffer); - pData->DSsbuffer = NULL; - if(pData->DSpbuffer != NULL) - IDirectSoundBuffer_Release(pData->DSpbuffer); - pData->DSpbuffer = NULL; - return ALC_FALSE; - } - - return ALC_TRUE; -} - -static void DSoundStopPlayback(ALCdevice *device) -{ - DSoundData *pData = device->ExtraData; - - if(!pData->thread) - return; - - pData->killNow = 1; - StopThread(pData->thread); - pData->thread = NULL; - - pData->killNow = 0; - - IDirectSoundNotify_Release(pData->DSnotify); - pData->DSnotify = NULL; - IDirectSoundBuffer_Release(pData->DSsbuffer); - pData->DSsbuffer = NULL; - if(pData->DSpbuffer != NULL) - IDirectSoundBuffer_Release(pData->DSpbuffer); - pData->DSpbuffer = NULL; -} - - -static const BackendFuncs DSoundFuncs = { - DSoundOpenPlayback, - DSoundClosePlayback, - DSoundResetPlayback, - DSoundStopPlayback, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL -}; - - -ALCboolean alcDSoundInit(BackendFuncs *FuncList) -{ - if(!DSoundLoad()) - return ALC_FALSE; - *FuncList = DSoundFuncs; - return ALC_TRUE; -} - -void alcDSoundDeinit(void) -{ - ALuint i; - - for(i = 0;i < NumDevices;++i) - free(DeviceList[i].name); - free(DeviceList); - DeviceList = NULL; - NumDevices = 0; - - if(ds_handle) - FreeLibrary(ds_handle); - ds_handle = NULL; -} - -void alcDSoundProbe(enum DevProbe type) -{ - HRESULT hr; - ALuint i; - - switch(type) - { - case DEVICE_PROBE: - AppendDeviceList(dsDevice); - break; - - case ALL_DEVICE_PROBE: - for(i = 0;i < NumDevices;++i) - free(DeviceList[i].name); - free(DeviceList); - DeviceList = NULL; - NumDevices = 0; - - hr = DirectSoundEnumerateA(DSoundEnumDevices, NULL); - if(FAILED(hr)) - ERR("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr); - else - { - for(i = 0;i < NumDevices;i++) - AppendAllDeviceList(DeviceList[i].name); - } - break; - - case CAPTURE_DEVICE_PROBE: - break; - } -} diff -r c41d773a85fb -r 82b9267a3e19 Alc/backends/mmdevapi.c --- a/Alc/backends/mmdevapi.c Tue Oct 25 13:03:35 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,775 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 2011 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#include "config.h" - -#define COBJMACROS -#define _WIN32_WINNT 0x0500 -#include -#include -#include - -#include -#include -#include -#include -#ifndef _WAVEFORMATEXTENSIBLE_ -#include -#include -#endif - -#include "alMain.h" -#include "AL/al.h" -#include "AL/alc.h" - - -DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); -DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); - -#define MONO SPEAKER_FRONT_CENTER -#define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT) -#define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT) -#define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT) -#define X5DOT1SIDE (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT) -#define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT) -#define X7DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT) - - -typedef struct { - IMMDevice *mmdev; - IAudioClient *client; - HANDLE hNotifyEvent; - - HANDLE MsgEvent; - - volatile int killNow; - ALvoid *thread; -} MMDevApiData; - - -static const ALCchar mmDevice[] = "WASAPI Default"; - - -static HANDLE ThreadHdl; -static DWORD ThreadID; - -typedef struct { - HANDLE FinishedEvt; - HRESULT result; -} ThreadRequest; - -#define WM_USER_OpenDevice (WM_USER+0) -#define WM_USER_ResetDevice (WM_USER+1) -#define WM_USER_StopDevice (WM_USER+2) -#define WM_USER_CloseDevice (WM_USER+3) - -static HRESULT WaitForResponse(ThreadRequest *req) -{ - if(WaitForSingleObject(req->FinishedEvt, INFINITE) == WAIT_OBJECT_0) - return req->result; - ERR("Message response error: %lu\n", GetLastError()); - return E_FAIL; -} - - -static ALuint MMDevApiProc(ALvoid *ptr) -{ - ALCdevice *device = ptr; - MMDevApiData *data = device->ExtraData; - union { - IAudioRenderClient *iface; - void *ptr; - } render; - UINT32 written, len; - BYTE *buffer; - HRESULT hr; - - hr = CoInitialize(NULL); - if(FAILED(hr)) - { - ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr); - aluHandleDisconnect(device); - return 0; - } - - hr = IAudioClient_GetService(data->client, &IID_IAudioRenderClient, &render.ptr); - if(FAILED(hr)) - { - ERR("Failed to get AudioRenderClient service: 0x%08lx\n", hr); - aluHandleDisconnect(device); - return 0; - } - - SetRTPriority(); - - while(!data->killNow) - { - hr = IAudioClient_GetCurrentPadding(data->client, &written); - if(FAILED(hr)) - { - ERR("Failed to get padding: 0x%08lx\n", hr); - aluHandleDisconnect(device); - break; - } - - len = device->UpdateSize*device->NumUpdates - written; - if(len < device->UpdateSize) - { - DWORD res; - res = WaitForSingleObjectEx(data->hNotifyEvent, 2000, FALSE); - if(res != WAIT_OBJECT_0) - ERR("WaitForSingleObjectEx error: 0x%lx\n", res); - continue; - } - len -= len%device->UpdateSize; - - hr = IAudioRenderClient_GetBuffer(render.iface, len, &buffer); - if(SUCCEEDED(hr)) - { - aluMixData(device, buffer, len); - hr = IAudioRenderClient_ReleaseBuffer(render.iface, len, 0); - } - if(FAILED(hr)) - { - ERR("Failed to buffer data: 0x%08lx\n", hr); - aluHandleDisconnect(device); - break; - } - } - - IAudioRenderClient_Release(render.iface); - - CoUninitialize(); - return 0; -} - - -static ALCboolean MakeExtensible(WAVEFORMATEXTENSIBLE *out, const WAVEFORMATEX *in) -{ - memset(out, 0, sizeof(*out)); - if(in->wFormatTag == WAVE_FORMAT_EXTENSIBLE) - *out = *(WAVEFORMATEXTENSIBLE*)in; - else if(in->wFormatTag == WAVE_FORMAT_PCM) - { - out->Format = *in; - out->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; - out->Format.cbSize = sizeof(*out) - sizeof(*in); - if(out->Format.nChannels == 1) - out->dwChannelMask = MONO; - else if(out->Format.nChannels == 2) - out->dwChannelMask = STEREO; - else - ERR("Unhandled PCM channel count: %d\n", out->Format.nChannels); - out->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - } - else if(in->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) - { - out->Format = *in; - out->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; - out->Format.cbSize = sizeof(*out) - sizeof(*in); - if(out->Format.nChannels == 1) - out->dwChannelMask = MONO; - else if(out->Format.nChannels == 2) - out->dwChannelMask = STEREO; - else - ERR("Unhandled IEEE float channel count: %d\n", out->Format.nChannels); - out->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; - } - else - { - ERR("Unhandled format tag: 0x%04x\n", in->wFormatTag); - return ALC_FALSE; - } - return ALC_TRUE; -} - -static HRESULT DoReset(ALCdevice *device) -{ - MMDevApiData *data = device->ExtraData; - WAVEFORMATEXTENSIBLE OutputType; - WAVEFORMATEX *wfx = NULL; - REFERENCE_TIME min_per; - UINT32 buffer_len, min_len; - HRESULT hr; - - hr = IAudioClient_GetMixFormat(data->client, &wfx); - if(FAILED(hr)) - { - ERR("Failed to get mix format: 0x%08lx\n", hr); - return hr; - } - - if(!MakeExtensible(&OutputType, wfx)) - { - CoTaskMemFree(wfx); - return E_FAIL; - } - CoTaskMemFree(wfx); - wfx = NULL; - - if(!(device->Flags&DEVICE_FREQUENCY_REQUEST)) - device->Frequency = OutputType.Format.nSamplesPerSec; - if(!(device->Flags&DEVICE_CHANNELS_REQUEST)) - { - if(OutputType.Format.nChannels == 1 && OutputType.dwChannelMask == MONO) - device->FmtChans = DevFmtMono; - else if(OutputType.Format.nChannels == 2 && OutputType.dwChannelMask == STEREO) - device->FmtChans = DevFmtStereo; - else if(OutputType.Format.nChannels == 4 && OutputType.dwChannelMask == QUAD) - device->FmtChans = DevFmtQuad; - else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1) - device->FmtChans = DevFmtX51; - else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1SIDE) - device->FmtChans = DevFmtX51Side; - else if(OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1) - device->FmtChans = DevFmtX61; - else if(OutputType.Format.nChannels == 8 && OutputType.dwChannelMask == X7DOT1) - device->FmtChans = DevFmtX71; - else - ERR("Unhandled channel config: %d -- 0x%08lx\n", OutputType.Format.nChannels, OutputType.dwChannelMask); - } - - switch(device->FmtChans) - { - case DevFmtMono: - OutputType.Format.nChannels = 1; - OutputType.dwChannelMask = MONO; - break; - case DevFmtStereo: - OutputType.Format.nChannels = 2; - OutputType.dwChannelMask = STEREO; - break; - case DevFmtQuad: - OutputType.Format.nChannels = 4; - OutputType.dwChannelMask = QUAD; - break; - case DevFmtX51: - OutputType.Format.nChannels = 6; - OutputType.dwChannelMask = X5DOT1; - break; - case DevFmtX51Side: - OutputType.Format.nChannels = 6; - OutputType.dwChannelMask = X5DOT1SIDE; - break; - case DevFmtX61: - OutputType.Format.nChannels = 7; - OutputType.dwChannelMask = X6DOT1; - break; - case DevFmtX71: - OutputType.Format.nChannels = 8; - OutputType.dwChannelMask = X7DOT1; - break; - } - switch(device->FmtType) - { - case DevFmtByte: - device->FmtType = DevFmtUByte; - /* fall-through */ - case DevFmtUByte: - OutputType.Format.wBitsPerSample = 8; - OutputType.Samples.wValidBitsPerSample = 8; - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - break; - case DevFmtUShort: - device->FmtType = DevFmtShort; - /* fall-through */ - case DevFmtShort: - OutputType.Format.wBitsPerSample = 16; - OutputType.Samples.wValidBitsPerSample = 16; - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - break; - case DevFmtFloat: - OutputType.Format.wBitsPerSample = 32; - OutputType.Samples.wValidBitsPerSample = 32; - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; - break; - } - OutputType.Format.nSamplesPerSec = device->Frequency; - - OutputType.Format.nBlockAlign = OutputType.Format.nChannels * - OutputType.Format.wBitsPerSample / 8; - OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec * - OutputType.Format.nBlockAlign; - - hr = IAudioClient_IsFormatSupported(data->client, AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx); - if(FAILED(hr)) - { - ERR("Failed to check format support: 0x%08lx\n", hr); - hr = IAudioClient_GetMixFormat(data->client, &wfx); - } - if(FAILED(hr)) - { - ERR("Failed to find a supported format: 0x%08lx\n", hr); - return hr; - } - - if(wfx != NULL) - { - if(!MakeExtensible(&OutputType, wfx)) - { - CoTaskMemFree(wfx); - return E_FAIL; - } - CoTaskMemFree(wfx); - wfx = NULL; - - if(device->Frequency != OutputType.Format.nSamplesPerSec) - { - if((device->Flags&DEVICE_FREQUENCY_REQUEST)) - ERR("Failed to set %dhz, got %ldhz instead\n", device->Frequency, OutputType.Format.nSamplesPerSec); - device->Flags &= ~DEVICE_FREQUENCY_REQUEST; - device->Frequency = OutputType.Format.nSamplesPerSec; - } - - if(!((device->FmtChans == DevFmtMono && OutputType.Format.nChannels == 1 && OutputType.dwChannelMask == MONO) || - (device->FmtChans == DevFmtStereo && OutputType.Format.nChannels == 2 && OutputType.dwChannelMask == STEREO) || - (device->FmtChans == DevFmtQuad && OutputType.Format.nChannels == 4 && OutputType.dwChannelMask == QUAD) || - (device->FmtChans == DevFmtX51 && OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1) || - (device->FmtChans == DevFmtX51Side && OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1SIDE) || - (device->FmtChans == DevFmtX61 && OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1) || - (device->FmtChans == DevFmtX71 && OutputType.Format.nChannels == 8 && OutputType.dwChannelMask == X7DOT1))) - { - if((device->Flags&DEVICE_CHANNELS_REQUEST)) - ERR("Failed to set %s, got %d channels (0x%08lx) instead\n", DevFmtChannelsString(device->FmtChans), OutputType.Format.nChannels, OutputType.dwChannelMask); - device->Flags &= ~DEVICE_CHANNELS_REQUEST; - - if(OutputType.Format.nChannels == 1 && OutputType.dwChannelMask == MONO) - device->FmtChans = DevFmtMono; - else if(OutputType.Format.nChannels == 2 && OutputType.dwChannelMask == STEREO) - device->FmtChans = DevFmtStereo; - else if(OutputType.Format.nChannels == 4 && OutputType.dwChannelMask == QUAD) - device->FmtChans = DevFmtQuad; - else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1) - device->FmtChans = DevFmtX51; - else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1SIDE) - device->FmtChans = DevFmtX51Side; - else if(OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1) - device->FmtChans = DevFmtX61; - else if(OutputType.Format.nChannels == 8 && OutputType.dwChannelMask == X7DOT1) - device->FmtChans = DevFmtX71; - else - { - ERR("Unhandled extensible channels: %d -- 0x%08lx\n", OutputType.Format.nChannels, OutputType.dwChannelMask); - device->FmtChans = DevFmtStereo; - OutputType.Format.nChannels = 2; - OutputType.dwChannelMask = STEREO; - } - } - - if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) - { - if(OutputType.Samples.wValidBitsPerSample == 0) - OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; - if(OutputType.Samples.wValidBitsPerSample != OutputType.Format.wBitsPerSample || - !((device->FmtType == DevFmtUByte && OutputType.Format.wBitsPerSample == 8) || - (device->FmtType == DevFmtShort && OutputType.Format.wBitsPerSample == 16))) - { - ERR("Failed to set %s samples, got %d/%d-bit instead\n", DevFmtTypeString(device->FmtType), OutputType.Samples.wValidBitsPerSample, OutputType.Format.wBitsPerSample); - if(OutputType.Format.wBitsPerSample == 8) - device->FmtType = DevFmtUByte; - else if(OutputType.Format.wBitsPerSample == 16) - device->FmtType = DevFmtShort; - else - { - device->FmtType = DevFmtShort; - OutputType.Format.wBitsPerSample = 16; - } - OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; - } - } - else if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) - { - if(OutputType.Samples.wValidBitsPerSample == 0) - OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; - if(OutputType.Samples.wValidBitsPerSample != OutputType.Format.wBitsPerSample || - !((device->FmtType == DevFmtFloat && OutputType.Format.wBitsPerSample == 32))) - { - ERR("Failed to set %s samples, got %d/%d-bit instead\n", DevFmtTypeString(device->FmtType), OutputType.Samples.wValidBitsPerSample, OutputType.Format.wBitsPerSample); - if(OutputType.Format.wBitsPerSample != 32) - { - device->FmtType = DevFmtFloat; - OutputType.Format.wBitsPerSample = 32; - } - OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; - } - } - else - { - ERR("Unhandled format sub-type\n"); - device->FmtType = DevFmtShort; - OutputType.Format.wBitsPerSample = 16; - OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - } - } - - SetDefaultWFXChannelOrder(device); - - hr = IAudioClient_GetDevicePeriod(data->client, &min_per, NULL); - if(SUCCEEDED(hr)) - { - min_len = (min_per*device->Frequency + 10000000-1) / 10000000; - if(min_len < device->UpdateSize) - min_len *= (device->UpdateSize + min_len/2)/min_len; - - device->NumUpdates = (device->NumUpdates*device->UpdateSize + min_len/2) / - min_len; - device->NumUpdates = maxu(device->NumUpdates, 2); - device->UpdateSize = min_len; - - hr = IAudioClient_Initialize(data->client, AUDCLNT_SHAREMODE_SHARED, - AUDCLNT_STREAMFLAGS_EVENTCALLBACK, - ((REFERENCE_TIME)device->UpdateSize* - device->NumUpdates*10000000 + - device->Frequency-1) / device->Frequency, - 0, &OutputType.Format, NULL); - } - if(FAILED(hr)) - { - ERR("Failed to initialize audio client: 0x%08lx\n", hr); - return hr; - } - - hr = IAudioClient_GetBufferSize(data->client, &buffer_len); - if(FAILED(hr)) - { - ERR("Failed to get audio buffer info: 0x%08lx\n", hr); - return hr; - } - - device->NumUpdates = buffer_len / device->UpdateSize; - if(device->NumUpdates <= 1) - { - device->NumUpdates = 1; - ERR("Audio client returned buffer_len < period*2; expect break up\n"); - } - - ResetEvent(data->hNotifyEvent); - hr = IAudioClient_SetEventHandle(data->client, data->hNotifyEvent); - if(SUCCEEDED(hr)) - hr = IAudioClient_Start(data->client); - if(FAILED(hr)) - { - ERR("Failed to start audio client: 0x%08lx\n", hr); - return hr; - } - - data->thread = StartThread(MMDevApiProc, device); - if(!data->thread) - { - IAudioClient_Stop(data->client); - ERR("Failed to start thread\n"); - return E_FAIL; - } - - return hr; -} - - -static DWORD CALLBACK MessageProc(void *ptr) -{ - ThreadRequest *req = ptr; - IMMDeviceEnumerator *Enumerator; - MMDevApiData *data; - ALCdevice *device; - HRESULT hr; - MSG msg; - - TRACE("Starting message thread\n"); - - hr = CoInitialize(NULL); - if(FAILED(hr)) - { - WARN("Failed to initialize COM: 0x%08lx\n", hr); - req->result = hr; - SetEvent(req->FinishedEvt); - return 0; - } - - hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); - if(FAILED(hr)) - { - WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr); - CoUninitialize(); - req->result = hr; - SetEvent(req->FinishedEvt); - return 0; - } - Enumerator = ptr; - IMMDeviceEnumerator_Release(Enumerator); - Enumerator = NULL; - - req->result = S_OK; - SetEvent(req->FinishedEvt); - - TRACE("Starting message loop\n"); - while(GetMessage(&msg, NULL, 0, 0)) - { - TRACE("Got message %u\n", msg.message); - switch(msg.message) - { - case WM_USER_OpenDevice: - req = (ThreadRequest*)msg.wParam; - device = (ALCdevice*)msg.lParam; - data = device->ExtraData; - - hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); - if(SUCCEEDED(hr)) - { - Enumerator = ptr; - hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(Enumerator, eRender, eMultimedia, &data->mmdev); - IMMDeviceEnumerator_Release(Enumerator); - Enumerator = NULL; - } - if(SUCCEEDED(hr)) - hr = IMMDevice_Activate(data->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); - if(SUCCEEDED(hr)) - data->client = ptr; - - if(FAILED(hr)) - { - if(data->mmdev) - IMMDevice_Release(data->mmdev); - data->mmdev = NULL; - } - - req->result = hr; - SetEvent(req->FinishedEvt); - continue; - - case WM_USER_ResetDevice: - req = (ThreadRequest*)msg.wParam; - device = (ALCdevice*)msg.lParam; - - req->result = DoReset(device); - SetEvent(req->FinishedEvt); - continue; - - case WM_USER_StopDevice: - req = (ThreadRequest*)msg.wParam; - device = (ALCdevice*)msg.lParam; - data = device->ExtraData; - - if(data->thread) - { - data->killNow = 1; - StopThread(data->thread); - data->thread = NULL; - - data->killNow = 0; - - IAudioClient_Stop(data->client); - } - - req->result = S_OK; - SetEvent(req->FinishedEvt); - continue; - - case WM_USER_CloseDevice: - req = (ThreadRequest*)msg.wParam; - device = (ALCdevice*)msg.lParam; - data = device->ExtraData; - - IAudioClient_Release(data->client); - data->client = NULL; - - IMMDevice_Release(data->mmdev); - data->mmdev = NULL; - - req->result = S_OK; - SetEvent(req->FinishedEvt); - continue; - - default: - ERR("Unexpected message: %u\n", msg.message); - continue; - } - } - TRACE("Message loop finished\n"); - - CoUninitialize(); - return 0; -} - - -static BOOL MMDevApiLoad(void) -{ - static HRESULT InitResult; - if(!ThreadHdl) - { - ThreadRequest req; - InitResult = E_FAIL; - - req.FinishedEvt = CreateEvent(NULL, FALSE, FALSE, NULL); - if(req.FinishedEvt == NULL) - ERR("Failed to create event: %lu\n", GetLastError()); - else - { - ThreadHdl = CreateThread(NULL, 0, MessageProc, &req, 0, &ThreadID); - if(ThreadHdl != NULL) - InitResult = WaitForResponse(&req); - CloseHandle(req.FinishedEvt); - } - } - return SUCCEEDED(InitResult); -} - - -static ALCboolean MMDevApiOpenPlayback(ALCdevice *device, const ALCchar *deviceName) -{ - MMDevApiData *data = NULL; - HRESULT hr; - - if(!deviceName) - deviceName = mmDevice; - else if(strcmp(deviceName, mmDevice) != 0) - return ALC_FALSE; - - //Initialise requested device - data = calloc(1, sizeof(MMDevApiData)); - if(!data) - { - alcSetError(device, ALC_OUT_OF_MEMORY); - return ALC_FALSE; - } - device->ExtraData = data; - - hr = S_OK; - data->hNotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - data->MsgEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if(data->hNotifyEvent == NULL || data->MsgEvent == NULL) - hr = E_FAIL; - - if(SUCCEEDED(hr)) - { - ThreadRequest req = { data->MsgEvent, 0 }; - - hr = E_FAIL; - if(PostThreadMessage(ThreadID, WM_USER_OpenDevice, (WPARAM)&req, (LPARAM)device)) - hr = WaitForResponse(&req); - } - - if(FAILED(hr)) - { - if(data->hNotifyEvent != NULL) - CloseHandle(data->hNotifyEvent); - data->hNotifyEvent = NULL; - if(data->MsgEvent != NULL) - CloseHandle(data->MsgEvent); - data->MsgEvent = NULL; - - free(data); - device->ExtraData = NULL; - - ERR("Device init failed: 0x%08lx\n", hr); - return ALC_FALSE; - } - - device->szDeviceName = strdup(deviceName); - return ALC_TRUE; -} - -static void MMDevApiClosePlayback(ALCdevice *device) -{ - MMDevApiData *data = device->ExtraData; - ThreadRequest req = { data->MsgEvent, 0 }; - - if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)device)) - (void)WaitForResponse(&req); - - CloseHandle(data->MsgEvent); - data->MsgEvent = NULL; - - CloseHandle(data->hNotifyEvent); - data->hNotifyEvent = NULL; - - free(data); - device->ExtraData = NULL; -} - -static ALCboolean MMDevApiResetPlayback(ALCdevice *device) -{ - MMDevApiData *data = device->ExtraData; - ThreadRequest req = { data->MsgEvent, 0 }; - HRESULT hr = E_FAIL; - - if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)device)) - hr = WaitForResponse(&req); - - return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE; -} - -static void MMDevApiStopPlayback(ALCdevice *device) -{ - MMDevApiData *data = device->ExtraData; - ThreadRequest req = { data->MsgEvent, 0 }; - - if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)device)) - (void)WaitForResponse(&req); -} - - -static const BackendFuncs MMDevApiFuncs = { - MMDevApiOpenPlayback, - MMDevApiClosePlayback, - MMDevApiResetPlayback, - MMDevApiStopPlayback, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL -}; - - -ALCboolean alcMMDevApiInit(BackendFuncs *FuncList) -{ - if(!MMDevApiLoad()) - return ALC_FALSE; - *FuncList = MMDevApiFuncs; - return ALC_TRUE; -} - -void alcMMDevApiDeinit(void) -{ - if(ThreadHdl) - { - TRACE("Sending WM_QUIT to Thread %04lx\n", ThreadID); - PostThreadMessage(ThreadID, WM_QUIT, 0, 0); - CloseHandle(ThreadHdl); - ThreadHdl = NULL; - } -} - -void alcMMDevApiProbe(enum DevProbe type) -{ - switch(type) - { - case DEVICE_PROBE: - AppendDeviceList(mmDevice); - break; - case ALL_DEVICE_PROBE: - AppendAllDeviceList(mmDevice); - break; - case CAPTURE_DEVICE_PROBE: - break; - } -} diff -r c41d773a85fb -r 82b9267a3e19 Alc/backends/opensl.c --- a/Alc/backends/opensl.c Tue Oct 25 13:03:35 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,425 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* This is an OpenAL backend for Android using the native audio APIs based on - * OpenSL ES 1.0.1. It is based on source code for the native-audio sample app - * bundled with NDK. - */ - -#include "config.h" - -#include -#include "alMain.h" -#include "AL/al.h" -#include "AL/alc.h" - - -#include -#if 1 -#include -#else -extern SLAPIENTRY const SLInterfaceID SL_IID_ANDROIDSIMPLEBUFFERQUEUE; - -struct SLAndroidSimpleBufferQueueItf_; -typedef const struct SLAndroidSimpleBufferQueueItf_ * const * SLAndroidSimpleBufferQueueItf; - -typedef void (*slAndroidSimpleBufferQueueCallback)(SLAndroidSimpleBufferQueueItf caller, void *pContext); - -typedef struct SLAndroidSimpleBufferQueueState_ { - SLuint32 count; - SLuint32 index; -} SLAndroidSimpleBufferQueueState; - - -struct SLAndroidSimpleBufferQueueItf_ { - SLresult (*Enqueue) ( - SLAndroidSimpleBufferQueueItf self, - const void *pBuffer, - SLuint32 size - ); - SLresult (*Clear) ( - SLAndroidSimpleBufferQueueItf self - ); - SLresult (*GetState) ( - SLAndroidSimpleBufferQueueItf self, - SLAndroidSimpleBufferQueueState *pState - ); - SLresult (*RegisterCallback) ( - SLAndroidSimpleBufferQueueItf self, - slAndroidSimpleBufferQueueCallback callback, - void* pContext - ); -}; - -#define SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE ((SLuint32) 0x800007BD) - -typedef struct SLDataLocator_AndroidSimpleBufferQueue { - SLuint32 locatorType; - SLuint32 numBuffers; -} SLDataLocator_AndroidSimpleBufferQueue; - -#endif - -/* Helper macros */ -#define SLObjectItf_Realize(a,b) ((*(a))->Realize((a),(b))) -#define SLObjectItf_GetInterface(a,b,c) ((*(a))->GetInterface((a),(b),(c))) -#define SLObjectItf_Destroy(a) ((*(a))->Destroy((a))) - -#define SLEngineItf_CreateOutputMix(a,b,c,d,e) ((*(a))->CreateOutputMix((a),(b),(c),(d),(e))) -#define SLEngineItf_CreateAudioPlayer(a,b,c,d,e,f,g) ((*(a))->CreateAudioPlayer((a),(b),(c),(d),(e),(f),(g))) - -#define SLPlayItf_SetPlayState(a,b) ((*(a))->SetPlayState((a),(b))) - - -typedef struct { - /* engine interfaces */ - SLObjectItf engineObject; - SLEngineItf engine; - - /* output mix interfaces */ - SLObjectItf outputMix; - - /* buffer queue player interfaces */ - SLObjectItf bufferQueueObject; - - void *buffer; - ALuint bufferSize; - - ALuint frameSize; -} osl_data; - - -static const ALCchar opensl_device[] = "OpenSL"; - - -static SLuint32 GetChannelMask(enum DevFmtChannels chans) -{ - switch(chans) - { - case DevFmtMono: return SL_SPEAKER_FRONT_CENTER; - case DevFmtStereo: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT; - case DevFmtQuad: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT| - SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT; - case DevFmtX51: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT| - SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY| - SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT; - case DevFmtX61: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT| - SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY| - SL_SPEAKER_BACK_CENTER| - SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT; - case DevFmtX71: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT| - SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY| - SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT| - SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT; - case DevFmtX51Side: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT| - SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY| - SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT; - } - return 0; -} - -static const char *res_str(SLresult result) -{ - switch(result) - { - case SL_RESULT_SUCCESS: return "Success"; - case SL_RESULT_PRECONDITIONS_VIOLATED: return "Preconditions violated"; - case SL_RESULT_PARAMETER_INVALID: return "Parameter invalid"; - case SL_RESULT_MEMORY_FAILURE: return "Memory failure"; - case SL_RESULT_RESOURCE_ERROR: return "Resource error"; - case SL_RESULT_RESOURCE_LOST: return "Resource lost"; - case SL_RESULT_IO_ERROR: return "I/O error"; - case SL_RESULT_BUFFER_INSUFFICIENT: return "Buffer insufficient"; - case SL_RESULT_CONTENT_CORRUPTED: return "Content corrupted"; - case SL_RESULT_CONTENT_UNSUPPORTED: return "Content unsupported"; - case SL_RESULT_CONTENT_NOT_FOUND: return "Content not found"; - case SL_RESULT_PERMISSION_DENIED: return "Permission denied"; - case SL_RESULT_FEATURE_UNSUPPORTED: return "Feature unsupported"; - case SL_RESULT_INTERNAL_ERROR: return "Internal error"; - case SL_RESULT_UNKNOWN_ERROR: return "Unknown error"; - case SL_RESULT_OPERATION_ABORTED: return "Operation aborted"; - case SL_RESULT_CONTROL_LOST: return "Control lost"; - case SL_RESULT_READONLY: return "ReadOnly"; - case SL_RESULT_ENGINEOPTION_UNSUPPORTED: return "Engine option unsupported"; - case SL_RESULT_SOURCE_SINK_INCOMPATIBLE: return "Source/Sink incompatible"; - } - return "Unknown error code"; -} - -#define PRINTERR(x, s) do { \ - if((x) != SL_RESULT_SUCCESS) \ - ERR("%s: %s\n", (s), res_str((x))); \ -} while(0) - -/* this callback handler is called every time a buffer finishes playing */ -static void opensl_callback(SLAndroidSimpleBufferQueueItf bq, void *context) -{ - ALCdevice *Device = context; - osl_data *data = Device->ExtraData; - SLresult result; - - aluMixData(Device, data->buffer, data->bufferSize/data->frameSize); - - result = (*bq)->Enqueue(bq, data->buffer, data->bufferSize); - PRINTERR(result, "bq->Enqueue"); -} - - -static ALCboolean opensl_open_playback(ALCdevice *Device, const ALCchar *deviceName) -{ - osl_data *data = NULL; - SLresult result; - - if(!deviceName) - deviceName = opensl_device; - else if(strcmp(deviceName, opensl_device) != 0) - return ALC_FALSE; - - data = calloc(1, sizeof(*data)); - if(!data) - { - alcSetError(Device, ALC_OUT_OF_MEMORY); - return ALC_FALSE; - } - - // create engine - result = slCreateEngine(&data->engineObject, 0, NULL, 0, NULL, NULL); - PRINTERR(result, "slCreateEngine"); - if(SL_RESULT_SUCCESS == result) - { - result = SLObjectItf_Realize(data->engineObject, SL_BOOLEAN_FALSE); - PRINTERR(result, "engine->Realize"); - } - if(SL_RESULT_SUCCESS == result) - { - result = SLObjectItf_GetInterface(data->engineObject, SL_IID_ENGINE, &data->engine); - PRINTERR(result, "engine->GetInterface"); - } - if(SL_RESULT_SUCCESS == result) - { - result = SLEngineItf_CreateOutputMix(data->engine, &data->outputMix, 0, NULL, NULL); - PRINTERR(result, "engine->CreateOutputMix"); - } - if(SL_RESULT_SUCCESS == result) - { - result = SLObjectItf_Realize(data->outputMix, SL_BOOLEAN_FALSE); - PRINTERR(result, "outputMix->Realize"); - } - - if(SL_RESULT_SUCCESS != result) - { - if(data->outputMix != NULL) - SLObjectItf_Destroy(data->outputMix); - data->outputMix = NULL; - - if(data->engineObject != NULL) - SLObjectItf_Destroy(data->engineObject); - data->engineObject = NULL; - data->engine = NULL; - - free(data); - return ALC_FALSE; - } - - Device->szDeviceName = strdup(deviceName); - Device->ExtraData = data; - - return ALC_TRUE; -} - - -static void opensl_close_playback(ALCdevice *Device) -{ - osl_data *data = Device->ExtraData; - - SLObjectItf_Destroy(data->outputMix); - data->outputMix = NULL; - - SLObjectItf_Destroy(data->engineObject); - data->engineObject = NULL; - data->engine = NULL; - - free(data); - Device->ExtraData = NULL; -} - -static ALCboolean opensl_reset_playback(ALCdevice *Device) -{ - osl_data *data = Device->ExtraData; - SLDataLocator_AndroidSimpleBufferQueue loc_bufq; - SLAndroidSimpleBufferQueueItf bufferQueue; - SLDataLocator_OutputMix loc_outmix; - SLDataFormat_PCM format_pcm; - SLDataSource audioSrc; - SLDataSink audioSnk; - SLPlayItf player; - SLInterfaceID id; - SLboolean req; - SLresult result; - ALuint i; - - - Device->UpdateSize = (ALuint64)Device->UpdateSize * 44100 / Device->Frequency; - Device->UpdateSize = Device->UpdateSize * Device->NumUpdates / 2; - Device->NumUpdates = 2; - - Device->Frequency = 44100; - Device->FmtChans = DevFmtStereo; - Device->FmtType = DevFmtShort; - - SetDefaultWFXChannelOrder(Device); - - - id = SL_IID_ANDROIDSIMPLEBUFFERQUEUE; - req = SL_BOOLEAN_TRUE; - - loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; - loc_bufq.numBuffers = Device->NumUpdates; - - format_pcm.formatType = SL_DATAFORMAT_PCM; - format_pcm.numChannels = ChannelsFromDevFmt(Device->FmtChans); - format_pcm.samplesPerSec = Device->Frequency * 1000; - format_pcm.bitsPerSample = BytesFromDevFmt(Device->FmtType) * 8; - format_pcm.containerSize = format_pcm.bitsPerSample; - format_pcm.channelMask = GetChannelMask(Device->FmtChans); - format_pcm.endianness = SL_BYTEORDER_NATIVE; - - audioSrc.pLocator = &loc_bufq; - audioSrc.pFormat = &format_pcm; - - loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; - loc_outmix.outputMix = data->outputMix; - audioSnk.pLocator = &loc_outmix; - audioSnk.pFormat = NULL; - - - result = SLEngineItf_CreateAudioPlayer(data->engine, &data->bufferQueueObject, &audioSrc, &audioSnk, 1, &id, &req); - PRINTERR(result, "engine->CreateAudioPlayer"); - if(SL_RESULT_SUCCESS == result) - { - result = SLObjectItf_Realize(data->bufferQueueObject, SL_BOOLEAN_FALSE); - PRINTERR(result, "bufferQueue->Realize"); - } - if(SL_RESULT_SUCCESS == result) - { - result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_BUFFERQUEUE, &bufferQueue); - PRINTERR(result, "bufferQueue->GetInterface"); - } - if(SL_RESULT_SUCCESS == result) - { - result = (*bufferQueue)->RegisterCallback(bufferQueue, opensl_callback, Device); - PRINTERR(result, "bufferQueue->RegisterCallback"); - } - if(SL_RESULT_SUCCESS == result) - { - data->frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); - data->bufferSize = Device->UpdateSize * data->frameSize; - data->buffer = calloc(1, data->bufferSize); - if(!data->buffer) - { - result = SL_RESULT_MEMORY_FAILURE; - PRINTERR(result, "calloc"); - } - } - /* enqueue the first buffer to kick off the callbacks */ - for(i = 0;i < Device->NumUpdates;i++) - { - if(SL_RESULT_SUCCESS == result) - { - result = (*bufferQueue)->Enqueue(bufferQueue, data->buffer, data->bufferSize); - PRINTERR(result, "bufferQueue->Enqueue"); - } - } - if(SL_RESULT_SUCCESS == result) - { - result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_PLAY, &player); - PRINTERR(result, "bufferQueue->GetInterface"); - } - if(SL_RESULT_SUCCESS == result) - { - result = SLPlayItf_SetPlayState(player, SL_PLAYSTATE_PLAYING); - PRINTERR(result, "player->SetPlayState"); - } - - if(SL_RESULT_SUCCESS != result) - { - if(data->bufferQueueObject != NULL) - SLObjectItf_Destroy(data->bufferQueueObject); - data->bufferQueueObject = NULL; - - free(data->buffer); - data->buffer = NULL; - data->bufferSize = 0; - - return ALC_FALSE; - } - - return ALC_TRUE; -} - - -static void opensl_stop_playback(ALCdevice *Device) -{ - osl_data *data = Device->ExtraData; - - if(data->bufferQueueObject != NULL) - SLObjectItf_Destroy(data->bufferQueueObject); - data->bufferQueueObject = NULL; - - free(data->buffer); - data->buffer = NULL; - data->bufferSize = 0; -} - - -static const BackendFuncs opensl_funcs = { - opensl_open_playback, - opensl_close_playback, - opensl_reset_playback, - opensl_stop_playback, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL -}; - - -ALCboolean alc_opensl_init(BackendFuncs *func_list) -{ - *func_list = opensl_funcs; - return ALC_TRUE; -} - -void alc_opensl_deinit(void) -{ -} - -void alc_opensl_probe(enum DevProbe type) -{ - switch(type) - { - case DEVICE_PROBE: - AppendDeviceList(opensl_device); - break; - case ALL_DEVICE_PROBE: - AppendAllDeviceList(opensl_device); - break; - case CAPTURE_DEVICE_PROBE: - break; - } -} diff -r c41d773a85fb -r 82b9267a3e19 Alc/backends/oss.c --- a/Alc/backends/oss.c Tue Oct 25 13:03:35 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,536 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2007 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "alMain.h" -#include "AL/al.h" -#include "AL/alc.h" - -#include - -/* - * The OSS documentation talks about SOUND_MIXER_READ, but the header - * only contains MIXER_READ. Play safe. Same for WRITE. - */ -#ifndef SOUND_MIXER_READ -#define SOUND_MIXER_READ MIXER_READ -#endif -#ifndef SOUND_MIXER_WRITE -#define SOUND_MIXER_WRITE MIXER_WRITE -#endif - -static const ALCchar oss_device[] = "OSS Default"; - -typedef struct { - int fd; - volatile int killNow; - ALvoid *thread; - - ALubyte *mix_data; - int data_size; - - RingBuffer *ring; - int doCapture; -} oss_data; - - -static int log2i(ALCuint x) -{ - int y = 0; - while (x > 1) - { - x >>= 1; - y++; - } - return y; -} - - -static ALuint OSSProc(ALvoid *ptr) -{ - ALCdevice *pDevice = (ALCdevice*)ptr; - oss_data *data = (oss_data*)pDevice->ExtraData; - ALint frameSize; - ssize_t wrote; - - SetRTPriority(); - - frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); - - while(!data->killNow && pDevice->Connected) - { - ALint len = data->data_size; - ALubyte *WritePtr = data->mix_data; - - aluMixData(pDevice, WritePtr, len/frameSize); - while(len > 0 && !data->killNow) - { - wrote = write(data->fd, WritePtr, len); - if(wrote < 0) - { - if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) - { - ERR("write failed: %s\n", strerror(errno)); - aluHandleDisconnect(pDevice); - break; - } - - Sleep(1); - continue; - } - - len -= wrote; - WritePtr += wrote; - } - } - - return 0; -} - -static ALuint OSSCaptureProc(ALvoid *ptr) -{ - ALCdevice *pDevice = (ALCdevice*)ptr; - oss_data *data = (oss_data*)pDevice->ExtraData; - int frameSize; - int amt; - - SetRTPriority(); - - frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); - - while(!data->killNow) - { - amt = read(data->fd, data->mix_data, data->data_size); - if(amt < 0) - { - ERR("read failed: %s\n", strerror(errno)); - aluHandleDisconnect(pDevice); - break; - } - if(amt == 0) - { - Sleep(1); - continue; - } - if(data->doCapture) - WriteRingBuffer(data->ring, data->mix_data, amt/frameSize); - } - - return 0; -} - -static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName) -{ - char driver[64]; - oss_data *data; - - strncpy(driver, GetConfigValue("oss", "device", "/dev/dsp"), sizeof(driver)-1); - driver[sizeof(driver)-1] = 0; - if(!deviceName) - deviceName = oss_device; - else if(strcmp(deviceName, oss_device) != 0) - return ALC_FALSE; - - data = (oss_data*)calloc(1, sizeof(oss_data)); - data->killNow = 0; - - data->fd = open(driver, O_WRONLY); - if(data->fd == -1) - { - free(data); - ERR("Could not open %s: %s\n", driver, strerror(errno)); - return ALC_FALSE; - } - - device->szDeviceName = strdup(deviceName); - device->ExtraData = data; - return ALC_TRUE; -} - -static void oss_close_playback(ALCdevice *device) -{ - oss_data *data = (oss_data*)device->ExtraData; - - close(data->fd); - free(data); - device->ExtraData = NULL; -} - -static ALCboolean oss_reset_playback(ALCdevice *device) -{ - oss_data *data = (oss_data*)device->ExtraData; - int numFragmentsLogSize; - int log2FragmentSize; - unsigned int periods; - audio_buf_info info; - ALuint frameSize; - int numChannels; - int ossFormat; - int ossSpeed; - char *err; - - switch(device->FmtType) - { - case DevFmtByte: - ossFormat = AFMT_S8; - break; - case DevFmtUByte: - ossFormat = AFMT_U8; - break; - case DevFmtUShort: - case DevFmtFloat: - device->FmtType = DevFmtShort; - /* fall-through */ - case DevFmtShort: - ossFormat = AFMT_S16_NE; - break; - } - - periods = device->NumUpdates; - numChannels = ChannelsFromDevFmt(device->FmtChans); - frameSize = numChannels * BytesFromDevFmt(device->FmtType); - - ossSpeed = device->Frequency; - log2FragmentSize = log2i(device->UpdateSize * frameSize); - - /* according to the OSS spec, 16 bytes are the minimum */ - if (log2FragmentSize < 4) - log2FragmentSize = 4; - /* Subtract one period since the temp mixing buffer counts as one. Still - * need at least two on the card, though. */ - if(periods > 2) periods--; - numFragmentsLogSize = (periods << 16) | log2FragmentSize; - -#define CHECKERR(func) if((func) < 0) { \ - err = #func; \ - goto err; \ -} - /* Don't fail if SETFRAGMENT fails. We can handle just about anything - * that's reported back via GETOSPACE */ - ioctl(data->fd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize); - CHECKERR(ioctl(data->fd, SNDCTL_DSP_SETFMT, &ossFormat)); - CHECKERR(ioctl(data->fd, SNDCTL_DSP_CHANNELS, &numChannels)); - CHECKERR(ioctl(data->fd, SNDCTL_DSP_SPEED, &ossSpeed)); - CHECKERR(ioctl(data->fd, SNDCTL_DSP_GETOSPACE, &info)); - if(0) - { - err: - ERR("%s failed: %s\n", err, strerror(errno)); - return ALC_FALSE; - } -#undef CHECKERR - - if((int)ChannelsFromDevFmt(device->FmtChans) != numChannels) - { - ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(device->FmtChans), numChannels); - return ALC_FALSE; - } - - if(!((ossFormat == AFMT_S8 && device->FmtType == DevFmtByte) || - (ossFormat == AFMT_U8 && device->FmtType == DevFmtUByte) || - (ossFormat == AFMT_S16_NE && device->FmtType == DevFmtShort))) - { - ERR("Failed to set %s samples, got OSS format %#x\n", DevFmtTypeString(device->FmtType), ossFormat); - return ALC_FALSE; - } - - if(device->Frequency != (ALuint)ossSpeed) - { - if((device->Flags&DEVICE_FREQUENCY_REQUEST)) - ERR("Failed to set %dhz, got %dhz instead\n", device->Frequency, ossSpeed); - device->Flags &= ~DEVICE_FREQUENCY_REQUEST; - device->Frequency = ossSpeed; - } - device->UpdateSize = info.fragsize / frameSize; - device->NumUpdates = info.fragments + 1; - - data->data_size = device->UpdateSize * frameSize; - data->mix_data = calloc(1, data->data_size); - - SetDefaultChannelOrder(device); - - data->thread = StartThread(OSSProc, device); - if(data->thread == NULL) - { - free(data->mix_data); - data->mix_data = NULL; - return ALC_FALSE; - } - - return ALC_TRUE; -} - -static void oss_stop_playback(ALCdevice *device) -{ - oss_data *data = (oss_data*)device->ExtraData; - - if(!data->thread) - return; - - data->killNow = 1; - StopThread(data->thread); - data->thread = NULL; - - data->killNow = 0; - if(ioctl(data->fd, SNDCTL_DSP_RESET) != 0) - ERR("Error resetting device: %s\n", strerror(errno)); - - free(data->mix_data); - data->mix_data = NULL; -} - - -static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName) -{ - int numFragmentsLogSize; - int log2FragmentSize; - unsigned int periods; - audio_buf_info info; - ALuint frameSize; - int numChannels; - char driver[64]; - oss_data *data; - int ossFormat; - int ossSpeed; - char *err; - - strncpy(driver, GetConfigValue("oss", "capture", "/dev/dsp"), sizeof(driver)-1); - driver[sizeof(driver)-1] = 0; - if(!deviceName) - deviceName = oss_device; - else if(strcmp(deviceName, oss_device) != 0) - return ALC_FALSE; - - data = (oss_data*)calloc(1, sizeof(oss_data)); - data->killNow = 0; - - data->fd = open(driver, O_RDONLY); - if(data->fd == -1) - { - free(data); - ERR("Could not open %s: %s\n", driver, strerror(errno)); - return ALC_FALSE; - } - - switch(device->FmtType) - { - case DevFmtByte: - ossFormat = AFMT_S8; - break; - case DevFmtUByte: - ossFormat = AFMT_U8; - break; - case DevFmtShort: - ossFormat = AFMT_S16_NE; - break; - case DevFmtUShort: - case DevFmtFloat: - free(data); - ERR("%s capture samples not supported on OSS\n", DevFmtTypeString(device->FmtType)); - return ALC_FALSE; - } - - periods = 4; - numChannels = ChannelsFromDevFmt(device->FmtChans); - frameSize = numChannels * BytesFromDevFmt(device->FmtType); - ossSpeed = device->Frequency; - log2FragmentSize = log2i(device->UpdateSize * device->NumUpdates * - frameSize / periods); - - /* according to the OSS spec, 16 bytes are the minimum */ - if (log2FragmentSize < 4) - log2FragmentSize = 4; - numFragmentsLogSize = (periods << 16) | log2FragmentSize; - -#define CHECKERR(func) if((func) < 0) { \ - err = #func; \ - goto err; \ -} - CHECKERR(ioctl(data->fd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize)); - CHECKERR(ioctl(data->fd, SNDCTL_DSP_SETFMT, &ossFormat)); - CHECKERR(ioctl(data->fd, SNDCTL_DSP_CHANNELS, &numChannels)); - CHECKERR(ioctl(data->fd, SNDCTL_DSP_SPEED, &ossSpeed)); - CHECKERR(ioctl(data->fd, SNDCTL_DSP_GETISPACE, &info)); - if(0) - { - err: - ERR("%s failed: %s\n", err, strerror(errno)); - close(data->fd); - free(data); - return ALC_FALSE; - } -#undef CHECKERR - - if((int)ChannelsFromDevFmt(device->FmtChans) != numChannels) - { - ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(device->FmtChans), numChannels); - close(data->fd); - free(data); - return ALC_FALSE; - } - - if(!((ossFormat == AFMT_S8 && device->FmtType == DevFmtByte) || - (ossFormat == AFMT_U8 && device->FmtType == DevFmtUByte) || - (ossFormat == AFMT_S16_NE && device->FmtType == DevFmtShort))) - { - ERR("Failed to set %s samples, got OSS format %#x\n", DevFmtTypeString(device->FmtType), ossFormat); - close(data->fd); - free(data); - return ALC_FALSE; - } - - data->ring = CreateRingBuffer(frameSize, device->UpdateSize * device->NumUpdates); - if(!data->ring) - { - ERR("Ring buffer create failed\n"); - close(data->fd); - free(data); - return ALC_FALSE; - } - - data->data_size = info.fragsize; - data->mix_data = calloc(1, data->data_size); - - device->ExtraData = data; - data->thread = StartThread(OSSCaptureProc, device); - if(data->thread == NULL) - { - device->ExtraData = NULL; - free(data->mix_data); - free(data); - return ALC_FALSE; - } - - device->szDeviceName = strdup(deviceName); - return ALC_TRUE; -} - -static void oss_close_capture(ALCdevice *device) -{ - oss_data *data = (oss_data*)device->ExtraData; - data->killNow = 1; - StopThread(data->thread); - - close(data->fd); - - DestroyRingBuffer(data->ring); - - free(data->mix_data); - free(data); - device->ExtraData = NULL; -} - -static void oss_start_capture(ALCdevice *pDevice) -{ - oss_data *data = (oss_data*)pDevice->ExtraData; - data->doCapture = 1; -} - -static void oss_stop_capture(ALCdevice *pDevice) -{ - oss_data *data = (oss_data*)pDevice->ExtraData; - data->doCapture = 0; -} - -static void oss_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples) -{ - oss_data *data = (oss_data*)pDevice->ExtraData; - if(lSamples <= (ALCuint)RingBufferSize(data->ring)) - ReadRingBuffer(data->ring, pBuffer, lSamples); - else - alcSetError(pDevice, ALC_INVALID_VALUE); -} - -static ALCuint oss_available_samples(ALCdevice *pDevice) -{ - oss_data *data = (oss_data*)pDevice->ExtraData; - return RingBufferSize(data->ring); -} - - -static const BackendFuncs oss_funcs = { - oss_open_playback, - oss_close_playback, - oss_reset_playback, - oss_stop_playback, - oss_open_capture, - oss_close_capture, - oss_start_capture, - oss_stop_capture, - oss_capture_samples, - oss_available_samples -}; - -ALCboolean alc_oss_init(BackendFuncs *func_list) -{ - *func_list = oss_funcs; - return ALC_TRUE; -} - -void alc_oss_deinit(void) -{ -} - -void alc_oss_probe(enum DevProbe type) -{ - switch(type) - { - case DEVICE_PROBE: - { -#ifdef HAVE_STAT - struct stat buf; - if(stat(GetConfigValue("oss", "device", "/dev/dsp"), &buf) == 0) -#endif - AppendDeviceList(oss_device); - } - break; - - case ALL_DEVICE_PROBE: - { -#ifdef HAVE_STAT - struct stat buf; - if(stat(GetConfigValue("oss", "device", "/dev/dsp"), &buf) == 0) -#endif - AppendAllDeviceList(oss_device); - } - break; - - case CAPTURE_DEVICE_PROBE: - { -#ifdef HAVE_STAT - struct stat buf; - if(stat(GetConfigValue("oss", "capture", "/dev/dsp"), &buf) == 0) -#endif - AppendCaptureDeviceList(oss_device); - } - break; - } -} diff -r c41d773a85fb -r 82b9267a3e19 Alc/backends/portaudio.c --- a/Alc/backends/portaudio.c Tue Oct 25 13:03:35 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,449 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2007 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#include "config.h" - -#include -#include -#include -#include "alMain.h" -#include "AL/al.h" -#include "AL/alc.h" - -#include - - -static const ALCchar pa_device[] = "PortAudio Default"; - - -static void *pa_handle; -#ifdef HAVE_DYNLOAD -#define MAKE_FUNC(x) static typeof(x) * p##x -MAKE_FUNC(Pa_Initialize); -MAKE_FUNC(Pa_Terminate); -MAKE_FUNC(Pa_GetErrorText); -MAKE_FUNC(Pa_StartStream); -MAKE_FUNC(Pa_StopStream); -MAKE_FUNC(Pa_OpenStream); -MAKE_FUNC(Pa_CloseStream); -MAKE_FUNC(Pa_GetDefaultOutputDevice); -MAKE_FUNC(Pa_GetStreamInfo); -#undef MAKE_FUNC - -#define Pa_Initialize pPa_Initialize -#define Pa_Terminate pPa_Terminate -#define Pa_GetErrorText pPa_GetErrorText -#define Pa_StartStream pPa_StartStream -#define Pa_StopStream pPa_StopStream -#define Pa_OpenStream pPa_OpenStream -#define Pa_CloseStream pPa_CloseStream -#define Pa_GetDefaultOutputDevice pPa_GetDefaultOutputDevice -#define Pa_GetStreamInfo pPa_GetStreamInfo -#endif - -static ALCboolean pa_load(void) -{ - if(!pa_handle) - { - PaError err; - -#ifdef HAVE_DYNLOAD -#ifdef _WIN32 -# define PALIB "portaudio.dll" -#elif defined(__APPLE__) && defined(__MACH__) -# define PALIB "libportaudio.2.dylib" -#elif defined(__OpenBSD__) -# define PALIB "libportaudio.so" -#else -# define PALIB "libportaudio.so.2" -#endif - - pa_handle = LoadLib(PALIB); - if(!pa_handle) - return ALC_FALSE; - -#define LOAD_FUNC(f) do { \ - p##f = GetSymbol(pa_handle, #f); \ - if(p##f == NULL) \ - { \ - CloseLib(pa_handle); \ - pa_handle = NULL; \ - return ALC_FALSE; \ - } \ -} while(0) - LOAD_FUNC(Pa_Initialize); - LOAD_FUNC(Pa_Terminate); - LOAD_FUNC(Pa_GetErrorText); - LOAD_FUNC(Pa_StartStream); - LOAD_FUNC(Pa_StopStream); - LOAD_FUNC(Pa_OpenStream); - LOAD_FUNC(Pa_CloseStream); - LOAD_FUNC(Pa_GetDefaultOutputDevice); - LOAD_FUNC(Pa_GetStreamInfo); -#undef LOAD_FUNC -#else - pa_handle = (void*)0xDEADBEEF; -#endif - - if((err=Pa_Initialize()) != paNoError) - { - ERR("Pa_Initialize() returned an error: %s\n", Pa_GetErrorText(err)); - CloseLib(pa_handle); - pa_handle = NULL; - return ALC_FALSE; - } - } - return ALC_TRUE; -} - - -typedef struct { - PaStream *stream; - ALuint update_size; - - RingBuffer *ring; -} pa_data; - - -static int pa_callback(const void *inputBuffer, void *outputBuffer, - unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, - const PaStreamCallbackFlags statusFlags, void *userData) -{ - ALCdevice *device = (ALCdevice*)userData; - - (void)inputBuffer; - (void)timeInfo; - (void)statusFlags; - - aluMixData(device, outputBuffer, framesPerBuffer); - return 0; -} - -static int pa_capture_cb(const void *inputBuffer, void *outputBuffer, - unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, - const PaStreamCallbackFlags statusFlags, void *userData) -{ - ALCdevice *device = (ALCdevice*)userData; - pa_data *data = (pa_data*)device->ExtraData; - - (void)outputBuffer; - (void)timeInfo; - (void)statusFlags; - - WriteRingBuffer(data->ring, inputBuffer, framesPerBuffer); - return 0; -} - - -static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName) -{ - PaStreamParameters outParams; - pa_data *data; - PaError err; - - if(!deviceName) - deviceName = pa_device; - else if(strcmp(deviceName, pa_device) != 0) - return ALC_FALSE; - - data = (pa_data*)calloc(1, sizeof(pa_data)); - data->update_size = device->UpdateSize; - - device->ExtraData = data; - - outParams.device = GetConfigValueInt("port", "device", -1); - if(outParams.device < 0) - outParams.device = Pa_GetDefaultOutputDevice(); - outParams.suggestedLatency = (device->UpdateSize*device->NumUpdates) / - (float)device->Frequency; - outParams.hostApiSpecificStreamInfo = NULL; - - switch(device->FmtType) - { - case DevFmtByte: - outParams.sampleFormat = paInt8; - break; - case DevFmtUByte: - outParams.sampleFormat = paUInt8; - break; - case DevFmtUShort: - device->FmtType = DevFmtShort; - /* fall-through */ - case DevFmtShort: - outParams.sampleFormat = paInt16; - break; - case DevFmtFloat: - outParams.sampleFormat = paFloat32; - break; - } - outParams.channelCount = ((device->FmtChans == DevFmtMono) ? 1 : 2); - - SetDefaultChannelOrder(device); - - err = Pa_OpenStream(&data->stream, NULL, &outParams, device->Frequency, - device->UpdateSize, paNoFlag, pa_callback, device); - if(err != paNoError) - { - ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err)); - device->ExtraData = NULL; - free(data); - return ALC_FALSE; - } - - device->szDeviceName = strdup(deviceName); - - if((ALuint)outParams.channelCount != ChannelsFromDevFmt(device->FmtChans)) - { - if(outParams.channelCount != 1 && outParams.channelCount != 2) - { - ERR("Unhandled channel count: %u\n", outParams.channelCount); - Pa_CloseStream(data->stream); - device->ExtraData = NULL; - free(data); - return ALC_FALSE; - } - if((device->Flags&DEVICE_CHANNELS_REQUEST)) - ERR("Failed to set %s, got %u channels instead\n", DevFmtChannelsString(device->FmtChans), outParams.channelCount); - device->Flags &= ~DEVICE_CHANNELS_REQUEST; - device->FmtChans = ((outParams.channelCount==1) ? DevFmtMono : DevFmtStereo); - } - - return ALC_TRUE; -} - -static void pa_close_playback(ALCdevice *device) -{ - pa_data *data = (pa_data*)device->ExtraData; - PaError err; - - err = Pa_CloseStream(data->stream); - if(err != paNoError) - ERR("Error closing stream: %s\n", Pa_GetErrorText(err)); - - free(data); - device->ExtraData = NULL; -} - -static ALCboolean pa_reset_playback(ALCdevice *device) -{ - pa_data *data = (pa_data*)device->ExtraData; - const PaStreamInfo *streamInfo; - PaError err; - - streamInfo = Pa_GetStreamInfo(data->stream); - if(device->Frequency != streamInfo->sampleRate) - { - if((device->Flags&DEVICE_FREQUENCY_REQUEST)) - ERR("PortAudio does not support changing sample rates (wanted %dhz, got %.1fhz)\n", device->Frequency, streamInfo->sampleRate); - device->Flags &= ~DEVICE_FREQUENCY_REQUEST; - device->Frequency = streamInfo->sampleRate; - } - device->UpdateSize = data->update_size; - - err = Pa_StartStream(data->stream); - if(err != paNoError) - { - ERR("Pa_StartStream() returned an error: %s\n", Pa_GetErrorText(err)); - return ALC_FALSE; - } - - return ALC_TRUE; -} - -static void pa_stop_playback(ALCdevice *device) -{ - pa_data *data = (pa_data*)device->ExtraData; - PaError err; - - err = Pa_StopStream(data->stream); - if(err != paNoError) - ERR("Error stopping stream: %s\n", Pa_GetErrorText(err)); -} - - -static ALCboolean pa_open_capture(ALCdevice *device, const ALCchar *deviceName) -{ - PaStreamParameters inParams; - ALuint frame_size; - pa_data *data; - PaError err; - - if(!deviceName) - deviceName = pa_device; - else if(strcmp(deviceName, pa_device) != 0) - return ALC_FALSE; - - data = (pa_data*)calloc(1, sizeof(pa_data)); - if(data == NULL) - { - alcSetError(device, ALC_OUT_OF_MEMORY); - return ALC_FALSE; - } - - frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); - data->ring = CreateRingBuffer(frame_size, device->UpdateSize*device->NumUpdates); - if(data->ring == NULL) - { - alcSetError(device, ALC_OUT_OF_MEMORY); - goto error; - } - - inParams.device = GetConfigValueInt("port", "capture", -1); - if(inParams.device < 0) - inParams.device = Pa_GetDefaultOutputDevice(); - inParams.suggestedLatency = 0.0f; - inParams.hostApiSpecificStreamInfo = NULL; - - switch(device->FmtType) - { - case DevFmtByte: - inParams.sampleFormat = paInt8; - break; - case DevFmtUByte: - inParams.sampleFormat = paUInt8; - break; - case DevFmtShort: - inParams.sampleFormat = paInt16; - break; - case DevFmtFloat: - inParams.sampleFormat = paFloat32; - break; - case DevFmtUShort: - ERR("Unsigned short samples not supported\n"); - goto error; - } - inParams.channelCount = ChannelsFromDevFmt(device->FmtChans); - - err = Pa_OpenStream(&data->stream, &inParams, NULL, device->Frequency, - paFramesPerBufferUnspecified, paNoFlag, pa_capture_cb, device); - if(err != paNoError) - { - ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err)); - goto error; - } - - device->szDeviceName = strdup(deviceName); - - device->ExtraData = data; - return ALC_TRUE; - -error: - DestroyRingBuffer(data->ring); - free(data); - return ALC_FALSE; -} - -static void pa_close_capture(ALCdevice *device) -{ - pa_data *data = (pa_data*)device->ExtraData; - PaError err; - - err = Pa_CloseStream(data->stream); - if(err != paNoError) - ERR("Error closing stream: %s\n", Pa_GetErrorText(err)); - - free(data); - device->ExtraData = NULL; -} - -static void pa_start_capture(ALCdevice *device) -{ - pa_data *data = device->ExtraData; - PaError err; - - err = Pa_StartStream(data->stream); - if(err != paNoError) - ERR("Error starting stream: %s\n", Pa_GetErrorText(err)); -} - -static void pa_stop_capture(ALCdevice *device) -{ - pa_data *data = (pa_data*)device->ExtraData; - PaError err; - - err = Pa_StopStream(data->stream); - if(err != paNoError) - ERR("Error stopping stream: %s\n", Pa_GetErrorText(err)); -} - -static void pa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples) -{ - pa_data *data = device->ExtraData; - if(samples <= (ALCuint)RingBufferSize(data->ring)) - ReadRingBuffer(data->ring, buffer, samples); - else - alcSetError(device, ALC_INVALID_VALUE); -} - -static ALCuint pa_available_samples(ALCdevice *device) -{ - pa_data *data = device->ExtraData; - return RingBufferSize(data->ring); -} - - -static const BackendFuncs pa_funcs = { - pa_open_playback, - pa_close_playback, - pa_reset_playback, - pa_stop_playback, - pa_open_capture, - pa_close_capture, - pa_start_capture, - pa_stop_capture, - pa_capture_samples, - pa_available_samples -}; - -ALCboolean alc_pa_init(BackendFuncs *func_list) -{ - if(!pa_load()) - return ALC_FALSE; - *func_list = pa_funcs; - return ALC_TRUE; -} - -void alc_pa_deinit(void) -{ - if(pa_handle) - { - Pa_Terminate(); -#ifdef HAVE_DYNLOAD - CloseLib(pa_handle); -#endif - pa_handle = NULL; - } -} - -void alc_pa_probe(enum DevProbe type) -{ - switch(type) - { - case DEVICE_PROBE: - AppendDeviceList(pa_device); - break; - case ALL_DEVICE_PROBE: - AppendAllDeviceList(pa_device); - break; - case CAPTURE_DEVICE_PROBE: - AppendCaptureDeviceList(pa_device); - break; - } -} diff -r c41d773a85fb -r 82b9267a3e19 Alc/backends/pulseaudio.c --- a/Alc/backends/pulseaudio.c Tue Oct 25 13:03:35 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1418 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 2009 by Konstantinos Natsakis - * Copyright (C) 2010 by Chris Robinson - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#include "config.h" - -#include "alMain.h" - -#include - -#if PA_API_VERSION == 11 -#define PA_STREAM_ADJUST_LATENCY 0x2000U -#define PA_STREAM_EARLY_REQUESTS 0x4000U -static __inline int PA_STREAM_IS_GOOD(pa_stream_state_t x) -{ - return (x == PA_STREAM_CREATING || x == PA_STREAM_READY); -} -static __inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x) -{ - return (x == PA_CONTEXT_CONNECTING || x == PA_CONTEXT_AUTHORIZING || - x == PA_CONTEXT_SETTING_NAME || x == PA_CONTEXT_READY); -} -#define PA_STREAM_IS_GOOD PA_STREAM_IS_GOOD -#define PA_CONTEXT_IS_GOOD PA_CONTEXT_IS_GOOD -#elif PA_API_VERSION != 12 -#error Invalid PulseAudio API version -#endif - -#ifndef PA_CHECK_VERSION -#define PA_CHECK_VERSION(major,minor,micro) \ - ((PA_MAJOR > (major)) || \ - (PA_MAJOR == (major) && PA_MINOR > (minor)) || \ - (PA_MAJOR == (major) && PA_MINOR == (minor) && PA_MICRO >= (micro))) -#endif - -static void *pa_handle; -#ifdef HAVE_DYNLOAD -#define MAKE_FUNC(x) static typeof(x) * p##x -MAKE_FUNC(pa_context_unref); -MAKE_FUNC(pa_sample_spec_valid); -MAKE_FUNC(pa_stream_drop); -MAKE_FUNC(pa_strerror); -MAKE_FUNC(pa_context_get_state); -MAKE_FUNC(pa_stream_get_state); -MAKE_FUNC(pa_threaded_mainloop_signal); -MAKE_FUNC(pa_stream_peek); -MAKE_FUNC(pa_threaded_mainloop_wait); -MAKE_FUNC(pa_threaded_mainloop_unlock); -MAKE_FUNC(pa_threaded_mainloop_in_thread); -MAKE_FUNC(pa_context_new); -MAKE_FUNC(pa_threaded_mainloop_stop); -MAKE_FUNC(pa_context_disconnect); -MAKE_FUNC(pa_threaded_mainloop_start); -MAKE_FUNC(pa_threaded_mainloop_get_api); -MAKE_FUNC(pa_context_set_state_callback); -MAKE_FUNC(pa_stream_write); -MAKE_FUNC(pa_xfree); -MAKE_FUNC(pa_stream_connect_record); -MAKE_FUNC(pa_stream_connect_playback); -MAKE_FUNC(pa_stream_readable_size); -MAKE_FUNC(pa_stream_writable_size); -MAKE_FUNC(pa_stream_cork); -MAKE_FUNC(pa_stream_is_suspended); -MAKE_FUNC(pa_stream_get_device_name); -MAKE_FUNC(pa_path_get_filename); -MAKE_FUNC(pa_get_binary_name); -MAKE_FUNC(pa_threaded_mainloop_free); -MAKE_FUNC(pa_context_errno); -MAKE_FUNC(pa_xmalloc); -MAKE_FUNC(pa_stream_unref); -MAKE_FUNC(pa_threaded_mainloop_accept); -MAKE_FUNC(pa_stream_set_write_callback); -MAKE_FUNC(pa_threaded_mainloop_new); -MAKE_FUNC(pa_context_connect); -MAKE_FUNC(pa_stream_set_buffer_attr); -MAKE_FUNC(pa_stream_get_buffer_attr); -MAKE_FUNC(pa_stream_get_sample_spec); -MAKE_FUNC(pa_stream_get_time); -MAKE_FUNC(pa_stream_set_read_callback); -MAKE_FUNC(pa_stream_set_state_callback); -MAKE_FUNC(pa_stream_set_moved_callback); -MAKE_FUNC(pa_stream_set_underflow_callback); -MAKE_FUNC(pa_stream_new); -MAKE_FUNC(pa_stream_disconnect); -MAKE_FUNC(pa_threaded_mainloop_lock); -MAKE_FUNC(pa_channel_map_init_auto); -MAKE_FUNC(pa_channel_map_parse); -MAKE_FUNC(pa_channel_map_snprint); -MAKE_FUNC(pa_channel_map_equal); -MAKE_FUNC(pa_context_get_server_info); -MAKE_FUNC(pa_context_get_sink_info_by_name); -MAKE_FUNC(pa_context_get_sink_info_list); -MAKE_FUNC(pa_context_get_source_info_list); -MAKE_FUNC(pa_operation_get_state); -MAKE_FUNC(pa_operation_unref); -#if PA_CHECK_VERSION(0,9,15) -MAKE_FUNC(pa_channel_map_superset); -MAKE_FUNC(pa_stream_set_buffer_attr_callback); -#endif -#if PA_CHECK_VERSION(0,9,16) -MAKE_FUNC(pa_stream_begin_write); -#endif -#undef MAKE_FUNC - -#define pa_context_unref ppa_context_unref -#define pa_sample_spec_valid ppa_sample_spec_valid -#define pa_stream_drop ppa_stream_drop -#define pa_strerror ppa_strerror -#define pa_context_get_state ppa_context_get_state -#define pa_stream_get_state ppa_stream_get_state -#define pa_threaded_mainloop_signal ppa_threaded_mainloop_signal -#define pa_stream_peek ppa_stream_peek -#define pa_threaded_mainloop_wait ppa_threaded_mainloop_wait -#define pa_threaded_mainloop_unlock ppa_threaded_mainloop_unlock -#define pa_threaded_mainloop_in_thread ppa_threaded_mainloop_in_thread -#define pa_context_new ppa_context_new -#define pa_threaded_mainloop_stop ppa_threaded_mainloop_stop -#define pa_context_disconnect ppa_context_disconnect -#define pa_threaded_mainloop_start ppa_threaded_mainloop_start -#define pa_threaded_mainloop_get_api ppa_threaded_mainloop_get_api -#define pa_context_set_state_callback ppa_context_set_state_callback -#define pa_stream_write ppa_stream_write -#define pa_xfree ppa_xfree -#define pa_stream_connect_record ppa_stream_connect_record -#define pa_stream_connect_playback ppa_stream_connect_playback -#define pa_stream_readable_size ppa_stream_readable_size -#define pa_stream_writable_size ppa_stream_writable_size -#define pa_stream_cork ppa_stream_cork -#define pa_stream_is_suspended ppa_stream_is_suspended -#define pa_stream_get_device_name ppa_stream_get_device_name -#define pa_path_get_filename ppa_path_get_filename -#define pa_get_binary_name ppa_get_binary_name -#define pa_threaded_mainloop_free ppa_threaded_mainloop_free -#define pa_context_errno ppa_context_errno -#define pa_xmalloc ppa_xmalloc -#define pa_stream_unref ppa_stream_unref -#define pa_threaded_mainloop_accept ppa_threaded_mainloop_accept -#define pa_stream_set_write_callback ppa_stream_set_write_callback -#define pa_threaded_mainloop_new ppa_threaded_mainloop_new -#define pa_context_connect ppa_context_connect -#define pa_stream_set_buffer_attr ppa_stream_set_buffer_attr -#define pa_stream_get_buffer_attr ppa_stream_get_buffer_attr -#define pa_stream_get_sample_spec ppa_stream_get_sample_spec -#define pa_stream_get_time ppa_stream_get_time -#define pa_stream_set_read_callback ppa_stream_set_read_callback -#define pa_stream_set_state_callback ppa_stream_set_state_callback -#define pa_stream_set_moved_callback ppa_stream_set_moved_callback -#define pa_stream_set_underflow_callback ppa_stream_set_underflow_callback -#define pa_stream_new ppa_stream_new -#define pa_stream_disconnect ppa_stream_disconnect -#define pa_threaded_mainloop_lock ppa_threaded_mainloop_lock -#define pa_channel_map_init_auto ppa_channel_map_init_auto -#define pa_channel_map_parse ppa_channel_map_parse -#define pa_channel_map_snprint ppa_channel_map_snprint -#define pa_channel_map_equal ppa_channel_map_equal -#define pa_context_get_server_info ppa_context_get_server_info -#define pa_context_get_sink_info_by_name ppa_context_get_sink_info_by_name -#define pa_context_get_sink_info_list ppa_context_get_sink_info_list -#define pa_context_get_source_info_list ppa_context_get_source_info_list -#define pa_operation_get_state ppa_operation_get_state -#define pa_operation_unref ppa_operation_unref -#if PA_CHECK_VERSION(0,9,15) -#define pa_channel_map_superset ppa_channel_map_superset -#define pa_stream_set_buffer_attr_callback ppa_stream_set_buffer_attr_callback -#endif -#if PA_CHECK_VERSION(0,9,16) -#define pa_stream_begin_write ppa_stream_begin_write -#endif - -#endif - -#ifndef PATH_MAX -#define PATH_MAX 4096 -#endif - -typedef struct { - char *device_name; - - ALCuint samples; - ALCuint frame_size; - - RingBuffer *ring; - - pa_buffer_attr attr; - pa_sample_spec spec; - - pa_threaded_mainloop *loop; - - ALvoid *thread; - volatile ALboolean killNow; - - pa_stream *stream; - pa_context *context; -} pulse_data; - -typedef struct { - char *name; - char *device_name; -} DevMap; - - -static const ALCchar pulse_device[] = "PulseAudio Default"; -static DevMap *allDevNameMap; -static ALuint numDevNames; -static DevMap *allCaptureDevNameMap; -static ALuint numCaptureDevNames; -static pa_context_flags_t pulse_ctx_flags; - - -static void context_state_callback(pa_context *context, void *pdata) -{ - pa_threaded_mainloop *loop = pdata; - pa_context_state_t state; - - state = pa_context_get_state(context); - if(state == PA_CONTEXT_READY || !PA_CONTEXT_IS_GOOD(state)) - pa_threaded_mainloop_signal(loop, 0); -} - -static pa_context *connect_context(pa_threaded_mainloop *loop, ALboolean silent) -{ - const char *name = "OpenAL Soft"; - char path_name[PATH_MAX]; - pa_context_state_t state; - pa_context *context; - int err; - - if(pa_get_binary_name(path_name, sizeof(path_name))) - name = pa_path_get_filename(path_name); - - context = pa_context_new(pa_threaded_mainloop_get_api(loop), name); - if(!context) - { - ERR("pa_context_new() failed\n"); - return NULL; - } - - pa_context_set_state_callback(context, context_state_callback, loop); - - if((err=pa_context_connect(context, NULL, pulse_ctx_flags, NULL)) >= 0) - { - while((state=pa_context_get_state(context)) != PA_CONTEXT_READY) - { - if(!PA_CONTEXT_IS_GOOD(state)) - { - err = pa_context_errno(context); - if(err > 0) err = -err; - break; - } - - pa_threaded_mainloop_wait(loop); - } - } - pa_context_set_state_callback(context, NULL, NULL); - - if(err < 0) - { - if(!silent) - ERR("Context did not connect: %s\n", pa_strerror(err)); - pa_context_unref(context); - return NULL; - } - - return context; -} - - -static ALCboolean pulse_load(void) //{{{ -{ - ALCboolean ret = ALC_FALSE; - if(!pa_handle) - { - pa_threaded_mainloop *loop; - -#ifdef HAVE_DYNLOAD - -#ifdef _WIN32 -#define PALIB "libpulse-0.dll" -#elif defined(__APPLE__) && defined(__MACH__) -#define PALIB "libpulse.0.dylib" -#else -#define PALIB "libpulse.so.0" -#endif - pa_handle = LoadLib(PALIB); - if(!pa_handle) - return ALC_FALSE; - -#define LOAD_FUNC(x) do { \ - p##x = GetSymbol(pa_handle, #x); \ - if(!(p##x)) { \ - CloseLib(pa_handle); \ - pa_handle = NULL; \ - return ALC_FALSE; \ - } \ -} while(0) - LOAD_FUNC(pa_context_unref); - LOAD_FUNC(pa_sample_spec_valid); - LOAD_FUNC(pa_stream_drop); - LOAD_FUNC(pa_strerror); - LOAD_FUNC(pa_context_get_state); - LOAD_FUNC(pa_stream_get_state); - LOAD_FUNC(pa_threaded_mainloop_signal); - LOAD_FUNC(pa_stream_peek); - LOAD_FUNC(pa_threaded_mainloop_wait); - LOAD_FUNC(pa_threaded_mainloop_unlock); - LOAD_FUNC(pa_threaded_mainloop_in_thread); - LOAD_FUNC(pa_context_new); - LOAD_FUNC(pa_threaded_mainloop_stop); - LOAD_FUNC(pa_context_disconnect); - LOAD_FUNC(pa_threaded_mainloop_start); - LOAD_FUNC(pa_threaded_mainloop_get_api); - LOAD_FUNC(pa_context_set_state_callback); - LOAD_FUNC(pa_stream_write); - LOAD_FUNC(pa_xfree); - LOAD_FUNC(pa_stream_connect_record); - LOAD_FUNC(pa_stream_connect_playback); - LOAD_FUNC(pa_stream_readable_size); - LOAD_FUNC(pa_stream_writable_size); - LOAD_FUNC(pa_stream_cork); - LOAD_FUNC(pa_stream_is_suspended); - LOAD_FUNC(pa_stream_get_device_name); - LOAD_FUNC(pa_path_get_filename); - LOAD_FUNC(pa_get_binary_name); - LOAD_FUNC(pa_threaded_mainloop_free); - LOAD_FUNC(pa_context_errno); - LOAD_FUNC(pa_xmalloc); - LOAD_FUNC(pa_stream_unref); - LOAD_FUNC(pa_threaded_mainloop_accept); - LOAD_FUNC(pa_stream_set_write_callback); - LOAD_FUNC(pa_threaded_mainloop_new); - LOAD_FUNC(pa_context_connect); - LOAD_FUNC(pa_stream_set_buffer_attr); - LOAD_FUNC(pa_stream_get_buffer_attr); - LOAD_FUNC(pa_stream_get_sample_spec); - LOAD_FUNC(pa_stream_get_time); - LOAD_FUNC(pa_stream_set_read_callback); - LOAD_FUNC(pa_stream_set_state_callback); - LOAD_FUNC(pa_stream_set_moved_callback); - LOAD_FUNC(pa_stream_set_underflow_callback); - LOAD_FUNC(pa_stream_new); - LOAD_FUNC(pa_stream_disconnect); - LOAD_FUNC(pa_threaded_mainloop_lock); - LOAD_FUNC(pa_channel_map_init_auto); - LOAD_FUNC(pa_channel_map_parse); - LOAD_FUNC(pa_channel_map_snprint); - LOAD_FUNC(pa_channel_map_equal); - LOAD_FUNC(pa_context_get_server_info); - LOAD_FUNC(pa_context_get_sink_info_by_name); - LOAD_FUNC(pa_context_get_sink_info_list); - LOAD_FUNC(pa_context_get_source_info_list); - LOAD_FUNC(pa_operation_get_state); - LOAD_FUNC(pa_operation_unref); -#undef LOAD_FUNC -#define LOAD_OPTIONAL_FUNC(x) do { \ - p##x = GetSymbol(pa_handle, #x); \ -} while(0) -#if PA_CHECK_VERSION(0,9,15) - LOAD_OPTIONAL_FUNC(pa_channel_map_superset); - LOAD_OPTIONAL_FUNC(pa_stream_set_buffer_attr_callback); -#endif -#if PA_CHECK_VERSION(0,9,16) - LOAD_OPTIONAL_FUNC(pa_stream_begin_write); -#endif -#undef LOAD_OPTIONAL_FUNC - -#else /* HAVE_DYNLOAD */ - pa_handle = (void*)0xDEADBEEF; -#endif - - if((loop=pa_threaded_mainloop_new()) && - pa_threaded_mainloop_start(loop) >= 0) - { - pa_context *context; - - pa_threaded_mainloop_lock(loop); - context = connect_context(loop, AL_TRUE); - if(context) - { - ret = ALC_TRUE; - - pa_context_disconnect(context); - pa_context_unref(context); - } - pa_threaded_mainloop_unlock(loop); - pa_threaded_mainloop_stop(loop); - } - if(loop) - pa_threaded_mainloop_free(loop); - - if(!ret) - { -#ifdef HAVE_DYNLOAD - CloseLib(pa_handle); -#endif - pa_handle = NULL; - } - } - return ret; -} //}}} - -// PulseAudio Event Callbacks //{{{ -static void stream_state_callback(pa_stream *stream, void *pdata) //{{{ -{ - pa_threaded_mainloop *loop = pdata; - pa_stream_state_t state; - - state = pa_stream_get_state(stream); - if(state == PA_STREAM_READY || !PA_STREAM_IS_GOOD(state)) - pa_threaded_mainloop_signal(loop, 0); -}//}}} - -static void stream_signal_callback(pa_stream *stream, void *pdata) //{{{ -{ - ALCdevice *Device = pdata; - pulse_data *data = Device->ExtraData; - (void)stream; - - pa_threaded_mainloop_signal(data->loop, 0); -}//}}} - -static void stream_buffer_attr_callback(pa_stream *stream, void *pdata) //{{{ -{ - ALCdevice *Device = pdata; - pulse_data *data = Device->ExtraData; - - LockDevice(Device); - - data->attr = *(pa_stream_get_buffer_attr(stream)); - Device->UpdateSize = data->attr.minreq / data->frame_size; - Device->NumUpdates = (data->attr.tlength/data->frame_size) / Device->UpdateSize; - if(Device->NumUpdates <= 1) - { - Device->NumUpdates = 1; - ERR("PulseAudio returned minreq > tlength/2; expect break up\n"); - } - - UnlockDevice(Device); -}//}}} - -static void stream_device_callback(pa_stream *stream, void *pdata) //{{{ -{ - ALCdevice *Device = pdata; - pulse_data *data = Device->ExtraData; - - free(data->device_name); - data->device_name = strdup(pa_stream_get_device_name(stream)); -}//}}} - -static void context_state_callback2(pa_context *context, void *pdata) //{{{ -{ - ALCdevice *Device = pdata; - pulse_data *data = Device->ExtraData; - - if(pa_context_get_state(context) == PA_CONTEXT_FAILED) - { - ERR("Received context failure!\n"); - aluHandleDisconnect(Device); - } - pa_threaded_mainloop_signal(data->loop, 0); -}//}}} - -static void stream_state_callback2(pa_stream *stream, void *pdata) //{{{ -{ - ALCdevice *Device = pdata; - pulse_data *data = Device->ExtraData; - - if(pa_stream_get_state(stream) == PA_STREAM_FAILED) - { - ERR("Received stream failure!\n"); - aluHandleDisconnect(Device); - } - pa_threaded_mainloop_signal(data->loop, 0); -}//}}} - -static void stream_success_callback(pa_stream *stream, int success, void *pdata) //{{{ -{ - ALCdevice *Device = pdata; - pulse_data *data = Device->ExtraData; - (void)stream; - (void)success; - - pa_threaded_mainloop_signal(data->loop, 0); -}//}}} - -static void sink_info_callback(pa_context *context, const pa_sink_info *info, int eol, void *pdata) //{{{ -{ - ALCdevice *device = pdata; - pulse_data *data = device->ExtraData; - char chanmap_str[256] = ""; - const struct { - const char *str; - enum DevFmtChannels chans; - } chanmaps[] = { - { "front-left,front-right,front-center,lfe,rear-left,rear-right,side-left,side-right", - DevFmtX71 }, - { "front-left,front-right,front-center,lfe,rear-center,side-left,side-right", - DevFmtX61 }, - { "front-left,front-right,front-center,lfe,rear-left,rear-right", - DevFmtX51 }, - { "front-left,front-right,front-center,lfe,side-left,side-right", - DevFmtX51Side }, - { "front-left,front-right,rear-left,rear-right", DevFmtQuad }, - { "front-left,front-right", DevFmtStereo }, - { "mono", DevFmtMono }, - { NULL, 0 } - }; - int i; - (void)context; - - if(eol) - { - pa_threaded_mainloop_signal(data->loop, 0); - return; - } - - for(i = 0;chanmaps[i].str;i++) - { - pa_channel_map map; - if(!pa_channel_map_parse(&map, chanmaps[i].str)) - continue; - - if(pa_channel_map_equal(&info->channel_map, &map) -#if PA_CHECK_VERSION(0,9,15) - || (pa_channel_map_superset && - pa_channel_map_superset(&info->channel_map, &map)) -#endif - ) - { - device->FmtChans = chanmaps[i].chans; - return; - } - } - - pa_channel_map_snprint(chanmap_str, sizeof(chanmap_str), &info->channel_map); - ERR("Failed to find format for channel map:\n %s\n", chanmap_str); -}//}}} - -static void sink_device_callback(pa_context *context, const pa_sink_info *info, int eol, void *pdata) //{{{ -{ - pa_threaded_mainloop *loop = pdata; - char str[1024]; - void *temp; - int count; - ALuint i; - - (void)context; - - if(eol) - { - pa_threaded_mainloop_signal(loop, 0); - return; - } - - count = 0; - do { - if(count == 0) - snprintf(str, sizeof(str), "%s", info->description); - else - snprintf(str, sizeof(str), "%s #%d", info->description, count+1); - count++; - - for(i = 0;i < numDevNames;i++) - { - if(strcmp(str, allDevNameMap[i].name) == 0) - break; - } - } while(i != numDevNames); - - temp = realloc(allDevNameMap, (numDevNames+1) * sizeof(*allDevNameMap)); - if(temp) - { - allDevNameMap = temp; - allDevNameMap[numDevNames].name = strdup(str); - allDevNameMap[numDevNames].device_name = strdup(info->name); - numDevNames++; - } -}//}}} - -static void source_device_callback(pa_context *context, const pa_source_info *info, int eol, void *pdata) //{{{ -{ - pa_threaded_mainloop *loop = pdata; - char str[1024]; - void *temp; - int count; - ALuint i; - - (void)context; - - if(eol) - { - pa_threaded_mainloop_signal(loop, 0); - return; - } - - count = 0; - do { - if(count == 0) - snprintf(str, sizeof(str), "%s", info->description); - else - snprintf(str, sizeof(str), "%s #%d", info->description, count+1); - count++; - - for(i = 0;i < numCaptureDevNames;i++) - { - if(strcmp(str, allCaptureDevNameMap[i].name) == 0) - break; - } - } while(i != numCaptureDevNames); - - temp = realloc(allCaptureDevNameMap, (numCaptureDevNames+1) * sizeof(*allCaptureDevNameMap)); - if(temp) - { - allCaptureDevNameMap = temp; - allCaptureDevNameMap[numCaptureDevNames].name = strdup(str); - allCaptureDevNameMap[numCaptureDevNames].device_name = strdup(info->name); - numCaptureDevNames++; - } -}//}}} -//}}} - -// PulseAudio I/O Callbacks //{{{ -static void stream_write_callback(pa_stream *stream, size_t len, void *pdata) //{{{ -{ - ALCdevice *Device = pdata; - pulse_data *data = Device->ExtraData; - (void)stream; - (void)len; - - pa_threaded_mainloop_signal(data->loop, 0); -} //}}} -//}}} - -static ALuint PulseProc(ALvoid *param) -{ - ALCdevice *Device = param; - pulse_data *data = Device->ExtraData; - ssize_t len; - - SetRTPriority(); - - pa_threaded_mainloop_lock(data->loop); - do { - len = (Device->Connected ? pa_stream_writable_size(data->stream) : 0); - len -= len%(Device->UpdateSize*data->frame_size); - if(len == 0) - { - pa_threaded_mainloop_wait(data->loop); - continue; - } - - while(len > 0) - { - size_t newlen = len; - void *buf; - pa_free_cb_t free_func = NULL; - -#if PA_CHECK_VERSION(0,9,16) - if(!pa_stream_begin_write || - pa_stream_begin_write(data->stream, &buf, &newlen) < 0) -#endif - { - buf = pa_xmalloc(newlen); - free_func = pa_xfree; - } - pa_threaded_mainloop_unlock(data->loop); - - aluMixData(Device, buf, newlen/data->frame_size); - - pa_threaded_mainloop_lock(data->loop); - pa_stream_write(data->stream, buf, newlen, free_func, 0, PA_SEEK_RELATIVE); - len -= newlen; - } - } while(Device->Connected && !data->killNow); - pa_threaded_mainloop_unlock(data->loop); - - return 0; -} - -static pa_stream *connect_playback_stream(ALCdevice *device, - pa_stream_flags_t flags, pa_buffer_attr *attr, pa_sample_spec *spec, - pa_channel_map *chanmap) -{ - pulse_data *data = device->ExtraData; - pa_stream_state_t state; - pa_stream *stream; - - stream = pa_stream_new(data->context, "Playback Stream", spec, chanmap); - if(!stream) - { - ERR("pa_stream_new() failed: %s\n", - pa_strerror(pa_context_errno(data->context))); - return NULL; - } - - pa_stream_set_state_callback(stream, stream_state_callback, data->loop); - - if(pa_stream_connect_playback(stream, data->device_name, attr, flags, NULL, NULL) < 0) - { - ERR("Stream did not connect: %s\n", - pa_strerror(pa_context_errno(data->context))); - pa_stream_unref(stream); - return NULL; - } - - while((state=pa_stream_get_state(stream)) != PA_STREAM_READY) - { - if(!PA_STREAM_IS_GOOD(state)) - { - ERR("Stream did not get ready: %s\n", - pa_strerror(pa_context_errno(data->context))); - pa_stream_unref(stream); - return NULL; - } - - pa_threaded_mainloop_wait(data->loop); - } - pa_stream_set_state_callback(stream, NULL, NULL); - - return stream; -} - -static void probe_devices(ALboolean capture) -{ - pa_threaded_mainloop *loop; - - if(capture == AL_FALSE) - allDevNameMap = malloc(sizeof(DevMap) * 1); - else - allCaptureDevNameMap = malloc(sizeof(DevMap) * 1); - - if((loop=pa_threaded_mainloop_new()) && - pa_threaded_mainloop_start(loop) >= 0) - { - pa_context *context; - - pa_threaded_mainloop_lock(loop); - context = connect_context(loop, AL_FALSE); - if(context) - { - pa_operation *o; - - if(capture == AL_FALSE) - o = pa_context_get_sink_info_list(context, sink_device_callback, loop); - else - o = pa_context_get_source_info_list(context, source_device_callback, loop); - while(pa_operation_get_state(o) == PA_OPERATION_RUNNING) - pa_threaded_mainloop_wait(loop); - pa_operation_unref(o); - - pa_context_disconnect(context); - pa_context_unref(context); - } - pa_threaded_mainloop_unlock(loop); - pa_threaded_mainloop_stop(loop); - } - if(loop) - pa_threaded_mainloop_free(loop); -} - - -static ALCboolean pulse_open(ALCdevice *device, const ALCchar *device_name) //{{{ -{ - pulse_data *data = pa_xmalloc(sizeof(pulse_data)); - memset(data, 0, sizeof(*data)); - - if(!(data->loop = pa_threaded_mainloop_new())) - { - ERR("pa_threaded_mainloop_new() failed!\n"); - goto out; - } - if(pa_threaded_mainloop_start(data->loop) < 0) - { - ERR("pa_threaded_mainloop_start() failed\n"); - goto out; - } - - pa_threaded_mainloop_lock(data->loop); - device->ExtraData = data; - - data->context = connect_context(data->loop, AL_FALSE); - if(!data->context) - { - pa_threaded_mainloop_unlock(data->loop); - goto out; - } - pa_context_set_state_callback(data->context, context_state_callback2, device); - - device->szDeviceName = strdup(device_name); - - pa_threaded_mainloop_unlock(data->loop); - return ALC_TRUE; - -out: - if(data->loop) - { - pa_threaded_mainloop_stop(data->loop); - pa_threaded_mainloop_free(data->loop); - } - - device->ExtraData = NULL; - pa_xfree(data); - return ALC_FALSE; -} //}}} - -static void pulse_close(ALCdevice *device) //{{{ -{ - pulse_data *data = device->ExtraData; - - pa_threaded_mainloop_lock(data->loop); - - if(data->stream) - { - pa_stream_disconnect(data->stream); - pa_stream_unref(data->stream); - } - - pa_context_disconnect(data->context); - pa_context_unref(data->context); - - pa_threaded_mainloop_unlock(data->loop); - - pa_threaded_mainloop_stop(data->loop); - pa_threaded_mainloop_free(data->loop); - - DestroyRingBuffer(data->ring); - free(data->device_name); - - device->ExtraData = NULL; - pa_xfree(data); -} //}}} -//}}} - -// OpenAL {{{ -static ALCboolean pulse_open_playback(ALCdevice *device, const ALCchar *device_name) //{{{ -{ - char *pulse_name = NULL; - pa_sample_spec spec; - pulse_data *data; - - if(!allDevNameMap) - probe_devices(AL_FALSE); - - if(!device_name) - device_name = pulse_device; - else if(strcmp(device_name, pulse_device) != 0) - { - ALuint i; - - for(i = 0;i < numDevNames;i++) - { - if(strcmp(device_name, allDevNameMap[i].name) == 0) - { - pulse_name = allDevNameMap[i].device_name; - break; - } - } - if(i == numDevNames) - return ALC_FALSE; - } - - if(pulse_open(device, device_name) == ALC_FALSE) - return ALC_FALSE; - - data = device->ExtraData; - - pa_threaded_mainloop_lock(data->loop); - - spec.format = PA_SAMPLE_S16NE; - spec.rate = 44100; - spec.channels = 2; - - data->device_name = pulse_name; - pa_stream *stream = connect_playback_stream(device, 0, NULL, &spec, NULL); - if(!stream) - { - pa_threaded_mainloop_unlock(data->loop); - goto fail; - } - - if(pa_stream_is_suspended(stream)) - { - ERR("Device is suspended\n"); - pa_stream_disconnect(stream); - pa_stream_unref(stream); - pa_threaded_mainloop_unlock(data->loop); - goto fail; - } - data->device_name = strdup(pa_stream_get_device_name(stream)); - - pa_stream_disconnect(stream); - pa_stream_unref(stream); - - pa_threaded_mainloop_unlock(data->loop); - - return ALC_TRUE; - -fail: - pulse_close(device); - return ALC_FALSE; -} //}}} - -static void pulse_close_playback(ALCdevice *device) //{{{ -{ - pulse_close(device); -} //}}} - -static ALCboolean pulse_reset_playback(ALCdevice *device) //{{{ -{ - pulse_data *data = device->ExtraData; - pa_stream_flags_t flags = 0; - pa_channel_map chanmap; - - pa_threaded_mainloop_lock(data->loop); - - if(!(device->Flags&DEVICE_CHANNELS_REQUEST)) - { - pa_operation *o; - o = pa_context_get_sink_info_by_name(data->context, data->device_name, sink_info_callback, device); - while(pa_operation_get_state(o) == PA_OPERATION_RUNNING) - pa_threaded_mainloop_wait(data->loop); - pa_operation_unref(o); - } - if(!(device->Flags&DEVICE_FREQUENCY_REQUEST)) - flags |= PA_STREAM_FIX_RATE; - - data->frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); - data->attr.prebuf = -1; - data->attr.fragsize = -1; - data->attr.minreq = device->UpdateSize * data->frame_size; - data->attr.tlength = data->attr.minreq * device->NumUpdates; - if(data->attr.tlength < data->attr.minreq*2) - data->attr.tlength = data->attr.minreq*2; - data->attr.maxlength = data->attr.tlength; - flags |= PA_STREAM_EARLY_REQUESTS; - flags |= PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE; - - switch(device->FmtType) - { - case DevFmtByte: - device->FmtType = DevFmtUByte; - /* fall-through */ - case DevFmtUByte: - data->spec.format = PA_SAMPLE_U8; - break; - case DevFmtUShort: - device->FmtType = DevFmtShort; - /* fall-through */ - case DevFmtShort: - data->spec.format = PA_SAMPLE_S16NE; - break; - case DevFmtFloat: - data->spec.format = PA_SAMPLE_FLOAT32NE; - break; - } - data->spec.rate = device->Frequency; - data->spec.channels = ChannelsFromDevFmt(device->FmtChans); - - if(pa_sample_spec_valid(&data->spec) == 0) - { - ERR("Invalid sample format\n"); - pa_threaded_mainloop_unlock(data->loop); - return ALC_FALSE; - } - - if(!pa_channel_map_init_auto(&chanmap, data->spec.channels, PA_CHANNEL_MAP_WAVEEX)) - { - ERR("Couldn't build map for channel count (%d)!\n", data->spec.channels); - pa_threaded_mainloop_unlock(data->loop); - return ALC_FALSE; - } - SetDefaultWFXChannelOrder(device); - - data->stream = connect_playback_stream(device, flags, &data->attr, &data->spec, &chanmap); - if(!data->stream) - { - pa_threaded_mainloop_unlock(data->loop); - return ALC_FALSE; - } - - pa_stream_set_state_callback(data->stream, stream_state_callback2, device); - - data->spec = *(pa_stream_get_sample_spec(data->stream)); - if(device->Frequency != data->spec.rate) - { - pa_operation *o; - - if((device->Flags&DEVICE_FREQUENCY_REQUEST)) - ERR("Failed to set frequency %dhz, got %dhz instead\n", device->Frequency, data->spec.rate); - device->Flags &= ~DEVICE_FREQUENCY_REQUEST; - - /* Server updated our playback rate, so modify the buffer attribs - * accordingly. */ - data->attr.minreq = (ALuint64)(data->attr.minreq/data->frame_size) * - data->spec.rate / device->Frequency * data->frame_size; - data->attr.tlength = data->attr.minreq * device->NumUpdates; - data->attr.maxlength = data->attr.tlength; - - o = pa_stream_set_buffer_attr(data->stream, &data->attr, - stream_success_callback, device); - while(pa_operation_get_state(o) == PA_OPERATION_RUNNING) - pa_threaded_mainloop_wait(data->loop); - pa_operation_unref(o); - - device->Frequency = data->spec.rate; - } - - stream_buffer_attr_callback(data->stream, device); -#if PA_CHECK_VERSION(0,9,15) - if(pa_stream_set_buffer_attr_callback) - pa_stream_set_buffer_attr_callback(data->stream, stream_buffer_attr_callback, device); -#endif - pa_stream_set_moved_callback(data->stream, stream_device_callback, device); - pa_stream_set_write_callback(data->stream, stream_write_callback, device); - pa_stream_set_underflow_callback(data->stream, stream_signal_callback, device); - - data->thread = StartThread(PulseProc, device); - if(!data->thread) - { -#if PA_CHECK_VERSION(0,9,15) - if(pa_stream_set_buffer_attr_callback) - pa_stream_set_buffer_attr_callback(data->stream, NULL, NULL); -#endif - pa_stream_set_moved_callback(data->stream, NULL, NULL); - pa_stream_set_write_callback(data->stream, NULL, NULL); - pa_stream_set_underflow_callback(data->stream, NULL, NULL); - pa_stream_disconnect(data->stream); - pa_stream_unref(data->stream); - data->stream = NULL; - - pa_threaded_mainloop_unlock(data->loop); - return ALC_FALSE; - } - - pa_threaded_mainloop_unlock(data->loop); - return ALC_TRUE; -} //}}} - -static void pulse_stop_playback(ALCdevice *device) //{{{ -{ - pulse_data *data = device->ExtraData; - - if(!data->stream) - return; - - data->killNow = AL_TRUE; - if(data->thread) - { - pa_threaded_mainloop_signal(data->loop, 0); - StopThread(data->thread); - data->thread = NULL; - } - data->killNow = AL_FALSE; - - pa_threaded_mainloop_lock(data->loop); - -#if PA_CHECK_VERSION(0,9,15) - if(pa_stream_set_buffer_attr_callback) - pa_stream_set_buffer_attr_callback(data->stream, NULL, NULL); -#endif - pa_stream_set_moved_callback(data->stream, NULL, NULL); - pa_stream_set_write_callback(data->stream, NULL, NULL); - pa_stream_set_underflow_callback(data->stream, NULL, NULL); - pa_stream_disconnect(data->stream); - pa_stream_unref(data->stream); - data->stream = NULL; - - pa_threaded_mainloop_unlock(data->loop); -} //}}} - - -static ALCboolean pulse_open_capture(ALCdevice *device, const ALCchar *device_name) //{{{ -{ - char *pulse_name = NULL; - pulse_data *data; - pa_stream_flags_t flags = 0; - pa_stream_state_t state; - pa_channel_map chanmap; - - if(!allCaptureDevNameMap) - probe_devices(AL_TRUE); - - if(!device_name) - device_name = pulse_device; - else if(strcmp(device_name, pulse_device) != 0) - { - ALuint i; - - for(i = 0;i < numCaptureDevNames;i++) - { - if(strcmp(device_name, allCaptureDevNameMap[i].name) == 0) - { - pulse_name = allCaptureDevNameMap[i].device_name; - break; - } - } - if(i == numCaptureDevNames) - return ALC_FALSE; - } - - if(pulse_open(device, device_name) == ALC_FALSE) - return ALC_FALSE; - - data = device->ExtraData; - pa_threaded_mainloop_lock(data->loop); - - data->samples = device->UpdateSize * device->NumUpdates; - data->frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); - if(data->samples < 100 * device->Frequency / 1000) - data->samples = 100 * device->Frequency / 1000; - - if(!(data->ring = CreateRingBuffer(data->frame_size, data->samples))) - { - pa_threaded_mainloop_unlock(data->loop); - goto fail; - } - - data->attr.minreq = -1; - data->attr.prebuf = -1; - data->attr.maxlength = data->samples * data->frame_size; - data->attr.tlength = -1; - data->attr.fragsize = minu(data->samples, 50*device->Frequency/1000) * - data->frame_size; - - data->spec.rate = device->Frequency; - data->spec.channels = ChannelsFromDevFmt(device->FmtChans); - - switch(device->FmtType) - { - case DevFmtUByte: - data->spec.format = PA_SAMPLE_U8; - break; - case DevFmtShort: - data->spec.format = PA_SAMPLE_S16NE; - break; - case DevFmtFloat: - data->spec.format = PA_SAMPLE_FLOAT32NE; - break; - case DevFmtByte: - case DevFmtUShort: - ERR("Capture format type %#x capture not supported on PulseAudio\n", device->FmtType); - pa_threaded_mainloop_unlock(data->loop); - goto fail; - } - - if(pa_sample_spec_valid(&data->spec) == 0) - { - ERR("Invalid sample format\n"); - pa_threaded_mainloop_unlock(data->loop); - goto fail; - } - - if(!pa_channel_map_init_auto(&chanmap, data->spec.channels, PA_CHANNEL_MAP_WAVEEX)) - { - ERR("Couldn't build map for channel count (%d)!\n", data->spec.channels); - pa_threaded_mainloop_unlock(data->loop); - goto fail; - } - - data->stream = pa_stream_new(data->context, "Capture Stream", &data->spec, &chanmap); - if(!data->stream) - { - ERR("pa_stream_new() failed: %s\n", - pa_strerror(pa_context_errno(data->context))); - - pa_threaded_mainloop_unlock(data->loop); - goto fail; - } - - pa_stream_set_state_callback(data->stream, stream_state_callback, data->loop); - - flags |= PA_STREAM_START_CORKED|PA_STREAM_ADJUST_LATENCY; - if(pa_stream_connect_record(data->stream, pulse_name, &data->attr, flags) < 0) - { - ERR("Stream did not connect: %s\n", - pa_strerror(pa_context_errno(data->context))); - - pa_stream_unref(data->stream); - data->stream = NULL; - - pa_threaded_mainloop_unlock(data->loop); - goto fail; - } - - while((state=pa_stream_get_state(data->stream)) != PA_STREAM_READY) - { - if(!PA_STREAM_IS_GOOD(state)) - { - ERR("Stream did not get ready: %s\n", - pa_strerror(pa_context_errno(data->context))); - - pa_stream_unref(data->stream); - data->stream = NULL; - - pa_threaded_mainloop_unlock(data->loop); - goto fail; - } - - pa_threaded_mainloop_wait(data->loop); - } - pa_stream_set_state_callback(data->stream, stream_state_callback2, device); - - pa_threaded_mainloop_unlock(data->loop); - return ALC_TRUE; - -fail: - pulse_close(device); - return ALC_FALSE; -} //}}} - -static void pulse_close_capture(ALCdevice *device) //{{{ -{ - pulse_close(device); -} //}}} - -static void pulse_start_capture(ALCdevice *device) //{{{ -{ - pulse_data *data = device->ExtraData; - pa_operation *o; - - pa_threaded_mainloop_lock(data->loop); - o = pa_stream_cork(data->stream, 0, stream_success_callback, device); - while(pa_operation_get_state(o) == PA_OPERATION_RUNNING) - pa_threaded_mainloop_wait(data->loop); - pa_operation_unref(o); - pa_threaded_mainloop_unlock(data->loop); -} //}}} - -static void pulse_stop_capture(ALCdevice *device) //{{{ -{ - pulse_data *data = device->ExtraData; - pa_operation *o; - - pa_threaded_mainloop_lock(data->loop); - o = pa_stream_cork(data->stream, 1, stream_success_callback, device); - while(pa_operation_get_state(o) == PA_OPERATION_RUNNING) - pa_threaded_mainloop_wait(data->loop); - pa_operation_unref(o); - pa_threaded_mainloop_unlock(data->loop); -} //}}} - -static ALCuint pulse_available_samples(ALCdevice *device) //{{{ -{ - pulse_data *data = device->ExtraData; - size_t samples; - - pa_threaded_mainloop_lock(data->loop); - /* Capture is done in fragment-sized chunks, so we loop until we get all - * that's available */ - samples = (device->Connected ? pa_stream_readable_size(data->stream) : 0); - while(samples > 0) - { - const void *buf; - size_t length; - - if(pa_stream_peek(data->stream, &buf, &length) < 0) - { - ERR("pa_stream_peek() failed: %s\n", - pa_strerror(pa_context_errno(data->context))); - break; - } - - WriteRingBuffer(data->ring, buf, length/data->frame_size); - samples -= length; - - pa_stream_drop(data->stream); - } - pa_threaded_mainloop_unlock(data->loop); - - return RingBufferSize(data->ring); -} //}}} - -static void pulse_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples) //{{{ -{ - pulse_data *data = device->ExtraData; - - if(pulse_available_samples(device) >= samples) - ReadRingBuffer(data->ring, buffer, samples); - else - alcSetError(device, ALC_INVALID_VALUE); -} //}}} - - -static const BackendFuncs pulse_funcs = { //{{{ - pulse_open_playback, - pulse_close_playback, - pulse_reset_playback, - pulse_stop_playback, - pulse_open_capture, - pulse_close_capture, - pulse_start_capture, - pulse_stop_capture, - pulse_capture_samples, - pulse_available_samples -}; //}}} - -ALCboolean alc_pulse_init(BackendFuncs *func_list) //{{{ -{ - if(!pulse_load()) - return ALC_FALSE; - - *func_list = pulse_funcs; - - pulse_ctx_flags = 0; - if(!GetConfigValueBool("pulse", "spawn-server", 0)) - pulse_ctx_flags |= PA_CONTEXT_NOAUTOSPAWN; - - return ALC_TRUE; -} //}}} - -void alc_pulse_deinit(void) //{{{ -{ - ALuint i; - - for(i = 0;i < numDevNames;++i) - { - free(allDevNameMap[i].name); - free(allDevNameMap[i].device_name); - } - free(allDevNameMap); - allDevNameMap = NULL; - numDevNames = 0; - - for(i = 0;i < numCaptureDevNames;++i) - { - free(allCaptureDevNameMap[i].name); - free(allCaptureDevNameMap[i].device_name); - } - free(allCaptureDevNameMap); - allCaptureDevNameMap = NULL; - numCaptureDevNames = 0; - -#ifdef HAVE_DYNLOAD - if(pa_handle) - CloseLib(pa_handle); - pa_handle = NULL; -#endif -} //}}} - -void alc_pulse_probe(enum DevProbe type) //{{{ -{ - pa_threaded_mainloop *loop; - ALuint i; - - switch(type) - { - case DEVICE_PROBE: - if((loop=pa_threaded_mainloop_new()) && - pa_threaded_mainloop_start(loop) >= 0) - { - pa_context *context; - - pa_threaded_mainloop_lock(loop); - context = connect_context(loop, AL_FALSE); - if(context) - { - AppendDeviceList(pulse_device); - - pa_context_disconnect(context); - pa_context_unref(context); - } - pa_threaded_mainloop_unlock(loop); - pa_threaded_mainloop_stop(loop); - } - if(loop) - pa_threaded_mainloop_free(loop); - break; - - case ALL_DEVICE_PROBE: - for(i = 0;i < numDevNames;++i) - { - free(allDevNameMap[i].name); - free(allDevNameMap[i].device_name); - } - free(allDevNameMap); - allDevNameMap = NULL; - numDevNames = 0; - - probe_devices(AL_FALSE); - - for(i = 0;i < numDevNames;i++) - AppendAllDeviceList(allDevNameMap[i].name); - break; - - case CAPTURE_DEVICE_PROBE: - for(i = 0;i < numCaptureDevNames;++i) - { - free(allCaptureDevNameMap[i].name); - free(allCaptureDevNameMap[i].device_name); - } - free(allCaptureDevNameMap); - allCaptureDevNameMap = NULL; - numCaptureDevNames = 0; - - probe_devices(AL_TRUE); - - for(i = 0;i < numCaptureDevNames;i++) - AppendCaptureDeviceList(allCaptureDevNameMap[i].name); - break; - } -} //}}} -//}}} diff -r c41d773a85fb -r 82b9267a3e19 Alc/backends/sndio.c --- a/Alc/backends/sndio.c Tue Oct 25 13:03:35 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,381 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2007 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#include "config.h" - -#include -#include -#include -#include "alMain.h" -#include "AL/al.h" -#include "AL/alc.h" - -#include - - -static const ALCchar sndio_device[] = "SndIO Default"; - - -static void *sndio_handle; -#ifdef HAVE_DYNLOAD -#define MAKE_FUNC(x) static typeof(x) * p##x -MAKE_FUNC(sio_initpar); -MAKE_FUNC(sio_open); -MAKE_FUNC(sio_close); -MAKE_FUNC(sio_setpar); -MAKE_FUNC(sio_getpar); -MAKE_FUNC(sio_getcap); -MAKE_FUNC(sio_onmove); -MAKE_FUNC(sio_write); -MAKE_FUNC(sio_read); -MAKE_FUNC(sio_start); -MAKE_FUNC(sio_stop); -MAKE_FUNC(sio_nfds); -MAKE_FUNC(sio_pollfd); -MAKE_FUNC(sio_revents); -MAKE_FUNC(sio_eof); -MAKE_FUNC(sio_setvol); -MAKE_FUNC(sio_onvol); - -#define sio_initpar psio_initpar -#define sio_open psio_open -#define sio_close psio_close -#define sio_setpar psio_setpar -#define sio_getpar psio_getpar -#define sio_getcap psio_getcap -#define sio_onmove psio_onmove -#define sio_write psio_write -#define sio_read psio_read -#define sio_start psio_start -#define sio_stop psio_stop -#define sio_nfds psio_nfds -#define sio_pollfd psio_pollfd -#define sio_revents psio_revents -#define sio_eof psio_eof -#define sio_setvol psio_setvol -#define sio_onvol psio_onvol -#endif - - -static ALCboolean sndio_load(void) -{ - if(!sndio_handle) - { -#ifdef HAVE_DYNLOAD - sndio_handle = LoadLib("libsndio.so"); - if(!sndio_handle) - return ALC_FALSE; - -#define LOAD_FUNC(f) do { \ - p##f = GetSymbol(sndio_handle, #f); \ - if(p##f == NULL) { \ - CloseLib(sndio_handle); \ - sndio_handle = NULL; \ - return ALC_FALSE; \ - } \ -} while(0) - LOAD_FUNC(sio_initpar); - LOAD_FUNC(sio_open); - LOAD_FUNC(sio_close); - LOAD_FUNC(sio_setpar); - LOAD_FUNC(sio_getpar); - LOAD_FUNC(sio_getcap); - LOAD_FUNC(sio_onmove); - LOAD_FUNC(sio_write); - LOAD_FUNC(sio_read); - LOAD_FUNC(sio_start); - LOAD_FUNC(sio_stop); - LOAD_FUNC(sio_nfds); - LOAD_FUNC(sio_pollfd); - LOAD_FUNC(sio_revents); - LOAD_FUNC(sio_eof); - LOAD_FUNC(sio_setvol); - LOAD_FUNC(sio_onvol); -#undef LOAD_FUNC -#else - sndio_handle = (void*)0xDEADBEEF; -#endif - } - return ALC_TRUE; -} - - -typedef struct { - struct sio_hdl *sndHandle; - - ALvoid *mix_data; - ALsizei data_size; - - volatile int killNow; - ALvoid *thread; -} sndio_data; - - -static ALuint sndio_proc(ALvoid *ptr) -{ - ALCdevice *device = ptr; - sndio_data *data = device->ExtraData; - ALsizei frameSize; - size_t wrote; - - SetRTPriority(); - - frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); - - while(!data->killNow && device->Connected) - { - ALsizei len = data->data_size; - ALubyte *WritePtr = data->mix_data; - - aluMixData(device, WritePtr, len/frameSize); - while(len > 0 && !data->killNow) - { - wrote = sio_write(data->sndHandle, WritePtr, len); - if(wrote == 0) - { - ERR("sio_write failed\n"); - aluHandleDisconnect(device); - break; - } - - len -= wrote; - WritePtr += wrote; - } - } - - return 0; -} - - - -static ALCboolean sndio_open_playback(ALCdevice *device, const ALCchar *deviceName) -{ - sndio_data *data; - - if(!deviceName) - deviceName = sndio_device; - else if(strcmp(deviceName, sndio_device) != 0) - return ALC_FALSE; - - data = calloc(1, sizeof(*data)); - data->killNow = 0; - - data->sndHandle = sio_open(NULL, SIO_PLAY, 0); - if(data->sndHandle == NULL) - { - free(data); - ERR("Could not open device\n"); - return ALC_FALSE; - } - - device->szDeviceName = strdup(deviceName); - device->ExtraData = data; - - return ALC_TRUE; -} - -static void sndio_close_playback(ALCdevice *device) -{ - sndio_data *data = device->ExtraData; - - sio_close(data->sndHandle); - free(data); - device->ExtraData = NULL; -} - -static ALCboolean sndio_reset_playback(ALCdevice *device) -{ - sndio_data *data = device->ExtraData; - struct sio_par par; - - sio_initpar(&par); - - par.rate = device->Frequency; - - par.pchan = ((device->FmtChans != DevFmtMono) ? 2 : 1); - - switch(device->FmtType) - { - case DevFmtByte: - par.bits = 8; - par.sig = 1; - break; - case DevFmtUByte: - par.bits = 8; - par.sig = 0; - break; - case DevFmtFloat: - device->FmtType = DevFmtShort; - /* fall-through */ - case DevFmtShort: - par.bits = 16; - par.sig = 1; - break; - case DevFmtUShort: - par.bits = 16; - par.sig = 0; - break; - } - par.le = SIO_LE_NATIVE; - - par.round = device->UpdateSize; - par.appbufsz = device->UpdateSize * (device->NumUpdates-1); - if(!par.appbufsz) par.appbufsz = device->UpdateSize; - - - if(!sio_setpar(data->sndHandle, &par) || !sio_getpar(data->sndHandle, &par)) - { - ERR("Failed to set device parameters\n"); - return ALC_FALSE; - } - - if(par.rate != device->Frequency) - { - if((device->Flags&DEVICE_FREQUENCY_REQUEST)) - ERR("Failed to set frequency %uhz, got %uhz instead\n", device->Frequency, par.rate); - device->Flags &= ~DEVICE_FREQUENCY_REQUEST; - device->Frequency = par.rate; - } - - if(par.pchan != ChannelsFromDevFmt(device->FmtChans)) - { - if(par.pchan != 1 && par.pchan != 2) - { - ERR("Unhandled channel count: %u\n", par.pchan); - return ALC_FALSE; - } - if((device->Flags&DEVICE_CHANNELS_REQUEST)) - ERR("Failed to set %s, got %u channels instead\n", DevFmtChannelsString(device->FmtChans), par.pchan); - device->Flags &= ~DEVICE_CHANNELS_REQUEST; - device->FmtChans = ((par.pchan==1) ? DevFmtMono : DevFmtStereo); - } - - if(par.bits != par.bps*8) - { - ERR("Padded samples not supported (%u of %u bits)\n", par.bits, par.bps*8); - return ALC_FALSE; - } - - if(par.bits == 8 && par.sig == 1) - device->FmtType = DevFmtByte; - else if(par.bits == 8 && par.sig == 0) - device->FmtType = DevFmtUByte; - else if(par.bits == 16 && par.sig == 1) - device->FmtType = DevFmtShort; - else if(par.bits == 16 && par.sig == 0) - device->FmtType = DevFmtUShort; - else - { - ERR("Unhandled sample format: %s %u-bit\n", (par.sig?"signed":"unsigned"), par.bits); - return ALC_FALSE; - } - - - device->UpdateSize = par.round; - device->NumUpdates = (par.bufsz/par.round) + 1; - - SetDefaultChannelOrder(device); - - - if(!sio_start(data->sndHandle)) - { - ERR("Error starting playback\n"); - return ALC_FALSE; - } - - data->data_size = device->UpdateSize * par.bps * par.pchan; - data->mix_data = calloc(1, data->data_size); - - data->thread = StartThread(sndio_proc, device); - if(data->thread == NULL) - { - sio_stop(data->sndHandle); - free(data->mix_data); - data->mix_data = NULL; - return ALC_FALSE; - } - - return ALC_TRUE; -} - -static void sndio_stop_playback(ALCdevice *device) -{ - sndio_data *data = device->ExtraData; - - if(!data->thread) - return; - - data->killNow = 1; - StopThread(data->thread); - data->thread = NULL; - - data->killNow = 0; - if(!sio_stop(data->sndHandle)) - ERR("Error stopping device\n"); - - free(data->mix_data); - data->mix_data = NULL; -} - - -static const BackendFuncs sndio_funcs = { - sndio_open_playback, - sndio_close_playback, - sndio_reset_playback, - sndio_stop_playback, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL -}; - -ALCboolean alc_sndio_init(BackendFuncs *func_list) -{ - if(!sndio_load()) - return ALC_FALSE; - *func_list = sndio_funcs; - return ALC_TRUE; -} - -void alc_sndio_deinit(void) -{ -#ifdef HAVE_DYNLOAD - if(sndio_handle) - CloseLib(sndio_handle); - sndio_handle = NULL; -#endif -} - -void alc_sndio_probe(enum DevProbe type) -{ - switch(type) - { - case DEVICE_PROBE: - AppendDeviceList(sndio_device); - break; - case ALL_DEVICE_PROBE: - AppendAllDeviceList(sndio_device); - break; - case CAPTURE_DEVICE_PROBE: - break; - } -} diff -r c41d773a85fb -r 82b9267a3e19 Alc/backends/solaris.c --- a/Alc/backends/solaris.c Tue Oct 25 13:03:35 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,282 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2007 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "alMain.h" -#include "AL/al.h" -#include "AL/alc.h" - -#include - - -static const ALCchar solaris_device[] = "Solaris Default"; - -typedef struct { - int fd; - volatile int killNow; - ALvoid *thread; - - ALubyte *mix_data; - int data_size; -} solaris_data; - - -static ALuint SolarisProc(ALvoid *ptr) -{ - ALCdevice *pDevice = (ALCdevice*)ptr; - solaris_data *data = (solaris_data*)pDevice->ExtraData; - ALint frameSize; - int wrote; - - SetRTPriority(); - - frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); - - while(!data->killNow && pDevice->Connected) - { - ALint len = data->data_size; - ALubyte *WritePtr = data->mix_data; - - aluMixData(pDevice, WritePtr, len/frameSize); - while(len > 0 && !data->killNow) - { - wrote = write(data->fd, WritePtr, len); - if(wrote < 0) - { - if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) - { - ERR("write failed: %s\n", strerror(errno)); - aluHandleDisconnect(pDevice); - break; - } - - Sleep(1); - continue; - } - - len -= wrote; - WritePtr += wrote; - } - } - - return 0; -} - - -static ALCboolean solaris_open_playback(ALCdevice *device, const ALCchar *deviceName) -{ - char driver[64]; - solaris_data *data; - - strncpy(driver, GetConfigValue("solaris", "device", "/dev/audio"), sizeof(driver)-1); - driver[sizeof(driver)-1] = 0; - - if(!deviceName) - deviceName = solaris_device; - else if(strcmp(deviceName, solaris_device) != 0) - return ALC_FALSE; - - data = (solaris_data*)calloc(1, sizeof(solaris_data)); - data->killNow = 0; - - data->fd = open(driver, O_WRONLY); - if(data->fd == -1) - { - free(data); - ERR("Could not open %s: %s\n", driver, strerror(errno)); - return ALC_FALSE; - } - - device->szDeviceName = strdup(deviceName); - device->ExtraData = data; - return ALC_TRUE; -} - -static void solaris_close_playback(ALCdevice *device) -{ - solaris_data *data = (solaris_data*)device->ExtraData; - - close(data->fd); - free(data); - device->ExtraData = NULL; -} - -static ALCboolean solaris_reset_playback(ALCdevice *device) -{ - solaris_data *data = (solaris_data*)device->ExtraData; - audio_info_t info; - ALuint frameSize; - int numChannels; - - AUDIO_INITINFO(&info); - - info.play.sample_rate = device->Frequency; - - if(device->FmtChans != DevFmtMono) - device->FmtChans = DevFmtStereo; - numChannels = ChannelsFromDevFmt(device->FmtChans); - info.play.channels = numChannels; - - switch(device->FmtType) - { - case DevFmtByte: - info.play.precision = 8; - info.play.encoding = AUDIO_ENCODING_LINEAR; - break; - case DevFmtUByte: - info.play.precision = 8; - info.play.encoding = AUDIO_ENCODING_LINEAR8; - break; - case DevFmtUShort: - case DevFmtFloat: - device->FmtType = DevFmtShort; - /* fall-through */ - case DevFmtShort: - info.play.precision = 16; - info.play.encoding = AUDIO_ENCODING_LINEAR; - break; - } - - frameSize = numChannels * BytesFromDevFmt(device->FmtType); - info.play.buffer_size = device->UpdateSize*device->NumUpdates * frameSize; - - if(ioctl(data->fd, AUDIO_SETINFO, &info) < 0) - { - ERR("ioctl failed: %s\n", strerror(errno)); - return ALC_FALSE; - } - - if(ChannelsFromDevFmt(device->FmtChans) != info.play.channels) - { - ERR("Could not set %d channels, got %d instead\n", ChannelsFromDevFmt(device->FmtChans), info.play.channels); - return ALC_FALSE; - } - - if(!((info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR && - device->FmtType == DevFmtByte) || - (info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR8 && - device->FmtType == DevFmtUByte) || - (info.play.precision == 16 && info.play.encoding == AUDIO_ENCODING_LINEAR && - device->FmtType == DevFmtShort))) - { - ERR("Could not set %#x sample type, got %d (%#x)\n", - device->FmtType, info.play.precision, info.play.encoding); - return ALC_FALSE; - } - - if(device->Frequency != info.play.sample_rate) - { - if((device->Flags&DEVICE_FREQUENCY_REQUEST)) - ERR("Failed to set requested frequency %dhz, got %dhz instead\n", device->Frequency, info.play.sample_rate); - device->Flags &= ~DEVICE_FREQUENCY_REQUEST; - device->Frequency = info.play.sample_rate; - } - device->UpdateSize = (info.play.buffer_size/device->NumUpdates) + 1; - - data->data_size = device->UpdateSize * frameSize; - data->mix_data = calloc(1, data->data_size); - - SetDefaultChannelOrder(device); - - data->thread = StartThread(SolarisProc, device); - if(data->thread == NULL) - { - free(data->mix_data); - data->mix_data = NULL; - return ALC_FALSE; - } - - return ALC_TRUE; -} - -static void solaris_stop_playback(ALCdevice *device) -{ - solaris_data *data = (solaris_data*)device->ExtraData; - - if(!data->thread) - return; - - data->killNow = 1; - StopThread(data->thread); - data->thread = NULL; - - data->killNow = 0; - if(ioctl(data->fd, AUDIO_DRAIN) < 0) - ERR("Error draining device: %s\n", strerror(errno)); - - free(data->mix_data); - data->mix_data = NULL; -} - - -static const BackendFuncs solaris_funcs = { - solaris_open_playback, - solaris_close_playback, - solaris_reset_playback, - solaris_stop_playback, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL -}; - -ALCboolean alc_solaris_init(BackendFuncs *func_list) -{ - *func_list = solaris_funcs; - return ALC_TRUE; -} - -void alc_solaris_deinit(void) -{ -} - -void alc_solaris_probe(enum DevProbe type) -{ -#ifdef HAVE_STAT - struct stat buf; - if(stat(GetConfigValue("solaris", "device", "/dev/audio"), &buf) != 0) - return; -#endif - - switch(type) - { - case DEVICE_PROBE: - AppendDeviceList(solaris_device); - break; - case ALL_DEVICE_PROBE: - AppendAllDeviceList(solaris_device); - break; - case CAPTURE_DEVICE_PROBE: - break; - } -} diff -r c41d773a85fb -r 82b9267a3e19 Alc/backends/wave.c --- a/Alc/backends/wave.c Tue Oct 25 13:03:35 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,357 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2007 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#include "config.h" - -#include -#include -#include -#include "alMain.h" -#include "AL/al.h" -#include "AL/alc.h" - - -typedef struct { - FILE *f; - long DataStart; - - ALvoid *buffer; - ALuint size; - - volatile int killNow; - ALvoid *thread; -} wave_data; - - -static const ALCchar waveDevice[] = "Wave File Writer"; - -static const ALubyte SUBTYPE_PCM[] = { - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, - 0x00, 0x38, 0x9b, 0x71 -}; -static const ALubyte SUBTYPE_FLOAT[] = { - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, - 0x00, 0x38, 0x9b, 0x71 -}; - -static const ALuint channel_masks[] = { - 0, /* invalid */ - 0x4, /* Mono */ - 0x1 | 0x2, /* Stereo */ - 0, /* 3 channel */ - 0x1 | 0x2 | 0x10 | 0x20, /* Quad */ - 0, /* 5 channel */ - 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20, /* 5.1 */ - 0x1 | 0x2 | 0x4 | 0x8 | 0x100 | 0x200 | 0x400, /* 6.1 */ - 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x200 | 0x400, /* 7.1 */ -}; - - -static void fwrite16le(ALushort val, FILE *f) -{ - fputc(val&0xff, f); - fputc((val>>8)&0xff, f); -} - -static void fwrite32le(ALuint val, FILE *f) -{ - fputc(val&0xff, f); - fputc((val>>8)&0xff, f); - fputc((val>>16)&0xff, f); - fputc((val>>24)&0xff, f); -} - - -static ALuint WaveProc(ALvoid *ptr) -{ - ALCdevice *pDevice = (ALCdevice*)ptr; - wave_data *data = (wave_data*)pDevice->ExtraData; - ALuint frameSize; - ALuint now, start; - ALuint64 avail, done; - size_t fs; - union { - short s; - char b[sizeof(short)]; - } uSB; - const ALuint restTime = (ALuint64)pDevice->UpdateSize * 1000 / - pDevice->Frequency / 2; - - uSB.s = 1; - frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); - - done = 0; - start = timeGetTime(); - while(!data->killNow && pDevice->Connected) - { - now = timeGetTime(); - - avail = (ALuint64)(now-start) * pDevice->Frequency / 1000; - if(avail < done) - { - /* Timer wrapped. Add the remainder of the cycle to the available - * count and reset the number of samples done */ - avail += (ALuint64)0xFFFFFFFFu*pDevice->Frequency/1000 - done; - done = 0; - } - if(avail-done < pDevice->UpdateSize) - { - Sleep(restTime); - continue; - } - - while(avail-done >= pDevice->UpdateSize) - { - aluMixData(pDevice, data->buffer, pDevice->UpdateSize); - done += pDevice->UpdateSize; - - if(uSB.b[0] != 1) - { - ALuint bytesize = BytesFromDevFmt(pDevice->FmtType); - ALubyte *bytes = data->buffer; - ALuint i; - - if(bytesize == 1) - { - for(i = 0;i < data->size;i++) - fputc(bytes[i], data->f); - } - else if(bytesize == 2) - { - for(i = 0;i < data->size;i++) - fputc(bytes[i^1], data->f); - } - else if(bytesize == 4) - { - for(i = 0;i < data->size;i++) - fputc(bytes[i^3], data->f); - } - } - else - fs = fwrite(data->buffer, frameSize, pDevice->UpdateSize, - data->f); - if(ferror(data->f)) - { - ERR("Error writing to file\n"); - aluHandleDisconnect(pDevice); - break; - } - } - } - - return 0; -} - -static ALCboolean wave_open_playback(ALCdevice *device, const ALCchar *deviceName) -{ - wave_data *data; - const char *fname; - - fname = GetConfigValue("wave", "file", ""); - if(!fname[0]) - return ALC_FALSE; - - if(!deviceName) - deviceName = waveDevice; - else if(strcmp(deviceName, waveDevice) != 0) - return ALC_FALSE; - - data = (wave_data*)calloc(1, sizeof(wave_data)); - - data->f = fopen(fname, "wb"); - if(!data->f) - { - free(data); - ERR("Could not open file '%s': %s\n", fname, strerror(errno)); - return ALC_FALSE; - } - - device->szDeviceName = strdup(deviceName); - device->ExtraData = data; - return ALC_TRUE; -} - -static void wave_close_playback(ALCdevice *device) -{ - wave_data *data = (wave_data*)device->ExtraData; - - fclose(data->f); - free(data); - device->ExtraData = NULL; -} - -static ALCboolean wave_reset_playback(ALCdevice *device) -{ - wave_data *data = (wave_data*)device->ExtraData; - ALuint channels=0, bits=0; - size_t val; - - fseek(data->f, 0, SEEK_SET); - clearerr(data->f); - - switch(device->FmtType) - { - case DevFmtByte: - device->FmtType = DevFmtUByte; - break; - case DevFmtUShort: - device->FmtType = DevFmtShort; - break; - case DevFmtUByte: - case DevFmtShort: - case DevFmtFloat: - break; - } - bits = BytesFromDevFmt(device->FmtType) * 8; - channels = ChannelsFromDevFmt(device->FmtChans); - - fprintf(data->f, "RIFF"); - fwrite32le(0xFFFFFFFF, data->f); // 'RIFF' header len; filled in at close - - fprintf(data->f, "WAVE"); - - fprintf(data->f, "fmt "); - fwrite32le(40, data->f); // 'fmt ' header len; 40 bytes for EXTENSIBLE - - // 16-bit val, format type id (extensible: 0xFFFE) - fwrite16le(0xFFFE, data->f); - // 16-bit val, channel count - fwrite16le(channels, data->f); - // 32-bit val, frequency - fwrite32le(device->Frequency, data->f); - // 32-bit val, bytes per second - fwrite32le(device->Frequency * channels * bits / 8, data->f); - // 16-bit val, frame size - fwrite16le(channels * bits / 8, data->f); - // 16-bit val, bits per sample - fwrite16le(bits, data->f); - // 16-bit val, extra byte count - fwrite16le(22, data->f); - // 16-bit val, valid bits per sample - fwrite16le(bits, data->f); - // 32-bit val, channel mask - fwrite32le(channel_masks[channels], data->f); - // 16 byte GUID, sub-type format - val = fwrite(((bits==32) ? SUBTYPE_FLOAT : SUBTYPE_PCM), 1, 16, data->f); - - fprintf(data->f, "data"); - fwrite32le(0xFFFFFFFF, data->f); // 'data' header len; filled in at close - - if(ferror(data->f)) - { - ERR("Error writing header: %s\n", strerror(errno)); - return ALC_FALSE; - } - - data->DataStart = ftell(data->f); - - data->size = device->UpdateSize * channels * bits / 8; - data->buffer = malloc(data->size); - if(!data->buffer) - { - ERR("Buffer malloc failed\n"); - return ALC_FALSE; - } - - SetDefaultWFXChannelOrder(device); - - data->thread = StartThread(WaveProc, device); - if(data->thread == NULL) - { - free(data->buffer); - data->buffer = NULL; - return ALC_FALSE; - } - - return ALC_TRUE; -} - -static void wave_stop_playback(ALCdevice *device) -{ - wave_data *data = (wave_data*)device->ExtraData; - ALuint dataLen; - long size; - - if(!data->thread) - return; - - data->killNow = 1; - StopThread(data->thread); - data->thread = NULL; - - data->killNow = 0; - - free(data->buffer); - data->buffer = NULL; - - size = ftell(data->f); - if(size > 0) - { - dataLen = size - data->DataStart; - if(fseek(data->f, data->DataStart-4, SEEK_SET) == 0) - fwrite32le(dataLen, data->f); // 'data' header len - if(fseek(data->f, 4, SEEK_SET) == 0) - fwrite32le(size-8, data->f); // 'WAVE' header len - } -} - - -static const BackendFuncs wave_funcs = { - wave_open_playback, - wave_close_playback, - wave_reset_playback, - wave_stop_playback, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL -}; - -ALCboolean alc_wave_init(BackendFuncs *func_list) -{ - *func_list = wave_funcs; - printf("WAVE: I'm init!!\n"); - return ALC_TRUE; -} - -void alc_wave_deinit(void) -{ -} - -void alc_wave_probe(enum DevProbe type) -{ - printf("WAVE: I'm being probed :)\n"); - if(!ConfigValueExists("wave", "file")) - return; - - switch(type) - { - case DEVICE_PROBE: - AppendDeviceList(waveDevice); - break; - case ALL_DEVICE_PROBE: - AppendAllDeviceList(waveDevice); - break; - case CAPTURE_DEVICE_PROBE: - break; - } -} diff -r c41d773a85fb -r 82b9267a3e19 Alc/backends/winmm.c --- a/Alc/backends/winmm.c Tue Oct 25 13:03:35 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,780 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2007 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#include "config.h" - -#define _WIN32_WINNT 0x0500 -#include -#include -#include - -#include -#include - -#include "alMain.h" -#include "AL/al.h" -#include "AL/alc.h" - - -typedef struct { - // MMSYSTEM Device - volatile ALboolean bWaveShutdown; - HANDLE hWaveThreadEvent; - HANDLE hWaveThread; - DWORD ulWaveThreadID; - LONG lWaveBuffersCommitted; - WAVEHDR WaveBuffer[4]; - - union { - HWAVEIN In; - HWAVEOUT Out; - } hWaveHandle; - - ALuint Frequency; - - RingBuffer *pRing; -} WinMMData; - - -static const ALCchar woDefault[] = "WaveOut Default"; - -static ALCchar **PlaybackDeviceList; -static ALuint NumPlaybackDevices; -static ALCchar **CaptureDeviceList; -static ALuint NumCaptureDevices; - - -static void ProbePlaybackDevices(void) -{ - ALuint i; - - for(i = 0;i < NumPlaybackDevices;i++) - free(PlaybackDeviceList[i]); - - NumPlaybackDevices = waveOutGetNumDevs(); - PlaybackDeviceList = realloc(PlaybackDeviceList, sizeof(ALCchar*) * NumPlaybackDevices); - for(i = 0;i < NumPlaybackDevices;i++) - { - WAVEOUTCAPS WaveCaps; - - PlaybackDeviceList[i] = NULL; - if(waveOutGetDevCaps(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR) - { - char name[1024]; - ALuint count, j; - - count = 0; - do { - if(count == 0) - snprintf(name, sizeof(name), "%s", WaveCaps.szPname); - else - snprintf(name, sizeof(name), "%s #%d", WaveCaps.szPname, count+1); - count++; - - for(j = 0;j < i;j++) - { - if(strcmp(name, PlaybackDeviceList[j]) == 0) - break; - } - } while(j != i); - - PlaybackDeviceList[i] = strdup(name); - } - } -} - -static void ProbeCaptureDevices(void) -{ - ALuint i; - - for(i = 0;i < NumCaptureDevices;i++) - free(CaptureDeviceList[i]); - - NumCaptureDevices = waveInGetNumDevs(); - CaptureDeviceList = realloc(CaptureDeviceList, sizeof(ALCchar*) * NumCaptureDevices); - for(i = 0;i < NumCaptureDevices;i++) - { - WAVEINCAPS WaveInCaps; - - CaptureDeviceList[i] = NULL; - if(waveInGetDevCaps(i, &WaveInCaps, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) - { - char name[1024]; - ALuint count, j; - - count = 0; - do { - if(count == 0) - snprintf(name, sizeof(name), "%s", WaveInCaps.szPname); - else - snprintf(name, sizeof(name), "%s #%d", WaveInCaps.szPname, count+1); - count++; - - for(j = 0;j < i;j++) - { - if(strcmp(name, CaptureDeviceList[j]) == 0) - break; - } - } while(j != i); - - CaptureDeviceList[i] = strdup(name); - } - } -} - - -/* - WaveOutProc - - Posts a message to 'PlaybackThreadProc' everytime a WaveOut Buffer is completed and - returns to the application (for more data) -*/ -static void CALLBACK WaveOutProc(HWAVEOUT hDevice,UINT uMsg,DWORD_PTR dwInstance,DWORD_PTR dwParam1,DWORD_PTR dwParam2) -{ - ALCdevice *pDevice = (ALCdevice*)dwInstance; - WinMMData *pData = pDevice->ExtraData; - - (void)hDevice; - (void)dwParam2; - - if(uMsg != WOM_DONE) - return; - - // Decrement number of buffers in use - InterlockedDecrement(&pData->lWaveBuffersCommitted); - - if(pData->bWaveShutdown == AL_FALSE) - { - // Notify Wave Processor Thread that a Wave Header has returned - PostThreadMessage(pData->ulWaveThreadID, uMsg, 0, dwParam1); - } - else - { - if(pData->lWaveBuffersCommitted == 0) - { - // Post 'Quit' Message to WaveOut Processor Thread - PostThreadMessage(pData->ulWaveThreadID, WM_QUIT, 0, 0); - } - } -} - -/* - PlaybackThreadProc - - Used by "MMSYSTEM" Device. Called when a WaveOut buffer has used up its - audio data. -*/ -static DWORD WINAPI PlaybackThreadProc(LPVOID lpParameter) -{ - ALCdevice *pDevice = (ALCdevice*)lpParameter; - WinMMData *pData = pDevice->ExtraData; - LPWAVEHDR pWaveHdr; - ALuint FrameSize; - MSG msg; - - FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); - - SetRTPriority(); - - while(GetMessage(&msg, NULL, 0, 0)) - { - if(msg.message != WOM_DONE || pData->bWaveShutdown) - continue; - - pWaveHdr = ((LPWAVEHDR)msg.lParam); - - aluMixData(pDevice, pWaveHdr->lpData, pWaveHdr->dwBufferLength/FrameSize); - - // Send buffer back to play more data - waveOutWrite(pData->hWaveHandle.Out, pWaveHdr, sizeof(WAVEHDR)); - InterlockedIncrement(&pData->lWaveBuffersCommitted); - } - - // Signal Wave Thread completed event - if(pData->hWaveThreadEvent) - SetEvent(pData->hWaveThreadEvent); - - ExitThread(0); - - return 0; -} - -/* - WaveInProc - - Posts a message to 'CaptureThreadProc' everytime a WaveIn Buffer is completed and - returns to the application (with more data) -*/ -static void CALLBACK WaveInProc(HWAVEIN hDevice,UINT uMsg,DWORD_PTR dwInstance,DWORD_PTR dwParam1,DWORD_PTR dwParam2) -{ - ALCdevice *pDevice = (ALCdevice*)dwInstance; - WinMMData *pData = pDevice->ExtraData; - - (void)hDevice; - (void)dwParam2; - - if(uMsg != WIM_DATA) - return; - - // Decrement number of buffers in use - InterlockedDecrement(&pData->lWaveBuffersCommitted); - - if(pData->bWaveShutdown == AL_FALSE) - { - // Notify Wave Processor Thread that a Wave Header has returned - PostThreadMessage(pData->ulWaveThreadID,uMsg,0,dwParam1); - } - else - { - if(pData->lWaveBuffersCommitted == 0) - { - // Post 'Quit' Message to WaveIn Processor Thread - PostThreadMessage(pData->ulWaveThreadID,WM_QUIT,0,0); - } - } -} - -/* - CaptureThreadProc - - Used by "MMSYSTEM" Device. Called when a WaveIn buffer had been filled with new - audio data. -*/ -static DWORD WINAPI CaptureThreadProc(LPVOID lpParameter) -{ - ALCdevice *pDevice = (ALCdevice*)lpParameter; - WinMMData *pData = pDevice->ExtraData; - LPWAVEHDR pWaveHdr; - ALuint FrameSize; - MSG msg; - - FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); - - while(GetMessage(&msg, NULL, 0, 0)) - { - if(msg.message != WIM_DATA || pData->bWaveShutdown) - continue; - - pWaveHdr = ((LPWAVEHDR)msg.lParam); - - WriteRingBuffer(pData->pRing, (ALubyte*)pWaveHdr->lpData, - pWaveHdr->dwBytesRecorded/FrameSize); - - // Send buffer back to capture more data - waveInAddBuffer(pData->hWaveHandle.In,pWaveHdr,sizeof(WAVEHDR)); - InterlockedIncrement(&pData->lWaveBuffersCommitted); - } - - // Signal Wave Thread completed event - if(pData->hWaveThreadEvent) - SetEvent(pData->hWaveThreadEvent); - - ExitThread(0); - - return 0; -} - - -static ALCboolean WinMMOpenPlayback(ALCdevice *pDevice, const ALCchar *deviceName) -{ - WAVEFORMATEX wfexFormat; - WinMMData *pData = NULL; - UINT lDeviceID = 0; - MMRESULT res; - ALuint i = 0; - - // Find the Device ID matching the deviceName if valid - if(!deviceName || strcmp(deviceName, woDefault) == 0) - lDeviceID = WAVE_MAPPER; - else - { - if(!PlaybackDeviceList) - ProbePlaybackDevices(); - - for(i = 0;i < NumPlaybackDevices;i++) - { - if(PlaybackDeviceList[i] && - strcmp(deviceName, PlaybackDeviceList[i]) == 0) - { - lDeviceID = i; - break; - } - } - if(i == NumPlaybackDevices) - return ALC_FALSE; - } - - pData = calloc(1, sizeof(*pData)); - if(!pData) - { - alcSetError(pDevice, ALC_OUT_OF_MEMORY); - return ALC_FALSE; - } - pDevice->ExtraData = pData; - - if(pDevice->FmtChans != DevFmtMono) - { - if((pDevice->Flags&DEVICE_CHANNELS_REQUEST) && - pDevice->FmtChans != DevFmtStereo) - { - ERR("Failed to set %s, got Stereo instead\n", DevFmtChannelsString(pDevice->FmtChans)); - pDevice->Flags &= ~DEVICE_CHANNELS_REQUEST; - } - pDevice->FmtChans = DevFmtStereo; - } - switch(pDevice->FmtType) - { - case DevFmtByte: - pDevice->FmtType = DevFmtUByte; - break; - case DevFmtUShort: - case DevFmtFloat: - pDevice->FmtType = DevFmtShort; - break; - case DevFmtUByte: - case DevFmtShort: - break; - } - - memset(&wfexFormat, 0, sizeof(WAVEFORMATEX)); - wfexFormat.wFormatTag = WAVE_FORMAT_PCM; - wfexFormat.nChannels = ChannelsFromDevFmt(pDevice->FmtChans); - wfexFormat.wBitsPerSample = BytesFromDevFmt(pDevice->FmtType) * 8; - wfexFormat.nBlockAlign = wfexFormat.wBitsPerSample * - wfexFormat.nChannels / 8; - wfexFormat.nSamplesPerSec = pDevice->Frequency; - wfexFormat.nAvgBytesPerSec = wfexFormat.nSamplesPerSec * - wfexFormat.nBlockAlign; - wfexFormat.cbSize = 0; - - if((res=waveOutOpen(&pData->hWaveHandle.Out, lDeviceID, &wfexFormat, (DWORD_PTR)&WaveOutProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR) - { - ERR("waveOutOpen failed: %u\n", res); - goto failure; - } - - pData->hWaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if(pData->hWaveThreadEvent == NULL) - { - ERR("CreateEvent failed: %lu\n", GetLastError()); - goto failure; - } - - pData->Frequency = pDevice->Frequency; - - pDevice->szDeviceName = strdup((lDeviceID==WAVE_MAPPER) ? woDefault : - PlaybackDeviceList[lDeviceID]); - return ALC_TRUE; - -failure: - if(pData->hWaveThreadEvent) - CloseHandle(pData->hWaveThreadEvent); - - if(pData->hWaveHandle.Out) - waveOutClose(pData->hWaveHandle.Out); - - free(pData); - pDevice->ExtraData = NULL; - return ALC_FALSE; -} - -static void WinMMClosePlayback(ALCdevice *device) -{ - WinMMData *pData = (WinMMData*)device->ExtraData; - - // Close the Wave device - CloseHandle(pData->hWaveThreadEvent); - pData->hWaveThreadEvent = 0; - - waveOutClose(pData->hWaveHandle.Out); - pData->hWaveHandle.Out = 0; - - free(pData); - device->ExtraData = NULL; -} - -static ALCboolean WinMMResetPlayback(ALCdevice *device) -{ - WinMMData *pData = (WinMMData*)device->ExtraData; - ALbyte *BufferData; - ALint lBufferSize; - ALuint i; - - pData->hWaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlaybackThreadProc, (LPVOID)device, 0, &pData->ulWaveThreadID); - if(pData->hWaveThread == NULL) - return ALC_FALSE; - - device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize * - pData->Frequency / device->Frequency); - if(device->Frequency != pData->Frequency) - { - if((device->Flags&DEVICE_FREQUENCY_REQUEST)) - ERR("WinMM does not support changing sample rates (wanted %dhz, got %dhz)\n", device->Frequency, pData->Frequency); - device->Flags &= ~DEVICE_FREQUENCY_REQUEST; - device->Frequency = pData->Frequency; - } - - SetDefaultWFXChannelOrder(device); - - pData->lWaveBuffersCommitted = 0; - - // Create 4 Buffers - lBufferSize = device->UpdateSize*device->NumUpdates / 4; - lBufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType); - - BufferData = calloc(4, lBufferSize); - for(i = 0;i < 4;i++) - { - memset(&pData->WaveBuffer[i], 0, sizeof(WAVEHDR)); - pData->WaveBuffer[i].dwBufferLength = lBufferSize; - pData->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData : - (pData->WaveBuffer[i-1].lpData + - pData->WaveBuffer[i-1].dwBufferLength)); - waveOutPrepareHeader(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR)); - waveOutWrite(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR)); - InterlockedIncrement(&pData->lWaveBuffersCommitted); - } - - return ALC_TRUE; -} - -static void WinMMStopPlayback(ALCdevice *device) -{ - WinMMData *pData = (WinMMData*)device->ExtraData; - void *buffer = NULL; - int i; - - if(pData->hWaveThread == NULL) - return; - - // Set flag to stop processing headers - pData->bWaveShutdown = AL_TRUE; - - // Wait for signal that Wave Thread has been destroyed - WaitForSingleObjectEx(pData->hWaveThreadEvent, 5000, FALSE); - - CloseHandle(pData->hWaveThread); - pData->hWaveThread = 0; - - pData->bWaveShutdown = AL_FALSE; - - // Release the wave buffers - for(i = 0;i < 4;i++) - { - waveOutUnprepareHeader(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR)); - if(i == 0) buffer = pData->WaveBuffer[i].lpData; - pData->WaveBuffer[i].lpData = NULL; - } - free(buffer); -} - - -static ALCboolean WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName) -{ - WAVEFORMATEX wfexCaptureFormat; - DWORD ulCapturedDataSize; - WinMMData *pData = NULL; - UINT lDeviceID = 0; - ALbyte *BufferData; - ALint lBufferSize; - MMRESULT res; - ALuint i; - - if(!CaptureDeviceList) - ProbeCaptureDevices(); - - // Find the Device ID matching the deviceName if valid - if(deviceName) - { - for(i = 0;i < NumCaptureDevices;i++) - { - if(CaptureDeviceList[i] && - strcmp(deviceName, CaptureDeviceList[i]) == 0) - { - lDeviceID = i; - break; - } - } - } - else - { - for(i = 0;i < NumCaptureDevices;i++) - { - if(CaptureDeviceList[i]) - { - lDeviceID = i; - break; - } - } - } - if(i == NumCaptureDevices) - return ALC_FALSE; - - pData = calloc(1, sizeof(*pData)); - if(!pData) - { - alcSetError(pDevice, ALC_OUT_OF_MEMORY); - return ALC_FALSE; - } - pDevice->ExtraData = pData; - - if((pDevice->FmtChans != DevFmtMono && pDevice->FmtChans != DevFmtStereo) || - (pDevice->FmtType != DevFmtUByte && pDevice->FmtType != DevFmtShort)) - { - alcSetError(pDevice, ALC_INVALID_ENUM); - goto failure; - } - - memset(&wfexCaptureFormat, 0, sizeof(WAVEFORMATEX)); - wfexCaptureFormat.wFormatTag = WAVE_FORMAT_PCM; - wfexCaptureFormat.nChannels = ChannelsFromDevFmt(pDevice->FmtChans); - wfexCaptureFormat.wBitsPerSample = BytesFromDevFmt(pDevice->FmtType) * 8; - wfexCaptureFormat.nBlockAlign = wfexCaptureFormat.wBitsPerSample * - wfexCaptureFormat.nChannels / 8; - wfexCaptureFormat.nSamplesPerSec = pDevice->Frequency; - wfexCaptureFormat.nAvgBytesPerSec = wfexCaptureFormat.nSamplesPerSec * - wfexCaptureFormat.nBlockAlign; - wfexCaptureFormat.cbSize = 0; - - if((res=waveInOpen(&pData->hWaveHandle.In, lDeviceID, &wfexCaptureFormat, (DWORD_PTR)&WaveInProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR) - { - ERR("waveInOpen failed: %u\n", res); - goto failure; - } - - pData->hWaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if(pData->hWaveThreadEvent == NULL) - { - ERR("CreateEvent failed: %lu\n", GetLastError()); - goto failure; - } - - pData->Frequency = pDevice->Frequency; - - // Allocate circular memory buffer for the captured audio - ulCapturedDataSize = pDevice->UpdateSize*pDevice->NumUpdates; - - // Make sure circular buffer is at least 100ms in size - if(ulCapturedDataSize < (wfexCaptureFormat.nSamplesPerSec / 10)) - ulCapturedDataSize = wfexCaptureFormat.nSamplesPerSec / 10; - - pData->pRing = CreateRingBuffer(wfexCaptureFormat.nBlockAlign, ulCapturedDataSize); - if(!pData->pRing) - goto failure; - - pData->lWaveBuffersCommitted = 0; - - // Create 4 Buffers of 50ms each - lBufferSize = wfexCaptureFormat.nAvgBytesPerSec / 20; - lBufferSize -= (lBufferSize % wfexCaptureFormat.nBlockAlign); - - BufferData = calloc(4, lBufferSize); - if(!BufferData) - goto failure; - - for(i = 0;i < 4;i++) - { - memset(&pData->WaveBuffer[i], 0, sizeof(WAVEHDR)); - pData->WaveBuffer[i].dwBufferLength = lBufferSize; - pData->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData : - (pData->WaveBuffer[i-1].lpData + - pData->WaveBuffer[i-1].dwBufferLength)); - pData->WaveBuffer[i].dwFlags = 0; - pData->WaveBuffer[i].dwLoops = 0; - waveInPrepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR)); - waveInAddBuffer(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR)); - InterlockedIncrement(&pData->lWaveBuffersCommitted); - } - - pData->hWaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CaptureThreadProc, (LPVOID)pDevice, 0, &pData->ulWaveThreadID); - if (pData->hWaveThread == NULL) - goto failure; - - pDevice->szDeviceName = strdup(CaptureDeviceList[lDeviceID]); - return ALC_TRUE; - -failure: - if(pData->hWaveThread) - CloseHandle(pData->hWaveThread); - - for(i = 0;i < 4;i++) - { - if(pData->WaveBuffer[i].lpData) - { - waveInUnprepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR)); - if(i == 0) - free(pData->WaveBuffer[i].lpData); - } - } - - if(pData->pRing) - DestroyRingBuffer(pData->pRing); - - if(pData->hWaveThreadEvent) - CloseHandle(pData->hWaveThreadEvent); - - if(pData->hWaveHandle.In) - waveInClose(pData->hWaveHandle.In); - - free(pData); - pDevice->ExtraData = NULL; - return ALC_FALSE; -} - -static void WinMMCloseCapture(ALCdevice *pDevice) -{ - WinMMData *pData = (WinMMData*)pDevice->ExtraData; - void *buffer = NULL; - int i; - - // Call waveOutReset to shutdown wave device - pData->bWaveShutdown = AL_TRUE; - waveInReset(pData->hWaveHandle.In); - - // Wait for signal that Wave Thread has been destroyed - WaitForSingleObjectEx(pData->hWaveThreadEvent, 5000, FALSE); - - CloseHandle(pData->hWaveThread); - pData->hWaveThread = 0; - - // Release the wave buffers - for(i = 0;i < 4;i++) - { - waveInUnprepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR)); - if(i == 0) buffer = pData->WaveBuffer[i].lpData; - pData->WaveBuffer[i].lpData = NULL; - } - free(buffer); - - DestroyRingBuffer(pData->pRing); - pData->pRing = NULL; - - // Close the Wave device - CloseHandle(pData->hWaveThreadEvent); - pData->hWaveThreadEvent = 0; - - waveInClose(pData->hWaveHandle.In); - pData->hWaveHandle.In = 0; - - free(pData); - pDevice->ExtraData = NULL; -} - -static void WinMMStartCapture(ALCdevice *pDevice) -{ - WinMMData *pData = (WinMMData*)pDevice->ExtraData; - waveInStart(pData->hWaveHandle.In); -} - -static void WinMMStopCapture(ALCdevice *pDevice) -{ - WinMMData *pData = (WinMMData*)pDevice->ExtraData; - waveInStop(pData->hWaveHandle.In); -} - -static ALCuint WinMMAvailableSamples(ALCdevice *pDevice) -{ - WinMMData *pData = (WinMMData*)pDevice->ExtraData; - return RingBufferSize(pData->pRing); -} - -static void WinMMCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples) -{ - WinMMData *pData = (WinMMData*)pDevice->ExtraData; - - if(WinMMAvailableSamples(pDevice) >= lSamples) - ReadRingBuffer(pData->pRing, pBuffer, lSamples); - else - alcSetError(pDevice, ALC_INVALID_VALUE); -} - - -static const BackendFuncs WinMMFuncs = { - WinMMOpenPlayback, - WinMMClosePlayback, - WinMMResetPlayback, - WinMMStopPlayback, - WinMMOpenCapture, - WinMMCloseCapture, - WinMMStartCapture, - WinMMStopCapture, - WinMMCaptureSamples, - WinMMAvailableSamples -}; - -ALCboolean alcWinMMInit(BackendFuncs *FuncList) -{ - *FuncList = WinMMFuncs; - return ALC_TRUE; -} - -void alcWinMMDeinit() -{ - ALuint lLoop; - - for(lLoop = 0;lLoop < NumPlaybackDevices;lLoop++) - free(PlaybackDeviceList[lLoop]); - free(PlaybackDeviceList); - PlaybackDeviceList = NULL; - - NumPlaybackDevices = 0; - - - for(lLoop = 0; lLoop < NumCaptureDevices; lLoop++) - free(CaptureDeviceList[lLoop]); - free(CaptureDeviceList); - CaptureDeviceList = NULL; - - NumCaptureDevices = 0; -} - -void alcWinMMProbe(enum DevProbe type) -{ - ALuint i; - - switch(type) - { - case DEVICE_PROBE: - ProbePlaybackDevices(); - if(NumPlaybackDevices > 0) - AppendDeviceList(woDefault); - break; - - case ALL_DEVICE_PROBE: - ProbePlaybackDevices(); - if(NumPlaybackDevices > 0) - AppendAllDeviceList(woDefault); - for(i = 0;i < NumPlaybackDevices;i++) - { - if(PlaybackDeviceList[i]) - AppendAllDeviceList(PlaybackDeviceList[i]); - } - break; - - case CAPTURE_DEVICE_PROBE: - ProbeCaptureDevices(); - for(i = 0;i < NumCaptureDevices;i++) - { - if(CaptureDeviceList[i]) - AppendCaptureDeviceList(CaptureDeviceList[i]); - } - break; - } -} diff -r c41d773a85fb -r 82b9267a3e19 CMakeLists.txt --- a/CMakeLists.txt Tue Oct 25 13:03:35 2011 -0700 +++ b/CMakeLists.txt Tue Oct 25 13:11:31 2011 -0700 @@ -25,32 +25,8 @@ SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE) -OPTION(ALSA "Check for ALSA backend" ON) -OPTION(OSS "Check for OSS backend" ON) -OPTION(SOLARIS "Check for Solaris backend" ON) -OPTION(SNDIO "Check for SndIO backend" ON) -OPTION(MMDEVAPI "Check for MMDevApi" ON) -OPTION(DSOUND "Check for DirectSound backend" ON) -OPTION(WINMM "Check for Windows Multimedia backend" ON) -OPTION(PORTAUDIO "Check for PortAudio backend" ON) -OPTION(PULSEAUDIO "Check for PulseAudio backend" ON) -OPTION(COREAUDIO "Check for CoreAudio backend" ON) -OPTION(OPENSL "Check for OpenSL backend" ON) -OPTION(WAVE "Enable Wave Writer backend" ON) OPTION(SEND "Enable Send Backend" ON) -OPTION(REQUIRE_ALSA "Require ALSA backend" OFF) -OPTION(REQUIRE_OSS "Require OSS backend" OFF) -OPTION(REQUIRE_SOLARIS "Require Solaris backend" OFF) -OPTION(REQUIRE_SNDIO "Require SndIO backend" OFF) -OPTION(REQUIRE_MMDEVAPI "Require MMDevApi" OFF) -OPTION(REQUIRE_DSOUND "Require DirectSound backend" OFF) -OPTION(REQUIRE_WINMM "Require Windows Multimedia backend" OFF) -OPTION(REQUIRE_PORTAUDIO "Require PortAudio backend" OFF) -OPTION(REQUIRE_PULSEAUDIO "Require PulseAudio backend" OFF) -OPTION(REQUIRE_COREAUDIO "Require CoreAudio backend" OFF) -OPTION(REQUIRE_OPENSL "Require OpenSL backend" OFF) - OPTION(DLOPEN "Check for the dlopen API for loading optional libs" ON) OPTION(WERROR "Treat compile warnings as errors" OFF) @@ -399,221 +375,8 @@ ) SET(BACKENDS "") -SET(HAVE_ALSA 0) -SET(HAVE_OSS 0) -SET(HAVE_SOLARIS 0) -SET(HAVE_SNDIO 0) -SET(HAVE_DSOUND 0) -SET(HAVE_WINMM 0) -SET(HAVE_PORTAUDIO 0) -SET(HAVE_PULSEAUDIO 0) -SET(HAVE_COREAUDIO 0) -SET(HAVE_OPENSL 0) -SET(HAVE_WAVE 0) -# Check ALSA backend -IF(ALSA) - CHECK_INCLUDE_FILE(alsa/asoundlib.h HAVE_ALSA_ASOUNDLIB_H) - IF(HAVE_ALSA_ASOUNDLIB_H) - CHECK_SHARED_FUNCTION_EXISTS(snd_pcm_open "alsa/asoundlib.h" asound "" HAVE_LIBASOUND) - IF(HAVE_LIBASOUND OR HAVE_DLFCN_H OR WIN32) - SET(HAVE_ALSA 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/alsa.c) - IF(HAVE_DLFCN_H OR WIN32) - SET(BACKENDS "${BACKENDS} ALSA,") - ELSE() - SET(BACKENDS "${BACKENDS} ALSA \(linked\),") - SET(EXTRA_LIBS asound ${EXTRA_LIBS}) - ENDIF() - ENDIF() - ENDIF() -ENDIF() -IF(REQUIRE_ALSA AND NOT HAVE_ALSA) - MESSAGE(FATAL_ERROR "Failed to enabled required ALSA backend") -ENDIF() - -# Check OSS backend -IF(OSS) - CHECK_INCLUDE_FILE(sys/soundcard.h HAVE_SYS_SOUNDCARD_H) - IF(HAVE_SYS_SOUNDCARD_H) - SET(HAVE_OSS 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/oss.c) - SET(BACKENDS "${BACKENDS} OSS,") - ENDIF() -ENDIF() -IF(REQUIRE_OSS AND NOT HAVE_OSS) - MESSAGE(FATAL_ERROR "Failed to enabled required OSS backend") -ENDIF() - -# Check Solaris backend -IF(SOLARIS) - CHECK_INCLUDE_FILE(sys/audioio.h HAVE_SYS_AUDIOIO_H) - IF(HAVE_SYS_AUDIOIO_H) - SET(HAVE_SOLARIS 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/solaris.c) - SET(BACKENDS "${BACKENDS} Solaris,") - ENDIF() -ENDIF() -IF(REQUIRE_SOLARIS AND NOT HAVE_SOLARIS) - MESSAGE(FATAL_ERROR "Failed to enabled required Solaris backend") -ENDIF() - -# Check SndIO backend -IF(SNDIO) - CHECK_INCLUDE_FILE(sndio.h HAVE_SNDIO_H) - IF(HAVE_SNDIO_H) - CHECK_SHARED_FUNCTION_EXISTS(sio_open "sndio.h" sndio "" HAVE_LIBSNDIO) - IF(HAVE_LIBSNDIO OR HAVE_DLFCN_H OR WIN32) - SET(HAVE_SNDIO 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/sndio.c) - IF(HAVE_DLFCN_H OR WIN32) - SET(BACKENDS "${BACKENDS} SndIO,") - ELSE() - SET(BACKENDS "${BACKENDS} SndIO \(linked\),") - SET(EXTRA_LIBS sndio ${EXTRA_LIBS}) - ENDIF() - ENDIF() - ENDIF() -ENDIF() -IF(REQUIRE_SNDIO AND NOT HAVE_SNDIO) - MESSAGE(FATAL_ERROR "Failed to enabled required SndIO backend") -ENDIF() - -# Check for MMDevApi backend -IF(HAVE_WINDOWS_H) - IF(MMDEVAPI) - CHECK_INCLUDE_FILE(mmdeviceapi.h HAVE_MMDEVICEAPI_H) - IF(HAVE_MMDEVICEAPI_H) - SET(HAVE_MMDEVAPI 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/mmdevapi.c) - - SET(BACKENDS "${BACKENDS} MMDevApi,") - ENDIF() - ENDIF() -ENDIF() -IF(REQUIRE_MMDEVAPI AND NOT HAVE_MMDEVAPI) - MESSAGE(FATAL_ERROR "Failed to enabled required MMDevApi backend") -ENDIF() - -# Check DSound/MMSystem backend -IF(DSOUND) - CHECK_INCLUDE_FILE(dsound.h HAVE_DSOUND_H) - IF(HAVE_DSOUND_H) - CHECK_SHARED_FUNCTION_EXISTS(DirectSoundCreate "dsound.h" dsound "" HAVE_LIBDSOUND) - IF(HAVE_LIBDSOUND OR HAVE_DLFCN_H OR WIN32) - SET(HAVE_DSOUND 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/dsound.c) - - IF(HAVE_DLFCN_H OR WIN32) - SET(BACKENDS "${BACKENDS} DirectSound,") - ELSE() - SET(BACKENDS "${BACKENDS} DirectSound \(linked\),") - SET(EXTRA_LIBS dsound ${EXTRA_LIBS}) - ENDIF() - ENDIF() - ENDIF() -ENDIF() -IF(REQUIRE_DSOUND AND NOT HAVE_DSOUND) - MESSAGE(FATAL_ERROR "Failed to enabled required DSound backend") -ENDIF() - -IF(HAVE_WINDOWS_H) - IF(WINMM) - CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H -D_WIN32_WINNT=0x0500) - IF(HAVE_MMSYSTEM_H AND HAVE_LIBWINMM) - SET(HAVE_WINMM 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/winmm.c) - SET(BACKENDS "${BACKENDS} WinMM,") - ENDIF() - ENDIF() -ENDIF() -IF(REQUIRE_WINMM AND NOT HAVE_WINMM) - MESSAGE(FATAL_ERROR "Failed to enable required WinMM backend") -ENDIF() - -# Check PortAudio backend -IF(PORTAUDIO) - CHECK_INCLUDE_FILE(portaudio.h HAVE_PORTAUDIO_H) - IF(HAVE_PORTAUDIO_H) - CHECK_SHARED_FUNCTION_EXISTS(Pa_Initialize "portaudio.h" portaudio "" HAVE_LIBPORTAUDIO) - IF(HAVE_LIBPORTAUDIO OR HAVE_DLFCN_H OR WIN32) - SET(HAVE_PORTAUDIO 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/portaudio.c) - IF(HAVE_DLFCN_H OR WIN32) - SET(BACKENDS "${BACKENDS} PortAudio,") - ELSE() - SET(BACKENDS "${BACKENDS} PortAudio \(linked\),") - SET(EXTRA_LIBS portaudio ${EXTRA_LIBS}) - ENDIF() - ENDIF() - ENDIF() -ENDIF() -IF(REQUIRE_PORTAUDIO AND NOT HAVE_PORTAUDIO) - MESSAGE(FATAL_ERROR "Failed to enabled required PortAudio backend") -ENDIF() - -# Check PulseAudio backend -IF(PULSEAUDIO) - CHECK_INCLUDE_FILE(pulse/pulseaudio.h HAVE_PULSE_PULSEAUDIO_H) - IF(HAVE_PULSE_PULSEAUDIO_H) - CHECK_SHARED_FUNCTION_EXISTS(pa_context_new "pulse/pulseaudio.h" pulse "" HAVE_LIBPULSE) - IF(HAVE_LIBPULSE OR HAVE_DLFCN_H OR WIN32) - SET(HAVE_PULSEAUDIO 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/pulseaudio.c) - IF(HAVE_DLFCN_H OR WIN32) - SET(BACKENDS "${BACKENDS} PulseAudio,") - ELSE() - SET(BACKENDS "${BACKENDS} PulseAudio \(linked\),") - SET(EXTRA_LIBS pulse ${EXTRA_LIBS}) - ENDIF() - ENDIF() - ENDIF() -ENDIF() -IF(REQUIRE_PULSEAUDIO AND NOT HAVE_PULSEAUDIO) - MESSAGE(FATAL_ERROR "Failed to enabled required PulseAudio backend") -ENDIF() - -# Check CoreAudio backend -IF(COREAUDIO) - CHECK_INCLUDE_FILE(/System/Library/Frameworks/CoreAudio.framework/Headers/CoreAudio.h HAVE_COREAUDIO_FRAMEWORK) - IF(HAVE_COREAUDIO_FRAMEWORK) - SET(HAVE_COREAUDIO 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/coreaudio.c) - SET(BACKENDS "${BACKENDS} CoreAudio,") - SET(EXTRA_LIBS /System/Library/Frameworks/CoreAudio.framework ${EXTRA_LIBS}) - SET(EXTRA_LIBS /System/Library/Frameworks/AudioUnit.framework ${EXTRA_LIBS}) - SET(EXTRA_LIBS /System/Library/Frameworks/ApplicationServices.framework ${EXTRA_LIBS}) - ENDIF() -ENDIF() -IF(REQUIRE_COREAUDIO AND NOT HAVE_COREAUDIO) - MESSAGE(FATAL_ERROR "Failed to enabled required CoreAudio backend") -ENDIF() - -# Check for OpenSL (Android) backend -IF(OPENSL) - CHECK_INCLUDE_FILE(SLES/OpenSLES_Android.h HAVE_SLES_OPENSLES_ANDROID_H) - IF(HAVE_SLES_OPENSLES_ANDROID_H) - CHECK_SHARED_FUNCTION_EXISTS(slCreateEngine "SLES/OpenSLES.h" OpenSLES "" HAVE_LIBOPENSLES) - IF(HAVE_LIBOPENSLES) - SET(HAVE_OPENSL 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/opensl.c) - SET(BACKENDS "${BACKENDS} OpenSL,") - SET(EXTRA_LIBS OpenSLES ${EXTRA_LIBS}) - ENDIF() - ENDIF() -ENDIF() -IF(REQUIRE_OPENSL AND NOT HAVE_OPENSL) - MESSAGE(FATAL_ERROR "Failed to enable required OpenSL backend") -ENDIF() - -# Optionally enable the Wave Writer backend -IF(WAVE) - SET(HAVE_WAVE 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/wave.c) - SET(BACKENDS "${BACKENDS} WaveFile,") -ENDIF() - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/send.c) SET(BACKENDS "${BACKENDS} Send,") @@ -682,14 +445,6 @@ MESSAGE(STATUS " ${BACKENDS}") MESSAGE(STATUS "") -IF(WIN32) - IF(NOT HAVE_DSOUND) - MESSAGE(STATUS "WARNING: Building the Windows version without DirectSound output") - MESSAGE(STATUS " This is probably NOT what you want!") - MESSAGE(STATUS "") - ENDIF() -ENDIF() - # Install alsoft.conf configuration file IF(ALSOFT_CONFIG) INSTALL(FILES alsoftrc.sample