From 21c84bcd96a2e457b446e53d3287878e32fc77e0 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Fri, 13 Nov 2015 20:11:12 -0400 Subject: Replace deprecated Carbon API calls with modern AudioComponent APIs in the CoreAudio backend. This prevents a deprecation notice from being output to stdout when alcOpenDevice is called in Mac OS X 10.11. The new API calls require Mac OS X 10.6 or newer. --- Alc/backends/coreaudio.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index 43e881da..d9264217 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -137,8 +137,8 @@ static OSStatus ca_capture_callback(void *inRefCon, AudioUnitRenderActionFlags * static ALCenum ca_open_playback(ALCdevice *device, const ALCchar *deviceName) { - ComponentDescription desc; - Component comp; + AudioComponentDescription desc; + AudioComponent comp; ca_data *data; OSStatus err; @@ -154,19 +154,19 @@ static ALCenum ca_open_playback(ALCdevice *device, const ALCchar *deviceName) desc.componentFlags = 0; desc.componentFlagsMask = 0; - comp = FindNextComponent(NULL, &desc); + comp = AudioComponentFindNext(NULL, &desc); if(comp == NULL) { - ERR("FindNextComponent failed\n"); + ERR("AudioComponentFindNext failed\n"); return ALC_INVALID_VALUE; } data = calloc(1, sizeof(*data)); - err = OpenAComponent(comp, &data->audioUnit); + err = AudioComponentInstanceNew(comp, &data->audioUnit); if(err != noErr) { - ERR("OpenAComponent failed\n"); + ERR("AudioComponentInstanceNew failed\n"); free(data); return ALC_INVALID_VALUE; } @@ -176,7 +176,7 @@ static ALCenum ca_open_playback(ALCdevice *device, const ALCchar *deviceName) if(err != noErr) { ERR("AudioUnitInitialize failed\n"); - CloseComponent(data->audioUnit); + AudioComponentInstanceDispose(data->audioUnit); free(data); return ALC_INVALID_VALUE; } @@ -191,7 +191,7 @@ static void ca_close_playback(ALCdevice *device) ca_data *data = (ca_data*)device->ExtraData; AudioUnitUninitialize(data->audioUnit); - CloseComponent(data->audioUnit); + AudioComponentInstanceDispose(data->audioUnit); free(data); device->ExtraData = NULL; @@ -374,12 +374,13 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) AudioStreamBasicDescription hardwareFormat; // The hardware format AudioStreamBasicDescription outputFormat; // The AudioUnit output format AURenderCallbackStruct input; - ComponentDescription desc; + AudioComponentDescription desc; AudioDeviceID inputDevice; UInt32 outputFrameCount; UInt32 propertySize; + AudioObjectPropertyAddress propertyAddress; UInt32 enableIO; - Component comp; + AudioComponent comp; ca_data *data; OSStatus err; @@ -395,10 +396,10 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) desc.componentFlagsMask = 0; // Search for component with given description - comp = FindNextComponent(NULL, &desc); + comp = AudioComponentFindNext(NULL, &desc); if(comp == NULL) { - ERR("FindNextComponent failed\n"); + ERR("AudioComponentFindNext failed\n"); return ALC_INVALID_VALUE; } @@ -406,10 +407,10 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) device->ExtraData = data; // Open the component - err = OpenAComponent(comp, &data->audioUnit); + err = AudioComponentInstanceNew(comp, &data->audioUnit); if(err != noErr) { - ERR("OpenAComponent failed\n"); + ERR("AudioComponentInstanceNew failed\n"); goto error; } @@ -432,11 +433,16 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) } // Get the default input device + propertySize = sizeof(AudioDeviceID); - err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &propertySize, &inputDevice); + propertyAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + + err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &propertySize, &inputDevice); if(err != noErr) { - ERR("AudioHardwareGetProperty failed\n"); + ERR("AudioObjectGetPropertyData failed\n"); goto error; } @@ -596,7 +602,7 @@ error: if(data->audioConverter) AudioConverterDispose(data->audioConverter); if(data->audioUnit) - CloseComponent(data->audioUnit); + AudioComponentInstanceDispose(data->audioUnit); free(data); device->ExtraData = NULL; @@ -613,7 +619,7 @@ static void ca_close_capture(ALCdevice *device) destroy_buffer_list(data->bufferList); AudioConverterDispose(data->audioConverter); - CloseComponent(data->audioUnit); + AudioComponentInstanceDispose(data->audioUnit); free(data); device->ExtraData = NULL; -- cgit v1.2.3 From c8a3e51296d367990b9603a8e53f24dd1068b23d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 23 Nov 2015 16:29:32 -0800 Subject: Fix the allow-resampler check for ALSA --- Alc/backends/alsa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Alc/backends') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 9a443c09..955fd8c0 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -770,7 +770,7 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self) } CHECK(snd_pcm_hw_params_set_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans))); /* set rate (implicitly constrains period/buffer parameters) */ - if(GetConfigValueBool(al_string_get_cstr(device->DeviceName), "alsa", "allow-resampler", 0)) + if(!GetConfigValueBool(al_string_get_cstr(device->DeviceName), "alsa", "allow-resampler", 0)) { if(snd_pcm_hw_params_set_rate_resample(self->pcmHandle, hp, 0) < 0) ERR("Failed to disable ALSA resampler\n"); -- cgit v1.2.3 From 63567526b0a17449baf57053d11688aa277a7e40 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 23 Nov 2015 16:50:31 -0800 Subject: Better handle inexact ALSA period counts --- Alc/backends/alsa.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Alc/backends') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 955fd8c0..43c46484 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -677,6 +677,7 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self) unsigned int rate; const char *funcerr; int allowmmap; + int dir; int err; switch(device->FmtType) @@ -787,7 +788,9 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self) /* retrieve configuration info */ CHECK(snd_pcm_hw_params_get_access(hp, &access)); CHECK(snd_pcm_hw_params_get_period_size(hp, &periodSizeInFrames, NULL)); - CHECK(snd_pcm_hw_params_get_periods(hp, &periods, NULL)); + CHECK(snd_pcm_hw_params_get_periods(hp, &periods, &dir)); + if(dir != 0) + WARN("Inexact period count: %u (%d)\n", periods, dir); snd_pcm_hw_params_free(hp); hp = NULL; -- cgit v1.2.3 From e45ff473618f3400def59fc3a06cec9fdc62452b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 4 Dec 2015 15:52:43 -0800 Subject: Reformat Windows device name dressing --- Alc/backends/dsound.c | 11 +++++------ Alc/backends/mmdevapi.c | 25 +++++++++++++------------ Alc/backends/winmm.c | 20 +++++++++----------- 3 files changed, 27 insertions(+), 29 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index 4db4b557..f27ab37b 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -60,7 +60,7 @@ 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 DEVNAME_TAIL " on OpenAL Soft" +#define DEVNAME_HEAD "OpenAL Soft on " #ifdef HAVE_DYNLOAD @@ -145,13 +145,12 @@ static BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHA { const DevMap *iter; - al_string_copy_wcstr(&entry.name, desc); - if(count == 0) - al_string_append_cstr(&entry.name, DEVNAME_TAIL); - else + al_string_copy_cstr(&entry.name, DEVNAME_HEAD); + al_string_append_wcstr(&entry.name, desc); + if(count != 0) { char str[64]; - snprintf(str, sizeof(str), " #%d"DEVNAME_TAIL, count+1); + snprintf(str, sizeof(str), " #%d", count+1); al_string_append_cstr(&entry.name, str); } diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index e8563d33..0134a46c 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -62,7 +62,7 @@ DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_FormFactor, 0x1da5d803, 0xd492, 0x4edd, 0x #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) #define X7DOT1_WIDE (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_FRONT_LEFT_OF_CENTER|SPEAKER_FRONT_RIGHT_OF_CENTER) -#define DEVNAME_TAIL " on OpenAL Soft" +#define DEVNAME_HEAD "OpenAL Soft on " typedef struct { @@ -125,10 +125,13 @@ static void get_device_name(IMMDevice *device, al_string *name) PROPVARIANT pvname; HRESULT hr; + al_string_copy_cstr(name, DEVNAME_HEAD); + hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps); if(FAILED(hr)) { WARN("OpenPropertyStore failed: 0x%08lx\n", hr); + al_string_append_cstr(name, "Unknown Device Name"); return; } @@ -136,11 +139,17 @@ static void get_device_name(IMMDevice *device, al_string *name) hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pvname); if(FAILED(hr)) + { WARN("GetValue Device_FriendlyName failed: 0x%08lx\n", hr); + al_string_append_cstr(name, "Unknown Device Name"); + } else if(pvname.vt == VT_LPWSTR) - al_string_copy_wcstr(name, pvname.pwszVal); + al_string_append_wcstr(name, pvname.pwszVal); else + { WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvname.vt); + al_string_append_cstr(name, "Unknown Device Name"); + } PropVariantClear(&pvname); IPropertyStore_Release(ps); @@ -193,12 +202,10 @@ static void add_device(IMMDevice *device, LPCWSTR devid, vector_DevMap *list) const DevMap *iter; al_string_copy(&entry.name, tmpname); - if(count == 0) - al_string_append_cstr(&entry.name, DEVNAME_TAIL); - else + if(count != 0) { char str[64]; - snprintf(str, sizeof(str), " #%d"DEVNAME_TAIL, count+1); + snprintf(str, sizeof(str), " #%d", count+1); al_string_append_cstr(&entry.name, str); } @@ -755,10 +762,7 @@ static HRESULT ALCmmdevPlayback_openProxy(ALCmmdevPlayback *self) { self->client = ptr; if(al_string_empty(device->DeviceName)) - { get_device_name(self->mmdev, &device->DeviceName); - al_string_append_cstr(&device->DeviceName, DEVNAME_TAIL); - } } if(FAILED(hr)) @@ -1412,10 +1416,7 @@ static HRESULT ALCmmdevCapture_openProxy(ALCmmdevCapture *self) { self->client = ptr; if(al_string_empty(device->DeviceName)) - { get_device_name(self->mmdev, &device->DeviceName); - al_string_append_cstr(&device->DeviceName, DEVNAME_TAIL); - } } if(FAILED(hr)) diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index bf97ef2e..3508ec49 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -37,7 +37,7 @@ #define WAVE_FORMAT_IEEE_FLOAT 0x0003 #endif -#define DEVNAME_TAIL " on OpenAL Soft" +#define DEVNAME_HEAD "OpenAL Soft on " static vector_al_string PlaybackDevices; @@ -71,13 +71,12 @@ static void ProbePlaybackDevices(void) ALuint count = 0; while(1) { - al_string_copy_wcstr(&dname, WaveCaps.szPname); - if(count == 0) - al_string_append_cstr(&dname, DEVNAME_TAIL); - else + al_string_copy_cstr(&dname, DEVNAME_HEAD); + al_string_append_wcstr(&dname, WaveCaps.szPname); + if(count != 0) { char str[64]; - snprintf(str, sizeof(str), " #%d"DEVNAME_TAIL, count+1); + snprintf(str, sizeof(str), " #%d", count+1); al_string_append_cstr(&dname, str); } count++; @@ -115,13 +114,12 @@ static void ProbeCaptureDevices(void) ALuint count = 0; while(1) { - al_string_copy_wcstr(&dname, WaveCaps.szPname); - if(count == 0) - al_string_append_cstr(&dname, DEVNAME_TAIL); - else + al_string_copy_cstr(&dname, DEVNAME_HEAD); + al_string_append_wcstr(&dname, WaveCaps.szPname); + if(count != 0) { char str[64]; - snprintf(str, sizeof(str), " #%d"DEVNAME_TAIL, count+1); + snprintf(str, sizeof(str), " #%d", count+1); al_string_append_cstr(&dname, str); } count++; -- cgit v1.2.3 From 01e43e5d4da47423a0457276febb01fb5efa84e4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 11 Dec 2015 09:24:40 -0800 Subject: Add includes to work around broken GNU headers and POSIX-2001 --- Alc/backends/oss.c | 1 + Alc/backends/solaris.c | 1 + 2 files changed, 2 insertions(+) (limited to 'Alc/backends') diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index dce42e21..1c3763c6 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c index 52ca9090..6eaf1ee5 100644 --- a/Alc/backends/solaris.c +++ b/Alc/backends/solaris.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include -- cgit v1.2.3 From df2ee7ba873153a7bfe53665fd273eef22d12c68 Mon Sep 17 00:00:00 2001 From: "Keegan Drake H.P" Date: Thu, 17 Dec 2015 19:20:08 -0600 Subject: Add device enumeration support for OSSv4 --- Alc/backends/oss.c | 233 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 206 insertions(+), 27 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 1c3763c6..c7fc404c 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -52,11 +52,158 @@ #define SOUND_MIXER_WRITE MIXER_WRITE #endif +#if defined(SOUND_VERSION) && (SOUND_VERSION) < 0x040000 +#define ALC_OSS_COMPAT +#endif +#ifndef SNDCTL_AUDIOINFO +#define ALC_OSS_COMPAT +#endif + +/* + * FreeBSD strongly discourages the use of specific devices, + * such as those returned in oss_audioinfo.devnode + */ +#ifdef __FreeBSD__ +#define ALC_OSS_DEVNODE_TRUC +#endif + +struct oss_device { + const ALCchar *handle; + const char *path; + struct oss_device *next; +}; + +static struct oss_device oss_playback = { + "OSS Default", + "/dev/dsp", + NULL +}; -static const ALCchar oss_device[] = "OSS Default"; +static struct oss_device oss_capture = { + "OSS Default", + "/dev/dsp", + NULL +}; -static const char *oss_driver = "/dev/dsp"; -static const char *oss_capture = "/dev/dsp"; +#ifdef ALC_OSS_COMPAT + +static void ALCossListPopulate(struct oss_device *playback, struct oss_device *capture) +{ + ; /* Stub */ +} + +static void ALCossListFree(struct oss_device *list) +{ + ; /* Stub */ +} + +#else + +static void ALCossListAppend(struct oss_device *list, char *handle, size_t hlen, char *path, size_t plen) { + struct oss_device *t; + struct oss_device *p; + void *m; + size_t i; + if (list == NULL || handle == NULL || path == NULL) + return; + /* skip the first item "OSS Default" */ + p = list; + t = list->next; +#ifdef ALC_OSS_DEVNODE_TRUC + for (i = 0; i < plen; i++) + if (path[i] == '.') + { + if (strncmp(path + i, handle + hlen + i - plen, plen - i) == 0) + hlen = hlen + i - plen; + plen = i; + } +#endif + if (handle == NULL || hlen == 0 || *handle == '\0') { + handle = path; + hlen = plen; + } + while (t != NULL && strncmp(t->path, path, plen) != 0) { + p = t; + t = t->next; + } + if (t != NULL) + return; + m = malloc(sizeof(struct oss_device) + hlen + plen + 2); + t = (struct oss_device *)m; + t->handle = (char *)((uintptr_t)m + sizeof(struct oss_device)); + t->path = stpncpy((char *)t->handle, handle, hlen) + 1; + ((char *)t->handle)[hlen] = '\0'; + strncpy((char *)t->path, path, plen); + ((char *)t->path)[plen] = '\0'; + t->next = NULL; + p->next = t; +} + +static void ALCossListPopulate(struct oss_device *playback, struct oss_device *capture) +{ + struct oss_sysinfo si; + struct oss_audioinfo ai; + int fd; + int i; + if ((fd = open("/dev/mixer", O_RDONLY)) < 0) + { + ERR("Could not open /dev/mixer\n"); + return; + } + if (ioctl(fd, SNDCTL_SYSINFO, &si) == -1) + { + ERR("SNDCTL_SYSINFO\n"); + goto err; + } + for (i = 0; i < si.numaudios; i++) + { + char *handle; + size_t len; + ai.dev = i; + if (ioctl(fd, SNDCTL_AUDIOINFO, &ai) == -1) + { + ERR("SNDCTL_SYSINFO\n"); + continue; + } + if (ai.handle[0] == '\0') + { + len = strnlen(ai.name, sizeof(ai.name)); + handle = ai.name; + } + else + { + len = strnlen(ai.handle, sizeof(ai.handle)); + handle = ai.handle; + } + if ((ai.caps & DSP_CAP_INPUT) && capture != NULL) + ALCossListAppend(capture, handle, len, ai.devnode, strnlen(ai.devnode, sizeof(ai.devnode))); + if ((ai.caps & DSP_CAP_OUTPUT) && playback != NULL) + ALCossListAppend(playback, handle, len, ai.devnode, strnlen(ai.devnode, sizeof(ai.devnode))); + } + close(fd); + return; +err: + if (fd >= 0) + close(fd); + return; +} + +static void ALCossListFree(struct oss_device *list) +{ + struct oss_device *cur, *t; + if (list == NULL) + return; + cur = list->next; + list->next = NULL; + while (cur != NULL) + { + t = cur->next; + free(cur); + cur = t; + } +} + +#endif static int log2i(ALCuint x) { @@ -69,7 +216,6 @@ static int log2i(ALCuint x) return y; } - typedef struct ALCplaybackOSS { DERIVE_FROM_TYPE(ALCbackend); @@ -153,19 +299,29 @@ static void ALCplaybackOSS_Construct(ALCplaybackOSS *self, ALCdevice *device) static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name) { + struct oss_device *dev = &oss_playback; ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; if(!name) - name = oss_device; - else if(strcmp(name, oss_device) != 0) - return ALC_INVALID_VALUE; + name = dev->handle; + else + { + while (dev != NULL) + { + if (strcmp(dev->handle, name) == 0) + break; + dev = dev->next; + } + if (dev == NULL) + return ALC_INVALID_VALUE; + } self->killNow = 0; - self->fd = open(oss_driver, O_WRONLY); + self->fd = open(dev->path, O_WRONLY); if(self->fd == -1) { - ERR("Could not open %s: %s\n", oss_driver, strerror(errno)); + ERR("Could not open %s: %s\n", dev->path, strerror(errno)); return ALC_INVALID_VALUE; } @@ -383,6 +539,7 @@ static void ALCcaptureOSS_Construct(ALCcaptureOSS *self, ALCdevice *device) static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + struct oss_device *dev = &oss_capture; int numFragmentsLogSize; int log2FragmentSize; unsigned int periods; @@ -394,14 +551,23 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) char *err; if(!name) - name = oss_device; - else if(strcmp(name, oss_device) != 0) - return ALC_INVALID_VALUE; + name = dev->handle; + else + { + while (dev != NULL) + { + if (strcmp(dev->handle, name) == 0) + break; + dev = dev->next; + } + if (dev == NULL) + return ALC_INVALID_VALUE; + } - self->fd = open(oss_capture, O_RDONLY); + self->fd = open(dev->path, O_RDONLY); if(self->fd == -1) { - ERR("Could not open %s: %s\n", oss_capture, strerror(errno)); + ERR("Could not open %s: %s\n", dev->path, strerror(errno)); return ALC_INVALID_VALUE; } @@ -547,7 +713,7 @@ typedef struct ALCossBackendFactory { ALCbackendFactory *ALCossBackendFactory_getFactory(void); static ALCboolean ALCossBackendFactory_init(ALCossBackendFactory *self); -static DECLARE_FORWARD(ALCossBackendFactory, ALCbackendFactory, void, deinit) +static void ALCossBackendFactory_deinit(ALCossBackendFactory *self); static ALCboolean ALCossBackendFactory_querySupport(ALCossBackendFactory *self, ALCbackend_Type type); static void ALCossBackendFactory_probe(ALCossBackendFactory *self, enum DevProbe type); static ALCbackend* ALCossBackendFactory_createBackend(ALCossBackendFactory *self, ALCdevice *device, ALCbackend_Type type); @@ -563,12 +729,19 @@ ALCbackendFactory *ALCossBackendFactory_getFactory(void) ALCboolean ALCossBackendFactory_init(ALCossBackendFactory* UNUSED(self)) { - ConfigValueStr(NULL, "oss", "device", &oss_driver); - ConfigValueStr(NULL, "oss", "capture", &oss_capture); + ConfigValueStr(NULL, "oss", "device", &oss_playback.path); + ConfigValueStr(NULL, "oss", "capture", &oss_capture.path); return ALC_TRUE; } +void ALCossBackendFactory_deinit(ALCossBackendFactory* UNUSED(self)) +{ + ALCossListFree(&oss_playback); + ALCossListFree(&oss_capture); +} + + ALCboolean ALCossBackendFactory_querySupport(ALCossBackendFactory* UNUSED(self), ALCbackend_Type type) { if(type == ALCbackend_Playback || type == ALCbackend_Capture) @@ -582,21 +755,27 @@ void ALCossBackendFactory_probe(ALCossBackendFactory* UNUSED(self), enum DevProb { case ALL_DEVICE_PROBE: { -#ifdef HAVE_STAT - struct stat buf; - if(stat(oss_driver, &buf) == 0) -#endif - AppendAllDevicesList(oss_device); + struct oss_device *cur = &oss_playback; + ALCossListFree(cur); + ALCossListPopulate(cur, NULL); + while (cur != NULL) + { + AppendAllDevicesList(cur->handle); + cur = cur->next; + } } break; case CAPTURE_DEVICE_PROBE: { -#ifdef HAVE_STAT - struct stat buf; - if(stat(oss_capture, &buf) == 0) -#endif - AppendCaptureDeviceList(oss_device); + struct oss_device *cur = &oss_capture; + ALCossListFree(cur); + ALCossListPopulate(NULL, cur); + while (cur != NULL) + { + AppendCaptureDeviceList(cur->handle); + cur = cur->next; + } } break; } -- cgit v1.2.3 From 5a73aa2502a36af15a2d19be4474093c232e04b2 Mon Sep 17 00:00:00 2001 From: "Keegan Drake H.P" Date: Thu, 17 Dec 2015 20:05:21 -0600 Subject: Added a check for an empty path --- Alc/backends/oss.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index c7fc404c..9ca92410 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -104,7 +104,7 @@ static void ALCossListAppend(struct oss_device *list, char *handle, size_t hlen, struct oss_device *p; void *m; size_t i; - if (list == NULL || handle == NULL || path == NULL) + if (list == NULL || handle == NULL || path == NULL || plen == 0 || path[0] == '\0') return; /* skip the first item "OSS Default" */ p = list; @@ -118,7 +118,7 @@ static void ALCossListAppend(struct oss_device *list, char *handle, size_t hlen, plen = i; } #endif - if (handle == NULL || hlen == 0 || *handle == '\0') { + if (handle == NULL || hlen == 0 || handle[0] == '\0') { handle = path; hlen = plen; } -- cgit v1.2.3 From bbd2876afb5265517d25e78d7dcaf7ccb494af0f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 21 Jan 2016 01:05:29 -0800 Subject: Improve the OSS enumeration code --- Alc/backends/oss.c | 134 ++++++++++++++++++++++++++++------------------------- 1 file changed, 71 insertions(+), 63 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 9ca92410..1e286791 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -52,7 +52,7 @@ #define SOUND_MIXER_WRITE MIXER_WRITE #endif -#if defined(SOUND_VERSION) && (SOUND_VERSION) < 0x040000 +#if defined(SOUND_VERSION) && (SOUND_VERSION < 0x040000) #define ALC_OSS_COMPAT #endif #ifndef SNDCTL_AUDIOINFO @@ -85,126 +85,134 @@ static struct oss_device oss_capture = { NULL }; -#ifdef ALC_OSS_COMPAT +#ifdef ALC_OSS_COMPAT -static void ALCossListPopulate(struct oss_device *playback, struct oss_device *capture) -{ - ; /* Stub */ -} - -static void ALCossListFree(struct oss_device *list) +static void ALCossListPopulate(struct oss_device *UNUSED(playback), struct oss_device *UNUSED(capture)) { - ; /* Stub */ } #else -static void ALCossListAppend(struct oss_device *list, char *handle, size_t hlen, char *path, size_t plen) { - struct oss_device *t; - struct oss_device *p; - void *m; +static void ALCossListAppend(struct oss_device *list, const char *handle, size_t hlen, const char *path, size_t plen) +{ + struct oss_device *next; + struct oss_device *last; size_t i; - if (list == NULL || handle == NULL || path == NULL || plen == 0 || path[0] == '\0') + + if(plen == 0 || path[0] == '\0') return; + /* skip the first item "OSS Default" */ - p = list; - t = list->next; + last = list; + next = list->next; #ifdef ALC_OSS_DEVNODE_TRUC - for (i = 0; i < plen; i++) - if (path[i] == '.') + for(i = 0;i < plen;i++) + { + if(path[i] == '.') { - if (strncmp(path + i, handle + hlen + i - plen, plen - i) == 0) + if(strncmp(path + i, handle + hlen + i - plen, plen - i) == 0) hlen = hlen + i - plen; plen = i; } + } +#else + (void)i; #endif - if (handle == NULL || hlen == 0 || handle[0] == '\0') { + if(handle[0] == '\0') + { handle = path; hlen = plen; } - while (t != NULL && strncmp(t->path, path, plen) != 0) { - p = t; - t = t->next; + + while(next != NULL) + { + if(strncmp(next->path, path, plen) == 0) + return; + last = next; + next = next->next; } - if (t != NULL) - return; - m = malloc(sizeof(struct oss_device) + hlen + plen + 2); - t = (struct oss_device *)m; - t->handle = (char *)((uintptr_t)m + sizeof(struct oss_device)); - t->path = stpncpy((char *)t->handle, handle, hlen) + 1; - ((char *)t->handle)[hlen] = '\0'; - strncpy((char *)t->path, path, plen); - ((char *)t->path)[plen] = '\0'; - t->next = NULL; - p->next = t; + + next = (struct oss_device*)malloc(sizeof(struct oss_device) + hlen + plen + 2); + next->handle = (char*)(next + 1); + next->path = next->handle + hlen + 1; + next->next = NULL; + last->next = next; + + strncpy((char*)next->handle, handle, hlen); + ((char*)next->handle)[hlen] = '\0'; + strncpy((char*)next->path, path, plen); + ((char*)next->path)[plen] = '\0'; + + TRACE("Got device \"%s\", \"%s\"\n", next->handle, next->path); } static void ALCossListPopulate(struct oss_device *playback, struct oss_device *capture) { struct oss_sysinfo si; struct oss_audioinfo ai; - int fd; - int i; - if ((fd = open("/dev/mixer", O_RDONLY)) < 0) + int fd, i; + + if((fd=open("/dev/mixer", O_RDONLY)) < 0) { ERR("Could not open /dev/mixer\n"); return; } - if (ioctl(fd, SNDCTL_SYSINFO, &si) == -1) + if(ioctl(fd, SNDCTL_SYSINFO, &si) == -1) { - ERR("SNDCTL_SYSINFO\n"); - goto err; + ERR("SNDCTL_SYSINFO failed: %s\n", strerror(errno)); + goto done; } - for (i = 0; i < si.numaudios; i++) + for(i = 0;i < si.numaudios;i++) { - char *handle; + const char *handle; size_t len; + ai.dev = i; - if (ioctl(fd, SNDCTL_AUDIOINFO, &ai) == -1) + if(ioctl(fd, SNDCTL_AUDIOINFO, &ai) == -1) { - ERR("SNDCTL_SYSINFO\n"); + ERR("SNDCTL_AUDIOINFO (%d) failed: %s\n", i, strerror(errno)); continue; } - if (ai.handle[0] == '\0') + if(ai.handle[0]) { - len = strnlen(ai.name, sizeof(ai.name)); - handle = ai.name; + len = strnlen(ai.handle, sizeof(ai.handle)); + handle = ai.handle; } else { - len = strnlen(ai.handle, sizeof(ai.handle)); - handle = ai.handle; + len = strnlen(ai.name, sizeof(ai.name)); + handle = ai.name; } - if ((ai.caps & DSP_CAP_INPUT) && capture != NULL) + if((ai.caps&DSP_CAP_INPUT) && capture != NULL) ALCossListAppend(capture, handle, len, ai.devnode, strnlen(ai.devnode, sizeof(ai.devnode))); - if ((ai.caps & DSP_CAP_OUTPUT) && playback != NULL) + if((ai.caps&DSP_CAP_OUTPUT) && playback != NULL) ALCossListAppend(playback, handle, len, ai.devnode, strnlen(ai.devnode, sizeof(ai.devnode))); } + +done: close(fd); - return; -err: - if (fd >= 0) - close(fd); - return; } +#endif + static void ALCossListFree(struct oss_device *list) { - struct oss_device *cur, *t; - if (list == NULL) + struct oss_device *cur; + if(list == NULL) return; + + /* skip the first item "OSS Default" */ cur = list->next; list->next = NULL; - while (cur != NULL) + + while(cur != NULL) { - t = cur->next; + struct oss_device *next = cur->next; free(cur); - cur = t; + cur = next; } } -#endif - static int log2i(ALCuint x) { int y = 0; -- cgit v1.2.3 From 9c05a16c9a394dea90fcefc29eb2ef2be06dc4b5 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 21 Jan 2016 02:08:45 -0800 Subject: Fix for systems that don't have strnlen --- Alc/backends/oss.c | 18 ++++++++++++++---- CMakeLists.txt | 3 ++- config.h.in | 3 +++ 3 files changed, 19 insertions(+), 5 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 1e286791..33d7750a 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -93,15 +94,21 @@ static void ALCossListPopulate(struct oss_device *UNUSED(playback), struct oss_d #else +#ifndef HAVE_STRNLEN +static size_t strnlen(const char *str, size_t maxlen) +{ + const char *end = memchr(str, 0, maxlen); + if(!end) return maxlen; + return end - str; +} +#endif + static void ALCossListAppend(struct oss_device *list, const char *handle, size_t hlen, const char *path, size_t plen) { struct oss_device *next; struct oss_device *last; size_t i; - if(plen == 0 || path[0] == '\0') - return; - /* skip the first item "OSS Default" */ last = list; next = list->next; @@ -173,7 +180,10 @@ static void ALCossListPopulate(struct oss_device *playback, struct oss_device *c ERR("SNDCTL_AUDIOINFO (%d) failed: %s\n", i, strerror(errno)); continue; } - if(ai.handle[0]) + if(ai.devnode[0] == '\0') + continue; + + if(ai.handle[0] != '\0') { len = strnlen(ai.handle, sizeof(ai.handle)); handle = ai.handle; diff --git a/CMakeLists.txt b/CMakeLists.txt index 513bd037..e503df92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -453,8 +453,8 @@ IF(HAVE_FLOAT_H) CHECK_SYMBOL_EXISTS(__control87_2 float.h HAVE___CONTROL87_2) ENDIF() -CHECK_FUNCTION_EXISTS(strtof HAVE_STRTOF) CHECK_FUNCTION_EXISTS(stat HAVE_STAT) +CHECK_FUNCTION_EXISTS(strtof HAVE_STRTOF) CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP) IF(NOT HAVE_STRCASECMP) CHECK_FUNCTION_EXISTS(_stricmp HAVE__STRICMP) @@ -475,6 +475,7 @@ IF(NOT HAVE_STRNCASECMP) ADD_DEFINITIONS(-Dstrncasecmp=_strnicmp) ENDIF() +CHECK_SYMBOL_EXISTS(strnlen string.h HAVE_STRNLEN) CHECK_SYMBOL_EXISTS(snprintf stdio.h HAVE_SNPRINTF) IF(NOT HAVE_SNPRINTF) CHECK_FUNCTION_EXISTS(_snprintf HAVE__SNPRINTF) diff --git a/config.h.in b/config.h.in index e66b1fe8..3bc3eb48 100644 --- a/config.h.in +++ b/config.h.in @@ -86,6 +86,9 @@ /* Define if we have the strtof function */ #cmakedefine HAVE_STRTOF +/* Define if we have the strnlen function */ +#cmakedefine HAVE_STRNLEN + /* Define if we have the __int64 type */ #cmakedefine HAVE___INT64 -- cgit v1.2.3 From 7de8db2960e374e34bd48cd26d22315e63d17ebb Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 23 Jan 2016 21:47:43 -0800 Subject: Replace multiple fputc calls with one fwrite --- Alc/backends/wave.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index 6b47c611..d54e21eb 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -56,16 +56,14 @@ static const ALubyte SUBTYPE_BFORMAT_FLOAT[] = { static void fwrite16le(ALushort val, FILE *f) { - fputc(val&0xff, f); - fputc((val>>8)&0xff, f); + ALubyte data[2] = { val&0xff, (val>>8)&0xff }; + fwrite(data, 1, 2, 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); + ALubyte data[4] = { val&0xff, (val>>8)&0xff, (val>>16)&0xff, (val>>24)&0xff }; + fwrite(data, 1, 4, f); } -- cgit v1.2.3 From 79e0f3e747880a3e7d8342a8602b796b84c0f322 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 25 Jan 2016 01:49:28 -0800 Subject: Don't write one byte at a time for the wave writer on big endian --- Alc/backends/wave.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index d54e21eb..3b87d645 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -163,31 +163,33 @@ static int ALCwaveBackend_mixerProc(void *ptr) if(!IS_LITTLE_ENDIAN) { ALuint bytesize = BytesFromDevFmt(device->FmtType); - ALubyte *bytes = self->mBuffer; ALuint i; - if(bytesize == 1) + if(bytesize == 2) { - for(i = 0;i < self->mSize;i++) - fputc(bytes[i], self->mFile); - } - else if(bytesize == 2) - { - for(i = 0;i < self->mSize;i++) - fputc(bytes[i^1], self->mFile); + ALushort *samples = self->mBuffer; + ALuint len = self->mSize / 2; + for(i = 0;i < len;i++) + { + ALushort samp = samples[i]; + samples[i] = (samp>>8) | (samp<<8); + } } else if(bytesize == 4) { - for(i = 0;i < self->mSize;i++) - fputc(bytes[i^3], self->mFile); + ALuint *samples = self->mBuffer; + ALuint len = self->mSize / 4; + for(i = 0;i < len;i++) + { + ALuint samp = samples[i]; + samples[i] = (samp>>24) | ((samp>>8)&0x0000ff00) | + ((samp<<8)&0x00ff0000) | (samp<<24); + } } } - else - { - fs = fwrite(self->mBuffer, frameSize, device->UpdateSize, - self->mFile); - (void)fs; - } + + fs = fwrite(self->mBuffer, frameSize, device->UpdateSize, self->mFile); + (void)fs; if(ferror(self->mFile)) { ERR("Error writing to file\n"); -- cgit v1.2.3 From f4fa41487c18ece49fddb512e3d9253e6eb1e92b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Feb 2016 16:14:27 -0800 Subject: Replace some CreateEvent calls with CreateEventW --- Alc/backends/dsound.c | 2 +- Alc/backends/mmdevapi.c | 12 ++++++------ common/threads.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index f27ab37b..c01e42ae 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -357,7 +357,7 @@ static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *de } hr = DS_OK; - self->NotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + self->NotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL); if(self->NotifyEvent == NULL) hr = E_FAIL; diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 0134a46c..c47ddee6 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -672,8 +672,8 @@ static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *devi { HRESULT hr = S_OK; - self->NotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - self->MsgEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + self->NotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + self->MsgEvent = CreateEventW(NULL, FALSE, FALSE, NULL); if(self->NotifyEvent == NULL || self->MsgEvent == NULL) { ERR("Failed to create message events: %lu\n", GetLastError()); @@ -1308,8 +1308,8 @@ static ALCenum ALCmmdevCapture_open(ALCmmdevCapture *self, const ALCchar *device { HRESULT hr = S_OK; - self->NotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - self->MsgEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + self->NotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + self->MsgEvent = CreateEventW(NULL, FALSE, FALSE, NULL); if(self->NotifyEvent == NULL || self->MsgEvent == NULL) { ERR("Failed to create message events: %lu\n", GetLastError()); @@ -1739,7 +1739,7 @@ static BOOL MMDevApiLoad(void) ThreadRequest req; InitResult = E_FAIL; - req.FinishedEvt = CreateEvent(NULL, FALSE, FALSE, NULL); + req.FinishedEvt = CreateEventW(NULL, FALSE, FALSE, NULL); if(req.FinishedEvt == NULL) ERR("Failed to create event: %lu\n", GetLastError()); else @@ -1796,7 +1796,7 @@ static void ALCmmdevBackendFactory_probe(ALCmmdevBackendFactory* UNUSED(self), e { ThreadRequest req = { NULL, 0 }; - req.FinishedEvt = CreateEvent(NULL, FALSE, FALSE, NULL); + req.FinishedEvt = CreateEventW(NULL, FALSE, FALSE, NULL); if(req.FinishedEvt == NULL) ERR("Failed to create event: %lu\n", GetLastError()); else diff --git a/common/threads.c b/common/threads.c index 127b9083..6272dd9f 100644 --- a/common/threads.c +++ b/common/threads.c @@ -306,8 +306,8 @@ int alcnd_init(alcnd_t *cond) InitRef(&icond->wait_count, 0); - icond->events[SIGNAL] = CreateEvent(NULL, FALSE, FALSE, NULL); - icond->events[BROADCAST] = CreateEvent(NULL, TRUE, FALSE, NULL); + icond->events[SIGNAL] = CreateEventW(NULL, FALSE, FALSE, NULL); + icond->events[BROADCAST] = CreateEventW(NULL, TRUE, FALSE, NULL); if(!icond->events[SIGNAL] || !icond->events[BROADCAST]) { if(icond->events[SIGNAL]) -- cgit v1.2.3 From 2c6e59c4ca50f186d19e1fd95fe058ea352c8900 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 22 Feb 2016 08:12:09 -0800 Subject: Fix when ESTRPIPE and EPIPE are the same --- Alc/backends/alsa.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Alc/backends') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 43c46484..b5715e18 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -588,7 +588,9 @@ static int ALCplaybackAlsa_mixerNoMMapProc(void *ptr) { case -EAGAIN: continue; +#if ESTRPIPE != EPIPE case -ESTRPIPE: +#endif case -EPIPE: case -EINTR: ret = snd_pcm_recover(self->pcmHandle, ret, 1); -- cgit v1.2.3 From d6163fe570e09a6fa65ef1f11eba3d6bcbd3aa9f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 29 Mar 2016 23:48:36 -0700 Subject: Convert remaining ringbuffers to the lockless variant --- Alc/backends/alsa.c | 35 +++++++++++++++------------------ Alc/backends/coreaudio.c | 22 ++++++++++++--------- Alc/backends/dsound.c | 18 +++++++++-------- Alc/backends/oss.c | 51 ++++++++++++++++++++++++------------------------ Alc/backends/winmm.c | 18 ++++++++--------- 5 files changed, 74 insertions(+), 70 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index b5715e18..3a0ed205 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -915,7 +915,7 @@ typedef struct ALCcaptureAlsa { ALsizei size; ALboolean doCapture; - RingBuffer *ring; + ll_ringbuffer_t *ring; snd_pcm_sframes_t last_avail; } ALCcaptureAlsa; @@ -1047,21 +1047,15 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name) if(needring) { - self->ring = CreateRingBuffer(FrameSizeFromDevFmt(device->FmtChans, device->FmtType), - device->UpdateSize*device->NumUpdates); + self->ring = ll_ringbuffer_create( + device->UpdateSize*device->NumUpdates + 1, + FrameSizeFromDevFmt(device->FmtChans, device->FmtType) + ); if(!self->ring) { ERR("ring buffer create failed\n"); goto error2; } - - self->size = snd_pcm_frames_to_bytes(self->pcmHandle, periodSizeInFrames); - self->buffer = malloc(self->size); - if(!self->buffer) - { - ERR("buffer malloc failed\n"); - goto error2; - } } al_string_copy_cstr(&device->DeviceName, name); @@ -1075,7 +1069,7 @@ error: error2: free(self->buffer); self->buffer = NULL; - DestroyRingBuffer(self->ring); + ll_ringbuffer_free(self->ring); self->ring = NULL; snd_pcm_close(self->pcmHandle); @@ -1085,7 +1079,7 @@ error2: static void ALCcaptureAlsa_close(ALCcaptureAlsa *self) { snd_pcm_close(self->pcmHandle); - DestroyRingBuffer(self->ring); + ll_ringbuffer_free(self->ring); free(self->buffer); self->buffer = NULL; @@ -1143,7 +1137,7 @@ static ALCenum ALCcaptureAlsa_captureSamples(ALCcaptureAlsa *self, ALCvoid *buff if(self->ring) { - ReadRingBuffer(self->ring, buffer, samples); + ll_ringbuffer_read(self->ring, buffer, samples); return ALC_NO_ERROR; } @@ -1246,12 +1240,15 @@ static ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self) while(avail > 0) { + ll_ringbuffer_data_t vec[2]; snd_pcm_sframes_t amt; - amt = snd_pcm_bytes_to_frames(self->pcmHandle, self->size); - if(avail < amt) amt = avail; + ll_ringbuffer_get_write_vector(self->ring, vec); + if(vec[0].len == 0) break; - amt = snd_pcm_readi(self->pcmHandle, self->buffer, amt); + amt = (vec[0].len < (snd_pcm_uframes_t)avail) ? + vec[0].len : (snd_pcm_uframes_t)avail; + amt = snd_pcm_readi(self->pcmHandle, vec[0].buf, amt); if(amt < 0) { ERR("read error: %s\n", snd_strerror(amt)); @@ -1275,11 +1272,11 @@ static ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self) continue; } - WriteRingBuffer(self->ring, self->buffer, amt); + ll_ringbuffer_write_advance(self->ring, amt); avail -= amt; } - return RingBufferSize(self->ring); + return ll_ringbuffer_read_space(self->ring); } static ALint64 ALCcaptureAlsa_getLatency(ALCcaptureAlsa *self) diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index d9264217..4907f362 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -45,7 +45,7 @@ typedef struct { AudioBufferList *bufferList; // Buffer for data coming from the input device ALCvoid *resampleBuffer; // Buffer for returned RingBuffer data when resampling - RingBuffer *ring; + ll_ringbuffer_t *ring; } ca_data; static const ALCchar ca_device[] = "CoreAudio Default"; @@ -102,7 +102,7 @@ static OSStatus ca_capture_conversion_callback(AudioConverterRef inAudioConverte 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)); + ll_ringbuffer_read(data->ring, data->resampleBuffer, *ioNumberDataPackets); // Set the input data ioData->mNumberBuffers = 1; @@ -130,7 +130,7 @@ static OSStatus ca_capture_callback(void *inRefCon, AudioUnitRenderActionFlags * return err; } - WriteRingBuffer(data->ring, data->bufferList->mBuffers[0].mData, inNumberFrames); + ll_ringbuffer_write(data->ring, data->bufferList->mBuffers[0].mData, inNumberFrames); return noErr; } @@ -586,16 +586,19 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) if(data->bufferList == NULL) goto error; - data->ring = CreateRingBuffer(data->frameSize, (device->UpdateSize * data->sampleRateRatio) * device->NumUpdates); - if(data->ring == NULL) - goto error; + data->ring = ll_ringbuffer_create( + device->UpdateSize*data->sampleRateRatio*device->NumUpdates + 1, + data->frameSize + ); + if(!data->ring) goto error; al_string_copy_cstr(&device->DeviceName, deviceName); return ALC_NO_ERROR; error: - DestroyRingBuffer(data->ring); + ll_ringbuffer_free(data->ring); + data->ring = NULL; free(data->resampleBuffer); destroy_buffer_list(data->bufferList); @@ -614,7 +617,8 @@ static void ca_close_capture(ALCdevice *device) { ca_data *data = (ca_data*)device->ExtraData; - DestroyRingBuffer(data->ring); + ll_ringbuffer_free(data->ring); + data->ring = NULL; free(data->resampleBuffer); destroy_buffer_list(data->bufferList); @@ -676,7 +680,7 @@ static ALCenum ca_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint sa static ALCuint ca_available_samples(ALCdevice *device) { ca_data *data = device->ExtraData; - return RingBufferSize(data->ring) / data->sampleRateRatio; + return ll_ringbuffer_read_space(data->ring) / data->sampleRateRatio; } diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index c01e42ae..68ac08f1 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -653,7 +653,8 @@ typedef struct ALCdsoundCapture { IDirectSoundCaptureBuffer *DSCbuffer; DWORD BufferBytes; DWORD Cursor; - RingBuffer *Ring; + + ll_ringbuffer_t *Ring; } ALCdsoundCapture; static void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device); @@ -823,7 +824,8 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi } if(SUCCEEDED(hr)) { - self->Ring = CreateRingBuffer(InputType.Format.nBlockAlign, device->UpdateSize * device->NumUpdates); + self->Ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates + 1, + InputType.Format.nBlockAlign); if(self->Ring == NULL) hr = DSERR_OUTOFMEMORY; } @@ -832,7 +834,7 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi { ERR("Device init failed: 0x%08lx\n", hr); - DestroyRingBuffer(self->Ring); + ll_ringbuffer_free(self->Ring); self->Ring = NULL; if(self->DSCbuffer != NULL) IDirectSoundCaptureBuffer_Release(self->DSCbuffer); @@ -854,7 +856,7 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi static void ALCdsoundCapture_close(ALCdsoundCapture *self) { - DestroyRingBuffer(self->Ring); + ll_ringbuffer_free(self->Ring); self->Ring = NULL; if(self->DSCbuffer != NULL) @@ -897,7 +899,7 @@ static void ALCdsoundCapture_stop(ALCdsoundCapture *self) static ALCenum ALCdsoundCapture_captureSamples(ALCdsoundCapture *self, ALCvoid *buffer, ALCuint samples) { - ReadRingBuffer(self->Ring, buffer, samples); + ll_ringbuffer_read(self->Ring, buffer, samples); return ALC_NO_ERROR; } @@ -929,9 +931,9 @@ static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self) } if(SUCCEEDED(hr)) { - WriteRingBuffer(self->Ring, ReadPtr1, ReadCnt1/FrameSize); + ll_ringbuffer_write(self->Ring, ReadPtr1, ReadCnt1/FrameSize); if(ReadPtr2 != NULL) - WriteRingBuffer(self->Ring, ReadPtr2, ReadCnt2/FrameSize); + ll_ringbuffer_write(self->Ring, ReadPtr2, ReadCnt2/FrameSize); hr = IDirectSoundCaptureBuffer_Unlock(self->DSCbuffer, ReadPtr1, ReadCnt1, ReadPtr2, ReadCnt2); @@ -945,7 +947,7 @@ static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self) } done: - return RingBufferSize(self->Ring); + return ll_ringbuffer_read_space(self->Ring); } diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 33d7750a..a61b4859 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -484,10 +484,7 @@ typedef struct ALCcaptureOSS { int fd; - ALubyte *read_data; - int data_size; - - RingBuffer *ring; + ll_ringbuffer_t *ring; int doCapture; volatile int killNow; @@ -517,7 +514,7 @@ static int ALCcaptureOSS_recordProc(void *ptr) ALCcaptureOSS *self = (ALCcaptureOSS*)ptr; ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; int frameSize; - int amt; + ssize_t amt; SetRTPriority(); althrd_setname(althrd_current(), RECORD_THREAD_NAME); @@ -526,22 +523,31 @@ static int ALCcaptureOSS_recordProc(void *ptr) while(!self->killNow) { - amt = read(self->fd, self->read_data, self->data_size); - if(amt < 0) + ll_ringbuffer_data_t vec[2]; + + amt = 0; + if(self->doCapture) { - ERR("read failed: %s\n", strerror(errno)); - ALCcaptureOSS_lock(self); - aluHandleDisconnect(device); - ALCcaptureOSS_unlock(self); - break; + ll_ringbuffer_get_write_vector(self->ring, vec); + if(vec[0].len > 0) + { + amt = read(self->fd, vec[0].buf, vec[0].len*frameSize); + if(amt < 0) + { + ERR("read failed: %s\n", strerror(errno)); + ALCcaptureOSS_lock(self); + aluHandleDisconnect(device); + ALCcaptureOSS_unlock(self); + break; + } + ll_ringbuffer_write_advance(self->ring, amt/frameSize); + } } if(amt == 0) { al_nssleep(1000000); continue; } - if(self->doCapture) - WriteRingBuffer(self->ring, self->read_data, amt/frameSize); } return 0; @@ -657,7 +663,7 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) return ALC_INVALID_VALUE; } - self->ring = CreateRingBuffer(frameSize, device->UpdateSize * device->NumUpdates); + self->ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates + 1, frameSize); if(!self->ring) { ERR("Ring buffer create failed\n"); @@ -666,13 +672,11 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) return ALC_OUT_OF_MEMORY; } - self->data_size = info.fragsize; - self->read_data = calloc(1, self->data_size); - self->killNow = 0; if(althrd_create(&self->thread, ALCcaptureOSS_recordProc, self) != althrd_success) { - device->ExtraData = NULL; + ll_ringbuffer_free(self->ring); + self->ring = NULL; close(self->fd); self->fd = -1; return ALC_OUT_OF_MEMORY; @@ -693,11 +697,8 @@ static void ALCcaptureOSS_close(ALCcaptureOSS *self) close(self->fd); self->fd = -1; - DestroyRingBuffer(self->ring); + ll_ringbuffer_free(self->ring); self->ring = NULL; - - free(self->read_data); - self->read_data = NULL; } static ALCboolean ALCcaptureOSS_start(ALCcaptureOSS *self) @@ -713,13 +714,13 @@ static void ALCcaptureOSS_stop(ALCcaptureOSS *self) static ALCenum ALCcaptureOSS_captureSamples(ALCcaptureOSS *self, ALCvoid *buffer, ALCuint samples) { - ReadRingBuffer(self->ring, buffer, samples); + ll_ringbuffer_read(self->ring, buffer, samples); return ALC_NO_ERROR; } static ALCuint ALCcaptureOSS_availableSamples(ALCcaptureOSS *self) { - return RingBufferSize(self->ring); + return ll_ringbuffer_read_space(self->ring); } diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index 3508ec49..0085251d 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -430,7 +430,7 @@ typedef struct ALCwinmmCapture { HWAVEIN InHdl; - RingBuffer *Ring; + ll_ringbuffer_t *Ring; WAVEFORMATEX Format; @@ -514,8 +514,9 @@ static int ALCwinmmCapture_captureProc(void *arg) break; WaveHdr = ((WAVEHDR*)msg.lParam); - WriteRingBuffer(self->Ring, (ALubyte*)WaveHdr->lpData, - WaveHdr->dwBytesRecorded/self->Format.nBlockAlign); + ll_ringbuffer_write(self->Ring, WaveHdr->lpData, + WaveHdr->dwBytesRecorded / self->Format.nBlockAlign + ); // Send buffer back to capture more data waveInAddBuffer(self->InHdl, WaveHdr, sizeof(WAVEHDR)); @@ -603,7 +604,7 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name) if(CapturedDataSize < (self->Format.nSamplesPerSec / 10)) CapturedDataSize = self->Format.nSamplesPerSec / 10; - self->Ring = CreateRingBuffer(self->Format.nBlockAlign, CapturedDataSize); + self->Ring = ll_ringbuffer_create(CapturedDataSize+1, self->Format.nBlockAlign); if(!self->Ring) goto failure; InitRef(&self->WaveBuffersCommitted, 0); @@ -644,8 +645,7 @@ failure: free(BufferData); } - if(self->Ring) - DestroyRingBuffer(self->Ring); + ll_ringbuffer_free(self->Ring); self->Ring = NULL; if(self->InHdl) @@ -678,7 +678,7 @@ static void ALCwinmmCapture_close(ALCwinmmCapture *self) } free(buffer); - DestroyRingBuffer(self->Ring); + ll_ringbuffer_free(self->Ring); self->Ring = NULL; // Close the Wave device @@ -699,13 +699,13 @@ static void ALCwinmmCapture_stop(ALCwinmmCapture *self) static ALCenum ALCwinmmCapture_captureSamples(ALCwinmmCapture *self, ALCvoid *buffer, ALCuint samples) { - ReadRingBuffer(self->Ring, buffer, samples); + ll_ringbuffer_read(self->Ring, buffer, samples); return ALC_NO_ERROR; } static ALCuint ALCwinmmCapture_availableSamples(ALCwinmmCapture *self) { - return RingBufferSize(self->Ring); + return ll_ringbuffer_read_space(self->Ring); } -- cgit v1.2.3 From 8145a26d07fd1a99c8cf72b1d02650e0988232b5 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 31 Mar 2016 16:21:49 -0700 Subject: Add a hack to workaround erroneous prebuf values from pulse --- Alc/backends/pulseaudio.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index 9ad04a71..ca8441aa 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -1051,10 +1051,12 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) { /* Server updated our playback rate, so modify the buffer attribs * accordingly. */ - device->NumUpdates = (ALuint)((ALdouble)device->NumUpdates / device->Frequency * - self->spec.rate + 0.5); + device->NumUpdates = (ALuint)clampd( + (ALdouble)device->NumUpdates/device->Frequency*self->spec.rate + 0.5, 2.0, 16.0 + ); + self->attr.minreq = device->UpdateSize * pa_frame_size(&self->spec); - self->attr.tlength = self->attr.minreq * clampu(device->NumUpdates, 2, 16); + self->attr.tlength = self->attr.minreq * device->NumUpdates; self->attr.maxlength = -1; self->attr.prebuf = 0; @@ -1069,10 +1071,31 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) ALCpulsePlayback_bufferAttrCallback(self->stream, self); len = self->attr.minreq / pa_frame_size(&self->spec); - device->NumUpdates = (ALuint)((ALdouble)device->NumUpdates/len*device->UpdateSize + 0.5); - device->NumUpdates = clampu(device->NumUpdates, 2, 16); + device->NumUpdates = (ALuint)clampd( + (ALdouble)device->NumUpdates/len*device->UpdateSize + 0.5, 2.0, 16.0 + ); device->UpdateSize = len; + /* HACK: prebuf should be 0 as that's what we set it to. However on some + * systems it comes back as non-0, so we have to make sure the device will + * write enough audio to start playback. The lack of manual start control + * may have unintended consequences, but it's better than not starting at + * all. + */ + if(self->attr.prebuf != 0) + { + len = self->attr.prebuf / pa_frame_size(&self->spec); + if(len <= device->UpdateSize*device->NumUpdates) + ERR("Non-0 prebuf, %u samples (%u bytes), device has %u samples\n", + len, self->attr.prebuf, device->UpdateSize*device->NumUpdates); + else + { + ERR("Large prebuf, %u samples (%u bytes), increasing device from %u samples", + len, self->attr.prebuf, device->UpdateSize*device->NumUpdates); + device->NumUpdates = (len+device->UpdateSize-1) / device->UpdateSize; + } + } + pa_threaded_mainloop_unlock(self->loop); return ALC_TRUE; } -- cgit v1.2.3 From 071f8a7b188a4e05b66a525e6f9d47f51b09223d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 5 Apr 2016 19:35:03 -0700 Subject: Also disable ALSA's resampler when not requesting a sample rate --- Alc/backends/alsa.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Alc/backends') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 3a0ed205..805d66e3 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -773,11 +773,14 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self) } CHECK(snd_pcm_hw_params_set_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans))); /* set rate (implicitly constrains period/buffer parameters) */ - if(!GetConfigValueBool(al_string_get_cstr(device->DeviceName), "alsa", "allow-resampler", 0)) + if(!GetConfigValueBool(al_string_get_cstr(device->DeviceName), "alsa", "allow-resampler", 0) || + !(device->Flags&DEVICE_FREQUENCY_REQUEST)) { if(snd_pcm_hw_params_set_rate_resample(self->pcmHandle, hp, 0) < 0) ERR("Failed to disable ALSA resampler\n"); } + else if(snd_pcm_hw_params_set_rate_resample(self->pcmHandle, hp, 1) < 0) + ERR("Failed to enable ALSA resampler\n"); CHECK(snd_pcm_hw_params_set_rate_near(self->pcmHandle, hp, &rate, NULL)); /* set buffer time (implicitly constrains period/buffer parameters) */ if((err=snd_pcm_hw_params_set_buffer_time_near(self->pcmHandle, hp, &bufferLen, NULL)) < 0) -- cgit v1.2.3 From e127072b41d64cd95f72572fe897fa8ec2f98ece Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 5 Apr 2016 20:21:32 -0700 Subject: Use al_malloc/al_free for allocations --- Alc/backends/alsa.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 805d66e3..3b37f3ca 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -845,7 +845,7 @@ static ALCboolean ALCplaybackAlsa_start(ALCplaybackAlsa *self) self->size = snd_pcm_frames_to_bytes(self->pcmHandle, device->UpdateSize); if(access == SND_PCM_ACCESS_RW_INTERLEAVED) { - self->buffer = malloc(self->size); + self->buffer = al_malloc(16, self->size); if(!self->buffer) { ERR("buffer malloc failed\n"); @@ -867,7 +867,7 @@ static ALCboolean ALCplaybackAlsa_start(ALCplaybackAlsa *self) if(althrd_create(&self->thread, thread_func, self) != althrd_success) { ERR("Could not create playback thread\n"); - free(self->buffer); + al_free(self->buffer); self->buffer = NULL; return ALC_FALSE; } @@ -890,7 +890,7 @@ static void ALCplaybackAlsa_stop(ALCplaybackAlsa *self) self->killNow = 1; althrd_join(self->thread, &res); - free(self->buffer); + al_free(self->buffer); self->buffer = NULL; } @@ -1070,8 +1070,6 @@ error: if(hp) snd_pcm_hw_params_free(hp); error2: - free(self->buffer); - self->buffer = NULL; ll_ringbuffer_free(self->ring); self->ring = NULL; snd_pcm_close(self->pcmHandle); @@ -1084,7 +1082,7 @@ static void ALCcaptureAlsa_close(ALCcaptureAlsa *self) snd_pcm_close(self->pcmHandle); ll_ringbuffer_free(self->ring); - free(self->buffer); + al_free(self->buffer); self->buffer = NULL; } @@ -1119,11 +1117,11 @@ static void ALCcaptureAlsa_stop(ALCcaptureAlsa *self) void *ptr; size = snd_pcm_frames_to_bytes(self->pcmHandle, avail); - ptr = malloc(size); + ptr = al_malloc(16, size); if(ptr) { ALCcaptureAlsa_captureSamples(self, ptr, avail); - free(self->buffer); + al_free(self->buffer); self->buffer = ptr; self->size = size; } @@ -1165,7 +1163,7 @@ static ALCenum ALCcaptureAlsa_captureSamples(ALCcaptureAlsa *self, ALCvoid *buff } else { - free(self->buffer); + al_free(self->buffer); self->buffer = NULL; self->size = 0; } -- cgit v1.2.3 From f4ff5fc106f39ad30cdf72eade4bade649777a85 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 15 Apr 2016 12:22:54 -0700 Subject: Shorten VECTOR_ITER_ macros to VECTOR_ --- Alc/backends/alsa.c | 19 ++++++++----------- Alc/backends/dsound.c | 6 +++--- Alc/backends/mmdevapi.c | 6 +++--- Alc/backends/pulseaudio.c | 12 ++++++------ Alc/backends/qsa.c | 4 ++-- Alc/backends/winmm.c | 12 ++++++------ Alc/helpers.c | 42 +++++++++++++++++++++--------------------- Alc/hrtf.c | 6 +++--- Alc/vector.h | 20 ++++++++++---------- OpenAL32/alAuxEffectSlot.c | 6 +++--- 10 files changed, 65 insertions(+), 68 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 3b37f3ca..7d23ecc3 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -237,16 +237,13 @@ static vector_DevMap CaptureDevices; static void clear_devlist(vector_DevMap *devlist) { - DevMap *iter, *end; - - iter = VECTOR_ITER_BEGIN(*devlist); - end = VECTOR_ITER_END(*devlist); - for(;iter != end;iter++) - { - AL_STRING_DEINIT(iter->name); - AL_STRING_DEINIT(iter->device_name); - } +#define FREE_DEV(i) do { \ + AL_STRING_DEINIT((i)->name); \ + AL_STRING_DEINIT((i)->device_name); \ +} while(0) + VECTOR_FOR_EACH(DevMap, *devlist, FREE_DEV); VECTOR_RESIZE(*devlist, 0); +#undef FREE_DEV } @@ -635,7 +632,7 @@ static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name) #define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, name) == 0) VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); #undef MATCH_NAME - if(iter == VECTOR_ITER_END(PlaybackDevices)) + if(iter == VECTOR_END(PlaybackDevices)) return ALC_INVALID_VALUE; driver = al_string_get_cstr(iter->device_name); } @@ -969,7 +966,7 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name) #define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, name) == 0) VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); #undef MATCH_NAME - if(iter == VECTOR_ITER_END(CaptureDevices)) + if(iter == VECTOR_END(CaptureDevices)) return ALC_INVALID_VALUE; driver = al_string_get_cstr(iter->device_name); } diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index 68ac08f1..454f7fa0 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -156,7 +156,7 @@ static BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHA #define MATCH_ENTRY(i) (al_string_cmp(entry.name, (i)->name) == 0) VECTOR_FIND_IF(iter, const DevMap, *devices, MATCH_ENTRY); - if(iter == VECTOR_ITER_END(*devices)) break; + if(iter == VECTOR_END(*devices)) break; #undef MATCH_ENTRY count++; } @@ -351,7 +351,7 @@ static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *de #define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, deviceName) == 0) VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); #undef MATCH_NAME - if(iter == VECTOR_ITER_END(PlaybackDevices)) + if(iter == VECTOR_END(PlaybackDevices)) return ALC_INVALID_VALUE; guid = &iter->guid; } @@ -712,7 +712,7 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi #define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, deviceName) == 0) VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); #undef MATCH_NAME - if(iter == VECTOR_ITER_END(CaptureDevices)) + if(iter == VECTOR_END(CaptureDevices)) return ALC_INVALID_VALUE; guid = &iter->guid; } diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index c47ddee6..8851678b 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -211,7 +211,7 @@ static void add_device(IMMDevice *device, LPCWSTR devid, vector_DevMap *list) #define MATCH_ENTRY(i) (al_string_cmp(entry.name, (i)->name) == 0) VECTOR_FIND_IF(iter, const DevMap, *list, MATCH_ENTRY); - if(iter == VECTOR_ITER_END(*list)) break; + if(iter == VECTOR_END(*list)) break; #undef MATCH_ENTRY count++; } @@ -696,7 +696,7 @@ static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *devi hr = E_FAIL; #define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, deviceName) == 0) VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); - if(iter == VECTOR_ITER_END(PlaybackDevices)) + if(iter == VECTOR_END(PlaybackDevices)) WARN("Failed to find device name matching \"%s\"\n", deviceName); else { @@ -1332,7 +1332,7 @@ static ALCenum ALCmmdevCapture_open(ALCmmdevCapture *self, const ALCchar *device hr = E_FAIL; #define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, deviceName) == 0) VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); - if(iter == VECTOR_ITER_END(CaptureDevices)) + if(iter == VECTOR_END(CaptureDevices)) WARN("Failed to find device name matching \"%s\"\n", deviceName); else { diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index ca8441aa..ccce2e00 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -527,7 +527,7 @@ static void ALCpulsePlayback_deviceCallback(pa_context *UNUSED(context), const p #define MATCH_INFO_NAME(iter) (al_string_cmp_cstr((iter)->device_name, info->name) == 0) VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_INFO_NAME); - if(iter != VECTOR_ITER_END(PlaybackDevices)) return; + if(iter != VECTOR_END(PlaybackDevices)) return; #undef MATCH_INFO_NAME AL_STRING_INIT(entry.name); @@ -548,7 +548,7 @@ static void ALCpulsePlayback_deviceCallback(pa_context *UNUSED(context), const p #define MATCH_ENTRY(i) (al_string_cmp(entry.name, (i)->name) == 0) VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_ENTRY); - if(iter == VECTOR_ITER_END(PlaybackDevices)) break; + if(iter == VECTOR_END(PlaybackDevices)) break; #undef MATCH_ENTRY count++; } @@ -861,7 +861,7 @@ static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name #define MATCH_NAME(iter) (al_string_cmp_cstr((iter)->name, name) == 0) VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); #undef MATCH_NAME - if(iter == VECTOR_ITER_END(PlaybackDevices)) + if(iter == VECTOR_END(PlaybackDevices)) return ALC_INVALID_VALUE; pulse_name = al_string_get_cstr(iter->device_name); dev_name = iter->name; @@ -1247,7 +1247,7 @@ static void ALCpulseCapture_deviceCallback(pa_context *UNUSED(context), const pa #define MATCH_INFO_NAME(iter) (al_string_cmp_cstr((iter)->device_name, info->name) == 0) VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_INFO_NAME); - if(iter != VECTOR_ITER_END(CaptureDevices)) return; + if(iter != VECTOR_END(CaptureDevices)) return; #undef MATCH_INFO_NAME AL_STRING_INIT(entry.name); @@ -1268,7 +1268,7 @@ static void ALCpulseCapture_deviceCallback(pa_context *UNUSED(context), const pa #define MATCH_ENTRY(i) (al_string_cmp(entry.name, (i)->name) == 0) VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_ENTRY); - if(iter == VECTOR_ITER_END(CaptureDevices)) break; + if(iter == VECTOR_END(CaptureDevices)) break; #undef MATCH_ENTRY count++; } @@ -1439,7 +1439,7 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name) #define MATCH_NAME(iter) (al_string_cmp_cstr((iter)->name, name) == 0) VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); #undef MATCH_NAME - if(iter == VECTOR_ITER_END(CaptureDevices)) + if(iter == VECTOR_END(CaptureDevices)) return ALC_INVALID_VALUE; pulse_name = al_string_get_cstr(iter->device_name); al_string_copy(&device->DeviceName, iter->name); diff --git a/Alc/backends/qsa.c b/Alc/backends/qsa.c index 291e49fc..a1fbce63 100644 --- a/Alc/backends/qsa.c +++ b/Alc/backends/qsa.c @@ -277,7 +277,7 @@ static ALCenum qsa_open_playback(ALCdevice* device, const ALCchar* deviceName) #define MATCH_DEVNAME(iter) ((iter)->name && strcmp(deviceName, (iter)->name)==0) VECTOR_FIND_IF(iter, const DevMap, DeviceNameMap, MATCH_DEVNAME); #undef MATCH_DEVNAME - if(iter == VECTOR_ITER_END(DeviceNameMap)) + if(iter == VECTOR_END(DeviceNameMap)) { free(data); return ALC_INVALID_DEVICE; @@ -624,7 +624,7 @@ static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName) #define MATCH_DEVNAME(iter) ((iter)->name && strcmp(deviceName, (iter)->name)==0) VECTOR_FIND_IF(iter, const DevMap, CaptureNameMap, MATCH_DEVNAME); #undef MATCH_DEVNAME - if(iter == VECTOR_ITER_END(CaptureNameMap)) + if(iter == VECTOR_END(CaptureNameMap)) { free(data); return ALC_INVALID_DEVICE; diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index 0085251d..664b3dfe 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -83,7 +83,7 @@ static void ProbePlaybackDevices(void) #define MATCH_ENTRY(i) (al_string_cmp(dname, *(i)) == 0) VECTOR_FIND_IF(iter, const al_string, PlaybackDevices, MATCH_ENTRY); - if(iter == VECTOR_ITER_END(PlaybackDevices)) break; + if(iter == VECTOR_END(PlaybackDevices)) break; #undef MATCH_ENTRY } @@ -126,7 +126,7 @@ static void ProbeCaptureDevices(void) #define MATCH_ENTRY(i) (al_string_cmp(dname, *(i)) == 0) VECTOR_FIND_IF(iter, const al_string, CaptureDevices, MATCH_ENTRY); - if(iter == VECTOR_ITER_END(CaptureDevices)) break; + if(iter == VECTOR_END(CaptureDevices)) break; #undef MATCH_ENTRY } @@ -258,11 +258,11 @@ static ALCenum ALCwinmmPlayback_open(ALCwinmmPlayback *self, const ALCchar *devi #define MATCH_DEVNAME(iter) (!al_string_empty(*(iter)) && \ (!deviceName || al_string_cmp_cstr(*(iter), deviceName) == 0)) VECTOR_FIND_IF(iter, const al_string, PlaybackDevices, MATCH_DEVNAME); - if(iter == VECTOR_ITER_END(PlaybackDevices)) + if(iter == VECTOR_END(PlaybackDevices)) return ALC_INVALID_VALUE; #undef MATCH_DEVNAME - DeviceID = (UINT)(iter - VECTOR_ITER_BEGIN(PlaybackDevices)); + DeviceID = (UINT)(iter - VECTOR_BEGIN(PlaybackDevices)); retry_open: memset(&self->Format, 0, sizeof(WAVEFORMATEX)); @@ -544,11 +544,11 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name) // Find the Device ID matching the deviceName if valid #define MATCH_DEVNAME(iter) (!al_string_empty(*(iter)) && (!name || al_string_cmp_cstr(*iter, name) == 0)) VECTOR_FIND_IF(iter, const al_string, CaptureDevices, MATCH_DEVNAME); - if(iter == VECTOR_ITER_END(CaptureDevices)) + if(iter == VECTOR_END(CaptureDevices)) return ALC_INVALID_VALUE; #undef MATCH_DEVNAME - DeviceID = (UINT)(iter - VECTOR_ITER_BEGIN(CaptureDevices)); + DeviceID = (UINT)(iter - VECTOR_BEGIN(CaptureDevices)); switch(device->FmtChans) { diff --git a/Alc/helpers.c b/Alc/helpers.c index 47851cf9..950a67bf 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -456,7 +456,7 @@ static void DirectorySearch(const char *path, const char *ext, vector_al_string FindClose(hdl); if(VECTOR_SIZE(*results) > base) - qsort(VECTOR_ITER_BEGIN(*results)+base, VECTOR_SIZE(*results)-base, + qsort(VECTOR_BEGIN(*results)+base, VECTOR_SIZE(*results)-base, sizeof(VECTOR_FRONT(*results)), StringSortCompare); } @@ -501,7 +501,7 @@ vector_al_string SearchDataFiles(const char *ext, const char *subdir) if(is_slash(VECTOR_BACK(path))) { VECTOR_POP_BACK(path); - *VECTOR_ITER_END(path) = 0; + *VECTOR_END(path) = 0; } } else if(!(cwdbuf=_wgetcwd(NULL, 0))) @@ -512,7 +512,7 @@ vector_al_string SearchDataFiles(const char *ext, const char *subdir) if(is_slash(VECTOR_BACK(path))) { VECTOR_POP_BACK(path); - *VECTOR_ITER_END(path) = 0; + *VECTOR_END(path) = 0; } free(cwdbuf); } @@ -629,8 +629,8 @@ static void DirectorySearch(const char *path, const char *ext, vector_al_string closedir(dir); if(VECTOR_SIZE(*results) > base) - qsort(VECTOR_ITER_BEGIN(*results)+base, VECTOR_SIZE(*results)-base, - sizeof(VECTOR_FRONT(*results)), StringSortCompare); + qsort(VECTOR_BEGIN(*results)+base, VECTOR_SIZE(*results)-base, + sizeof(VECTOR_FRONT(*results)), StringSortCompare); } } @@ -673,7 +673,7 @@ vector_al_string SearchDataFiles(const char *ext, const char *subdir) if(VECTOR_BACK(path) == '/') { VECTOR_POP_BACK(path); - *VECTOR_ITER_END(path) = 0; + *VECTOR_END(path) = 0; } al_string_append_cstr(&path, "/.local/share/"); al_string_append_cstr(&path, subdir); @@ -826,7 +826,7 @@ void al_string_clear(al_string *str) */ VECTOR_RESERVE(*str, 1); VECTOR_RESIZE(*str, 0); - *VECTOR_ITER_END(*str) = 0; + *VECTOR_END(*str) = 0; } } @@ -858,8 +858,8 @@ void al_string_copy(al_string *str, const_al_string from) size_t len = al_string_length(from); VECTOR_RESERVE(*str, len+1); VECTOR_RESIZE(*str, 0); - VECTOR_INSERT(*str, VECTOR_ITER_END(*str), VECTOR_ITER_BEGIN(from), VECTOR_ITER_BEGIN(from)+len); - *VECTOR_ITER_END(*str) = 0; + VECTOR_INSERT(*str, VECTOR_END(*str), VECTOR_BEGIN(from), VECTOR_BEGIN(from)+len); + *VECTOR_END(*str) = 0; } void al_string_copy_cstr(al_string *str, const al_string_char_type *from) @@ -867,8 +867,8 @@ void al_string_copy_cstr(al_string *str, const al_string_char_type *from) size_t len = strlen(from); VECTOR_RESERVE(*str, len+1); VECTOR_RESIZE(*str, 0); - VECTOR_INSERT(*str, VECTOR_ITER_END(*str), from, from+len); - *VECTOR_ITER_END(*str) = 0; + VECTOR_INSERT(*str, VECTOR_END(*str), from, from+len); + *VECTOR_END(*str) = 0; } void al_string_copy_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to) @@ -876,15 +876,15 @@ void al_string_copy_range(al_string *str, const al_string_char_type *from, const size_t len = to - from; VECTOR_RESERVE(*str, len+1); VECTOR_RESIZE(*str, 0); - VECTOR_INSERT(*str, VECTOR_ITER_END(*str), from, to); - *VECTOR_ITER_END(*str) = 0; + VECTOR_INSERT(*str, VECTOR_END(*str), from, to); + *VECTOR_END(*str) = 0; } void al_string_append_char(al_string *str, const al_string_char_type c) { VECTOR_RESERVE(*str, al_string_length(*str)+2); VECTOR_PUSH_BACK(*str, c); - *VECTOR_ITER_END(*str) = 0; + *VECTOR_END(*str) = 0; } void al_string_append_cstr(al_string *str, const al_string_char_type *from) @@ -893,8 +893,8 @@ void al_string_append_cstr(al_string *str, const al_string_char_type *from) if(len != 0) { VECTOR_RESERVE(*str, al_string_length(*str)+len+1); - VECTOR_INSERT(*str, VECTOR_ITER_END(*str), from, from+len); - *VECTOR_ITER_END(*str) = 0; + VECTOR_INSERT(*str, VECTOR_END(*str), from, from+len); + *VECTOR_END(*str) = 0; } } @@ -903,8 +903,8 @@ void al_string_append_range(al_string *str, const al_string_char_type *from, con if(to != from) { VECTOR_RESERVE(*str, al_string_length(*str)+(to-from)+1); - VECTOR_INSERT(*str, VECTOR_ITER_END(*str), from, to); - *VECTOR_ITER_END(*str) = 0; + VECTOR_INSERT(*str, VECTOR_END(*str), from, to); + *VECTOR_END(*str) = 0; } } @@ -917,7 +917,7 @@ void al_string_copy_wcstr(al_string *str, const wchar_t *from) VECTOR_RESERVE(*str, len); VECTOR_RESIZE(*str, len-1); WideCharToMultiByte(CP_UTF8, 0, from, -1, &VECTOR_FRONT(*str), len, NULL, NULL); - *VECTOR_ITER_END(*str) = 0; + *VECTOR_END(*str) = 0; } } @@ -930,7 +930,7 @@ void al_string_append_wcstr(al_string *str, const wchar_t *from) VECTOR_RESERVE(*str, strlen+len); VECTOR_RESIZE(*str, strlen+len-1); WideCharToMultiByte(CP_UTF8, 0, from, -1, &VECTOR_FRONT(*str) + strlen, len, NULL, NULL); - *VECTOR_ITER_END(*str) = 0; + *VECTOR_END(*str) = 0; } } @@ -943,7 +943,7 @@ void al_string_append_wrange(al_string *str, const wchar_t *from, const wchar_t VECTOR_RESERVE(*str, strlen+len+1); VECTOR_RESIZE(*str, strlen+len); WideCharToMultiByte(CP_UTF8, 0, from, (int)(to-from), &VECTOR_FRONT(*str) + strlen, len+1, NULL, NULL); - *VECTOR_ITER_END(*str) = 0; + *VECTOR_END(*str) = 0; } } #endif diff --git a/Alc/hrtf.c b/Alc/hrtf.c index 49c9793b..9549c010 100644 --- a/Alc/hrtf.c +++ b/Alc/hrtf.c @@ -595,7 +595,7 @@ static void AddFileEntry(vector_HrtfEntry *list, al_string *filename) #define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0) VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_NAME); #undef MATCH_NAME - } while(iter != VECTOR_ITER_END(*list)); + } while(iter != VECTOR_END(*list)); TRACE("Adding entry \"%s\" from file \"%s\"\n", al_string_get_cstr(entry.name), al_string_get_cstr(*filename)); @@ -667,11 +667,11 @@ vector_HrtfEntry EnumerateHrtf(const_al_string devname) /* Find the preferred HRTF and move it to the front of the list. */ #define FIND_ENTRY(i) (al_string_cmp_cstr((i)->name, defaulthrtf) == 0) VECTOR_FIND_IF(iter, const HrtfEntry, list, FIND_ENTRY); - if(iter != VECTOR_ITER_END(list) && iter != VECTOR_ITER_BEGIN(list)) + if(iter != VECTOR_END(list) && iter != VECTOR_BEGIN(list)) { HrtfEntry entry = *iter; memmove(&VECTOR_ELEM(list,1), &VECTOR_ELEM(list,0), - (iter-VECTOR_ITER_BEGIN(list))*sizeof(HrtfEntry)); + (iter-VECTOR_BEGIN(list))*sizeof(HrtfEntry)); VECTOR_ELEM(list,0) = entry; } else diff --git a/Alc/vector.h b/Alc/vector.h index c1fc925d..cb64b5a9 100644 --- a/Alc/vector.h +++ b/Alc/vector.h @@ -39,8 +39,8 @@ ALboolean vector_resize(char *ptr, size_t base_size, size_t obj_size, size_t obj #define VECTOR_CAPACITY(_x) ((_x) ? (_x)->Capacity : 0) #define VECTOR_SIZE(_x) ((_x) ? (_x)->Size : 0) -#define VECTOR_ITER_BEGIN(_x) ((_x) ? (_x)->Data + 0 : NULL) -#define VECTOR_ITER_END(_x) ((_x) ? (_x)->Data + (_x)->Size : NULL) +#define VECTOR_BEGIN(_x) ((_x) ? (_x)->Data + 0 : NULL) +#define VECTOR_END(_x) ((_x) ? (_x)->Data + (_x)->Size : NULL) ALboolean vector_insert(char *ptr, size_t base_size, size_t obj_size, void *ins_pos, const void *datstart, const void *datend); #ifdef __GNUC__ @@ -67,22 +67,22 @@ ALboolean vector_insert(char *ptr, size_t base_size, size_t obj_size, void *ins_ #define VECTOR_ELEM(_x, _o) ((_x)->Data[(_o)]) #define VECTOR_FOR_EACH(_t, _x, _f) do { \ - _t *_iter = VECTOR_ITER_BEGIN((_x)); \ - _t *_end = VECTOR_ITER_END((_x)); \ + _t *_iter = VECTOR_BEGIN((_x)); \ + _t *_end = VECTOR_END((_x)); \ for(;_iter != _end;++_iter) \ _f(_iter); \ } while(0) #define VECTOR_FOR_EACH_PARAMS(_t, _x, _f, ...) do { \ - _t *_iter = VECTOR_ITER_BEGIN((_x)); \ - _t *_end = VECTOR_ITER_END((_x)); \ + _t *_iter = VECTOR_BEGIN((_x)); \ + _t *_end = VECTOR_END((_x)); \ for(;_iter != _end;++_iter) \ _f(__VA_ARGS__, _iter); \ } while(0) #define VECTOR_FIND_IF(_i, _t, _x, _f) do { \ - _t *_iter = VECTOR_ITER_BEGIN((_x)); \ - _t *_end = VECTOR_ITER_END((_x)); \ + _t *_iter = VECTOR_BEGIN((_x)); \ + _t *_end = VECTOR_END((_x)); \ for(;_iter != _end;++_iter) \ { \ if(_f(_iter)) \ @@ -92,8 +92,8 @@ ALboolean vector_insert(char *ptr, size_t base_size, size_t obj_size, void *ins_ } while(0) #define VECTOR_FIND_IF_PARMS(_i, _t, _x, _f, ...) do { \ - _t *_iter = VECTOR_ITER_BEGIN((_x)); \ - _t *_end = VECTOR_ITER_END((_x)); \ + _t *_iter = VECTOR_BEGIN((_x)); \ + _t *_end = VECTOR_END((_x)); \ for(;_iter != _end;++_iter) \ { \ if(_f(__VA_ARGS__, _iter)) \ diff --git a/OpenAL32/alAuxEffectSlot.c b/OpenAL32/alAuxEffectSlot.c index 0364c33c..9780cff3 100644 --- a/OpenAL32/alAuxEffectSlot.c +++ b/OpenAL32/alAuxEffectSlot.c @@ -98,7 +98,7 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo effectslots[cur] = slot->id; } - err = AddEffectSlotArray(context, VECTOR_ITER_BEGIN(slotvec), n); + err = AddEffectSlotArray(context, VECTOR_BEGIN(slotvec), n); if(err != AL_NO_ERROR) { alDeleteAuxiliaryEffectSlots(cur, effectslots); @@ -394,7 +394,7 @@ static ALenum AddEffectSlotArray(ALCcontext *context, ALeffectslot **start, ALsi ALenum err = AL_NO_ERROR; LockContext(context); - if(!VECTOR_INSERT(context->ActiveAuxSlots, VECTOR_ITER_END(context->ActiveAuxSlots), start, start+count)) + if(!VECTOR_INSERT(context->ActiveAuxSlots, VECTOR_END(context->ActiveAuxSlots), start, start+count)) err = AL_OUT_OF_MEMORY; UnlockContext(context); @@ -408,7 +408,7 @@ static void RemoveEffectSlotArray(ALCcontext *context, const ALeffectslot *slot) LockContext(context); #define MATCH_SLOT(_i) (slot == *(_i)) VECTOR_FIND_IF(iter, ALeffectslot*, context->ActiveAuxSlots, MATCH_SLOT); - if(iter != VECTOR_ITER_END(context->ActiveAuxSlots)) + if(iter != VECTOR_END(context->ActiveAuxSlots)) { *iter = VECTOR_BACK(context->ActiveAuxSlots); VECTOR_POP_BACK(context->ActiveAuxSlots); -- cgit v1.2.3 From e8b274d34993010462cba1086871015b3db1ccfb Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 22 May 2016 21:03:16 -0700 Subject: Properly pluralize some messages --- Alc/ALc.c | 15 ++++++++++----- Alc/backends/mmdevapi.c | 7 ++++--- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index 3a2ac287..1e501aec 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -2139,21 +2139,24 @@ static ALCvoid FreeDevice(ALCdevice *device) if(device->BufferMap.size > 0) { - WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size); + WARN("(%p) Deleting %d Buffer%s\n", device, device->BufferMap.size, + (device->BufferMap.size==1)?"":"s"); ReleaseALBuffers(device); } ResetUIntMap(&device->BufferMap); if(device->EffectMap.size > 0) { - WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size); + WARN("(%p) Deleting %d Effect%s\n", device, device->EffectMap.size, + (device->EffectMap.size==1)?"":"s"); ReleaseALEffects(device); } ResetUIntMap(&device->EffectMap); if(device->FilterMap.size > 0) { - WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size); + WARN("(%p) Deleting %d Filter%s\n", device, device->FilterMap.size, + (device->FilterMap.size==1)?"":"s"); ReleaseALFilters(device); } ResetUIntMap(&device->FilterMap); @@ -2300,14 +2303,16 @@ static void FreeContext(ALCcontext *context) if(context->SourceMap.size > 0) { - WARN("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size); + WARN("(%p) Deleting %d Source%s\n", context, context->SourceMap.size, + (context->SourceMap.size==1)?"":"s"); ReleaseALSources(context); } ResetUIntMap(&context->SourceMap); if(context->EffectSlotMap.size > 0) { - WARN("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size); + WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context, context->EffectSlotMap.size, + (context->EffectSlotMap.size==1)?"":"s"); ReleaseALAuxiliaryEffectSlots(context); } ResetUIntMap(&context->EffectSlotMap); diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 8851678b..938488ac 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -1574,9 +1574,10 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) wfx->nChannels != OutputType.Format.nChannels || wfx->nBlockAlign != OutputType.Format.nBlockAlign) { - ERR("Did not get matching format, wanted: %s %s %uhz, got: %d channel(s) %d-bit %luhz\n", - DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), device->Frequency, - wfx->nChannels, wfx->wBitsPerSample, wfx->nSamplesPerSec); + ERR("Failed to get matching format, wanted: %s %s %uhz, got: %d channel%s %d-bit %luhz\n", + DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), + device->Frequency, wfx->nChannels, (wfx->nChannels==1)?"":"s", wfx->wBitsPerSample, + wfx->nSamplesPerSec); CoTaskMemFree(wfx); return E_FAIL; } -- cgit v1.2.3 From 6d4380a48c28f21d271d4eb5e668443bc8a0f50e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 28 May 2016 00:43:14 -0700 Subject: Change the backend getLatency method to return the clock time too This will also allow backends to better synchronize the tracked clock time with the device output latency, without necessarily needing to lock if the backend API can allow for it. --- Alc/backends/alsa.c | 30 ++++++++++++++++++++++-------- Alc/backends/base.c | 19 +++++++++++++++---- Alc/backends/base.h | 23 +++++++++++++++++++---- Alc/backends/dsound.c | 4 ++-- Alc/backends/jack.c | 12 +++++++----- Alc/backends/loopback.c | 2 +- Alc/backends/mmdevapi.c | 15 +++++++++++---- Alc/backends/null.c | 2 +- Alc/backends/oss.c | 4 ++-- Alc/backends/portaudio.c | 4 ++-- Alc/backends/pulseaudio.c | 38 +++++++++++++++++++++++++------------- Alc/backends/solaris.c | 2 +- Alc/backends/wave.c | 2 +- Alc/backends/winmm.c | 4 ++-- OpenAL32/alSource.c | 11 ++++++++--- 15 files changed, 119 insertions(+), 53 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 7d23ecc3..280f5019 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -410,7 +410,7 @@ static ALCboolean ALCplaybackAlsa_start(ALCplaybackAlsa *self); static void ALCplaybackAlsa_stop(ALCplaybackAlsa *self); static DECLARE_FORWARD2(ALCplaybackAlsa, ALCbackend, ALCenum, captureSamples, void*, ALCuint) static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, ALCuint, availableSamples) -static ALint64 ALCplaybackAlsa_getLatency(ALCplaybackAlsa *self); +static ClockLatency ALCplaybackAlsa_getClockLatency(ALCplaybackAlsa *self); static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, void, lock) static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCplaybackAlsa) @@ -891,18 +891,25 @@ static void ALCplaybackAlsa_stop(ALCplaybackAlsa *self) self->buffer = NULL; } -static ALint64 ALCplaybackAlsa_getLatency(ALCplaybackAlsa *self) +static ClockLatency ALCplaybackAlsa_getClockLatency(ALCplaybackAlsa *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; snd_pcm_sframes_t delay = 0; + ClockLatency ret; int err; + ALCplaybackAlsa_lock(self); + ret.ClockTime = GetDeviceClockTime(device); if((err=snd_pcm_delay(self->pcmHandle, &delay)) < 0) { ERR("Failed to get pcm delay: %s\n", snd_strerror(err)); - return 0; + delay = 0; } - return maxi64((ALint64)delay*1000000000/device->Frequency, 0); + if(delay < 0) delay = 0; + ret.Latency = delay * DEVICE_CLOCK_RES / device->Frequency; + ALCplaybackAlsa_unlock(self); + + return ret; } @@ -929,7 +936,7 @@ static ALCboolean ALCcaptureAlsa_start(ALCcaptureAlsa *self); static void ALCcaptureAlsa_stop(ALCcaptureAlsa *self); static ALCenum ALCcaptureAlsa_captureSamples(ALCcaptureAlsa *self, ALCvoid *buffer, ALCuint samples); static ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self); -static ALint64 ALCcaptureAlsa_getLatency(ALCcaptureAlsa *self); +static ClockLatency ALCcaptureAlsa_getClockLatency(ALCcaptureAlsa *self); static DECLARE_FORWARD(ALCcaptureAlsa, ALCbackend, void, lock) static DECLARE_FORWARD(ALCcaptureAlsa, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCcaptureAlsa) @@ -1277,18 +1284,25 @@ static ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self) return ll_ringbuffer_read_space(self->ring); } -static ALint64 ALCcaptureAlsa_getLatency(ALCcaptureAlsa *self) +static ClockLatency ALCcaptureAlsa_getClockLatency(ALCcaptureAlsa *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; snd_pcm_sframes_t delay = 0; + ClockLatency ret; int err; + ALCcaptureAlsa_lock(self); + ret.ClockTime = GetDeviceClockTime(device); if((err=snd_pcm_delay(self->pcmHandle, &delay)) < 0) { ERR("Failed to get pcm delay: %s\n", snd_strerror(err)); - return 0; + delay = 0; } - return maxi64((ALint64)delay*1000000000/device->Frequency, 0); + if(delay < 0) delay = 0; + ret.Latency = delay * DEVICE_CLOCK_RES / device->Frequency; + ALCcaptureAlsa_unlock(self); + + return ret; } diff --git a/Alc/backends/base.c b/Alc/backends/base.c index ebeb31bf..07c33ba1 100644 --- a/Alc/backends/base.c +++ b/Alc/backends/base.c @@ -8,6 +8,8 @@ #include "backends/base.h" +extern inline ALuint64 GetDeviceClockTime(ALCdevice *device); + /* Base ALCbackend method implementations. */ void ALCbackend_Construct(ALCbackend *self, ALCdevice *device) { @@ -37,9 +39,18 @@ ALCuint ALCbackend_availableSamples(ALCbackend* UNUSED(self)) return 0; } -ALint64 ALCbackend_getLatency(ALCbackend* UNUSED(self)) +ClockLatency ALCbackend_getClockLatency(ALCbackend *self) { - return 0; + ALCdevice *device = self->mDevice; + ClockLatency ret; + + almtx_lock(&self->mMutex); + ret.ClockTime = GetDeviceClockTime(device); + // TODO: Perhaps should be NumUpdates-1 worth of UpdateSize? + ret.Latency = 0; + almtx_unlock(&self->mMutex); + + return ret; } void ALCbackend_lock(ALCbackend *self) @@ -77,7 +88,7 @@ static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self); static void PlaybackWrapper_stop(PlaybackWrapper *self); static DECLARE_FORWARD2(PlaybackWrapper, ALCbackend, ALCenum, captureSamples, void*, ALCuint) static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ALCuint, availableSamples) -static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ClockLatency, getClockLatency) static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, lock) static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(PlaybackWrapper) @@ -137,7 +148,7 @@ static ALCboolean CaptureWrapper_start(CaptureWrapper *self); static void CaptureWrapper_stop(CaptureWrapper *self); static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples); static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self); -static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ClockLatency, getClockLatency) static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, lock) static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(CaptureWrapper) diff --git a/Alc/backends/base.h b/Alc/backends/base.h index f6b4b80a..04795b36 100644 --- a/Alc/backends/base.h +++ b/Alc/backends/base.h @@ -5,6 +5,21 @@ #include "threads.h" +typedef struct ClockLatency { + ALint64 ClockTime; + ALint64 Latency; +} ClockLatency; + +/* Helper to get the current clock time from the device's ClockBase, and + * SamplesDone converted from the sample rate. + */ +inline ALuint64 GetDeviceClockTime(ALCdevice *device) +{ + return device->ClockBase + (device->SamplesDone * DEVICE_CLOCK_RES / + device->Frequency); +} + + struct ALCbackendVtable; typedef struct ALCbackend { @@ -20,7 +35,7 @@ void ALCbackend_Destruct(ALCbackend *self); ALCboolean ALCbackend_reset(ALCbackend *self); ALCenum ALCbackend_captureSamples(ALCbackend *self, void *buffer, ALCuint samples); ALCuint ALCbackend_availableSamples(ALCbackend *self); -ALint64 ALCbackend_getLatency(ALCbackend *self); +ClockLatency ALCbackend_getClockLatency(ALCbackend *self); void ALCbackend_lock(ALCbackend *self); void ALCbackend_unlock(ALCbackend *self); @@ -37,7 +52,7 @@ struct ALCbackendVtable { ALCenum (*const captureSamples)(ALCbackend*, void*, ALCuint); ALCuint (*const availableSamples)(ALCbackend*); - ALint64 (*const getLatency)(ALCbackend*); + ClockLatency (*const getClockLatency)(ALCbackend*); void (*const lock)(ALCbackend*); void (*const unlock)(ALCbackend*); @@ -54,7 +69,7 @@ DECLARE_THUNK(T, ALCbackend, ALCboolean, start) \ DECLARE_THUNK(T, ALCbackend, void, stop) \ DECLARE_THUNK2(T, ALCbackend, ALCenum, captureSamples, void*, ALCuint) \ DECLARE_THUNK(T, ALCbackend, ALCuint, availableSamples) \ -DECLARE_THUNK(T, ALCbackend, ALint64, getLatency) \ +DECLARE_THUNK(T, ALCbackend, ClockLatency, getClockLatency) \ DECLARE_THUNK(T, ALCbackend, void, lock) \ DECLARE_THUNK(T, ALCbackend, void, unlock) \ static void T##_ALCbackend_Delete(void *ptr) \ @@ -70,7 +85,7 @@ static const struct ALCbackendVtable T##_ALCbackend_vtable = { \ T##_ALCbackend_stop, \ T##_ALCbackend_captureSamples, \ T##_ALCbackend_availableSamples, \ - T##_ALCbackend_getLatency, \ + T##_ALCbackend_getClockLatency, \ T##_ALCbackend_lock, \ T##_ALCbackend_unlock, \ \ diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index 454f7fa0..1ff99352 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -199,7 +199,7 @@ static ALCboolean ALCdsoundPlayback_start(ALCdsoundPlayback *self); static void ALCdsoundPlayback_stop(ALCdsoundPlayback *self); static DECLARE_FORWARD2(ALCdsoundPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint) static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, ALCuint, availableSamples) -static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, ClockLatency, getClockLatency) static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, void, lock) static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCdsoundPlayback) @@ -666,7 +666,7 @@ static ALCboolean ALCdsoundCapture_start(ALCdsoundCapture *self); static void ALCdsoundCapture_stop(ALCdsoundCapture *self); static ALCenum ALCdsoundCapture_captureSamples(ALCdsoundCapture *self, ALCvoid *buffer, ALCuint samples); static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self); -static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, ClockLatency, getClockLatency) static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, void, lock) static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCdsoundCapture) diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index 69d1277a..cfdc62e8 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -148,7 +148,7 @@ static ALCboolean ALCjackPlayback_start(ALCjackPlayback *self); static void ALCjackPlayback_stop(ALCjackPlayback *self); static DECLARE_FORWARD2(ALCjackPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint) static DECLARE_FORWARD(ALCjackPlayback, ALCbackend, ALCuint, availableSamples) -static ALint64 ALCjackPlayback_getLatency(ALCjackPlayback *self); +static ClockLatency ALCjackPlayback_getClockLatency(ALCjackPlayback *self); static void ALCjackPlayback_lock(ALCjackPlayback *self); static void ALCjackPlayback_unlock(ALCjackPlayback *self); DECLARE_DEFAULT_ALLOCATORS(ALCjackPlayback) @@ -506,16 +506,18 @@ static void ALCjackPlayback_stop(ALCjackPlayback *self) } -static ALint64 ALCjackPlayback_getLatency(ALCjackPlayback *self) +static ClockLatency ALCjackPlayback_getClockLatency(ALCjackPlayback *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - ALint64 latency; + ClockLatency ret; ALCjackPlayback_lock(self); - latency = ll_ringbuffer_read_space(self->Ring); + ret.ClockTime = GetDeviceClockTime(device); + ret.Latency = ll_ringbuffer_read_space(self->Ring) * DEVICE_CLOCK_RES / + device->Frequency; ALCjackPlayback_unlock(self); - return latency * 1000000000 / device->Frequency; + return ret; } diff --git a/Alc/backends/loopback.c b/Alc/backends/loopback.c index 3e577f78..0164bc5a 100644 --- a/Alc/backends/loopback.c +++ b/Alc/backends/loopback.c @@ -41,7 +41,7 @@ static ALCboolean ALCloopback_start(ALCloopback *self); static void ALCloopback_stop(ALCloopback *self); static DECLARE_FORWARD2(ALCloopback, ALCbackend, ALCenum, captureSamples, void*, ALCuint) static DECLARE_FORWARD(ALCloopback, ALCbackend, ALCuint, availableSamples) -static DECLARE_FORWARD(ALCloopback, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCloopback, ALCbackend, ClockLatency, getClockLatency) static DECLARE_FORWARD(ALCloopback, ALCbackend, void, lock) static DECLARE_FORWARD(ALCloopback, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCloopback) diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 938488ac..f102e385 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -508,7 +508,7 @@ static void ALCmmdevPlayback_stop(ALCmmdevPlayback *self); static void ALCmmdevPlayback_stopProxy(ALCmmdevPlayback *self); static DECLARE_FORWARD2(ALCmmdevPlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint) static DECLARE_FORWARD(ALCmmdevPlayback, ALCbackend, ALCuint, availableSamples) -static ALint64 ALCmmdevPlayback_getLatency(ALCmmdevPlayback *self); +static ClockLatency ALCmmdevPlayback_getClockLatency(ALCmmdevPlayback *self); static DECLARE_FORWARD(ALCmmdevPlayback, ALCbackend, void, lock) static DECLARE_FORWARD(ALCmmdevPlayback, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCmmdevPlayback) @@ -1139,10 +1139,17 @@ static void ALCmmdevPlayback_stopProxy(ALCmmdevPlayback *self) } -static ALint64 ALCmmdevPlayback_getLatency(ALCmmdevPlayback *self) +static ClockLatency ALCmmdevPlayback_getClockLatency(ALCmmdevPlayback *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return (ALint64)self->Padding * 1000000000 / device->Frequency; + ClockLatency ret; + + ALCmmdevPlayback_lock(self); + ret.ClockTime = GetDeviceClockTime(device); + ret.Latency = self->Padding * DEVICE_CLOCK_RES / device->Frequency; + ALCmmdevPlayback_unlock(self); + + return ret; } @@ -1181,7 +1188,7 @@ static void ALCmmdevCapture_stop(ALCmmdevCapture *self); static void ALCmmdevCapture_stopProxy(ALCmmdevCapture *self); static ALCenum ALCmmdevCapture_captureSamples(ALCmmdevCapture *self, ALCvoid *buffer, ALCuint samples); static ALuint ALCmmdevCapture_availableSamples(ALCmmdevCapture *self); -static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, ClockLatency, getClockLatency) static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, void, lock) static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCmmdevCapture) diff --git a/Alc/backends/null.c b/Alc/backends/null.c index 99729c0a..5b153cd9 100644 --- a/Alc/backends/null.c +++ b/Alc/backends/null.c @@ -51,7 +51,7 @@ static ALCboolean ALCnullBackend_start(ALCnullBackend *self); static void ALCnullBackend_stop(ALCnullBackend *self); static DECLARE_FORWARD2(ALCnullBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint) static DECLARE_FORWARD(ALCnullBackend, ALCbackend, ALCuint, availableSamples) -static DECLARE_FORWARD(ALCnullBackend, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCnullBackend, ALCbackend, ClockLatency, getClockLatency) static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, lock) static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCnullBackend) diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index a61b4859..432c75f2 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -257,7 +257,7 @@ static ALCboolean ALCplaybackOSS_start(ALCplaybackOSS *self); static void ALCplaybackOSS_stop(ALCplaybackOSS *self); static DECLARE_FORWARD2(ALCplaybackOSS, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint) static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, ALCuint, availableSamples) -static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, ClockLatency, getClockLatency) static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, void, lock) static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCplaybackOSS) @@ -502,7 +502,7 @@ static ALCboolean ALCcaptureOSS_start(ALCcaptureOSS *self); static void ALCcaptureOSS_stop(ALCcaptureOSS *self); static ALCenum ALCcaptureOSS_captureSamples(ALCcaptureOSS *self, ALCvoid *buffer, ALCuint samples); static ALCuint ALCcaptureOSS_availableSamples(ALCcaptureOSS *self); -static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, ClockLatency, getClockLatency) static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, void, lock) static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCcaptureOSS) diff --git a/Alc/backends/portaudio.c b/Alc/backends/portaudio.c index f45833c6..1dbca941 100644 --- a/Alc/backends/portaudio.c +++ b/Alc/backends/portaudio.c @@ -145,7 +145,7 @@ static ALCboolean ALCportPlayback_start(ALCportPlayback *self); static void ALCportPlayback_stop(ALCportPlayback *self); static DECLARE_FORWARD2(ALCportPlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint) static DECLARE_FORWARD(ALCportPlayback, ALCbackend, ALCuint, availableSamples) -static DECLARE_FORWARD(ALCportPlayback, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCportPlayback, ALCbackend, ClockLatency, getClockLatency) static DECLARE_FORWARD(ALCportPlayback, ALCbackend, void, lock) static DECLARE_FORWARD(ALCportPlayback, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCportPlayback) @@ -340,7 +340,7 @@ static ALCboolean ALCportCapture_start(ALCportCapture *self); static void ALCportCapture_stop(ALCportCapture *self); static ALCenum ALCportCapture_captureSamples(ALCportCapture *self, ALCvoid *buffer, ALCuint samples); static ALCuint ALCportCapture_availableSamples(ALCportCapture *self); -static DECLARE_FORWARD(ALCportCapture, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCportCapture, ALCbackend, ClockLatency, getClockLatency) static DECLARE_FORWARD(ALCportCapture, ALCbackend, void, lock) static DECLARE_FORWARD(ALCportCapture, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCportCapture) diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index ccce2e00..d317b576 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -489,7 +489,7 @@ static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self); static void ALCpulsePlayback_stop(ALCpulsePlayback *self); static DECLARE_FORWARD2(ALCpulsePlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint) static DECLARE_FORWARD(ALCpulsePlayback, ALCbackend, ALCuint, availableSamples) -static ALint64 ALCpulsePlayback_getLatency(ALCpulsePlayback *self); +static ClockLatency ALCpulsePlayback_getClockLatency(ALCpulsePlayback *self); static void ALCpulsePlayback_lock(ALCpulsePlayback *self); static void ALCpulsePlayback_unlock(ALCpulsePlayback *self); DECLARE_DEFAULT_ALLOCATORS(ALCpulsePlayback) @@ -1136,11 +1136,14 @@ static void ALCpulsePlayback_stop(ALCpulsePlayback *self) } -static ALint64 ALCpulsePlayback_getLatency(ALCpulsePlayback *self) +static ClockLatency ALCpulsePlayback_getClockLatency(ALCpulsePlayback *self) { pa_usec_t latency = 0; + ClockLatency ret; int neg, err; + pa_threaded_mainloop_lock(self->loop); + ret.ClockTime = GetDeviceClockTime(STATIC_CAST(ALCbackend,self)->mDevice); if((err=pa_stream_get_latency(self->stream, &latency, &neg)) != 0) { /* FIXME: if err = -PA_ERR_NODATA, it means we were called too soon @@ -1149,11 +1152,14 @@ static ALint64 ALCpulsePlayback_getLatency(ALCpulsePlayback *self) * dummy value? Either way, it shouldn't be 0. */ if(err != -PA_ERR_NODATA) ERR("Failed to get stream latency: 0x%x\n", err); - return 0; + latency = 0; + neg = 0; } - if(neg) latency = 0; - return (ALint64)minu64(latency, U64(0x7fffffffffffffff)/1000) * 1000; + ret.Latency = minu64(latency, U64(0xffffffffffffffff)/1000) * 1000; + pa_threaded_mainloop_unlock(self->loop); + + return ret; } @@ -1209,7 +1215,7 @@ static ALCboolean ALCpulseCapture_start(ALCpulseCapture *self); static void ALCpulseCapture_stop(ALCpulseCapture *self); static ALCenum ALCpulseCapture_captureSamples(ALCpulseCapture *self, ALCvoid *buffer, ALCuint samples); static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self); -static ALint64 ALCpulseCapture_getLatency(ALCpulseCapture *self); +static ClockLatency ALCpulseCapture_getClockLatency(ALCpulseCapture *self); static void ALCpulseCapture_lock(ALCpulseCapture *self); static void ALCpulseCapture_unlock(ALCpulseCapture *self); DECLARE_DEFAULT_ALLOCATORS(ALCpulseCapture) @@ -1639,19 +1645,25 @@ static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self) } -static ALint64 ALCpulseCapture_getLatency(ALCpulseCapture *self) +static ClockLatency ALCpulseCapture_getClockLatency(ALCpulseCapture *self) { pa_usec_t latency = 0; - int neg; + ClockLatency ret; + int neg, err; - if(pa_stream_get_latency(self->stream, &latency, &neg) != 0) + pa_threaded_mainloop_lock(self->loop); + ret.ClockTime = GetDeviceClockTime(STATIC_CAST(ALCbackend,self)->mDevice); + if((err=pa_stream_get_latency(self->stream, &latency, &neg)) != 0) { - ERR("Failed to get stream latency!\n"); - return 0; + ERR("Failed to get stream latency: 0x%x\n", err); + latency = 0; + neg = 0; } - if(neg) latency = 0; - return (ALint64)minu64(latency, U64(0x7fffffffffffffff)/1000) * 1000; + ret.Latency = minu64(latency, U64(0xffffffffffffffff)/1000) * 1000; + pa_threaded_mainloop_unlock(self->loop); + + return ret; } diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c index 6eaf1ee5..01472e6a 100644 --- a/Alc/backends/solaris.c +++ b/Alc/backends/solaris.c @@ -65,7 +65,7 @@ static ALCboolean ALCsolarisBackend_start(ALCsolarisBackend *self); static void ALCsolarisBackend_stop(ALCsolarisBackend *self); static DECLARE_FORWARD2(ALCsolarisBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint) static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, ALCuint, availableSamples) -static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, ClockLatency, getClockLatency) static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, void, lock) static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCsolarisBackend) diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index 3b87d645..af996233 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -91,7 +91,7 @@ static ALCboolean ALCwaveBackend_start(ALCwaveBackend *self); static void ALCwaveBackend_stop(ALCwaveBackend *self); static DECLARE_FORWARD2(ALCwaveBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint) static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, ALCuint, availableSamples) -static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, ClockLatency, getClockLatency) static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, void, lock) static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCwaveBackend) diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index 664b3dfe..180f764b 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -164,7 +164,7 @@ static ALCboolean ALCwinmmPlayback_start(ALCwinmmPlayback *self); static void ALCwinmmPlayback_stop(ALCwinmmPlayback *self); static DECLARE_FORWARD2(ALCwinmmPlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint) static DECLARE_FORWARD(ALCwinmmPlayback, ALCbackend, ALCuint, availableSamples) -static DECLARE_FORWARD(ALCwinmmPlayback, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCwinmmPlayback, ALCbackend, ClockLatency, getClockLatency) static DECLARE_FORWARD(ALCwinmmPlayback, ALCbackend, void, lock) static DECLARE_FORWARD(ALCwinmmPlayback, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCwinmmPlayback) @@ -451,7 +451,7 @@ static ALCboolean ALCwinmmCapture_start(ALCwinmmCapture *self); static void ALCwinmmCapture_stop(ALCwinmmCapture *self); static ALCenum ALCwinmmCapture_captureSamples(ALCwinmmCapture *self, ALCvoid *buffer, ALCuint samples); static ALCuint ALCwinmmCapture_availableSamples(ALCwinmmCapture *self); -static DECLARE_FORWARD(ALCwinmmCapture, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCwinmmCapture, ALCbackend, ClockLatency, getClockLatency) static DECLARE_FORWARD(ALCwinmmCapture, ALCbackend, void, lock) static DECLARE_FORWARD(ALCwinmmCapture, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCwinmmCapture) diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index ec32ac8d..e04199b3 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -1006,6 +1006,7 @@ static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SourceProp p { ALCdevice *device = Context->Device; ALbufferlistitem *BufferList; + ClockLatency clocktime; ALint ivals[3]; ALboolean err; @@ -1107,9 +1108,10 @@ static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SourceProp p case AL_SEC_OFFSET_LATENCY_SOFT: LockContext(Context); + clocktime = V0(device->Backend,getClockLatency)(); + values[0] = GetSourceSecOffset(Source); - values[1] = (ALdouble)(V0(device->Backend,getLatency)()) / - 1000000000.0; + values[1] = (ALdouble)clocktime.Latency / 1000000000.0; UnlockContext(Context); return AL_TRUE; @@ -1382,6 +1384,7 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp prop, ALint64 *values) { ALCdevice *device = Context->Device; + ClockLatency clocktime; ALdouble dvals[6]; ALint ivals[3]; ALboolean err; @@ -1390,8 +1393,10 @@ static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp { case AL_SAMPLE_OFFSET_LATENCY_SOFT: LockContext(Context); + clocktime = V0(device->Backend,getClockLatency)(); + values[0] = GetSourceSampleOffset(Source); - values[1] = V0(device->Backend,getLatency)(); + values[1] = clocktime.Latency; UnlockContext(Context); return AL_TRUE; -- cgit v1.2.3 From 612b24fa9186776cf77b095f723aea5b4b1fc4ab Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 30 May 2016 02:10:06 -0700 Subject: Clean up a couple variable names and declarations --- Alc/ALc.c | 8 ++++---- Alc/backends/base.c | 5 ++--- 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index b4582b0e..d41aa0d4 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -782,13 +782,13 @@ static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL); static almtx_t ListLock; static inline void LockLists(void) { - int lockret = almtx_lock(&ListLock); - assert(lockret == althrd_success); + int ret = almtx_lock(&ListLock); + assert(ret == althrd_success); } static inline void UnlockLists(void) { - int unlockret = almtx_unlock(&ListLock); - assert(unlockret == althrd_success); + int ret = almtx_unlock(&ListLock); + assert(ret == althrd_success); } /************************************************ diff --git a/Alc/backends/base.c b/Alc/backends/base.c index 07c33ba1..ff808f53 100644 --- a/Alc/backends/base.c +++ b/Alc/backends/base.c @@ -13,10 +13,9 @@ extern inline ALuint64 GetDeviceClockTime(ALCdevice *device); /* Base ALCbackend method implementations. */ void ALCbackend_Construct(ALCbackend *self, ALCdevice *device) { - int ret; - self->mDevice = device; - ret = almtx_init(&self->mMutex, almtx_recursive); + int ret = almtx_init(&self->mMutex, almtx_recursive); assert(ret == althrd_success); + self->mDevice = device; } void ALCbackend_Destruct(ALCbackend *self) -- cgit v1.2.3 From 5e11a738c6b18a367070450ec46dfb714fe433d7 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 26 Jul 2016 11:45:20 -0700 Subject: Combine VECTOR_RESIZE and VECTOR_RESERVE --- Alc/backends/alsa.c | 2 +- Alc/backends/dsound.c | 2 +- Alc/backends/mmdevapi.c | 8 +--- Alc/backends/pulseaudio.c | 2 +- Alc/backends/qsa.c | 7 ++- Alc/backends/winmm.c | 6 +-- Alc/helpers.c | 107 ++++++++++++---------------------------------- Alc/vector.h | 39 +++++++++++++---- 8 files changed, 69 insertions(+), 104 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 280f5019..7a9045bb 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -242,7 +242,7 @@ static void clear_devlist(vector_DevMap *devlist) AL_STRING_DEINIT((i)->device_name); \ } while(0) VECTOR_FOR_EACH(DevMap, *devlist, FREE_DEV); - VECTOR_RESIZE(*devlist, 0); + VECTOR_RESIZE(*devlist, 0, 0); #undef FREE_DEV } diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index 1ff99352..da6fbacf 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -123,7 +123,7 @@ static void clear_devlist(vector_DevMap *list) { #define DEINIT_STR(i) AL_STRING_DEINIT((i)->name) VECTOR_FOR_EACH(DevMap, *list, DEINIT_STR); - VECTOR_RESIZE(*list, 0); + VECTOR_RESIZE(*list, 0, 0); #undef DEINIT_STR } diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index f102e385..60d3be00 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -79,7 +79,7 @@ static void clear_devlist(vector_DevMap *list) (i)->devid = NULL; \ } while(0) VECTOR_FOR_EACH(DevMap, *list, CLEAR_DEVMAP); - VECTOR_RESIZE(*list, 0); + VECTOR_RESIZE(*list, 0, 0); #undef CLEAR_DEVMAP } @@ -258,11 +258,7 @@ static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ve if(SUCCEEDED(hr) && count > 0) { clear_devlist(list); - if(!VECTOR_RESERVE(*list, count)) - { - IMMDeviceCollection_Release(coll); - return E_OUTOFMEMORY; - } + VECTOR_RESIZE(*list, 0, count); hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, flowdir, eMultimedia, &defdev); diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index d317b576..220c1b7d 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -443,7 +443,7 @@ static void clear_devlist(vector_DevMap *list) #define DEINIT_STRS(i) (AL_STRING_DEINIT((i)->name),AL_STRING_DEINIT((i)->device_name)) VECTOR_FOR_EACH(DevMap, *list, DEINIT_STRS); #undef DEINIT_STRS - VECTOR_RESIZE(*list, 0); + VECTOR_RESIZE(*list, 0, 0); } diff --git a/Alc/backends/qsa.c b/Alc/backends/qsa.c index a1fbce63..b7923517 100644 --- a/Alc/backends/qsa.c +++ b/Alc/backends/qsa.c @@ -117,8 +117,7 @@ static void deviceList(int type, vector_DevMap *devmap) if(max_cards < 0) return; - VECTOR_RESERVE(*devmap, max_cards+1); - VECTOR_RESIZE(*devmap, 0); + VECTOR_RESIZE(*devmap, 0, max_cards+1); entry.name = strdup(qsaDevice); entry.card = 0; @@ -893,8 +892,8 @@ void alc_qsa_probe(enum DevProbe type) case ALL_DEVICE_PROBE: #define FREE_NAME(iter) free((iter)->name) VECTOR_FOR_EACH(DevMap, DeviceNameMap, FREE_NAME); + VECTOR_RESIZE(DeviceNameMap, 0, 0); #undef FREE_NAME - VECTOR_RESIZE(DeviceNameMap, 0); deviceList(SND_PCM_CHANNEL_PLAYBACK, &DeviceNameMap); #define APPEND_DEVICE(iter) AppendAllDevicesList((iter)->name) @@ -905,8 +904,8 @@ void alc_qsa_probe(enum DevProbe type) case CAPTURE_DEVICE_PROBE: #define FREE_NAME(iter) free((iter)->name) VECTOR_FOR_EACH(DevMap, CaptureNameMap, FREE_NAME); + VECTOR_RESIZE(CaptureNameMap, 0, 0); #undef FREE_NAME - VECTOR_RESIZE(CaptureNameMap, 0); deviceList(SND_PCM_CHANNEL_CAPTURE, &CaptureNameMap); #define APPEND_DEVICE(iter) AppendCaptureDeviceList((iter)->name) diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index 180f764b..6e990a35 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -46,7 +46,7 @@ static vector_al_string CaptureDevices; static void clear_devlist(vector_al_string *list) { VECTOR_FOR_EACH(al_string, *list, al_string_deinit); - VECTOR_RESIZE(*list, 0); + VECTOR_RESIZE(*list, 0, 0); } @@ -58,7 +58,7 @@ static void ProbePlaybackDevices(void) clear_devlist(&PlaybackDevices); numdevs = waveOutGetNumDevs(); - VECTOR_RESERVE(PlaybackDevices, numdevs); + VECTOR_RESIZE(PlaybackDevices, 0, numdevs); for(i = 0;i < numdevs;i++) { WAVEOUTCAPSW WaveCaps; @@ -101,7 +101,7 @@ static void ProbeCaptureDevices(void) clear_devlist(&CaptureDevices); numdevs = waveInGetNumDevs(); - VECTOR_RESERVE(CaptureDevices, numdevs); + VECTOR_RESIZE(CaptureDevices, 0, numdevs); for(i = 0;i < numdevs;i++) { WAVEINCAPSW WaveCaps; diff --git a/Alc/helpers.c b/Alc/helpers.c index e065b022..2a059c68 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -838,51 +838,6 @@ void SetRTPriority(void) } -ALboolean vector_reserve(char *ptr, size_t base_size, size_t obj_size, size_t obj_count, ALboolean exact) -{ - vector_ *vecptr = (vector_*)ptr; - if((*vecptr ? (*vecptr)->Capacity : 0) < obj_count) - { - size_t old_size = (*vecptr ? (*vecptr)->Size : 0); - void *temp; - - /* Use the next power-of-2 size if we don't need to allocate the exact - * amount. This is preferred when regularly increasing the vector since - * it means fewer reallocations. Though it means it also wastes some - * memory. */ - if(exact == AL_FALSE && obj_count < INT_MAX) - obj_count = NextPowerOf2((ALuint)obj_count); - - /* Need to be explicit with the caller type's base size, because it - * could have extra padding before the start of the array (that is, - * sizeof(*vector_) may not equal base_size). */ - temp = al_calloc(16, base_size + obj_size*obj_count); - if(temp == NULL) return AL_FALSE; - if(*vecptr) - memcpy(((ALubyte*)temp)+base_size, ((ALubyte*)*vecptr)+base_size, - obj_size*old_size); - - al_free(*vecptr); - *vecptr = temp; - (*vecptr)->Capacity = obj_count; - (*vecptr)->Size = old_size; - } - return AL_TRUE; -} - -ALboolean vector_resize(char *ptr, size_t base_size, size_t obj_size, size_t obj_count) -{ - vector_ *vecptr = (vector_*)ptr; - if(*vecptr || obj_count > 0) - { - if(!vector_reserve((char*)vecptr, base_size, obj_size, obj_count, AL_TRUE)) - return AL_FALSE; - (*vecptr)->Size = obj_count; - } - return AL_TRUE; -} - - extern inline void al_string_deinit(al_string *str); extern inline size_t al_string_length(const_al_string str); extern inline ALboolean al_string_empty(const_al_string str); @@ -896,9 +851,8 @@ void al_string_clear(al_string *str) * is to ensure we have space to add a null terminator in the string * data so it can be used as a C-style string. */ - VECTOR_RESERVE(*str, 1); - VECTOR_RESIZE(*str, 0); - *VECTOR_END(*str) = 0; + VECTOR_RESIZE(*str, 0, 1); + VECTOR_ELEM(*str, 0) = 0; } } @@ -930,11 +884,10 @@ void al_string_copy(al_string *str, const_al_string from) size_t len = al_string_length(from); size_t i; - VECTOR_RESERVE(*str, len+1); - VECTOR_RESIZE(*str, len); + VECTOR_RESIZE(*str, len, len+1); for(i = 0;i < len;i++) VECTOR_ELEM(*str, i) = VECTOR_ELEM(from, i); - *VECTOR_END(*str) = 0; + VECTOR_ELEM(*str, i) = 0; } void al_string_copy_cstr(al_string *str, const al_string_char_type *from) @@ -942,11 +895,10 @@ void al_string_copy_cstr(al_string *str, const al_string_char_type *from) size_t len = strlen(from); size_t i; - VECTOR_RESERVE(*str, len+1); - VECTOR_RESIZE(*str, len); + VECTOR_RESIZE(*str, len, len+1); for(i = 0;i < len;i++) VECTOR_ELEM(*str, i) = from[i]; - *VECTOR_END(*str) = 0; + VECTOR_ELEM(*str, i) = 0; } void al_string_copy_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to) @@ -954,18 +906,18 @@ void al_string_copy_range(al_string *str, const al_string_char_type *from, const size_t len = to - from; size_t i; - VECTOR_RESERVE(*str, len+1); - VECTOR_RESIZE(*str, len); + VECTOR_RESIZE(*str, len, len+1); for(i = 0;i < len;i++) VECTOR_ELEM(*str, i) = from[i]; - *VECTOR_END(*str) = 0; + VECTOR_ELEM(*str, i) = 0; } void al_string_append_char(al_string *str, const al_string_char_type c) { - VECTOR_RESERVE(*str, al_string_length(*str)+2); + size_t len = al_string_length(*str); + VECTOR_RESIZE(*str, len, len+2); VECTOR_PUSH_BACK(*str, c); - *VECTOR_END(*str) = 0; + VECTOR_ELEM(*str, len+1) = 0; } void al_string_append_cstr(al_string *str, const al_string_char_type *from) @@ -976,27 +928,25 @@ void al_string_append_cstr(al_string *str, const al_string_char_type *from) size_t base = al_string_length(*str); size_t i; - VECTOR_RESERVE(*str, base+len+1); - VECTOR_RESIZE(*str, base+len); + VECTOR_RESIZE(*str, base+len, base+len+1); for(i = 0;i < len;i++) VECTOR_ELEM(*str, base+i) = from[i]; - *VECTOR_END(*str) = 0; + VECTOR_ELEM(*str, base+i) = 0; } } void al_string_append_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to) { - if(to != from) + size_t len = to - from; + if(len != 0) { size_t base = al_string_length(*str); - size_t len = to - from; size_t i; - VECTOR_RESERVE(*str, base+len+1); - VECTOR_RESIZE(*str, base+len); + VECTOR_RESIZE(*str, base+len, base+len+1); for(i = 0;i < len;i++) VECTOR_ELEM(*str, base+i) = from[i]; - *VECTOR_END(*str) = 0; + VECTOR_ELEM(*str, base+i) = 0; } } @@ -1006,10 +956,9 @@ void al_string_copy_wcstr(al_string *str, const wchar_t *from) int len; if((len=WideCharToMultiByte(CP_UTF8, 0, from, -1, NULL, 0, NULL, NULL)) > 0) { - VECTOR_RESERVE(*str, len); - VECTOR_RESIZE(*str, len-1); + VECTOR_RESIZE(*str, len-1, len); WideCharToMultiByte(CP_UTF8, 0, from, -1, &VECTOR_FRONT(*str), len, NULL, NULL); - *VECTOR_END(*str) = 0; + VECTOR_ELEM(*str, len-1) = 0; } } @@ -1018,11 +967,10 @@ void al_string_append_wcstr(al_string *str, const wchar_t *from) int len; if((len=WideCharToMultiByte(CP_UTF8, 0, from, -1, NULL, 0, NULL, NULL)) > 0) { - size_t strlen = al_string_length(*str); - VECTOR_RESERVE(*str, strlen+len); - VECTOR_RESIZE(*str, strlen+len-1); - WideCharToMultiByte(CP_UTF8, 0, from, -1, &VECTOR_FRONT(*str) + strlen, len, NULL, NULL); - *VECTOR_END(*str) = 0; + size_t base = al_string_length(*str); + VECTOR_RESIZE(*str, base+len-1, base+len); + WideCharToMultiByte(CP_UTF8, 0, from, -1, &VECTOR_ELEM(*str, base), len, NULL, NULL); + VECTOR_ELEM(*str, base+len-1) = 0; } } @@ -1031,11 +979,10 @@ void al_string_append_wrange(al_string *str, const wchar_t *from, const wchar_t int len; if((len=WideCharToMultiByte(CP_UTF8, 0, from, (int)(to-from), NULL, 0, NULL, NULL)) > 0) { - size_t strlen = al_string_length(*str); - VECTOR_RESERVE(*str, strlen+len+1); - VECTOR_RESIZE(*str, strlen+len); - WideCharToMultiByte(CP_UTF8, 0, from, (int)(to-from), &VECTOR_FRONT(*str) + strlen, len+1, NULL, NULL); - *VECTOR_END(*str) = 0; + size_t base = al_string_length(*str); + VECTOR_RESIZE(*str, base+len, base+len+1); + WideCharToMultiByte(CP_UTF8, 0, from, (int)(to-from), &VECTOR_ELEM(*str, base), len+1, NULL, NULL); + VECTOR_ELEM(*str, base+len) = 0; } } #endif diff --git a/Alc/vector.h b/Alc/vector.h index 12de74f5..b340fe71 100644 --- a/Alc/vector.h +++ b/Alc/vector.h @@ -31,12 +31,32 @@ typedef const _##N* const_##N; #define VECTOR_INIT_STATIC() NULL #define VECTOR_DEINIT(_x) do { al_free((_x)); (_x) = NULL; } while(0) -/* Helper to increase a vector's reserve. Do not call directly. */ -ALboolean vector_reserve(char *ptr, size_t base_size, size_t obj_size, size_t obj_count, ALboolean exact); -#define VECTOR_RESERVE(_x, _c) (vector_reserve((char*)&(_x), sizeof(*(_x)), sizeof((_x)->Data[0]), (_c), AL_TRUE)) - -ALboolean vector_resize(char *ptr, size_t base_size, size_t obj_size, size_t obj_count); -#define VECTOR_RESIZE(_x, _c) (vector_resize((char*)&(_x), sizeof(*(_x)), sizeof((_x)->Data[0]), (_c))) +#define VECTOR_RESIZE(_x, _s, _c) do { \ + size_t _size = (_s); \ + size_t _cap = (_c); \ + if(_size > _cap) \ + _cap = _size; \ + \ + if(!(_x) && _cap == 0) \ + break; \ + \ + if(((_x) ? (_x)->Capacity : 0) < _cap) \ + { \ + size_t old_size = ((_x) ? (_x)->Size : 0); \ + void *temp; \ + \ + temp = al_calloc(16, sizeof(*(_x)) + sizeof((_x)->Data[0])*_cap); \ + assert(temp != NULL); \ + if((_x)) \ + memcpy(((ALubyte*)temp)+sizeof(*(_x)), (_x)->Data, \ + sizeof((_x)->Data[0])*old_size); \ + \ + al_free((_x)); \ + (_x) = temp; \ + (_x)->Capacity = _cap; \ + } \ + (_x)->Size = _size; \ +} while(0) \ #define VECTOR_CAPACITY(_x) ((_x) ? (_x)->Capacity : 0) #define VECTOR_SIZE(_x) ((_x) ? (_x)->Size : 0) @@ -44,8 +64,11 @@ ALboolean vector_resize(char *ptr, size_t base_size, size_t obj_size, size_t obj #define VECTOR_BEGIN(_x) ((_x) ? (_x)->Data + 0 : NULL) #define VECTOR_END(_x) ((_x) ? (_x)->Data + (_x)->Size : NULL) -#define VECTOR_PUSH_BACK(_x, _obj) (vector_reserve((char*)&(_x), sizeof(*(_x)), sizeof((_x)->Data[0]), VECTOR_SIZE(_x)+1, AL_FALSE) && \ - (((_x)->Data[(_x)->Size++] = (_obj)),AL_TRUE)) +#define VECTOR_PUSH_BACK(_x, _obj) do { \ + size_t _pbsize = VECTOR_SIZE(_x)+1; \ + VECTOR_RESIZE(_x, _pbsize, _pbsize); \ + (_x)->Data[(_x)->Size-1] = (_obj); \ +} while(0) #define VECTOR_POP_BACK(_x) ((void)((_x)->Size--)) #define VECTOR_BACK(_x) ((_x)->Data[(_x)->Size-1]) -- cgit v1.2.3 From b5b3ea95f899410a5392fb633ace74c10bbd9921 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 29 Jul 2016 21:55:43 -0700 Subject: Add a config to output first-, second-, or third-order ambisonics Currently incomplete, as second- and third-order output will not correctly handle B-Format input buffers. A standalone up-sampler will be needed, similar to the high-quality decoder. Also, output is ACN ordering with SN3D normalization. A config option will eventually be provided to change this if desired. --- Alc/ALc.c | 58 +++++++++++++++++++++++++++++++++++++++++++---- Alc/backends/coreaudio.c | 3 +++ Alc/backends/dsound.c | 6 +++++ Alc/backends/mmdevapi.c | 6 +++++ Alc/backends/opensl.c | 6 ++++- Alc/backends/pulseaudio.c | 3 +++ Alc/backends/wave.c | 5 ++++ Alc/backends/winmm.c | 3 +++ Alc/effects/reverb.c | 4 +++- Alc/panning.c | 42 +++++++++++++++++++++++++++++++++- OpenAL32/Include/alMain.h | 3 +++ 11 files changed, 132 insertions(+), 7 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index b6192317..13f881dd 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -1294,6 +1294,9 @@ const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans) case DevFmtX61: return "6.1 Surround"; case DevFmtX71: return "7.1 Surround"; case DevFmtBFormat3D: return "B-Format 3D"; + case DevFmtAmbi1: return "Ambisonics (1st Order)"; + case DevFmtAmbi2: return "Ambisonics (2nd Order)"; + case DevFmtAmbi3: return "Ambisonics (3rd Order)"; } return "(unknown channels)"; } @@ -1325,6 +1328,9 @@ ALuint ChannelsFromDevFmt(enum DevFmtChannels chans) case DevFmtX61: return 7; case DevFmtX71: return 8; case DevFmtBFormat3D: return 4; + case DevFmtAmbi1: return 4; + case DevFmtAmbi2: return 9; + case DevFmtAmbi3: return 16; } return 0; } @@ -1493,6 +1499,41 @@ void SetDefaultWFXChannelOrder(ALCdevice *device) device->RealOut.ChannelName[2] = Aux2; device->RealOut.ChannelName[3] = Aux3; break; + case DevFmtAmbi1: + device->RealOut.ChannelName[0] = Aux0; + device->RealOut.ChannelName[1] = Aux1; + device->RealOut.ChannelName[2] = Aux2; + device->RealOut.ChannelName[3] = Aux3; + break; + case DevFmtAmbi2: + device->RealOut.ChannelName[0] = Aux0; + device->RealOut.ChannelName[1] = Aux1; + device->RealOut.ChannelName[2] = Aux2; + device->RealOut.ChannelName[3] = Aux3; + device->RealOut.ChannelName[4] = Aux4; + device->RealOut.ChannelName[5] = Aux5; + device->RealOut.ChannelName[6] = Aux6; + device->RealOut.ChannelName[7] = Aux7; + device->RealOut.ChannelName[8] = Aux8; + break; + case DevFmtAmbi3: + device->RealOut.ChannelName[0] = Aux0; + device->RealOut.ChannelName[1] = Aux1; + device->RealOut.ChannelName[2] = Aux2; + device->RealOut.ChannelName[3] = Aux3; + device->RealOut.ChannelName[4] = Aux4; + device->RealOut.ChannelName[5] = Aux5; + device->RealOut.ChannelName[6] = Aux6; + device->RealOut.ChannelName[7] = Aux7; + device->RealOut.ChannelName[8] = Aux8; + device->RealOut.ChannelName[9] = Aux9; + device->RealOut.ChannelName[10] = Aux10; + device->RealOut.ChannelName[11] = Aux11; + device->RealOut.ChannelName[12] = Aux12; + device->RealOut.ChannelName[13] = Aux13; + device->RealOut.ChannelName[14] = Aux14; + device->RealOut.ChannelName[15] = Aux15; + break; } } @@ -1535,6 +1576,9 @@ void SetDefaultChannelOrder(ALCdevice *device) case DevFmtX51: case DevFmtX61: case DevFmtBFormat3D: + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: SetDefaultWFXChannelOrder(device); break; } @@ -1992,10 +2036,12 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) /* Allocate extra channels for any post-filter output. */ size = device->Dry.NumChannels * sizeof(device->Dry.Buffer[0]); - if(device->AmbiDecoder && bformatdec_getOrder(device->AmbiDecoder) >= 2) + if((device->AmbiDecoder && bformatdec_getOrder(device->AmbiDecoder) >= 2)) size += (ChannelsFromDevFmt(device->FmtChans)+4) * sizeof(device->Dry.Buffer[0]); else if(device->Hrtf || device->Uhj_Encoder || device->AmbiDecoder) size += ChannelsFromDevFmt(device->FmtChans) * sizeof(device->Dry.Buffer[0]); + else if(device->FmtChans == DevFmtAmbi2 || device->FmtChans == DevFmtAmbi3) + size += 4 * sizeof(device->Dry.Buffer[0]); device->Dry.Buffer = al_calloc(16, size); if(!device->Dry.Buffer) { @@ -2014,10 +2060,11 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) device->RealOut.NumChannels = device->Dry.NumChannels; } - if(device->AmbiDecoder && bformatdec_getOrder(device->AmbiDecoder) >= 2) + if((device->AmbiDecoder && bformatdec_getOrder(device->AmbiDecoder) >= 2) || + device->FmtChans == DevFmtAmbi2 || device->FmtChans == DevFmtAmbi3) { - /* Higher-order high quality decoding requires upsampling first-order - * content, so make sure to mix it separately. + /* Higher-order rendering requires upsampling first-order content, so + * make sure to mix it separately. */ device->FOAOut.Buffer = device->RealOut.Buffer + device->RealOut.NumChannels; device->FOAOut.NumChannels = 4; @@ -3409,6 +3456,9 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) { "surround61", DevFmtX61 }, { "surround71", DevFmtX71 }, { "surround51rear", DevFmtX51Rear }, + { "ambisonic1", DevFmtAmbi1 }, + { "ambisonic2", DevFmtAmbi2 }, + { "ambisonic3", DevFmtAmbi3 }, }; size_t i; diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index 4907f362..3d610fcb 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -529,6 +529,9 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) case DevFmtX61: case DevFmtX71: case DevFmtBFormat3D: + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: ERR("%s not supported\n", DevFmtChannelsString(device->FmtChans)); goto error; } diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index da6fbacf..a477360c 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -473,6 +473,9 @@ static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self) OutputType.dwChannelMask = SPEAKER_FRONT_CENTER; break; case DevFmtBFormat3D: + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: device->FmtChans = DevFmtStereo; /*fall-through*/ case DevFmtStereo: @@ -789,6 +792,9 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi SPEAKER_SIDE_RIGHT; break; case DevFmtBFormat3D: + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: break; } diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 60d3be00..03f2f56b 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -882,6 +882,9 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self) OutputType.dwChannelMask = MONO; break; case DevFmtBFormat3D: + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: device->FmtChans = DevFmtStereo; /*fall-through*/ case DevFmtStereo: @@ -1523,6 +1526,9 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) break; case DevFmtBFormat3D: + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: return E_FAIL; } switch(device->FmtType) diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 7b8fdb25..7e053b81 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -79,7 +79,11 @@ static SLuint32 GetChannelMask(enum DevFmtChannels chans) 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 DevFmtBFormat3D: break; + case DevFmtBFormat3D: + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: + break; } return 0; } diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index 220c1b7d..a4d8438b 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -999,6 +999,9 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) mapname = "mono"; break; case DevFmtBFormat3D: + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: device->FmtChans = DevFmtStereo; /*fall-through*/ case DevFmtStereo: diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index af996233..85b4c720 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -277,6 +277,11 @@ static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self) case DevFmtX51Rear: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020; break; case DevFmtX61: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x100 | 0x200 | 0x400; break; case DevFmtX71: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x200 | 0x400; break; + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: + device->FmtChans = DevFmtBFormat3D; + /*fall-through*/ case DevFmtBFormat3D: isbformat = 1; chanmask = 0; diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index 6e990a35..45547cee 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -562,6 +562,9 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name) case DevFmtX61: case DevFmtX71: case DevFmtBFormat3D: + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: return ALC_INVALID_ENUM; } diff --git a/Alc/effects/reverb.c b/Alc/effects/reverb.c index 9b0dbe1d..7f69e06f 100644 --- a/Alc/effects/reverb.c +++ b/Alc/effects/reverb.c @@ -961,7 +961,9 @@ static ALvoid ALreverbState_update(ALreverbState *State, const ALCdevice *Device props->Reverb.LateReverbPan, gain, props->Reverb.ReflectionsGain, props->Reverb.LateReverbGain, State); - else if(Device->FmtChans == DevFmtBFormat3D || Device->AmbiDecoder) + else if(Device->FmtChans == DevFmtBFormat3D || Device->FmtChans == DevFmtAmbi1 || + Device->FmtChans == DevFmtAmbi2 || Device->FmtChans == DevFmtAmbi3 || + Device->AmbiDecoder) Update3DPanning(Device, props->Reverb.ReflectionsPan, props->Reverb.LateReverbPan, gain, props->Reverb.ReflectionsGain, diff --git a/Alc/panning.c b/Alc/panning.c index f81a6fc0..0c1bf06f 100644 --- a/Alc/panning.c +++ b/Alc/panning.c @@ -575,6 +575,9 @@ static void InitPanning(ALCdevice *device) break; case DevFmtBFormat3D: + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: break; } @@ -593,6 +596,40 @@ static void InitPanning(ALCdevice *device) device->FOAOut.Ambi = device->Dry.Ambi; device->FOAOut.CoeffCount = device->Dry.CoeffCount; } + else if(device->FmtChans == DevFmtAmbi1) + { + count = 4; + for(i = 0;i < count;i++) + { + device->Dry.Ambi.Map[i].Scale = 1.0f/SN3D2N3DScale[i]; + device->Dry.Ambi.Map[i].Index = i; + } + device->Dry.CoeffCount = 0; + device->Dry.NumChannels = count; + + device->FOAOut.Ambi = device->Dry.Ambi; + device->FOAOut.CoeffCount = device->Dry.CoeffCount; + } + else if(device->FmtChans == DevFmtAmbi2 || device->FmtChans == DevFmtAmbi3) + { + count = (device->FmtChans == DevFmtAmbi3) ? 16 : + (device->FmtChans == DevFmtAmbi2) ? 9 : 1; + for(i = 0;i < count;i++) + { + device->Dry.Ambi.Map[i].Scale = 1.0f/SN3D2N3DScale[i]; + device->Dry.Ambi.Map[i].Index = i; + } + device->Dry.CoeffCount = 0; + device->Dry.NumChannels = count; + + memset(&device->FOAOut.Ambi, 0, sizeof(device->FOAOut.Ambi)); + for(i = 0;i < 4;i++) + { + device->FOAOut.Ambi.Map[i].Scale = 1.0f; + device->FOAOut.Ambi.Map[i].Index = i; + } + device->FOAOut.CoeffCount = 0; + } else { SetChannelMap(device->RealOut.ChannelName, device->Dry.Ambi.Coeffs, @@ -835,10 +872,13 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf case DevFmtX51Rear: layout = "surround51rear"; break; case DevFmtX61: layout = "surround61"; break; case DevFmtX71: layout = "surround71"; break; - /* Mono, Stereo, and B-Fornat output don't use custom decoders. */ + /* Mono, Stereo, and Ambisonics output don't use custom decoders. */ case DevFmtMono: case DevFmtStereo: case DevFmtBFormat3D: + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: break; } if(layout) diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 05abc0fa..34533da9 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -448,6 +448,9 @@ enum DevFmtChannels { DevFmtX51Rear = 0x80000000, DevFmtBFormat3D, + DevFmtAmbi1, + DevFmtAmbi2, + DevFmtAmbi3, DevFmtChannelsDefault = DevFmtStereo }; -- cgit v1.2.3 From bff5268ed49261db9bfe432a0439bb4d508d8997 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 31 Jul 2016 08:13:41 -0700 Subject: Remove DevFmtBFormat3D, which is covered by DevFmtAmbi1 --- Alc/ALc.c | 9 --------- Alc/backends/coreaudio.c | 1 - Alc/backends/dsound.c | 2 -- Alc/backends/mmdevapi.c | 2 -- Alc/backends/opensl.c | 1 - Alc/backends/pulseaudio.c | 1 - Alc/backends/wave.c | 7 +++---- Alc/backends/winmm.c | 1 - Alc/effects/reverb.c | 2 +- Alc/panning.c | 19 +------------------ OpenAL32/Include/alMain.h | 2 +- 11 files changed, 6 insertions(+), 41 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index 1119a270..cfd3a077 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -1293,7 +1293,6 @@ const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans) case DevFmtX51Rear: return "5.1 Surround (Rear)"; case DevFmtX61: return "6.1 Surround"; case DevFmtX71: return "7.1 Surround"; - case DevFmtBFormat3D: return "B-Format 3D"; case DevFmtAmbi1: return "Ambisonics (1st Order)"; case DevFmtAmbi2: return "Ambisonics (2nd Order)"; case DevFmtAmbi3: return "Ambisonics (3rd Order)"; @@ -1327,7 +1326,6 @@ ALuint ChannelsFromDevFmt(enum DevFmtChannels chans) case DevFmtX51Rear: return 6; case DevFmtX61: return 7; case DevFmtX71: return 8; - case DevFmtBFormat3D: return 4; case DevFmtAmbi1: return 4; case DevFmtAmbi2: return 9; case DevFmtAmbi3: return 16; @@ -1493,12 +1491,6 @@ void SetDefaultWFXChannelOrder(ALCdevice *device) device->RealOut.ChannelName[6] = SideLeft; device->RealOut.ChannelName[7] = SideRight; break; - case DevFmtBFormat3D: - device->RealOut.ChannelName[0] = Aux0; - device->RealOut.ChannelName[1] = Aux1; - device->RealOut.ChannelName[2] = Aux2; - device->RealOut.ChannelName[3] = Aux3; - break; case DevFmtAmbi1: device->RealOut.ChannelName[0] = Aux0; device->RealOut.ChannelName[1] = Aux1; @@ -1575,7 +1567,6 @@ void SetDefaultChannelOrder(ALCdevice *device) case DevFmtQuad: case DevFmtX51: case DevFmtX61: - case DevFmtBFormat3D: case DevFmtAmbi1: case DevFmtAmbi2: case DevFmtAmbi3: diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index 3d610fcb..cde3d505 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -528,7 +528,6 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) case DevFmtX51Rear: case DevFmtX61: case DevFmtX71: - case DevFmtBFormat3D: case DevFmtAmbi1: case DevFmtAmbi2: case DevFmtAmbi3: diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index a477360c..bb38d516 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -472,7 +472,6 @@ static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self) case DevFmtMono: OutputType.dwChannelMask = SPEAKER_FRONT_CENTER; break; - case DevFmtBFormat3D: case DevFmtAmbi1: case DevFmtAmbi2: case DevFmtAmbi3: @@ -791,7 +790,6 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; break; - case DevFmtBFormat3D: case DevFmtAmbi1: case DevFmtAmbi2: case DevFmtAmbi3: diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 03f2f56b..bcef0a5f 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -881,7 +881,6 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self) OutputType.Format.nChannels = 1; OutputType.dwChannelMask = MONO; break; - case DevFmtBFormat3D: case DevFmtAmbi1: case DevFmtAmbi2: case DevFmtAmbi3: @@ -1525,7 +1524,6 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) OutputType.dwChannelMask = X7DOT1; break; - case DevFmtBFormat3D: case DevFmtAmbi1: case DevFmtAmbi2: case DevFmtAmbi3: diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 7e053b81..0796c49a 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -79,7 +79,6 @@ static SLuint32 GetChannelMask(enum DevFmtChannels chans) 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 DevFmtBFormat3D: case DevFmtAmbi1: case DevFmtAmbi2: case DevFmtAmbi3: diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index a4d8438b..f46386e4 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -998,7 +998,6 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) case DevFmtMono: mapname = "mono"; break; - case DevFmtBFormat3D: case DevFmtAmbi1: case DevFmtAmbi2: case DevFmtAmbi3: diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index 85b4c720..9bf5a727 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -249,7 +249,7 @@ static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self) clearerr(self->mFile); if(GetConfigValueBool(NULL, "wave", "bformat", 0)) - device->FmtChans = DevFmtBFormat3D; + device->FmtChans = DevFmtAmbi1; switch(device->FmtType) { @@ -280,9 +280,8 @@ static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self) case DevFmtAmbi1: case DevFmtAmbi2: case DevFmtAmbi3: - device->FmtChans = DevFmtBFormat3D; - /*fall-through*/ - case DevFmtBFormat3D: + /* .amb output requires FuMa */ + device->AmbiFmt = AmbiFormat_FuMa; isbformat = 1; chanmask = 0; break; diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index 45547cee..9d8f8e9d 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -561,7 +561,6 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name) case DevFmtX51Rear: case DevFmtX61: case DevFmtX71: - case DevFmtBFormat3D: case DevFmtAmbi1: case DevFmtAmbi2: case DevFmtAmbi3: diff --git a/Alc/effects/reverb.c b/Alc/effects/reverb.c index b89b1988..71c39f8c 100644 --- a/Alc/effects/reverb.c +++ b/Alc/effects/reverb.c @@ -961,7 +961,7 @@ static ALvoid ALreverbState_update(ALreverbState *State, const ALCdevice *Device props->Reverb.LateReverbPan, gain, props->Reverb.ReflectionsGain, props->Reverb.LateReverbGain, State); - else if(Device->AmbiDecoder || (Device->FmtChans >= DevFmtBFormat3D && + else if(Device->AmbiDecoder || (Device->FmtChans >= DevFmtAmbi1 && Device->FmtChans <= DevFmtAmbi3)) Update3DPanning(Device, props->Reverb.ReflectionsPan, props->Reverb.LateReverbPan, gain, diff --git a/Alc/panning.c b/Alc/panning.c index 685c3de6..d4d7c25b 100644 --- a/Alc/panning.c +++ b/Alc/panning.c @@ -578,29 +578,13 @@ static void InitPanning(ALCdevice *device) coeffcount = 16; break; - case DevFmtBFormat3D: case DevFmtAmbi1: case DevFmtAmbi2: case DevFmtAmbi3: break; } - if(device->FmtChans == DevFmtBFormat3D) - { - count = 4; - for(i = 0;i < count;i++) - { - ALuint acn = FuMa2ACN[i]; - device->Dry.Ambi.Map[i].Scale = 1.0f/FuMa2N3DScale[acn]; - device->Dry.Ambi.Map[i].Index = acn; - } - device->Dry.CoeffCount = 0; - device->Dry.NumChannels = count; - - device->FOAOut.Ambi = device->Dry.Ambi; - device->FOAOut.CoeffCount = device->Dry.CoeffCount; - } - else if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3) + if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3) { const ALuint *acnmap = (device->AmbiFmt == AmbiFormat_FuMa) ? FuMa2ACN : ACN2ACN; const ALfloat *n3dcale = (device->AmbiFmt == AmbiFormat_FuMa) ? FuMa2N3DScale : @@ -885,7 +869,6 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf /* Mono, Stereo, and Ambisonics output don't use custom decoders. */ case DevFmtMono: case DevFmtStereo: - case DevFmtBFormat3D: case DevFmtAmbi1: case DevFmtAmbi2: case DevFmtAmbi3: diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index dff94487..3b6113ef 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -447,7 +447,7 @@ enum DevFmtChannels { /* Similar to 5.1, except using rear channels instead of sides */ DevFmtX51Rear = 0x80000000, - DevFmtBFormat3D, + /* Ambisonic formats should be kept together */ DevFmtAmbi1, DevFmtAmbi2, DevFmtAmbi3, -- cgit v1.2.3 From 48b954160ec5bffab04d072cdfd0685ca521c407 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 3 Aug 2016 19:07:35 -0700 Subject: Look for the correct DLL for JACK on Windows --- Alc/backends/jack.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'Alc/backends') diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index cfdc62e8..517f99a4 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -94,7 +94,12 @@ static ALCboolean jack_load(void) #ifdef HAVE_DYNLOAD if(!jack_handle) { - jack_handle = LoadLib("libjack.so.0"); +#ifdef _WIN32 +#define JACKLIB "libjack.dll" +#else +#define JACKLIB "libjack.so.0" +#endif + jack_handle = LoadLib(JACKLIB); if(!jack_handle) return ALC_FALSE; -- cgit v1.2.3 From f775f2537920ef0031926872c57332e99c048f63 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 4 Aug 2016 21:06:00 -0700 Subject: Modify NumUpdates for different sample rates instead of UpdateSize Not that this really changes anything since the CoreAudio backend doesn't honor the ALCdevice's buffer metrics, nor accurately report the device's actual metrics. But it clears up warnings from a non-multiple-of-four update size if the sample rate causes it to change. --- Alc/backends/coreaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Alc/backends') diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index cde3d505..24aeabd4 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -238,7 +238,7 @@ static ALCboolean ca_reset_playback(ALCdevice *device) if(device->Frequency != streamFormat.mSampleRate) { - device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize * + device->NumUpdates = (ALuint)((ALuint64)device->NumUpdates * streamFormat.mSampleRate / device->Frequency); device->Frequency = streamFormat.mSampleRate; -- cgit v1.2.3 From 9a60184bf63640f0b12b9e4a894b98e83212d229 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 11 Aug 2016 20:43:54 -0700 Subject: Set a JACK error message handler when initializing the backend JACK2 will print error messages to stderr if it fails to connect to a server. Users who don't normally use JACK but have the client lib installed will get those messages even though OpenAL Soft will continue on to find a working backend without trouble. So to avoid it, set an error message handler that'll log them as warnings. This isn't that great because there's no way to tell whether the error messages are due to the server not running, or some other problem. And it resets the callback to the default afterward even if it may have been set to something else before. JACK2, which is what needs this workaround in the first place, doesn't export the jack_error_callback pointer to properly save and restore it. --- Alc/backends/jack.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'Alc/backends') diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index 517f99a4..283df297 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -54,6 +54,7 @@ static const ALCchar jackDevice[] = "JACK Default"; MAGIC(jack_get_ports); \ MAGIC(jack_free); \ MAGIC(jack_get_sample_rate); \ + MAGIC(jack_set_error_function); \ MAGIC(jack_set_process_callback); \ MAGIC(jack_set_buffer_size_callback); \ MAGIC(jack_set_buffer_size); \ @@ -78,6 +79,7 @@ JACK_FUNCS(MAKE_FUNC); #define jack_get_ports pjack_get_ports #define jack_free pjack_free #define jack_get_sample_rate pjack_get_sample_rate +#define jack_set_error_function pjack_set_error_function #define jack_set_process_callback pjack_set_process_callback #define jack_set_buffer_size_callback pjack_set_buffer_size_callback #define jack_set_buffer_size pjack_set_buffer_size @@ -537,6 +539,11 @@ static void ALCjackPlayback_unlock(ALCjackPlayback *self) } +static void jack_msg_handler(const char *message) +{ + WARN("%s\n", message); +} + typedef struct ALCjackBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); } ALCjackBackendFactory; @@ -552,7 +559,10 @@ static ALCboolean ALCjackBackendFactory_init(ALCjackBackendFactory* UNUSED(self) if(!GetConfigValueBool(NULL, "jack", "spawn-server", 0)) ClientOptions |= JackNoStartServer; + + jack_set_error_function(jack_msg_handler); client = jack_client_open("alsoft", ClientOptions, &status, NULL); + jack_set_error_function(NULL); if(client == NULL) { WARN("jack_client_open() failed, 0x%02x\n", status); -- cgit v1.2.3 From 6b7e14f11f6eea9d77dcf6076fbecaffb1b6d1ab Mon Sep 17 00:00:00 2001 From: Dmytry Lavrov Date: Tue, 6 Sep 2016 19:22:42 -0500 Subject: mmdevapi: Allow specifying output device by it's audio endpoint GUID or by the device id string (Oculus VR api requires you to play back on a specific device). --- Alc/backends/mmdevapi.c | 53 +++++++++++++++++++++++++++++++++++++++++-------- Alc/helpers.c | 1 + 2 files changed, 46 insertions(+), 8 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index bcef0a5f..b444a341 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -52,6 +52,7 @@ DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0 DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14); DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_FormFactor, 0x1da5d803, 0xd492, 0x4edd, 0x8c,0x23, 0xe0,0xc0,0xff,0xee,0x7f,0x0e, 0); +DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23,0xe0, 0xc0,0xff,0xee,0x7f,0x0e, 4 ); #define MONO SPEAKER_FRONT_CENTER #define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT) @@ -67,6 +68,7 @@ DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_FormFactor, 0x1da5d803, 0xd492, 0x4edd, 0x typedef struct { al_string name; + al_string endpoint_guid; // obtained from PKEY_AudioEndpoint_GUID , set to "Unknown device GUID" if absent. WCHAR *devid; } DevMap; TYPEDEF_VECTOR(DevMap, vector_DevMap) @@ -75,6 +77,7 @@ static void clear_devlist(vector_DevMap *list) { #define CLEAR_DEVMAP(i) do { \ AL_STRING_DEINIT((i)->name); \ + AL_STRING_DEINIT((i)->endpoint_guid); \ free((i)->devid); \ (i)->devid = NULL; \ } while(0) @@ -119,10 +122,11 @@ static HRESULT WaitForResponse(ThreadRequest *req) } -static void get_device_name(IMMDevice *device, al_string *name) +static void get_device_name_and_guid(IMMDevice *device, al_string *name, al_string *guid) { IPropertyStore *ps; PROPVARIANT pvname; + PROPVARIANT pvguid; HRESULT hr; al_string_copy_cstr(name, DEVNAME_HEAD); @@ -132,6 +136,7 @@ static void get_device_name(IMMDevice *device, al_string *name) { WARN("OpenPropertyStore failed: 0x%08lx\n", hr); al_string_append_cstr(name, "Unknown Device Name"); + if(guid!=NULL)al_string_copy_cstr(guid, "Unknown Device GUID"); return; } @@ -150,8 +155,28 @@ static void get_device_name(IMMDevice *device, al_string *name) WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvname.vt); al_string_append_cstr(name, "Unknown Device Name"); } - PropVariantClear(&pvname); + + if(guid!=NULL){ + PropVariantInit(&pvguid); + + hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&PKEY_AudioEndpoint_GUID, &pvguid); + if(FAILED(hr)) + { + WARN("GetValue AudioEndpoint_GUID failed: 0x%08lx\n", hr); + al_string_copy_cstr(guid, "Unknown Device GUID"); + } + else if(pvguid.vt == VT_LPWSTR) + al_string_copy_wcstr(guid, pvguid.pwszVal); + else + { + WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvguid.vt); + al_string_copy_cstr(guid, "Unknown Device GUID"); + } + + PropVariantClear(&pvguid); + } + IPropertyStore_Release(ps); } @@ -193,9 +218,10 @@ static void add_device(IMMDevice *device, LPCWSTR devid, vector_DevMap *list) AL_STRING_INIT(tmpname); AL_STRING_INIT(entry.name); + AL_STRING_INIT(entry.endpoint_guid); entry.devid = strdupW(devid); - get_device_name(device, &tmpname); + get_device_name_and_guid(device, &tmpname, &entry.endpoint_guid); while(1) { @@ -216,7 +242,7 @@ static void add_device(IMMDevice *device, LPCWSTR devid, vector_DevMap *list) count++; } - TRACE("Got device \"%s\", \"%ls\"\n", al_string_get_cstr(entry.name), entry.devid); + TRACE("Got device \"%s\", %s, \"%ls\"\n", al_string_get_cstr(entry.name), al_string_get_cstr(entry.endpoint_guid), entry.devid); VECTOR_PUSH_BACK(*list, entry); AL_STRING_DEINIT(tmpname); @@ -663,6 +689,17 @@ static ALCboolean MakeExtensible(WAVEFORMATEXTENSIBLE *out, const WAVEFORMATEX * return ALC_TRUE; } + static ALCboolean match_name_or_guid(const DevMap *iter, const ALCchar *deviceName){ + al_string tmp_id; + ALCboolean result; + result=AL_FALSE; + if (al_string_cmp_cstr(iter->name, deviceName) == 0 || al_string_cmp_cstr(iter->endpoint_guid, deviceName) == 0) return ALC_TRUE; + AL_STRING_INIT(tmp_id); + al_string_copy_wcstr(&tmp_id, iter->devid); + if(al_string_cmp_cstr(tmp_id, deviceName)==0)result=AL_TRUE; + AL_STRING_DEINIT(tmp_id); + return result; +} static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *deviceName) { @@ -690,7 +727,7 @@ static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *devi } hr = E_FAIL; -#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, deviceName) == 0) +#define MATCH_NAME(i) (match_name_or_guid((i), (deviceName))==ALC_TRUE) VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); if(iter == VECTOR_END(PlaybackDevices)) WARN("Failed to find device name matching \"%s\"\n", deviceName); @@ -758,7 +795,7 @@ static HRESULT ALCmmdevPlayback_openProxy(ALCmmdevPlayback *self) { self->client = ptr; if(al_string_empty(device->DeviceName)) - get_device_name(self->mmdev, &device->DeviceName); + get_device_name_and_guid(self->mmdev, &device->DeviceName, NULL); } if(FAILED(hr)) @@ -1335,7 +1372,7 @@ static ALCenum ALCmmdevCapture_open(ALCmmdevCapture *self, const ALCchar *device } hr = E_FAIL; -#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, deviceName) == 0) +#define MATCH_NAME(i) (match_name_or_guid((i), (deviceName))==ALC_TRUE) VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); if(iter == VECTOR_END(CaptureDevices)) WARN("Failed to find device name matching \"%s\"\n", deviceName); @@ -1421,7 +1458,7 @@ static HRESULT ALCmmdevCapture_openProxy(ALCmmdevCapture *self) { self->client = ptr; if(al_string_empty(device->DeviceName)) - get_device_name(self->mmdev, &device->DeviceName); + get_device_name_and_guid(self->mmdev, &device->DeviceName, NULL); } if(FAILED(hr)) diff --git a/Alc/helpers.c b/Alc/helpers.c index 9d7d564f..9b6c7894 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -65,6 +65,7 @@ DEFINE_GUID(IID_IAudioCaptureClient, 0xc8adbd64, 0xe71e, 0x48a0, 0xa4,0xde, 0x1 #include DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14); DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_FormFactor, 0x1da5d803, 0xd492, 0x4edd, 0x8c,0x23, 0xe0,0xc0,0xff,0xee,0x7f,0x0e, 0); +DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23,0xe0, 0xc0,0xff,0xee,0x7f,0x0e, 4 ); #endif #endif #endif /* AL_NO_UID_DEFS */ -- cgit v1.2.3 From ef67d17a842a315eac3ef863edc8682a5c033032 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 7 Sep 2016 09:22:34 -0700 Subject: Simplify mmdevapi's device name search Avoids converting each enumerated devid from WSTR to UTF-8, and instead just converts the device name from UTF-8 to WSTR once if needed. --- Alc/backends/mmdevapi.c | 50 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 17 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index b444a341..31092db7 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -242,7 +242,7 @@ static void add_device(IMMDevice *device, LPCWSTR devid, vector_DevMap *list) count++; } - TRACE("Got device \"%s\", %s, \"%ls\"\n", al_string_get_cstr(entry.name), al_string_get_cstr(entry.endpoint_guid), entry.devid); + TRACE("Got device \"%s\", \"%s\", \"%ls\"\n", al_string_get_cstr(entry.name), al_string_get_cstr(entry.endpoint_guid), entry.devid); VECTOR_PUSH_BACK(*list, entry); AL_STRING_DEINIT(tmpname); @@ -689,18 +689,6 @@ static ALCboolean MakeExtensible(WAVEFORMATEXTENSIBLE *out, const WAVEFORMATEX * return ALC_TRUE; } - static ALCboolean match_name_or_guid(const DevMap *iter, const ALCchar *deviceName){ - al_string tmp_id; - ALCboolean result; - result=AL_FALSE; - if (al_string_cmp_cstr(iter->name, deviceName) == 0 || al_string_cmp_cstr(iter->endpoint_guid, deviceName) == 0) return ALC_TRUE; - AL_STRING_INIT(tmp_id); - al_string_copy_wcstr(&tmp_id, iter->devid); - if(al_string_cmp_cstr(tmp_id, deviceName)==0)result=AL_TRUE; - AL_STRING_DEINIT(tmp_id); - return result; -} - static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *deviceName) { HRESULT hr = S_OK; @@ -727,8 +715,23 @@ static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *devi } hr = E_FAIL; -#define MATCH_NAME(i) (match_name_or_guid((i), (deviceName))==ALC_TRUE) +#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, deviceName) == 0 || \ + al_string_cmp_cstr((i)->endpoint_guid, deviceName) == 0) VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); +#undef MATCH_NAME + if(iter == VECTOR_END(PlaybackDevices)) + { + int len; + if((len=MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, NULL, 0)) > 0) + { + WCHAR *wname = calloc(sizeof(WCHAR), len); + MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, wname, len); +#define MATCH_NAME(i) (wcscmp((i)->devid, wname) == 0) + VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); +#undef MATCH_NAME + free(wname); + } + } if(iter == VECTOR_END(PlaybackDevices)) WARN("Failed to find device name matching \"%s\"\n", deviceName); else @@ -738,7 +741,6 @@ static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *devi al_string_copy(&device->DeviceName, iter->name); hr = S_OK; } -#undef MATCH_NAME } } @@ -1372,8 +1374,23 @@ static ALCenum ALCmmdevCapture_open(ALCmmdevCapture *self, const ALCchar *device } hr = E_FAIL; -#define MATCH_NAME(i) (match_name_or_guid((i), (deviceName))==ALC_TRUE) +#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, deviceName) == 0 || \ + al_string_cmp_cstr((i)->endpoint_guid, deviceName) == 0) VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); +#undef MATCH_NAME + if(iter == VECTOR_END(CaptureDevices)) + { + int len; + if((len=MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, NULL, 0)) > 0) + { + WCHAR *wname = calloc(sizeof(WCHAR), len); + MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, wname, len); +#define MATCH_NAME(i) (wcscmp((i)->devid, wname) == 0) + VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); +#undef MATCH_NAME + free(wname); + } + } if(iter == VECTOR_END(CaptureDevices)) WARN("Failed to find device name matching \"%s\"\n", deviceName); else @@ -1383,7 +1400,6 @@ static ALCenum ALCmmdevCapture_open(ALCmmdevCapture *self, const ALCchar *device al_string_copy(&device->DeviceName, iter->name); hr = S_OK; } -#undef MATCH_NAME } } -- cgit v1.2.3 From d89624b03c2622c7deb2104ddf9318b131de67ab Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 21 Sep 2016 15:16:09 -0700 Subject: Recognize Headset formfactors as headphones --- Alc/backends/mmdevapi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Alc/backends') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 31092db7..7cad93a9 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -1063,7 +1063,9 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self) OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; } get_device_formfactor(self->mmdev, &formfactor); - device->IsHeadphones = (device->FmtChans == DevFmtStereo && formfactor == Headphones); + device->IsHeadphones = (device->FmtChans == DevFmtStereo && + (formfactor == Headphones || formfactor == Headset) + ); SetDefaultWFXChannelOrder(device); -- cgit v1.2.3 From a0e4696f5578fa42ec0ac7ac47141bf41fb727ff Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 4 Oct 2016 11:20:01 -0700 Subject: Include wtypes.h for defining Windows' property keys --- Alc/backends/mmdevapi.c | 1 + Alc/helpers.c | 1 + 2 files changed, 2 insertions(+) (limited to 'Alc/backends') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 7cad93a9..3882b08f 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include diff --git a/Alc/helpers.c b/Alc/helpers.c index d4b44ced..0a6982e9 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -62,6 +62,7 @@ DEFINE_GUID(IID_IAudioRenderClient, 0xf294acfc, 0x3146, 0x4483, 0xa7,0xbf, 0xa DEFINE_GUID(IID_IAudioCaptureClient, 0xc8adbd64, 0xe71e, 0x48a0, 0xa4,0xde, 0x18,0x5c,0x39,0x5c,0xd3,0x17); #ifdef HAVE_MMDEVAPI +#include #include #include DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14); -- cgit v1.2.3 From 939d16d57c2e766828848ab6b10b5e943f2ba024 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 3 Nov 2016 23:29:33 -0700 Subject: Include the full JACK ringbuffer size for the device period count --- Alc/backends/jack.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index 283df297..fa04c594 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -211,12 +211,14 @@ static int ALCjackPlayback_bufferSizeNotify(jack_nframes_t numframes, void *arg) ALCjackPlayback_lock(self); device->UpdateSize = numframes; device->NumUpdates = 2; - TRACE("%u update size x%u\n", device->UpdateSize, device->NumUpdates); bufsize = device->UpdateSize; if(ConfigValueUInt(al_string_get_cstr(device->DeviceName), "jack", "buffer-size", &bufsize)) bufsize = maxu(NextPowerOf2(bufsize), device->UpdateSize); bufsize += device->UpdateSize; + device->NumUpdates = bufsize / device->UpdateSize; + + TRACE("%u update size x%u\n", device->UpdateSize, device->NumUpdates); ll_ringbuffer_free(self->Ring); self->Ring = ll_ringbuffer_create(bufsize, FrameSizeFromDevFmt(device->FmtChans, device->FmtType)); @@ -248,8 +250,9 @@ static int ALCjackPlayback_process(jack_nframes_t numframes, void *arg) todo = minu(numframes, data[0].len); for(c = 0;c < numchans;c++) { + const ALfloat *restrict in = ((ALfloat*)data[0].buf) + c; for(i = 0;i < todo;i++) - out[c][i] = ((ALfloat*)data[0].buf)[i*numchans + c]; + out[c][i] = in[i*numchans]; out[c] += todo; } total += todo; @@ -259,8 +262,9 @@ static int ALCjackPlayback_process(jack_nframes_t numframes, void *arg) { for(c = 0;c < numchans;c++) { + const ALfloat *restrict in = ((ALfloat*)data[1].buf) + c; for(i = 0;i < todo;i++) - out[c][i] = ((ALfloat*)data[1].buf)[i*numchans + c]; + out[c][i] = in[i*numchans]; out[c] += todo; } total += todo; @@ -407,6 +411,7 @@ static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self) if(ConfigValueUInt(al_string_get_cstr(device->DeviceName), "jack", "buffer-size", &bufsize)) bufsize = maxu(NextPowerOf2(bufsize), device->UpdateSize); bufsize += device->UpdateSize; + device->NumUpdates = bufsize / device->UpdateSize; /* Force 32-bit float output. */ device->FmtType = DevFmtFloat; -- cgit v1.2.3 From 338e0d72b447e5d8825b05e19790c997a3eaa8fd Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 1 Dec 2016 18:11:52 -0800 Subject: Ensure OSS devices are enumerated when a name is requested. --- Alc/backends/oss.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 432c75f2..2dca9232 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -320,10 +320,15 @@ static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name) struct oss_device *dev = &oss_playback; ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - if(!name) + if(!name || strcmp(name, dev->handle) == 0) name = dev->handle; else { + if(!dev->next) + { + ALCossListPopulate(&oss_playback, NULL); + dev = &oss_playback; + } while (dev != NULL) { if (strcmp(dev->handle, name) == 0) @@ -574,10 +579,15 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) int ossSpeed; char *err; - if(!name) + if(!name || strcmp(name, dev->handle) == 0) name = dev->handle; else { + if(!dev->next) + { + ALCossListPopulate(NULL, &oss_capture); + dev = &oss_capture; + } while (dev != NULL) { if (strcmp(dev->handle, name) == 0) -- cgit v1.2.3 From 66569295e5ac27dcddb4f20d25a30801af7ca992 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 1 Dec 2016 18:26:18 -0800 Subject: Minor cleanup for ALCossListPopulate --- Alc/backends/oss.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 2dca9232..41f2c39f 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -88,7 +88,7 @@ static struct oss_device oss_capture = { #ifdef ALC_OSS_COMPAT -static void ALCossListPopulate(struct oss_device *UNUSED(playback), struct oss_device *UNUSED(capture)) +static void ALCossListPopulate(struct oss_device *UNUSED(devlist), int UNUSED(type_flag)) { } @@ -153,7 +153,7 @@ static void ALCossListAppend(struct oss_device *list, const char *handle, size_t TRACE("Got device \"%s\", \"%s\"\n", next->handle, next->path); } -static void ALCossListPopulate(struct oss_device *playback, struct oss_device *capture) +static void ALCossListPopulate(struct oss_device *devlist, int type_flag) { struct oss_sysinfo si; struct oss_audioinfo ai; @@ -193,10 +193,9 @@ static void ALCossListPopulate(struct oss_device *playback, struct oss_device *c len = strnlen(ai.name, sizeof(ai.name)); handle = ai.name; } - if((ai.caps&DSP_CAP_INPUT) && capture != NULL) - ALCossListAppend(capture, handle, len, ai.devnode, strnlen(ai.devnode, sizeof(ai.devnode))); - if((ai.caps&DSP_CAP_OUTPUT) && playback != NULL) - ALCossListAppend(playback, handle, len, ai.devnode, strnlen(ai.devnode, sizeof(ai.devnode))); + if((ai.caps&type_flag)) + ALCossListAppend(devlist, handle, len, ai.devnode, + strnlen(ai.devnode, sizeof(ai.devnode))); } done: @@ -326,7 +325,7 @@ static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name) { if(!dev->next) { - ALCossListPopulate(&oss_playback, NULL); + ALCossListPopulate(&oss_playback, DSP_CAP_OUTPUT); dev = &oss_playback; } while (dev != NULL) @@ -585,7 +584,7 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) { if(!dev->next) { - ALCossListPopulate(NULL, &oss_capture); + ALCossListPopulate(&oss_capture, DSP_CAP_INPUT); dev = &oss_capture; } while (dev != NULL) @@ -780,33 +779,30 @@ ALCboolean ALCossBackendFactory_querySupport(ALCossBackendFactory* UNUSED(self), void ALCossBackendFactory_probe(ALCossBackendFactory* UNUSED(self), enum DevProbe type) { + struct oss_device *cur; switch(type) { case ALL_DEVICE_PROBE: - { - struct oss_device *cur = &oss_playback; - ALCossListFree(cur); - ALCossListPopulate(cur, NULL); - while (cur != NULL) + ALCossListFree(&oss_playback); + ALCossListPopulate(&oss_playback, DSP_CAP_OUTPUT); + cur = &oss_playback; + while(cur != NULL) { AppendAllDevicesList(cur->handle); cur = cur->next; } - } - break; + break; case CAPTURE_DEVICE_PROBE: - { - struct oss_device *cur = &oss_capture; - ALCossListFree(cur); - ALCossListPopulate(NULL, cur); - while (cur != NULL) + ALCossListFree(&oss_capture); + ALCossListPopulate(&oss_capture, DSP_CAP_INPUT); + cur = &oss_capture; + while(cur != NULL) { AppendCaptureDeviceList(cur->handle); cur = cur->next; } - } - break; + break; } } -- cgit v1.2.3 From 70378925b0a9dbc58cc49e7888afcf4b7d55a17c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 1 Dec 2016 18:34:29 -0800 Subject: Warn when a given device name isn't found for OSS --- Alc/backends/oss.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 41f2c39f..689a5c71 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -328,14 +328,17 @@ static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name) ALCossListPopulate(&oss_playback, DSP_CAP_OUTPUT); dev = &oss_playback; } - while (dev != NULL) + while(dev != NULL) { if (strcmp(dev->handle, name) == 0) break; dev = dev->next; } - if (dev == NULL) + if(dev == NULL) + { + WARN("Could not find \"%s\" in device list\n", name); return ALC_INVALID_VALUE; + } } self->killNow = 0; @@ -587,14 +590,17 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) ALCossListPopulate(&oss_capture, DSP_CAP_INPUT); dev = &oss_capture; } - while (dev != NULL) + while(dev != NULL) { if (strcmp(dev->handle, name) == 0) break; dev = dev->next; } - if (dev == NULL) + if(dev == NULL) + { + WARN("Could not find \"%s\" in device list\n", name); return ALC_INVALID_VALUE; + } } self->fd = open(dev->path, O_RDONLY); -- cgit v1.2.3 From e270a9784bdacecedb98312a4e2e9ef75ef7df62 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 21 Dec 2016 10:54:19 -0800 Subject: Add missing macros for OSS3/Free compatibility --- Alc/backends/oss.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Alc/backends') diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 689a5c71..62563235 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -88,6 +88,8 @@ static struct oss_device oss_capture = { #ifdef ALC_OSS_COMPAT +#define DSP_CAP_OUTPUT 0x00020000 +#define DSP_CAP_INPUT 0x00010000 static void ALCossListPopulate(struct oss_device *UNUSED(devlist), int UNUSED(type_flag)) { } -- cgit v1.2.3 From 315bd556acdc4b8b67b073f64d472f243a96544d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 21 Dec 2016 17:20:11 -0800 Subject: Convert the SndIO backend to the updated API --- Alc/ALc.c | 2 +- Alc/backends/base.h | 1 + Alc/backends/sndio.c | 204 ++++++++++++++++++++++++++++------------------ OpenAL32/Include/alMain.h | 3 - 4 files changed, 128 insertions(+), 82 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index f1e1ad1f..1690c9fe 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -81,7 +81,7 @@ static struct BackendInfo BackendList[] = { { "solaris", ALCsolarisBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, #endif #ifdef HAVE_SNDIO - { "sndio", NULL, alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs }, + { "sndio", ALCsndioBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, #endif #ifdef HAVE_QSA { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs }, diff --git a/Alc/backends/base.h b/Alc/backends/base.h index 04795b36..94177405 100644 --- a/Alc/backends/base.h +++ b/Alc/backends/base.h @@ -140,6 +140,7 @@ ALCbackendFactory *ALCalsaBackendFactory_getFactory(void); ALCbackendFactory *ALCossBackendFactory_getFactory(void); ALCbackendFactory *ALCjackBackendFactory_getFactory(void); ALCbackendFactory *ALCsolarisBackendFactory_getFactory(void); +ALCbackendFactory *ALCsndioBackendFactory_getFactory(void); ALCbackendFactory *ALCmmdevBackendFactory_getFactory(void); ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void); ALCbackendFactory *ALCwinmmBackendFactory_getFactory(void); diff --git a/Alc/backends/sndio.c b/Alc/backends/sndio.c index 52bff13a..af519794 100644 --- a/Alc/backends/sndio.c +++ b/Alc/backends/sndio.c @@ -28,19 +28,16 @@ #include "alu.h" #include "threads.h" -#include +#include "backends/base.h" +#include -static const ALCchar sndio_device[] = "SndIO Default"; -static ALCboolean sndio_load(void) -{ - return ALC_TRUE; -} +typedef struct ALCsndioBackend { + DERIVE_FROM_TYPE(ALCbackend); -typedef struct { struct sio_hdl *sndHandle; ALvoid *mix_data; @@ -48,13 +45,53 @@ typedef struct { volatile int killNow; althrd_t thread; -} sndio_data; +} ALCsndioBackend; + +static int ALCsndioBackend_mixerProc(void *ptr); + +static void ALCsndioBackend_Construct(ALCsndioBackend *self, ALCdevice *device); +static void ALCsndioBackend_Destruct(ALCsndioBackend *self); +static ALCenum ALCsndioBackend_open(ALCsndioBackend *self, const ALCchar *name); +static void ALCsndioBackend_close(ALCsndioBackend *self); +static ALCboolean ALCsndioBackend_reset(ALCsndioBackend *self); +static ALCboolean ALCsndioBackend_start(ALCsndioBackend *self); +static void ALCsndioBackend_stop(ALCsndioBackend *self); +static DECLARE_FORWARD2(ALCsndioBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint) +static DECLARE_FORWARD(ALCsndioBackend, ALCbackend, ALCuint, availableSamples) +static DECLARE_FORWARD(ALCsndioBackend, ALCbackend, ClockLatency, getClockLatency) +static DECLARE_FORWARD(ALCsndioBackend, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCsndioBackend, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCsndioBackend) + +DEFINE_ALCBACKEND_VTABLE(ALCsndioBackend); + + +static const ALCchar sndio_device[] = "SndIO Default"; + + +static void ALCsndioBackend_Construct(ALCsndioBackend *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCsndioBackend, ALCbackend, self); +} + +static void ALCsndioBackend_Destruct(ALCsndioBackend *self) +{ + if(self->sndHandle) + sio_close(self->sndHandle); + self->sndHandle = NULL; + + al_free(self->mix_data); + self->mix_data = NULL; + + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} -static int sndio_proc(void *ptr) +static int ALCsndioBackend_mixerProc(void *ptr) { - ALCdevice *device = ptr; - sndio_data *data = device->ExtraData; + ALCsndioBackend *self = (ALCsndioBackend*)ptr; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; ALsizei frameSize; size_t wrote; @@ -63,15 +100,15 @@ static int sndio_proc(void *ptr) frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); - while(!data->killNow && device->Connected) + while(!self->killNow && device->Connected) { - ALsizei len = data->data_size; - ALubyte *WritePtr = data->mix_data; + ALsizei len = self->data_size; + ALubyte *WritePtr = self->mix_data; aluMixData(device, WritePtr, len/frameSize); - while(len > 0 && !data->killNow) + while(len > 0 && !self->killNow) { - wrote = sio_write(data->sndHandle, WritePtr, len); + wrote = sio_write(self->sndHandle, WritePtr, len); if(wrote == 0) { ERR("sio_write failed\n"); @@ -90,45 +127,36 @@ static int sndio_proc(void *ptr) } - -static ALCenum sndio_open_playback(ALCdevice *device, const ALCchar *deviceName) +static ALCenum ALCsndioBackend_open(ALCsndioBackend *self, const ALCchar *name) { - sndio_data *data; + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; - if(!deviceName) - deviceName = sndio_device; - else if(strcmp(deviceName, sndio_device) != 0) + if(!name) + name = sndio_device; + else if(strcmp(name, sndio_device) != 0) return ALC_INVALID_VALUE; - data = calloc(1, sizeof(*data)); - data->killNow = 0; - - data->sndHandle = sio_open(NULL, SIO_PLAY, 0); - if(data->sndHandle == NULL) + self->sndHandle = sio_open(NULL, SIO_PLAY, 0); + if(self->sndHandle == NULL) { - free(data); ERR("Could not open device\n"); return ALC_INVALID_VALUE; } - al_string_copy_cstr(&device->DeviceName, deviceName); - device->ExtraData = data; + al_string_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } -static void sndio_close_playback(ALCdevice *device) +static void ALCsndioBackend_close(ALCsndioBackend *self) { - sndio_data *data = device->ExtraData; - - sio_close(data->sndHandle); - free(data); - device->ExtraData = NULL; + sio_close(self->sndHandle); + self->sndHandle = NULL; } -static ALCboolean sndio_reset_playback(ALCdevice *device) +static ALCboolean ALCsndioBackend_reset(ALCsndioBackend *self) { - sndio_data *data = device->ExtraData; + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; struct sio_par par; sio_initpar(&par); @@ -170,7 +198,7 @@ static ALCboolean sndio_reset_playback(ALCdevice *device) 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)) + if(!sio_setpar(self->sndHandle, &par) || !sio_getpar(self->sndHandle, &par)) { ERR("Failed to set device parameters\n"); return ALC_FALSE; @@ -211,77 +239,84 @@ static ALCboolean sndio_reset_playback(ALCdevice *device) return ALC_TRUE; } -static ALCboolean sndio_start_playback(ALCdevice *device) +static ALCboolean ALCsndioBackend_start(ALCsndioBackend *self) { - sndio_data *data = device->ExtraData; + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; - if(!sio_start(data->sndHandle)) + self->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + al_free(self->mix_data); + self->mix_data = al_calloc(16, self->data_size); + + if(!sio_start(self->sndHandle)) { ERR("Error starting playback\n"); return ALC_FALSE; } - data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType); - data->mix_data = calloc(1, data->data_size); - - data->killNow = 0; - if(althrd_create(&data->thread, sndio_proc, device) != althrd_success) + self->killNow = 0; + if(althrd_create(&self->thread, ALCsndioBackend_mixerProc, self) != althrd_success) { - sio_stop(data->sndHandle); - free(data->mix_data); - data->mix_data = NULL; + sio_stop(self->sndHandle); return ALC_FALSE; } return ALC_TRUE; } -static void sndio_stop_playback(ALCdevice *device) +static void ALCsndioBackend_stop(ALCsndioBackend *self) { - sndio_data *data = device->ExtraData; int res; - if(data->killNow) + if(self->killNow) return; - data->killNow = 1; - althrd_join(data->thread, &res); + self->killNow = 1; + althrd_join(self->thread, &res); - if(!sio_stop(data->sndHandle)) + if(!sio_stop(self->sndHandle)) ERR("Error stopping device\n"); - free(data->mix_data); - data->mix_data = NULL; + al_free(self->mix_data); + self->mix_data = NULL; } -static const BackendFuncs sndio_funcs = { - sndio_open_playback, - sndio_close_playback, - sndio_reset_playback, - sndio_start_playback, - sndio_stop_playback, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL -}; - -ALCboolean alc_sndio_init(BackendFuncs *func_list) +typedef struct ALCsndioBackendFactory { + DERIVE_FROM_TYPE(ALCbackendFactory); +} ALCsndioBackendFactory; +#define ALCSNDIOBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCsndioBackendFactory, ALCbackendFactory) } } + +ALCbackendFactory *ALCsndioBackendFactory_getFactory(void); + +static ALCboolean ALCsndioBackendFactory_init(ALCsndioBackendFactory *self); +static DECLARE_FORWARD(ALCsndioBackendFactory, ALCbackendFactory, void, deinit) +static ALCboolean ALCsndioBackendFactory_querySupport(ALCsndioBackendFactory *self, ALCbackend_Type type); +static void ALCsndioBackendFactory_probe(ALCsndioBackendFactory *self, enum DevProbe type); +static ALCbackend* ALCsndioBackendFactory_createBackend(ALCsndioBackendFactory *self, ALCdevice *device, ALCbackend_Type type); +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCsndioBackendFactory); + + +ALCbackendFactory *ALCsndioBackendFactory_getFactory(void) { - if(!sndio_load()) - return ALC_FALSE; - *func_list = sndio_funcs; + static ALCsndioBackendFactory factory = ALCSNDIOBACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); +} + + +static ALCboolean ALCsndioBackendFactory_init(ALCsndioBackendFactory* UNUSED(self)) +{ + /* No dynamic loading */ return ALC_TRUE; } -void alc_sndio_deinit(void) +static ALCboolean ALCsndioBackendFactory_querySupport(ALCsndioBackendFactory* UNUSED(self), ALCbackend_Type type) { + if(type == ALCbackend_Playback) + return ALC_TRUE; + return ALC_FALSE; } -void alc_sndio_probe(enum DevProbe type) +static void ALCsndioBackendFactory_probe(ALCsndioBackendFactory* UNUSED(self), enum DevProbe type) { switch(type) { @@ -292,3 +327,16 @@ void alc_sndio_probe(enum DevProbe type) break; } } + +static ALCbackend* ALCsndioBackendFactory_createBackend(ALCsndioBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + { + ALCsndioBackend *backend; + NEW_OBJ(backend, ALCsndioBackend)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + + return NULL; +} diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 837e1082..5a5c3923 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -401,9 +401,6 @@ typedef struct { ALCuint (*AvailableSamples)(ALCdevice*); } BackendFuncs; -ALCboolean alc_sndio_init(BackendFuncs *func_list); -void alc_sndio_deinit(void); -void alc_sndio_probe(enum DevProbe type); ALCboolean alc_ca_init(BackendFuncs *func_list); void alc_ca_deinit(void); void alc_ca_probe(enum DevProbe type); -- cgit v1.2.3 From e20f0ae5a3c68767a7e08df96fbfa707f36ea6db Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 10 Jan 2017 03:02:26 -0800 Subject: Hold Pulse's mainloop lock while calling capture functions Since commit c837484015e, the backend's lock is no longer implicitly held when calling capture functions. A separate mutex is used to ensure serial access, and its up to the backend to protect against races and reentrancy with the audio API. --- Alc/backends/pulseaudio.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index f46386e4..fa07da3e 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -1558,17 +1558,20 @@ static void ALCpulseCapture_close(ALCpulseCapture *self) static ALCboolean ALCpulseCapture_start(ALCpulseCapture *self) { pa_operation *o; + pa_threaded_mainloop_lock(self->loop); o = pa_stream_cork(self->stream, 0, stream_success_callback, self->loop); wait_for_operation(o, self->loop); - + pa_threaded_mainloop_unlock(self->loop); return ALC_TRUE; } static void ALCpulseCapture_stop(ALCpulseCapture *self) { pa_operation *o; + pa_threaded_mainloop_lock(self->loop); o = pa_stream_cork(self->stream, 1, stream_success_callback, self->loop); wait_for_operation(o, self->loop); + pa_threaded_mainloop_unlock(self->loop); } static ALCenum ALCpulseCapture_captureSamples(ALCpulseCapture *self, ALCvoid *buffer, ALCuint samples) @@ -1579,6 +1582,7 @@ static ALCenum ALCpulseCapture_captureSamples(ALCpulseCapture *self, ALCvoid *bu /* Capture is done in fragment-sized chunks, so we loop until we get all * that's available */ self->last_readable -= todo; + pa_threaded_mainloop_lock(self->loop); while(todo > 0) { size_t rem = todo; @@ -1618,6 +1622,7 @@ static ALCenum ALCpulseCapture_captureSamples(ALCpulseCapture *self, ALCvoid *bu self->cap_len = 0; } } + pa_threaded_mainloop_unlock(self->loop); if(todo > 0) memset(buffer, ((device->FmtType==DevFmtUByte) ? 0x80 : 0), todo); @@ -1631,7 +1636,9 @@ static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self) if(device->Connected) { - ssize_t got = pa_stream_readable_size(self->stream); + ssize_t got; + pa_threaded_mainloop_lock(self->loop); + got = pa_stream_readable_size(self->stream); if(got < 0) { ERR("pa_stream_readable_size() failed: %s\n", pa_strerror(got)); @@ -1639,6 +1646,7 @@ static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self) } else if((size_t)got > self->cap_len) readable += got - self->cap_len; + pa_threaded_mainloop_unlock(self->loop); } if(self->last_readable < readable) -- cgit v1.2.3 From 43ab6075f9d40f0eabfaf15e37f6fed6e92b14f6 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 10 Jan 2017 03:17:23 -0800 Subject: Use proper atomics in the OSS backend --- Alc/backends/oss.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 62563235..2da096f6 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -243,7 +243,7 @@ typedef struct ALCplaybackOSS { ALubyte *mix_data; int data_size; - volatile int killNow; + ATOMIC(ALenum) killNow; althrd_t thread; } ALCplaybackOSS; @@ -277,13 +277,13 @@ static int ALCplaybackOSS_mixerProc(void *ptr) frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); - while(!self->killNow && device->Connected) + while(!ATOMIC_LOAD_SEQ(&self->killNow) && device->Connected) { ALint len = self->data_size; ALubyte *WritePtr = self->mix_data; aluMixData(device, WritePtr, len/frameSize); - while(len > 0 && !self->killNow) + while(len > 0 && !ATOMIC_LOAD_SEQ(&self->killNow)) { wrote = write(self->fd, WritePtr, len); if(wrote < 0) @@ -314,6 +314,8 @@ static void ALCplaybackOSS_Construct(ALCplaybackOSS *self, ALCdevice *device) { ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCplaybackOSS, ALCbackend, self); + + ATOMIC_INIT(&self->killNow, AL_FALSE); } static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name) @@ -343,8 +345,6 @@ static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name) } } - self->killNow = 0; - self->fd = open(dev->path, O_WRONLY); if(self->fd == -1) { @@ -459,7 +459,7 @@ static ALCboolean ALCplaybackOSS_start(ALCplaybackOSS *self) self->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType); self->mix_data = calloc(1, self->data_size); - self->killNow = 0; + ATOMIC_STORE_SEQ(&self->killNow, AL_FALSE); if(althrd_create(&self->thread, ALCplaybackOSS_mixerProc, self) != althrd_success) { free(self->mix_data); @@ -474,10 +474,8 @@ static void ALCplaybackOSS_stop(ALCplaybackOSS *self) { int res; - if(self->killNow) + if(ATOMIC_EXCHANGE_SEQ(ALenum, &self->killNow, AL_TRUE)) return; - - self->killNow = 1; althrd_join(self->thread, &res); if(ioctl(self->fd, SNDCTL_DSP_RESET) != 0) @@ -494,9 +492,9 @@ typedef struct ALCcaptureOSS { int fd; ll_ringbuffer_t *ring; - int doCapture; + ATOMIC(ALenum) doCapture; - volatile int killNow; + ATOMIC(ALenum) killNow; althrd_t thread; } ALCcaptureOSS; @@ -530,12 +528,12 @@ static int ALCcaptureOSS_recordProc(void *ptr) frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); - while(!self->killNow) + while(!ATOMIC_LOAD_SEQ(&self->killNow)) { ll_ringbuffer_data_t vec[2]; amt = 0; - if(self->doCapture) + if(ATOMIC_LOAD_SEQ(&self->doCapture)) { ll_ringbuffer_get_write_vector(self->ring, vec); if(vec[0].len > 0) @@ -567,6 +565,9 @@ static void ALCcaptureOSS_Construct(ALCcaptureOSS *self, ALCdevice *device) { ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCcaptureOSS, ALCbackend, self); + + ATOMIC_INIT(&self->doCapture, AL_FALSE); + ATOMIC_INIT(&self->killNow, AL_FALSE); } static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) @@ -689,7 +690,6 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) return ALC_OUT_OF_MEMORY; } - self->killNow = 0; if(althrd_create(&self->thread, ALCcaptureOSS_recordProc, self) != althrd_success) { ll_ringbuffer_free(self->ring); @@ -708,7 +708,7 @@ static void ALCcaptureOSS_close(ALCcaptureOSS *self) { int res; - self->killNow = 1; + ATOMIC_STORE_SEQ(&self->killNow, AL_TRUE); althrd_join(self->thread, &res); close(self->fd); @@ -720,13 +720,13 @@ static void ALCcaptureOSS_close(ALCcaptureOSS *self) static ALCboolean ALCcaptureOSS_start(ALCcaptureOSS *self) { - self->doCapture = 1; + ATOMIC_STORE_SEQ(&self->doCapture, AL_TRUE); return ALC_TRUE; } static void ALCcaptureOSS_stop(ALCcaptureOSS *self) { - self->doCapture = 0; + ATOMIC_STORE_SEQ(&self->doCapture, AL_FALSE); } static ALCenum ALCcaptureOSS_captureSamples(ALCcaptureOSS *self, ALCvoid *buffer, ALCuint samples) -- cgit v1.2.3 From 58f84170b6237a3c847cdccaaa3c666e7ba710d6 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 10 Jan 2017 05:12:54 -0800 Subject: Avoid using some LP types --- Alc/backends/mmdevapi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 3882b08f..92089416 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -211,7 +211,7 @@ static void get_device_formfactor(IMMDevice *device, EndpointFormFactor *formfac } -static void add_device(IMMDevice *device, LPCWSTR devid, vector_DevMap *list) +static void add_device(IMMDevice *device, const WCHAR *devid, vector_DevMap *list) { int count = 0; al_string tmpname; @@ -249,9 +249,9 @@ static void add_device(IMMDevice *device, LPCWSTR devid, vector_DevMap *list) AL_STRING_DEINIT(tmpname); } -static LPWSTR get_device_id(IMMDevice *device) +static WCHAR *get_device_id(IMMDevice *device) { - LPWSTR devid; + WCHAR *devid; HRESULT hr; hr = IMMDevice_GetId(device, &devid); @@ -268,7 +268,7 @@ static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ve { IMMDeviceCollection *coll; IMMDevice *defdev = NULL; - LPWSTR defdevid = NULL; + WCHAR *defdevid = NULL; HRESULT hr; UINT count; UINT i; @@ -300,7 +300,7 @@ static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ve for(i = 0;i < count;++i) { IMMDevice *device; - LPWSTR devid; + WCHAR *devid; hr = IMMDeviceCollection_Item(coll, i, &device); if(FAILED(hr)) continue; -- cgit v1.2.3 From d2e5aa79ddc79bccde67d375cffea8f9922ca611 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 18 Jan 2017 07:13:23 -0800 Subject: Use ALsizei in more places --- Alc/ALc.c | 8 ++--- Alc/ALu.c | 2 +- Alc/backends/solaris.c | 6 ++-- Alc/mixer.c | 66 +++++++++++++++++++------------------- Alc/panning.c | 28 ++++++++-------- OpenAL32/Include/alAuxEffectSlot.h | 4 +-- OpenAL32/Include/alBuffer.h | 16 ++++----- OpenAL32/Include/alMain.h | 16 ++++----- OpenAL32/Include/alSource.h | 8 ++--- OpenAL32/Include/alu.h | 14 ++++---- OpenAL32/alBuffer.c | 20 ++++++------ 11 files changed, 94 insertions(+), 94 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index 0b558ff7..80378d91 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -1310,8 +1310,8 @@ const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans) return "(unknown channels)"; } -extern inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type); -ALuint BytesFromDevFmt(enum DevFmtType type) +extern inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type); +ALsizei BytesFromDevFmt(enum DevFmtType type) { switch(type) { @@ -1325,7 +1325,7 @@ ALuint BytesFromDevFmt(enum DevFmtType type) } return 0; } -ALuint ChannelsFromDevFmt(enum DevFmtChannels chans) +ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans) { switch(chans) { @@ -2093,7 +2093,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) device->FOAOut.Buffer = device->Dry.Buffer; device->FOAOut.NumChannels = device->Dry.NumChannels; } - TRACE("Channel config, Dry: %u, FOA: %u, Real: %u\n", device->Dry.NumChannels, + TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device->Dry.NumChannels, device->FOAOut.NumChannels, device->RealOut.NumChannels); SetMixerFPUMode(&oldMode); diff --git a/Alc/ALu.c b/Alc/ALu.c index 02b4ffe8..9b03b85a 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -1400,7 +1400,7 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size) ALsource *source; ALCcontext *ctx; FPUCtl oldMode; - ALuint i, c; + ALsizei i, c; SetMixerFPUMode(&oldMode); diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c index 01472e6a..792f717a 100644 --- a/Alc/backends/solaris.c +++ b/Alc/backends/solaris.c @@ -177,8 +177,8 @@ static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self) { ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; audio_info_t info; - ALuint frameSize; - int numChannels; + ALsizei frameSize; + ALsizei numChannels; AUDIO_INITINFO(&info); @@ -220,7 +220,7 @@ static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self) return ALC_FALSE; } - if(ChannelsFromDevFmt(device->FmtChans) != info.play.channels) + if(ChannelsFromDevFmt(device->FmtChans) != (ALsizei)info.play.channels) { ERR("Could not set %d channels, got %d instead\n", ChannelsFromDevFmt(device->FmtChans), info.play.channels); return ALC_FALSE; diff --git a/Alc/mixer.c b/Alc/mixer.c index 2d804b1f..58192055 100644 --- a/Alc/mixer.c +++ b/Alc/mixer.c @@ -307,9 +307,9 @@ static inline ALfloat Sample_ALfloat(ALfloat val) { return val; } #define DECL_TEMPLATE(T) \ -static inline void Load_##T(ALfloat *dst, const T *src, ALuint srcstep, ALuint samples)\ +static inline void Load_##T(ALfloat *dst, const T *src, ALint srcstep, ALsizei samples)\ { \ - ALuint i; \ + ALsizei i; \ for(i = 0;i < samples;i++) \ dst[i] = Sample_##T(src[i*srcstep]); \ } @@ -320,7 +320,7 @@ DECL_TEMPLATE(ALfloat) #undef DECL_TEMPLATE -static void LoadSamples(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtType srctype, ALuint samples) +static void LoadSamples(ALfloat *dst, const ALvoid *src, ALint srcstep, enum FmtType srctype, ALsizei samples) { switch(srctype) { @@ -336,9 +336,9 @@ static void LoadSamples(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum Fm } } -static inline void SilenceSamples(ALfloat *dst, ALuint samples) +static inline void SilenceSamples(ALfloat *dst, ALsizei samples) { - ALuint i; + ALsizei i; for(i = 0;i < samples;i++) dst[i] = 0.0f; } @@ -346,9 +346,9 @@ static inline void SilenceSamples(ALfloat *dst, ALuint samples) static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter, ALfloat *restrict dst, const ALfloat *restrict src, - ALuint numsamples, enum ActiveFilters type) + ALsizei numsamples, enum ActiveFilters type) { - ALuint i; + ALsizei i; switch(type) { case AF_None: @@ -369,7 +369,7 @@ static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter for(i = 0;i < numsamples;) { ALfloat temp[256]; - ALuint todo = minu(256, numsamples-i); + ALsizei todo = mini(256, numsamples-i); ALfilterState_process(lpfilter, temp, src+i, todo); ALfilterState_process(hpfilter, dst+i, temp, todo); @@ -381,21 +381,22 @@ static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter } -ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) +ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei SamplesToDo) { ResamplerFunc Resample; ALbufferlistitem *BufferListItem; ALuint DataPosInt, DataPosFrac; ALboolean Looping; - ALuint increment; + ALint increment; ALenum State; - ALuint OutPos; - ALuint NumChannels; - ALuint SampleSize; + ALsizei OutPos; + ALsizei NumChannels; + ALsizei SampleSize; ALint64 DataSize64; - ALuint Counter; - ALuint IrSize; - ALuint chan, send, j; + ALsizei Counter; + ALsizei IrSize; + ALsizei chan, j; + ALuint send; /* Get source info */ State = AL_PLAYING; /* Only called while playing. */ @@ -415,7 +416,7 @@ ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint Sam Counter = voice->Moving ? SamplesToDo : 0; OutPos = 0; do { - ALuint SrcBufferSize, DstBufferSize; + ALsizei SrcBufferSize, DstBufferSize; /* Figure out how many buffer samples will be needed */ DataSize64 = SamplesToDo-OutPos; @@ -424,7 +425,7 @@ ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint Sam DataSize64 >>= FRACTIONBITS; DataSize64 += MAX_POST_SAMPLES+MAX_PRE_SAMPLES; - SrcBufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE); + SrcBufferSize = (ALsizei)mini64(DataSize64, BUFFERSIZE); /* Figure out how many samples we can actually mix from this. */ DataSize64 = SrcBufferSize; @@ -432,8 +433,8 @@ ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint Sam DataSize64 <<= FRACTIONBITS; DataSize64 -= DataPosFrac; - DstBufferSize = (ALuint)((DataSize64+(increment-1)) / increment); - DstBufferSize = minu(DstBufferSize, (SamplesToDo-OutPos)); + DstBufferSize = (ALsizei)((DataSize64+(increment-1)) / increment); + DstBufferSize = mini(DstBufferSize, (SamplesToDo-OutPos)); /* Some mixers like having a multiple of 4, so try to give that unless * this is the last update. */ @@ -444,7 +445,7 @@ ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint Sam { const ALfloat *ResampledData; ALfloat *SrcData = Device->SourceData; - ALuint SrcDataSize; + ALsizei SrcDataSize; /* Load the previous samples into the source data first. */ memcpy(SrcData, voice->PrevSamples[chan], MAX_PRE_SAMPLES*sizeof(ALfloat)); @@ -454,7 +455,7 @@ ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint Sam { const ALbuffer *ALBuffer = BufferListItem->buffer; const ALubyte *Data = ALBuffer->data; - ALuint DataSize; + ALsizei DataSize; /* Offset buffer data to current channel */ Data += chan*SampleSize; @@ -478,13 +479,12 @@ ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint Sam } else { - ALuint LoopStart = ALBuffer->LoopStart; - ALuint LoopEnd = ALBuffer->LoopEnd; + ALsizei LoopStart = ALBuffer->LoopStart; + ALsizei LoopEnd = ALBuffer->LoopEnd; /* Load what's left of this loop iteration, then load * repeats of the loop section */ - DataSize = LoopEnd - DataPosInt; - DataSize = minu(SrcBufferSize - SrcDataSize, DataSize); + DataSize = minu(SrcBufferSize - SrcDataSize, LoopEnd - DataPosInt); LoadSamples(&SrcData[SrcDataSize], &Data[DataPosInt * NumChannels*SampleSize], NumChannels, ALBuffer->FmtType, DataSize); @@ -493,7 +493,7 @@ ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint Sam DataSize = LoopEnd-LoopStart; while(SrcBufferSize > SrcDataSize) { - DataSize = minu(SrcBufferSize - SrcDataSize, DataSize); + DataSize = mini(SrcBufferSize - SrcDataSize, DataSize); LoadSamples(&SrcData[SrcDataSize], &Data[LoopStart * NumChannels*SampleSize], NumChannels, ALBuffer->FmtType, DataSize); @@ -645,22 +645,22 @@ ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint Sam OutPos += DstBufferSize; voice->Offset += DstBufferSize; - Counter = maxu(DstBufferSize, Counter) - DstBufferSize; + Counter = maxi(DstBufferSize, Counter) - DstBufferSize; /* Handle looping sources */ while(1) { const ALbuffer *ALBuffer; - ALuint DataSize = 0; - ALuint LoopStart = 0; - ALuint LoopEnd = 0; + ALsizei DataSize = 0; + ALsizei LoopStart = 0; + ALsizei LoopEnd = 0; if((ALBuffer=BufferListItem->buffer) != NULL) { DataSize = ALBuffer->SampleLen; LoopStart = ALBuffer->LoopStart; LoopEnd = ALBuffer->LoopEnd; - if(LoopEnd > DataPosInt) + if((ALuint)LoopEnd > DataPosInt) break; } @@ -671,7 +671,7 @@ ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint Sam break; } - if(DataSize > DataPosInt) + if((ALuint)DataSize > DataPosInt) break; if(!(BufferListItem=BufferListItem->next)) diff --git a/Alc/panning.c b/Alc/panning.c index e1ad6d0b..a0576e0d 100644 --- a/Alc/panning.c +++ b/Alc/panning.c @@ -209,9 +209,9 @@ void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat } -void ComputeAmbientGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]) +void ComputeAmbientGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]) { - ALuint i; + ALsizei i; for(i = 0;i < numchans;i++) { @@ -224,10 +224,10 @@ void ComputeAmbientGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, ALf gains[i] = 0.0f; } -void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALuint numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]) +void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]) { ALfloat gain = 0.0f; - ALuint i; + ALsizei i; for(i = 0;i < numchans;i++) { @@ -239,9 +239,9 @@ void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALuint numchans, ALfl gains[i] = 0.0f; } -void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, ALuint numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]) +void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALsizei numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]) { - ALuint i, j; + ALsizei i, j; for(i = 0;i < numchans;i++) { @@ -254,9 +254,9 @@ void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, ALu gains[i] = 0.0f; } -void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALuint numchans, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]) +void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]) { - ALuint i; + ALsizei i; for(i = 0;i < numchans;i++) gains[i] = chanmap[i].Scale * coeffs[chanmap[i].Index] * ingain; @@ -264,9 +264,9 @@ void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALuint numchans, cons gains[i] = 0.0f; } -void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]) +void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]) { - ALuint i, j; + ALsizei i, j; for(i = 0;i < numchans;i++) { @@ -279,9 +279,9 @@ void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, gains[i] = 0.0f; } -void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALuint numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]) +void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]) { - ALuint i; + ALsizei i; for(i = 0;i < numchans;i++) gains[i] = chanmap[i].Scale * mtx[chanmap[i].Index] * ingain; @@ -342,13 +342,13 @@ typedef struct ChannelMap { } ChannelMap; static void SetChannelMap(const enum Channel *devchans, ChannelConfig *ambicoeffs, - const ChannelMap *chanmap, size_t count, ALuint *outcount, + const ChannelMap *chanmap, size_t count, ALsizei *outcount, ALboolean isfuma) { const ALsizei *acnmap = isfuma ? FuMa2ACN : ACN2ACN; const ALfloat *n3dscale = isfuma ? FuMa2N3DScale : UnitScale; size_t j, k; - ALuint i; + ALsizei i; for(i = 0;i < MAX_OUTPUT_CHANNELS && devchans[i] != InvalidChannel;i++) { diff --git a/OpenAL32/Include/alAuxEffectSlot.h b/OpenAL32/Include/alAuxEffectSlot.h index 70fcac5c..40ff1393 100644 --- a/OpenAL32/Include/alAuxEffectSlot.h +++ b/OpenAL32/Include/alAuxEffectSlot.h @@ -18,7 +18,7 @@ typedef struct ALeffectState { const struct ALeffectStateVtable *vtbl; ALfloat (*OutBuffer)[BUFFERSIZE]; - ALuint OutChannels; + ALsizei OutChannels; } ALeffectState; void ALeffectState_Construct(ALeffectState *state); @@ -120,7 +120,7 @@ typedef struct ALeffectslot { /* Self ID */ ALuint id; - ALuint NumChannels; + ALsizei NumChannels; BFChannelConfig ChanMap[MAX_EFFECT_CHANNELS]; /* Wet buffer configuration is ACN channel order with N3D scaling: * * Channel 0 is the unattenuated mono signal. diff --git a/OpenAL32/Include/alBuffer.h b/OpenAL32/Include/alBuffer.h index e99af050..062be452 100644 --- a/OpenAL32/Include/alBuffer.h +++ b/OpenAL32/Include/alBuffer.h @@ -36,9 +36,9 @@ enum UserFmtChannels { UserFmtBFormat3D = AL_BFORMAT3D_SOFT, /* WXYZ */ }; -ALuint BytesFromUserFmt(enum UserFmtType type); -ALuint ChannelsFromUserFmt(enum UserFmtChannels chans); -inline ALuint FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type) +ALsizei BytesFromUserFmt(enum UserFmtType type); +ALsizei ChannelsFromUserFmt(enum UserFmtChannels chans); +inline ALsizei FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type) { return ChannelsFromUserFmt(chans) * BytesFromUserFmt(type); } @@ -63,9 +63,9 @@ enum FmtChannels { }; #define MAX_INPUT_CHANNELS (8) -ALuint BytesFromFmt(enum FmtType type); -ALuint ChannelsFromFmt(enum FmtChannels chans); -inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type) +ALsizei BytesFromFmt(enum FmtType type); +ALsizei ChannelsFromFmt(enum FmtChannels chans); +inline ALsizei FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type) { return ChannelsFromFmt(chans) * BytesFromFmt(type); } @@ -87,8 +87,8 @@ typedef struct ALbuffer { ALsizei OriginalSize; ALsizei OriginalAlign; - ALsizei LoopStart; - ALsizei LoopEnd; + ALsizei LoopStart; + ALsizei LoopEnd; ATOMIC(ALsizei) UnpackAlign; ATOMIC(ALsizei) PackAlign; diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index fca98be9..fd90a49a 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -499,9 +499,9 @@ enum DevFmtChannels { }; #define MAX_OUTPUT_CHANNELS (16) -ALuint BytesFromDevFmt(enum DevFmtType type); -ALuint ChannelsFromDevFmt(enum DevFmtChannels chans); -inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type) +ALsizei BytesFromDevFmt(enum DevFmtType type); +ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans); +inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type) { return ChannelsFromDevFmt(chans) * BytesFromDevFmt(type); } @@ -682,20 +682,20 @@ struct ALCdevice_struct * first-order, 9 for second-order, etc). If the count is 0, Ambi.Map * is used instead to map each output to a coefficient index. */ - ALuint CoeffCount; + ALsizei CoeffCount; ALfloat (*Buffer)[BUFFERSIZE]; - ALuint NumChannels; + ALsizei NumChannels; } Dry; /* First-order ambisonics output, to be upsampled to the dry buffer if different. */ struct { AmbiConfig Ambi; /* Will only be 4 or 0. */ - ALuint CoeffCount; + ALsizei CoeffCount; ALfloat (*Buffer)[BUFFERSIZE]; - ALuint NumChannels; + ALsizei NumChannels; } FOAOut; /* "Real" output, which will be written to the device buffer. May alias the @@ -705,7 +705,7 @@ struct ALCdevice_struct enum Channel ChannelName[MAX_OUTPUT_CHANNELS]; ALfloat (*Buffer)[BUFFERSIZE]; - ALuint NumChannels; + ALsizei NumChannels; } RealOut; /* Running count of the mixer invocations, in 31.1 fixed point. This diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h index 8b793102..4f04efe2 100644 --- a/OpenAL32/Include/alSource.h +++ b/OpenAL32/Include/alSource.h @@ -96,12 +96,12 @@ typedef struct ALvoice { struct { ALfloat (*Buffer)[BUFFERSIZE]; - ALuint Channels; + ALsizei Channels; } DirectOut; struct { ALfloat (*Buffer)[BUFFERSIZE]; - ALuint Channels; + ALsizei Channels; } SendOut[MAX_SENDS]; struct { @@ -194,8 +194,8 @@ typedef struct ALsource { ATOMIC(ALboolean) looping; /** Current buffer sample info. */ - ALuint NumChannels; - ALuint SampleSize; + ALsizei NumChannels; + ALsizei SampleSize; ALenum NeedsUpdate; diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h index 21b787d2..dba167d4 100644 --- a/OpenAL32/Include/alu.h +++ b/OpenAL32/Include/alu.h @@ -313,8 +313,8 @@ void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat else \ ComputeAmbientGainsBF((b).Ambi.Map, (b).NumChannels, g, o); \ } while (0) -void ComputeAmbientGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]); -void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALuint numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]); +void ComputeAmbientGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]); +void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]); /** * ComputePanningGains @@ -328,8 +328,8 @@ void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALuint numchans, ALfl else \ ComputePanningGainsBF((b).Ambi.Map, (b).NumChannels, c, g, o); \ } while (0) -void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, ALuint numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]); -void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALuint numchans, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]); +void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALsizei numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]); +void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]); /** * ComputeFirstOrderGains @@ -344,11 +344,11 @@ void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALuint numchans, cons else \ ComputeFirstOrderGainsBF((b).Ambi.Map, (b).NumChannels, m, g, o); \ } while (0) -void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]); -void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALuint numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]); +void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]); +void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]); -ALvoid MixSource(struct ALvoice *voice, struct ALsource *source, ALCdevice *Device, ALuint SamplesToDo); +ALvoid MixSource(struct ALvoice *voice, struct ALsource *source, ALCdevice *Device, ALsizei SamplesToDo); ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size); /* Caller must lock the device. */ diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.c index 24470d64..45a8cb5b 100644 --- a/OpenAL32/alBuffer.c +++ b/OpenAL32/alBuffer.c @@ -42,8 +42,8 @@ extern inline void LockBuffersWrite(ALCdevice *device); extern inline void UnlockBuffersWrite(ALCdevice *device); extern inline struct ALbuffer *LookupBuffer(ALCdevice *device, ALuint id); extern inline struct ALbuffer *RemoveBuffer(ALCdevice *device, ALuint id); -extern inline ALuint FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type); -extern inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type); +extern inline ALsizei FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type); +extern inline ALsizei FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type); static ALboolean IsValidType(ALenum type); static ALboolean IsValidChannels(ALenum channels); @@ -145,7 +145,7 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi ALCcontext *context; ALbuffer *albuf; ALenum newformat = AL_NONE; - ALuint framesize; + ALsizei framesize; ALsizei align; ALenum err; @@ -293,9 +293,9 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, cons ALCdevice *device; ALCcontext *context; ALbuffer *albuf; - ALuint byte_align; - ALuint channels; - ALuint bytes; + ALsizei byte_align; + ALsizei channels; + ALsizei bytes; ALsizei align; context = GetContextRef(); @@ -1074,7 +1074,7 @@ ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, } -ALuint BytesFromUserFmt(enum UserFmtType type) +ALsizei BytesFromUserFmt(enum UserFmtType type) { switch(type) { @@ -1095,7 +1095,7 @@ ALuint BytesFromUserFmt(enum UserFmtType type) } return 0; } -ALuint ChannelsFromUserFmt(enum UserFmtChannels chans) +ALsizei ChannelsFromUserFmt(enum UserFmtChannels chans) { switch(chans) { @@ -1190,7 +1190,7 @@ static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, return AL_FALSE; } -ALuint BytesFromFmt(enum FmtType type) +ALsizei BytesFromFmt(enum FmtType type) { switch(type) { @@ -1200,7 +1200,7 @@ ALuint BytesFromFmt(enum FmtType type) } return 0; } -ALuint ChannelsFromFmt(enum FmtChannels chans) +ALsizei ChannelsFromFmt(enum FmtChannels chans) { switch(chans) { -- cgit v1.2.3 From 67ffdf7a78ae3e48b1fbdd866ad7c2add7e5b6fd Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 26 Jan 2017 18:23:29 -0800 Subject: Try to use the system sample rate with Android --- Alc/backends/opensl.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 6 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 0796c49a..32f6fa7d 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -22,9 +22,11 @@ #include "config.h" #include +#include #include "alMain.h" #include "alu.h" +#include "compat.h" #include "threads.h" #include @@ -231,16 +233,64 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device) SLDataFormat_PCM format_pcm; SLDataSource audioSrc; SLDataSink audioSnk; + ALuint sampleRate; SLInterfaceID id; - SLboolean req; SLresult result; + SLboolean req; + if((Device->Flags&DEVICE_FREQUENCY_REQUEST)) + sampleRate = Device->Frequency; + else + { + JNIEnv *env = Android_GetJNIEnv(); + + /* Get necessary stuff for using java.lang.Integer, + * android.content.Context, and android.media.AudioManager. + */ + jclass int_cls = JCALL(env,FindClass)("java/lang/Integer"); + jmethodID int_parseint = JCALL(env,GetStaticMethodID)(int_cls, + "parseInt", "(Ljava/lang/String;)I" + ); + + jclass ctx_cls = (*env)->FindClass(env, "android/content/Context"); + jfieldID ctx_audsvc = (*env)->GetStaticFieldID(env, ctx_cls, + "AUDIO_SERVICE", "Ljava/lang/String;" + ); + jmethodID ctx_getSysSvc = (*env)->GetMethodID(env, ctx_cls, + "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;" + ); + + jclass audmgr_cls = JCALL(env,FindClass)("android/media/AudioManager"); + jfieldID audmgr_prop_out_srate = JCALL(env,GetStaticFieldID)(audmgr_cls, + "PROPERTY_OUTPUT_SAMPLE_RATE", "Ljava/lang/String;" + ); + jmethodID audmgr_getproperty = JCALL(env,GetMethodID)(audmgr_cls, + "getProperty", "(Ljava/lang/String;)Ljava/lang/Object;" + ); + + /* Now make the calls. */ + //AudioManager audMgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE); + jobject audMgr = JCALL(env,CallStaticObjectMethod)(ctx_cls, ctx_getSysSvc, + JCALL(env,GetStaticObjectField)(ctx_cls, ctx_audsvc) + ); + + //String srateStr = audMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE); + jstring srateStr = JCALL(env,CallObjectMethod)(audMgr, audmgr_getproperty, + JCALL(env,GetStaticObjectField)(audmgr_cls, audmgr_prop_out_srate) + ); + + //int sampleRate = Integer.parseInt(srateStr); + sampleRate = JCALL(env,CallStaticIntMethod)(int_cls, int_parseint, srateStr); + + if(!sampleRate) sampleRate = Device->Frequency; + else sampleRate = maxu(sampleRate, MIN_OUTPUT_RATE); + } - Device->UpdateSize = (ALuint64)Device->UpdateSize * 44100 / Device->Frequency; - Device->UpdateSize = Device->UpdateSize * Device->NumUpdates / 2; - Device->NumUpdates = 2; - - Device->Frequency = 44100; + if(sampleRate != Device->Frequency) + { + Device->NumUpdates = Device->NumUpdates * sampleRate / Device->Frequency; + Device->Frequency = sampleRate; + } Device->FmtChans = DevFmtStereo; Device->FmtType = DevFmtShort; -- cgit v1.2.3 From 19e96c6fefa3a6e946c5f82ee8311917caeb6545 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 27 Jan 2017 01:46:44 -0800 Subject: Round and clamp the scaled update count with opensl --- Alc/backends/opensl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Alc/backends') diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 32f6fa7d..84e73f7b 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -282,13 +282,16 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device) //int sampleRate = Integer.parseInt(srateStr); sampleRate = JCALL(env,CallStaticIntMethod)(int_cls, int_parseint, srateStr); + TRACE("Got system sample rate %uhz\n", sampleRate); if(!sampleRate) sampleRate = Device->Frequency; else sampleRate = maxu(sampleRate, MIN_OUTPUT_RATE); } if(sampleRate != Device->Frequency) { - Device->NumUpdates = Device->NumUpdates * sampleRate / Device->Frequency; + Device->NumUpdates = (Device->NumUpdates*sampleRate + (Device->Frequency>>1)) / + Device->Frequency; + Device->NumUpdates = maxu(Device->NumUpdates, 2); Device->Frequency = sampleRate; } Device->FmtChans = DevFmtStereo; -- cgit v1.2.3 From 6b2297b5080ca5ba56759ca2f28206c9af277d42 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 27 Jan 2017 15:42:06 -0800 Subject: Add more traces for the Java calls being made --- Alc/backends/opensl.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 84e73f7b..c1065692 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -251,6 +251,7 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device) jmethodID int_parseint = JCALL(env,GetStaticMethodID)(int_cls, "parseInt", "(Ljava/lang/String;)I" ); + TRACE("Integer: %p, parseInt: %p\n", int_cls, int_parseint); jclass ctx_cls = (*env)->FindClass(env, "android/content/Context"); jfieldID ctx_audsvc = (*env)->GetStaticFieldID(env, ctx_cls, @@ -259,6 +260,8 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device) jmethodID ctx_getSysSvc = (*env)->GetMethodID(env, ctx_cls, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;" ); + TRACE("Context: %p, AUDIO_SERVICE: %p, getSystemService: %p\n", + ctx_cls, ctx_audsvc, ctx_getSysSvc); jclass audmgr_cls = JCALL(env,FindClass)("android/media/AudioManager"); jfieldID audmgr_prop_out_srate = JCALL(env,GetStaticFieldID)(audmgr_cls, @@ -267,22 +270,34 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device) jmethodID audmgr_getproperty = JCALL(env,GetMethodID)(audmgr_cls, "getProperty", "(Ljava/lang/String;)Ljava/lang/Object;" ); + TRACE("AudioManager: %p, PROPERTY_OUTPUT_SAMPLE_RATE: %p, getProperty: %p\n", + audmgr_cls, audmgr_prop_out_srate, audmgr_getproperty); + + const char *strchars; + jstring strobj; /* Now make the calls. */ //AudioManager audMgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE); - jobject audMgr = JCALL(env,CallStaticObjectMethod)(ctx_cls, ctx_getSysSvc, - JCALL(env,GetStaticObjectField)(ctx_cls, ctx_audsvc) - ); + strobj = JCALL(env,GetStaticObjectField)(ctx_cls, ctx_audsvc); + jobject audMgr = JCALL(env,CallStaticObjectMethod)(ctx_cls, ctx_getSysSvc, strobj); + strchars = JCALL(env,GetStringUTFChars)(strobj, NULL); + TRACE("Context.getSystemService(%s) = %p\n", strchars, audMgr); + JCALL(env,ReleaseStringUTFChars)(strobj, strchars); //String srateStr = audMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE); - jstring srateStr = JCALL(env,CallObjectMethod)(audMgr, audmgr_getproperty, - JCALL(env,GetStaticObjectField)(audmgr_cls, audmgr_prop_out_srate) - ); + strobj = JCALL(env,GetStaticObjectField)(audmgr_cls, audmgr_prop_out_srate); + jstring srateStr = JCALL(env,CallObjectMethod)(audMgr, audmgr_getproperty, strobj); + strchars = JCALL(env,GetStringUTFChars)(strobj, NULL); + TRACE("audMgr.getProperty(%s) = %p\n", strchars, srateStr); + JCALL(env,ReleaseStringUTFChars)(strobj, strchars); //int sampleRate = Integer.parseInt(srateStr); sampleRate = JCALL(env,CallStaticIntMethod)(int_cls, int_parseint, srateStr); - TRACE("Got system sample rate %uhz\n", sampleRate); + strchars = JCALL(env,GetStringUTFChars)(srateStr, NULL); + TRACE("Got system sample rate %uhz (%s)\n", sampleRate, strchars); + JCALL(env,ReleaseStringUTFChars)(srateStr, strchars); + if(!sampleRate) sampleRate = Device->Frequency; else sampleRate = maxu(sampleRate, MIN_OUTPUT_RATE); } -- cgit v1.2.3 From 2c1791752aebea9f2cf83df155db607eaeeb2046 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 2 Feb 2017 06:14:01 -0800 Subject: Android's AudioManager.getProperty(String) returns a String --- Alc/backends/opensl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Alc/backends') diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index c1065692..51fe11f6 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -268,7 +268,7 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device) "PROPERTY_OUTPUT_SAMPLE_RATE", "Ljava/lang/String;" ); jmethodID audmgr_getproperty = JCALL(env,GetMethodID)(audmgr_cls, - "getProperty", "(Ljava/lang/String;)Ljava/lang/Object;" + "getProperty", "(Ljava/lang/String;)Ljava/lang/String;" ); TRACE("AudioManager: %p, PROPERTY_OUTPUT_SAMPLE_RATE: %p, getProperty: %p\n", audmgr_cls, audmgr_prop_out_srate, audmgr_getproperty); -- cgit v1.2.3 From 428cde5dc26191871111e1edbea85ade952898aa Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 3 Feb 2017 09:41:21 -0800 Subject: Call getSystemService as a non-static function --- Alc/backends/opensl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 51fe11f6..1e4bcb06 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -253,11 +253,11 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device) ); TRACE("Integer: %p, parseInt: %p\n", int_cls, int_parseint); - jclass ctx_cls = (*env)->FindClass(env, "android/content/Context"); - jfieldID ctx_audsvc = (*env)->GetStaticFieldID(env, ctx_cls, + jclass ctx_cls = JCALL(env,FindClass)("android/content/Context"); + jfieldID ctx_audsvc = JCALL(env,GetStaticFieldID)(ctx_cls, "AUDIO_SERVICE", "Ljava/lang/String;" ); - jmethodID ctx_getSysSvc = (*env)->GetMethodID(env, ctx_cls, + jmethodID ctx_getSysSvc = JCALL(env,GetMethodID)(ctx_cls, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;" ); TRACE("Context: %p, AUDIO_SERVICE: %p, getSystemService: %p\n", @@ -279,7 +279,7 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device) /* Now make the calls. */ //AudioManager audMgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE); strobj = JCALL(env,GetStaticObjectField)(ctx_cls, ctx_audsvc); - jobject audMgr = JCALL(env,CallStaticObjectMethod)(ctx_cls, ctx_getSysSvc, strobj); + jobject audMgr = JCALL(env,CallObjectMethod)(ctx_cls, ctx_getSysSvc, strobj); strchars = JCALL(env,GetStringUTFChars)(strobj, NULL); TRACE("Context.getSystemService(%s) = %p\n", strchars, audMgr); JCALL(env,ReleaseStringUTFChars)(strobj, strchars); -- cgit v1.2.3 From af362c2d05097fce816b5c5d911d6650eb6bef37 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 5 Feb 2017 14:25:17 -0800 Subject: Fix for NULL JNIEnv Which can happen with native-only apps --- Alc/ALc.c | 6 ++++++ Alc/backends/opensl.c | 8 +++----- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index 91ff79af..39e29f9f 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -1179,6 +1179,12 @@ static void CleanupJNIEnv(void* UNUSED(ptr)) void *Android_GetJNIEnv(void) { + if(!gJavaVM) + { + WARN("gJavaVM is NULL!\n"); + return NULL; + } + /* http://developer.android.com/guide/practices/jni.html * * All threads are Linux threads, scheduled by the kernel. They're usually diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 1e4bcb06..08530d95 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -237,13 +237,11 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device) SLInterfaceID id; SLresult result; SLboolean req; + JNIEnv *env; - if((Device->Flags&DEVICE_FREQUENCY_REQUEST)) - sampleRate = Device->Frequency; - else + sampleRate = Device->Frequency; + if(!(Device->Flags&DEVICE_FREQUENCY_REQUEST) && (env=Android_GetJNIEnv()) != NULL) { - JNIEnv *env = Android_GetJNIEnv(); - /* Get necessary stuff for using java.lang.Integer, * android.content.Context, and android.media.AudioManager. */ -- cgit v1.2.3 From 9f10ae466c089388db1bd9ff236eec50ed98b157 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 7 Feb 2017 06:25:11 -0800 Subject: Convert the OpenSL backend to the new backend API This also removes the buffer queue callback's call to aluMixData, which could potentially block on a mutex. --- Alc/ALc.c | 2 +- Alc/backends/base.h | 1 + Alc/backends/opensl.c | 608 +++++++++++++++++++++++++++++++++++--------------- 3 files changed, 434 insertions(+), 177 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index 39e29f9f..94e19267 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -99,7 +99,7 @@ static struct BackendInfo BackendList[] = { { "port", ALCportBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, #endif #ifdef HAVE_OPENSL - { "opensl", NULL, alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs }, + { "opensl", ALCopenslBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, #endif { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, diff --git a/Alc/backends/base.h b/Alc/backends/base.h index 94177405..4f398047 100644 --- a/Alc/backends/base.h +++ b/Alc/backends/base.h @@ -145,6 +145,7 @@ ALCbackendFactory *ALCmmdevBackendFactory_getFactory(void); ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void); ALCbackendFactory *ALCwinmmBackendFactory_getFactory(void); ALCbackendFactory *ALCportBackendFactory_getFactory(void); +ALCbackendFactory *ALCopenslBackendFactory_getFactory(void); ALCbackendFactory *ALCnullBackendFactory_getFactory(void); ALCbackendFactory *ALCwaveBackendFactory_getFactory(void); ALCbackendFactory *ALCloopbackFactory_getFactory(void); diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 08530d95..878519bd 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -29,33 +29,17 @@ #include "compat.h" #include "threads.h" +#include "backends/base.h" + #include #include +#include /* Helper macros */ #define VCALL(obj, func) ((*(obj))->func((obj), EXTRACT_VCALL_ARGS #define VCALL0(obj, func) ((*(obj))->func((obj) EXTRACT_VCALL_ARGS -typedef struct { - /* engine interfaces */ - SLObjectItf engineObject; - SLEngineItf engine; - - /* output mix interfaces */ - SLObjectItf outputMix; - - /* buffer queue player interfaces */ - SLObjectItf bufferQueueObject; - - void *buffer; - ALuint bufferSize; - ALuint curBuffer; - - ALuint frameSize; -} osl_data; - - static const ALCchar opensl_device[] = "OpenSL"; @@ -89,6 +73,26 @@ static SLuint32 GetChannelMask(enum DevFmtChannels chans) return 0; } +#ifdef SL_DATAFORMAT_PCM_EX +static SLuint32 GetTypeRepresentation(enum DevFmtType type) +{ + switch(type) + { + case DevFmtUByte: + case DevFmtUShort: + case DevFmtUInt: + return SL_PCM_REPRESENTATION_UNSIGNED_INT; + case DevFmtByte: + case DevFmtShort: + case DevFmtInt: + return SL_PCM_REPRESENTATION_SIGNED_INT; + case DevFmtFloat: + return SL_PCM_REPRESENTATION_FLOAT; + } + return 0; +} +#endif + static const char *res_str(SLresult result) { switch(result) @@ -128,120 +132,315 @@ static const char *res_str(SLresult result) ERR("%s: %s\n", (s), res_str((x))); \ } while(0) + +typedef struct ALCopenslPlayback { + DERIVE_FROM_TYPE(ALCbackend); + + /* engine interfaces */ + SLObjectItf mEngineObj; + SLEngineItf mEngine; + + /* output mix interfaces */ + SLObjectItf mOutputMix; + + /* buffer queue player interfaces */ + SLObjectItf mBufferQueueObj; + + ll_ringbuffer_t *mRing; + alcnd_t mCond; + + ALsizei mFrameSize; + + ATOMIC(ALboolean) mKillNow; + althrd_t mThread; +} ALCopenslPlayback; + +static void ALCopenslPlayback_process(SLAndroidSimpleBufferQueueItf bq, void *context); +static int ALCopenslPlayback_mixerProc(void *arg); + +static void ALCopenslPlayback_Construct(ALCopenslPlayback *self, ALCdevice *device); +static void ALCopenslPlayback_Destruct(ALCopenslPlayback *self); +static ALCenum ALCopenslPlayback_open(ALCopenslPlayback *self, const ALCchar *name); +static void ALCopenslPlayback_close(ALCopenslPlayback *self); +static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self); +static ALCboolean ALCopenslPlayback_start(ALCopenslPlayback *self); +static void ALCopenslPlayback_stop(ALCopenslPlayback *self); +static DECLARE_FORWARD2(ALCopenslPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint) +static DECLARE_FORWARD(ALCopenslPlayback, ALCbackend, ALCuint, availableSamples) +static ClockLatency ALCopenslPlayback_getClockLatency(ALCopenslPlayback *self); +static DECLARE_FORWARD(ALCopenslPlayback, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCopenslPlayback, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCopenslPlayback) + +DEFINE_ALCBACKEND_VTABLE(ALCopenslPlayback); + + +static void ALCopenslPlayback_Construct(ALCopenslPlayback *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCopenslPlayback, ALCbackend, self); + + self->mEngineObj = NULL; + self->mEngine = NULL; + self->mOutputMix = NULL; + self->mBufferQueueObj = NULL; + + self->mRing = NULL; + alcnd_init(&self->mCond); + + self->mFrameSize = 0; + + ATOMIC_INIT(&self->mKillNow, AL_FALSE); +} + +static void ALCopenslPlayback_Destruct(ALCopenslPlayback* self) +{ + if(self->mBufferQueueObj != NULL) + VCALL0(self->mBufferQueueObj,Destroy)(); + self->mBufferQueueObj = NULL; + + if(self->mOutputMix != NULL) + VCALL0(self->mOutputMix,Destroy)(); + self->mOutputMix = NULL; + + if(self->mEngineObj != NULL) + VCALL0(self->mEngineObj,Destroy)(); + self->mEngineObj = NULL; + self->mEngine = NULL; + + ll_ringbuffer_free(self->mRing); + self->mRing = NULL; + + alcnd_destroy(&self->mCond); + + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + + /* this callback handler is called every time a buffer finishes playing */ -static void opensl_callback(SLAndroidSimpleBufferQueueItf bq, void *context) +static void ALCopenslPlayback_process(SLAndroidSimpleBufferQueueItf UNUSED(bq), void *context) { - ALCdevice *Device = context; - osl_data *data = Device->ExtraData; - ALvoid *buf; + ALCopenslPlayback *self = context; + + /* A note on the ringbuffer usage: The buffer queue seems to hold on to the + * pointer passed to the Enqueue method, rather than copying the audio. + * Consequently, the ringbuffer contains the audio that is currently queued + * and waiting to play. This process() callback is called when a buffer is + * finished, so we simply move the read pointer up to indicate the space is + * available for writing again, and wake up the mixer thread to mix and + * queue more audio. + */ + ll_ringbuffer_read_advance(self->mRing, 1); + + alcnd_signal(&self->mCond); +} + + +static int ALCopenslPlayback_mixerProc(void *arg) +{ + ALCopenslPlayback *self = arg; + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + SLAndroidSimpleBufferQueueItf bufferQueue; + ll_ringbuffer_data_t data[2]; + SLPlayItf player; SLresult result; + size_t padding; - buf = (ALbyte*)data->buffer + data->curBuffer*data->bufferSize; - aluMixData(Device, buf, data->bufferSize/data->frameSize); + SetRTPriority(); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); - result = VCALL(bq,Enqueue)(buf, data->bufferSize); - PRINTERR(result, "bq->Enqueue"); + result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_BUFFERQUEUE, &bufferQueue); + PRINTERR(result, "bufferQueue->GetInterface SL_IID_BUFFERQUEUE"); + if(SL_RESULT_SUCCESS == result) + { + result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_PLAY, &player); + PRINTERR(result, "bufferQueue->GetInterface SL_IID_PLAY"); + } + if(SL_RESULT_SUCCESS != result) + { + ALCopenslPlayback_lock(self); + aluHandleDisconnect(device); + ALCopenslPlayback_unlock(self); + return 1; + } + + /* NOTE: The ringbuffer will be larger than the desired buffer metrics. + * Calculate the amount of extra space so we know how much to keep unused. + */ + padding = ll_ringbuffer_write_space(self->mRing) - device->NumUpdates; + + ALCopenslPlayback_lock(self); + while(ATOMIC_LOAD_SEQ(&self->mKillNow) == AL_FALSE && device->Connected) + { + size_t todo, len0, len1; + + if(ll_ringbuffer_write_space(self->mRing) <= padding) + { + SLuint32 state = 0; + + result = VCALL(player,GetPlayState)(&state); + PRINTERR(result, "player->GetPlayState"); + if(SL_RESULT_SUCCESS == result && state != SL_PLAYSTATE_PLAYING) + { + result = VCALL(player,SetPlayState)(SL_PLAYSTATE_PLAYING); + PRINTERR(result, "player->SetPlayState"); + } + if(SL_RESULT_SUCCESS != result) + { + aluHandleDisconnect(device); + break; + } + + /* NOTE: Unfortunately, there is an unavoidable race condition + * here. It's possible for the process() method to run, updating + * the read pointer and signaling the condition variable, in + * between checking the write size and waiting for the condition + * variable here. This will cause alcnd_wait to wait until the + * *next* process() invocation signals the condition variable + * again. + * + * However, this should only happen if the mixer is running behind + * anyway (as ideally we'll be asleep in alcnd_wait by the time the + * process() method is invoked), so this behavior is not completely + * unwarranted. It's unfortunate since it'll be wasting time + * sleeping that could be used to catch up, but there's no way + * around it without blocking in the process() method. + */ + if(ll_ringbuffer_write_space(self->mRing) <= padding) + { + alcnd_wait(&self->mCond, &STATIC_CAST(ALCbackend,self)->mMutex); + continue; + } + } + + ll_ringbuffer_get_write_vector(self->mRing, data); + todo = data[0].len+data[1].len - padding; + + len0 = minu(todo, data[0].len); + len1 = minu(todo-len0, data[1].len); + + aluMixData(device, data[0].buf, len0*device->UpdateSize); + for(size_t i = 0;i < len0;i++) + { + result = VCALL(bufferQueue,Enqueue)(data[0].buf, device->UpdateSize*self->mFrameSize); + PRINTERR(result, "bufferQueue->Enqueue"); + if(SL_RESULT_SUCCESS == result) + ll_ringbuffer_write_advance(self->mRing, 1); + + data[0].buf += device->UpdateSize*self->mFrameSize; + } + + if(len1 > 0) + { + aluMixData(device, data[1].buf, len1*device->UpdateSize); + for(size_t i = 0;i < len1;i++) + { + result = VCALL(bufferQueue,Enqueue)(data[1].buf, device->UpdateSize*self->mFrameSize); + PRINTERR(result, "bufferQueue->Enqueue"); + if(SL_RESULT_SUCCESS == result) + ll_ringbuffer_write_advance(self->mRing, 1); + + data[1].buf += device->UpdateSize*self->mFrameSize; + } + } + } + ALCopenslPlayback_unlock(self); - data->curBuffer = (data->curBuffer+1) % Device->NumUpdates; + return 0; } -static ALCenum opensl_open_playback(ALCdevice *Device, const ALCchar *deviceName) +static ALCenum ALCopenslPlayback_open(ALCopenslPlayback *self, const ALCchar *name) { - osl_data *data = NULL; + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; SLresult result; - if(!deviceName) - deviceName = opensl_device; - else if(strcmp(deviceName, opensl_device) != 0) + if(!name) + name = opensl_device; + else if(strcmp(name, opensl_device) != 0) return ALC_INVALID_VALUE; - data = calloc(1, sizeof(*data)); - if(!data) - return ALC_OUT_OF_MEMORY; - // create engine - result = slCreateEngine(&data->engineObject, 0, NULL, 0, NULL, NULL); + result = slCreateEngine(&self->mEngineObj, 0, NULL, 0, NULL, NULL); PRINTERR(result, "slCreateEngine"); if(SL_RESULT_SUCCESS == result) { - result = VCALL(data->engineObject,Realize)(SL_BOOLEAN_FALSE); + result = VCALL(self->mEngineObj,Realize)(SL_BOOLEAN_FALSE); PRINTERR(result, "engine->Realize"); } if(SL_RESULT_SUCCESS == result) { - result = VCALL(data->engineObject,GetInterface)(SL_IID_ENGINE, &data->engine); + result = VCALL(self->mEngineObj,GetInterface)(SL_IID_ENGINE, &self->mEngine); PRINTERR(result, "engine->GetInterface"); } if(SL_RESULT_SUCCESS == result) { - result = VCALL(data->engine,CreateOutputMix)(&data->outputMix, 0, NULL, NULL); + result = VCALL(self->mEngine,CreateOutputMix)(&self->mOutputMix, 0, NULL, NULL); PRINTERR(result, "engine->CreateOutputMix"); } if(SL_RESULT_SUCCESS == result) { - result = VCALL(data->outputMix,Realize)(SL_BOOLEAN_FALSE); + result = VCALL(self->mOutputMix,Realize)(SL_BOOLEAN_FALSE); PRINTERR(result, "outputMix->Realize"); } if(SL_RESULT_SUCCESS != result) { - if(data->outputMix != NULL) - VCALL0(data->outputMix,Destroy)(); - data->outputMix = NULL; + if(self->mOutputMix != NULL) + VCALL0(self->mOutputMix,Destroy)(); + self->mOutputMix = NULL; - if(data->engineObject != NULL) - VCALL0(data->engineObject,Destroy)(); - data->engineObject = NULL; - data->engine = NULL; + if(self->mEngineObj != NULL) + VCALL0(self->mEngineObj,Destroy)(); + self->mEngineObj = NULL; + self->mEngine = NULL; - free(data); return ALC_INVALID_VALUE; } - al_string_copy_cstr(&Device->DeviceName, deviceName); - Device->ExtraData = data; + al_string_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } - -static void opensl_close_playback(ALCdevice *Device) +static void ALCopenslPlayback_close(ALCopenslPlayback *self) { - osl_data *data = Device->ExtraData; - - if(data->bufferQueueObject != NULL) - VCALL0(data->bufferQueueObject,Destroy)(); - data->bufferQueueObject = NULL; - - VCALL0(data->outputMix,Destroy)(); - data->outputMix = NULL; + if(self->mBufferQueueObj != NULL) + VCALL0(self->mBufferQueueObj,Destroy)(); + self->mBufferQueueObj = NULL; - VCALL0(data->engineObject,Destroy)(); - data->engineObject = NULL; - data->engine = NULL; + VCALL0(self->mOutputMix,Destroy)(); + self->mOutputMix = NULL; - free(data); - Device->ExtraData = NULL; + VCALL0(self->mEngineObj,Destroy)(); + self->mEngineObj = NULL; + self->mEngine = NULL; } -static ALCboolean opensl_reset_playback(ALCdevice *Device) +static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self) { - osl_data *data = Device->ExtraData; + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; SLDataLocator_AndroidSimpleBufferQueue loc_bufq; SLDataLocator_OutputMix loc_outmix; - SLDataFormat_PCM format_pcm; SLDataSource audioSrc; SLDataSink audioSnk; ALuint sampleRate; - SLInterfaceID id; + SLInterfaceID ids[2]; + SLboolean reqs[2]; SLresult result; - SLboolean req; JNIEnv *env; - sampleRate = Device->Frequency; - if(!(Device->Flags&DEVICE_FREQUENCY_REQUEST) && (env=Android_GetJNIEnv()) != NULL) + if(self->mBufferQueueObj != NULL) + VCALL0(self->mBufferQueueObj,Destroy)(); + self->mBufferQueueObj = NULL; + + sampleRate = device->Frequency; + if(!(device->Flags&DEVICE_FREQUENCY_REQUEST) && (env=Android_GetJNIEnv()) != NULL) { + /* FIXME: Disabled until I figure out how to get the Context needed for + * the getSystemService call. + */ +#if 0 /* Get necessary stuff for using java.lang.Integer, * android.content.Context, and android.media.AudioManager. */ @@ -296,64 +495,99 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device) TRACE("Got system sample rate %uhz (%s)\n", sampleRate, strchars); JCALL(env,ReleaseStringUTFChars)(srateStr, strchars); - if(!sampleRate) sampleRate = Device->Frequency; + if(!sampleRate) sampleRate = device->Frequency; else sampleRate = maxu(sampleRate, MIN_OUTPUT_RATE); +#endif } - if(sampleRate != Device->Frequency) + if(sampleRate != device->Frequency) { - Device->NumUpdates = (Device->NumUpdates*sampleRate + (Device->Frequency>>1)) / - Device->Frequency; - Device->NumUpdates = maxu(Device->NumUpdates, 2); - Device->Frequency = sampleRate; + device->NumUpdates = (device->NumUpdates*sampleRate + (device->Frequency>>1)) / + device->Frequency; + device->NumUpdates = maxu(device->NumUpdates, 2); + device->Frequency = sampleRate; } - Device->FmtChans = DevFmtStereo; - Device->FmtType = DevFmtShort; - SetDefaultWFXChannelOrder(Device); + device->FmtChans = DevFmtStereo; + device->FmtType = DevFmtShort; + SetDefaultWFXChannelOrder(device); + self->mFrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); - id = SL_IID_ANDROIDSIMPLEBUFFERQUEUE; - req = SL_BOOLEAN_TRUE; loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; - loc_bufq.numBuffers = Device->NumUpdates; - + loc_bufq.numBuffers = device->NumUpdates; + +#ifdef SL_DATAFORMAT_PCM_EX + SLDataFormat_PCM_EX format_pcm; + format_pcm.formatType = SL_DATAFORMAT_PCM_EX; + format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans); + format_pcm.sampleRate = 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 = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : + SL_BYTEORDER_BIGENDIAN; + format_pcm.representation = GetTypeRepresentation(device->FmtType); +#else + SLDataFormat_PCM format_pcm; 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.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.channelMask = GetChannelMask(device->FmtChans); format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN; +#endif audioSrc.pLocator = &loc_bufq; audioSrc.pFormat = &format_pcm; loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; - loc_outmix.outputMix = data->outputMix; + loc_outmix.outputMix = self->mOutputMix; audioSnk.pLocator = &loc_outmix; audioSnk.pFormat = NULL; - if(data->bufferQueueObject != NULL) - VCALL0(data->bufferQueueObject,Destroy)(); - data->bufferQueueObject = NULL; + ids[0] = SL_IID_ANDROIDSIMPLEBUFFERQUEUE; + reqs[0] = SL_BOOLEAN_TRUE; + ids[1] = SL_IID_ANDROIDCONFIGURATION; + reqs[1] = SL_BOOLEAN_FALSE; - result = VCALL(data->engine,CreateAudioPlayer)(&data->bufferQueueObject, &audioSrc, &audioSnk, 1, &id, &req); + result = VCALL(self->mEngine,CreateAudioPlayer)(&self->mBufferQueueObj, + &audioSrc, &audioSnk, COUNTOF(ids), ids, reqs + ); PRINTERR(result, "engine->CreateAudioPlayer"); if(SL_RESULT_SUCCESS == result) { - result = VCALL(data->bufferQueueObject,Realize)(SL_BOOLEAN_FALSE); + /* Set the stream type to "media" (games, music, etc), if possible. */ + SLAndroidConfigurationItf config; + result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDCONFIGURATION, &config); + PRINTERR(result, "bufferQueue->GetInterface SL_IID_ANDROIDCONFIGURATION"); + if(SL_RESULT_SUCCESS == result) + { + SLint32 streamType = SL_ANDROID_STREAM_MEDIA; + result = VCALL(config,SetConfiguration)(SL_ANDROID_KEY_STREAM_TYPE, + &streamType, sizeof(streamType) + ); + PRINTERR(result, "config->SetConfiguration"); + } + + /* Clear any error since this was optional. */ + result = SL_RESULT_SUCCESS; + } + if(SL_RESULT_SUCCESS == result) + { + result = VCALL(self->mBufferQueueObj,Realize)(SL_BOOLEAN_FALSE); PRINTERR(result, "bufferQueue->Realize"); } if(SL_RESULT_SUCCESS != result) { - if(data->bufferQueueObject != NULL) - VCALL0(data->bufferQueueObject,Destroy)(); - data->bufferQueueObject = NULL; + if(self->mBufferQueueObj != NULL) + VCALL0(self->mBufferQueueObj,Destroy)(); + self->mBufferQueueObj = NULL; return ALC_FALSE; } @@ -361,64 +595,35 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device) return ALC_TRUE; } -static ALCboolean opensl_start_playback(ALCdevice *Device) +static ALCboolean ALCopenslPlayback_start(ALCopenslPlayback *self) { - osl_data *data = Device->ExtraData; + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; SLAndroidSimpleBufferQueueItf bufferQueue; - SLPlayItf player; SLresult result; - ALuint i; - result = VCALL(data->bufferQueueObject,GetInterface)(SL_IID_BUFFERQUEUE, &bufferQueue); - PRINTERR(result, "bufferQueue->GetInterface"); - if(SL_RESULT_SUCCESS == result) - { - result = VCALL(bufferQueue,RegisterCallback)(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(Device->NumUpdates, 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) - { - ALvoid *buf = (ALbyte*)data->buffer + i*data->bufferSize; - result = VCALL(bufferQueue,Enqueue)(buf, data->bufferSize); - PRINTERR(result, "bufferQueue->Enqueue"); - } - } - data->curBuffer = 0; - if(SL_RESULT_SUCCESS == result) - { - result = VCALL(data->bufferQueueObject,GetInterface)(SL_IID_PLAY, &player); - PRINTERR(result, "bufferQueue->GetInterface"); - } - if(SL_RESULT_SUCCESS == result) - { - result = VCALL(player,SetPlayState)(SL_PLAYSTATE_PLAYING); - PRINTERR(result, "player->SetPlayState"); - } + ll_ringbuffer_free(self->mRing); + /* NOTE: Add an extra update since one period's worth of audio in the ring + * buffer will always be left unfilled because one element of the ring + * buffer will not be writeable, and we only write in period-sized chunks. + */ + self->mRing = ll_ringbuffer_create(device->NumUpdates + 1, + self->mFrameSize*device->UpdateSize); + result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, + &bufferQueue); + PRINTERR(result, "bufferQueue->GetInterface"); if(SL_RESULT_SUCCESS != result) - { - if(data->bufferQueueObject != NULL) - VCALL0(data->bufferQueueObject,Destroy)(); - data->bufferQueueObject = NULL; + return ALC_FALSE; - free(data->buffer); - data->buffer = NULL; - data->bufferSize = 0; + result = VCALL(bufferQueue,RegisterCallback)(ALCopenslPlayback_process, self); + PRINTERR(result, "bufferQueue->RegisterCallback"); + if(SL_RESULT_SUCCESS != result) + return ALC_FALSE; + ATOMIC_STORE_SEQ(&self->mKillNow, AL_FALSE); + if(althrd_create(&self->mThread, ALCopenslPlayback_mixerProc, self) != althrd_success) + { + ERR("Failed to start mixer thread\n"); return ALC_FALSE; } @@ -426,14 +631,27 @@ static ALCboolean opensl_start_playback(ALCdevice *Device) } -static void opensl_stop_playback(ALCdevice *Device) +static void ALCopenslPlayback_stop(ALCopenslPlayback *self) { - osl_data *data = Device->ExtraData; - SLPlayItf player; SLAndroidSimpleBufferQueueItf bufferQueue; + SLPlayItf player; SLresult result; - - result = VCALL(data->bufferQueueObject,GetInterface)(SL_IID_PLAY, &player); + int res; + + if(ATOMIC_EXCHANGE_SEQ(ALboolean, &self->mKillNow, AL_TRUE)) + return; + + /* Lock the backend to ensure we don't flag the mixer to die and signal the + * mixer to wake up in between it checking the flag and going to sleep and + * wait for a wakeup (potentially leading to it never waking back up to see + * the flag). + */ + ALCopenslPlayback_lock(self); + ALCopenslPlayback_unlock(self); + alcnd_signal(&self->mCond); + althrd_join(self->mThread, &res); + + result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_PLAY, &player); PRINTERR(result, "bufferQueue->GetInterface"); if(SL_RESULT_SUCCESS == result) { @@ -441,7 +659,8 @@ static void opensl_stop_playback(ALCdevice *Device) PRINTERR(result, "player->SetPlayState"); } - result = VCALL(data->bufferQueueObject,GetInterface)(SL_IID_BUFFERQUEUE, &bufferQueue); + result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, + &bufferQueue); PRINTERR(result, "bufferQueue->GetInterface"); if(SL_RESULT_SUCCESS == result) { @@ -449,6 +668,11 @@ static void opensl_stop_playback(ALCdevice *Device) PRINTERR(result, "bufferQueue->Clear"); } if(SL_RESULT_SUCCESS == result) + { + result = VCALL(bufferQueue,RegisterCallback)(NULL, NULL); + PRINTERR(result, "bufferQueue->RegisterCallback"); + } + if(SL_RESULT_SUCCESS == result) { SLAndroidSimpleBufferQueueState state; do { @@ -458,45 +682,77 @@ static void opensl_stop_playback(ALCdevice *Device) PRINTERR(result, "bufferQueue->GetState"); } - free(data->buffer); - data->buffer = NULL; - data->bufferSize = 0; + ll_ringbuffer_free(self->mRing); + self->mRing = NULL; } +static ClockLatency ALCopenslPlayback_getClockLatency(ALCopenslPlayback *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + ClockLatency ret; + + ALCopenslPlayback_lock(self); + ret.ClockTime = GetDeviceClockTime(device); + ret.Latency = ll_ringbuffer_read_space(self->mRing) * DEVICE_CLOCK_RES / + device->Frequency; + ALCopenslPlayback_unlock(self); -static const BackendFuncs opensl_funcs = { - opensl_open_playback, - opensl_close_playback, - opensl_reset_playback, - opensl_start_playback, - opensl_stop_playback, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL -}; + return ret; +} -ALCboolean alc_opensl_init(BackendFuncs *func_list) +typedef struct ALCopenslBackendFactory { + DERIVE_FROM_TYPE(ALCbackendFactory); +} ALCopenslBackendFactory; +#define ALCOPENSLBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCopenslBackendFactory, ALCbackendFactory) } } + +static ALCboolean ALCopenslBackendFactory_init(ALCopenslBackendFactory* UNUSED(self)) { - *func_list = opensl_funcs; return ALC_TRUE; } -void alc_opensl_deinit(void) +static void ALCopenslBackendFactory_deinit(ALCopenslBackendFactory* UNUSED(self)) +{ +} + +static ALCboolean ALCopenslBackendFactory_querySupport(ALCopenslBackendFactory* UNUSED(self), ALCbackend_Type type) { + if(type == ALCbackend_Playback) + return ALC_TRUE; + return ALC_FALSE; } -void alc_opensl_probe(enum DevProbe type) +static void ALCopenslBackendFactory_probe(ALCopenslBackendFactory* UNUSED(self), enum DevProbe type) { switch(type) { case ALL_DEVICE_PROBE: AppendAllDevicesList(opensl_device); break; + case CAPTURE_DEVICE_PROBE: break; } } + +static ALCbackend* ALCopenslBackendFactory_createBackend(ALCopenslBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + { + ALCopenslPlayback *backend; + NEW_OBJ(backend, ALCopenslPlayback)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + + return NULL; +} + +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCopenslBackendFactory); + + +ALCbackendFactory *ALCopenslBackendFactory_getFactory(void) +{ + static ALCopenslBackendFactory factory = ALCOPENSLBACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); +} -- cgit v1.2.3 From c771b82a39bcbb29b2ab97b3e592ee96a190e7cc Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 7 Feb 2017 10:29:31 -0800 Subject: Use the correct IID for the opensl buffer queue --- Alc/backends/opensl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 878519bd..a667dc70 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -249,8 +249,9 @@ static int ALCopenslPlayback_mixerProc(void *arg) SetRTPriority(); althrd_setname(althrd_current(), MIXER_THREAD_NAME); - result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_BUFFERQUEUE, &bufferQueue); - PRINTERR(result, "bufferQueue->GetInterface SL_IID_BUFFERQUEUE"); + result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, + &bufferQueue); + PRINTERR(result, "bufferQueue->GetInterface SL_IID_ANDROIDSIMPLEBUFFERQUEUE"); if(SL_RESULT_SUCCESS == result) { result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_PLAY, &player); -- cgit v1.2.3 From d8c42918f46e2439c81c4d4562df8fa7ad2e01fd Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 18 Feb 2017 15:58:15 -0800 Subject: Use select() to wait for audio with OSS and Solaris --- Alc/backends/oss.c | 146 +++++++++++++++++++++++++++++-------------------- Alc/backends/solaris.c | 76 ++++++++++++++++--------- 2 files changed, 137 insertions(+), 85 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 2da096f6..8934181b 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -269,42 +269,64 @@ static int ALCplaybackOSS_mixerProc(void *ptr) { ALCplaybackOSS *self = (ALCplaybackOSS*)ptr; ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - ALint frameSize; + struct timeval timeout; + ALubyte *write_ptr; + ALint frame_size; + ALint to_write; ssize_t wrote; + fd_set wfds; + int sret; SetRTPriority(); althrd_setname(althrd_current(), MIXER_THREAD_NAME); - frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + ALCplaybackOSS_lock(self); while(!ATOMIC_LOAD_SEQ(&self->killNow) && device->Connected) { - ALint len = self->data_size; - ALubyte *WritePtr = self->mix_data; + FD_ZERO(&wfds); + FD_SET(self->fd, &wfds); + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + ALCplaybackOSS_unlock(self); + sret = select(self->fd+1, NULL, &wfds, NULL, &timeout); + ALCplaybackOSS_lock(self); + if(sret < 0) + { + if(errno == EINTR) + continue; + ERR("select failed: %s\n", strerror(errno)); + aluHandleDisconnect(device); + break; + } + else if(sret == 0) + { + WARN("select timeout\n"); + continue; + } - aluMixData(device, WritePtr, len/frameSize); - while(len > 0 && !ATOMIC_LOAD_SEQ(&self->killNow)) + write_ptr = self->mix_data; + to_write = self->data_size; + aluMixData(device, write_ptr, to_write/frame_size); + while(to_write > 0 && !ATOMIC_LOAD_SEQ(&self->killNow)) { - wrote = write(self->fd, WritePtr, len); + wrote = write(self->fd, write_ptr, to_write); if(wrote < 0) { - if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) - { - ERR("write failed: %s\n", strerror(errno)); - ALCplaybackOSS_lock(self); - aluHandleDisconnect(device); - ALCplaybackOSS_unlock(self); - break; - } - - al_nssleep(1000000); - continue; + if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + continue; + ERR("write failed: %s\n", strerror(errno)); + aluHandleDisconnect(device); + break; } - len -= wrote; - WritePtr += wrote; + to_write -= wrote; + write_ptr += wrote; } } + ALCplaybackOSS_unlock(self); return 0; } @@ -492,7 +514,6 @@ typedef struct ALCcaptureOSS { int fd; ll_ringbuffer_t *ring; - ATOMIC(ALenum) doCapture; ATOMIC(ALenum) killNow; althrd_t thread; @@ -520,41 +541,55 @@ static int ALCcaptureOSS_recordProc(void *ptr) { ALCcaptureOSS *self = (ALCcaptureOSS*)ptr; ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - int frameSize; + struct timeval timeout; + int frame_size; + fd_set rfds; ssize_t amt; + int sret; SetRTPriority(); althrd_setname(althrd_current(), RECORD_THREAD_NAME); - frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); while(!ATOMIC_LOAD_SEQ(&self->killNow)) { ll_ringbuffer_data_t vec[2]; - amt = 0; - if(ATOMIC_LOAD_SEQ(&self->doCapture)) + FD_ZERO(&rfds); + FD_SET(self->fd, &rfds); + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + sret = select(self->fd+1, &rfds, NULL, NULL, &timeout); + if(sret < 0) { - ll_ringbuffer_get_write_vector(self->ring, vec); - if(vec[0].len > 0) - { - amt = read(self->fd, vec[0].buf, vec[0].len*frameSize); - if(amt < 0) - { - ERR("read failed: %s\n", strerror(errno)); - ALCcaptureOSS_lock(self); - aluHandleDisconnect(device); - ALCcaptureOSS_unlock(self); - break; - } - ll_ringbuffer_write_advance(self->ring, amt/frameSize); - } + if(errno == EINTR) + continue; + ERR("select failed: %s\n", strerror(errno)); + aluHandleDisconnect(device); + break; } - if(amt == 0) + else if(sret == 0) { - al_nssleep(1000000); + WARN("select timeout\n"); continue; } + + ll_ringbuffer_get_write_vector(self->ring, vec); + if(vec[0].len > 0) + { + amt = read(self->fd, vec[0].buf, vec[0].len*frame_size); + if(amt < 0) + { + ERR("read failed: %s\n", strerror(errno)); + ALCcaptureOSS_lock(self); + aluHandleDisconnect(device); + ALCcaptureOSS_unlock(self); + break; + } + ll_ringbuffer_write_advance(self->ring, amt/frame_size); + } } return 0; @@ -566,7 +601,6 @@ static void ALCcaptureOSS_Construct(ALCcaptureOSS *self, ALCdevice *device) ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCcaptureOSS, ALCbackend, self); - ATOMIC_INIT(&self->doCapture, AL_FALSE); ATOMIC_INIT(&self->killNow, AL_FALSE); } @@ -690,15 +724,6 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) return ALC_OUT_OF_MEMORY; } - if(althrd_create(&self->thread, ALCcaptureOSS_recordProc, self) != althrd_success) - { - ll_ringbuffer_free(self->ring); - self->ring = NULL; - close(self->fd); - self->fd = -1; - return ALC_OUT_OF_MEMORY; - } - al_string_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; @@ -706,11 +731,6 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) static void ALCcaptureOSS_close(ALCcaptureOSS *self) { - int res; - - ATOMIC_STORE_SEQ(&self->killNow, AL_TRUE); - althrd_join(self->thread, &res); - close(self->fd); self->fd = -1; @@ -720,13 +740,23 @@ static void ALCcaptureOSS_close(ALCcaptureOSS *self) static ALCboolean ALCcaptureOSS_start(ALCcaptureOSS *self) { - ATOMIC_STORE_SEQ(&self->doCapture, AL_TRUE); + ATOMIC_STORE_SEQ(&self->killNow, AL_FALSE); + if(althrd_create(&self->thread, ALCcaptureOSS_recordProc, self) != althrd_success) + return ALC_FALSE; return ALC_TRUE; } static void ALCcaptureOSS_stop(ALCcaptureOSS *self) { - ATOMIC_STORE_SEQ(&self->doCapture, AL_FALSE); + int res; + + if(ATOMIC_EXCHANGE_SEQ(ALenum, &self->killNow, AL_TRUE)) + return; + + althrd_join(self->thread, &res); + + if(ioctl(self->fd, SNDCTL_DSP_RESET) != 0) + ERR("Error resetting device: %s\n", strerror(errno)); } static ALCenum ALCcaptureOSS_captureSamples(ALCcaptureOSS *self, ALCvoid *buffer, ALCuint samples) diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c index 792f717a..c70e0b46 100644 --- a/Alc/backends/solaris.c +++ b/Alc/backends/solaris.c @@ -50,7 +50,7 @@ typedef struct ALCsolarisBackend { ALubyte *mix_data; int data_size; - volatile int killNow; + ATOMIC(ALenum) killNow; althrd_t thread; } ALCsolarisBackend; @@ -84,6 +84,7 @@ static void ALCsolarisBackend_Construct(ALCsolarisBackend *self, ALCdevice *devi SET_VTABLE2(ALCsolarisBackend, ALCbackend, self); self->fd = -1; + ATOMIC_INIT(&self->killNow, AL_FALSE); } static void ALCsolarisBackend_Destruct(ALCsolarisBackend *self) @@ -103,43 +104,65 @@ static void ALCsolarisBackend_Destruct(ALCsolarisBackend *self) static int ALCsolarisBackend_mixerProc(void *ptr) { ALCsolarisBackend *self = ptr; - ALCdevice *Device = STATIC_CAST(ALCbackend,self)->mDevice; - ALint frameSize; - int wrote; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + struct timeval timeout; + ALubyte *write_ptr; + ALint frame_size; + ALint to_write; + ssize_t wrote; + fd_set wfds; + int sret; SetRTPriority(); althrd_setname(althrd_current(), MIXER_THREAD_NAME); - frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); + frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); - while(!self->killNow && Device->Connected) + ALCsolarisBackend_lock(self); + while(!ATOMIC_LOAD_SEQ(&self->killNow) && device->Connected) { - ALint len = self->data_size; - ALubyte *WritePtr = self->mix_data; + FD_ZERO(&wfds); + FD_SET(self->fd, &wfds); + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + ALCsolarisBackend_unlock(self); + sret = select(self->fd+1, NULL, &wfds, NULL, &timeout); + ALCsolarisBackend_lock(self); + if(sret < 0) + { + if(errno == EINTR) + continue; + ERR("select failed: %s\n", strerror(errno)); + aluHandleDisconnect(device); + break; + } + else if(sret == 0) + { + WARN("select timeout\n"); + continue; + } - aluMixData(Device, WritePtr, len/frameSize); - while(len > 0 && !self->killNow) + write_ptr = self->mix_data; + to_write = self->data_size; + aluMixData(device, write_ptr, to_write/frame_size); + while(to_write > 0 && !ATOMIC_LOAD_SEQ(&self->killNow)) { - wrote = write(self->fd, WritePtr, len); + wrote = write(self->fd, write_ptr, to_write); if(wrote < 0) { - if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) - { - ERR("write failed: %s\n", strerror(errno)); - ALCsolarisBackend_lock(self); - aluHandleDisconnect(Device); - ALCsolarisBackend_unlock(self); - break; - } - - al_nssleep(1000000); - continue; + if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + continue; + ERR("write failed: %s\n", strerror(errno)); + aluHandleDisconnect(device); + break; } - len -= wrote; - WritePtr += wrote; + to_write -= wrote; + write_ptr += wrote; } } + ALCsolarisBackend_unlock(self); return 0; } @@ -250,7 +273,7 @@ static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self) static ALCboolean ALCsolarisBackend_start(ALCsolarisBackend *self) { - self->killNow = 0; + ATOMIC_STORE_SEQ(&self->killNow, AL_FALSE); if(althrd_create(&self->thread, ALCsolarisBackend_mixerProc, self) != althrd_success) return ALC_FALSE; return ALC_TRUE; @@ -260,10 +283,9 @@ static void ALCsolarisBackend_stop(ALCsolarisBackend *self) { int res; - if(self->killNow) + if(ATOMIC_EXCHANGE_SEQ(int, &self->killNow, AL_TRUE)) return; - self->killNow = 1; althrd_join(self->thread, &res); if(ioctl(self->fd, AUDIO_DRAIN) < 0) -- cgit v1.2.3 From 2448f88e70f6207ad5743f0a55eaa5de7cbce737 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 18 Feb 2017 16:55:48 -0800 Subject: Return some device latency by default A device will never have 0 latency. OpenAL Soft itself uses a sample buffer length of UpdateSize*NumUpdates, and during playback will have about (NumUpdates-1) periods filled, more or less. Without a more accurate measurement from the playback system, this is better than reporting 0. --- Alc/backends/base.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/base.c b/Alc/backends/base.c index ff808f53..e4305653 100644 --- a/Alc/backends/base.c +++ b/Alc/backends/base.c @@ -4,6 +4,7 @@ #include #include "alMain.h" +#include "alu.h" #include "backends/base.h" @@ -45,8 +46,12 @@ ClockLatency ALCbackend_getClockLatency(ALCbackend *self) almtx_lock(&self->mMutex); ret.ClockTime = GetDeviceClockTime(device); - // TODO: Perhaps should be NumUpdates-1 worth of UpdateSize? - ret.Latency = 0; + /* NOTE: The device will generally have about all but one periods filled at + * any given time during playback. Without a more accurate measurement from + * the output, this is an okay approximation. + */ + ret.Latency = device->UpdateSize * DEVICE_CLOCK_RES / device->Frequency * + maxu(device->NumUpdates-1, 1); almtx_unlock(&self->mMutex); return ret; -- cgit v1.2.3 From 247f56249ade334f8f7ef9eda9c380af0278562f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 18 Feb 2017 17:32:07 -0800 Subject: Always lock the device backend before calling aluMixData --- Alc/ALc.c | 4 +++ Alc/ALu.c | 2 -- Alc/backends/coreaudio.c | 2 ++ Alc/backends/dsound.c | 2 ++ Alc/backends/mmdevapi.c | 4 +-- Alc/backends/null.c | 2 ++ Alc/backends/portaudio.c | 2 ++ Alc/backends/qsa.c | 89 +++++++++++++++++++++++------------------------- Alc/backends/sndio.c | 2 ++ Alc/backends/wave.c | 2 ++ Alc/backends/winmm.c | 2 ++ 11 files changed, 63 insertions(+), 50 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index 1028321e..17b2727d 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -4182,7 +4182,11 @@ FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, AL else if(samples < 0 || (samples > 0 && buffer == NULL)) alcSetError(device, ALC_INVALID_VALUE); else + { + V0(device->Backend,lock)(); aluMixData(device, buffer, samples); + V0(device->Backend,unlock)(); + } if(device) ALCdevice_DecRef(device); } diff --git a/Alc/ALu.c b/Alc/ALu.c index d5065199..9dcef6ff 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -1423,7 +1423,6 @@ void aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size) memset(device->FOAOut.Buffer[c], 0, SamplesToDo*sizeof(ALfloat)); IncrementRef(&device->MixCount); - V0(device->Backend,lock)(); if((slot=device->DefaultSlot) != NULL) { @@ -1488,7 +1487,6 @@ void aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size) device->SamplesDone += SamplesToDo; device->ClockBase += (device->SamplesDone/device->Frequency) * DEVICE_CLOCK_RES; device->SamplesDone %= device->Frequency; - V0(device->Backend,unlock)(); IncrementRef(&device->MixCount); if(device->Hrtf.Handle) diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index 24aeabd4..eb93f9ea 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -89,8 +89,10 @@ static OSStatus ca_callback(void *inRefCon, AudioUnitRenderActionFlags *ioAction ALCdevice *device = (ALCdevice*)inRefCon; ca_data *data = (ca_data*)device->ExtraData; + ALCdevice_Lock(device); aluMixData(device, ioData->mBuffers[0].mData, ioData->mBuffers[0].mDataByteSize / data->frameSize); + ALCdevice_Unlock(device); return noErr; } diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index bb38d516..084d1125 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -299,8 +299,10 @@ FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr) if(SUCCEEDED(err)) { // If we have an active context, mix data directly into output buffer otherwise fill with silence + ALCdevice_Lock(device); aluMixData(device, WritePtr1, WriteCnt1/FrameSize); aluMixData(device, WritePtr2, WriteCnt2/FrameSize); + ALCdevice_Unlock(device); // Unlock output buffer only when successfully locked IDirectSoundBuffer_Unlock(self->Buffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2); diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 92089416..6ff9d931 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -629,10 +629,10 @@ FORCE_ALIGN static int ALCmmdevPlayback_mixerProc(void *arg) hr = IAudioRenderClient_GetBuffer(self->render, len, &buffer); if(SUCCEEDED(hr)) { - V0(device->Backend,lock)(); + ALCmmdevPlayback_lock(self); aluMixData(device, buffer, len); self->Padding = written + len; - V0(device->Backend,unlock)(); + ALCmmdevPlayback_unlock(self); hr = IAudioRenderClient_ReleaseBuffer(self->render, len, 0); } if(FAILED(hr)) diff --git a/Alc/backends/null.c b/Alc/backends/null.c index 5b153cd9..41636538 100644 --- a/Alc/backends/null.c +++ b/Alc/backends/null.c @@ -109,7 +109,9 @@ static int ALCnullBackend_mixerProc(void *ptr) al_nssleep(restTime); else while(avail-done >= device->UpdateSize) { + ALCnullBackend_lock(self); aluMixData(device, NULL, device->UpdateSize); + ALCnullBackend_unlock(self); done += device->UpdateSize; } } diff --git a/Alc/backends/portaudio.c b/Alc/backends/portaudio.c index 1dbca941..129b0606 100644 --- a/Alc/backends/portaudio.c +++ b/Alc/backends/portaudio.c @@ -177,7 +177,9 @@ static int ALCportPlayback_WriteCallback(const void *UNUSED(inputBuffer), void * { ALCportPlayback *self = userData; + ALCportPlayback_lock(self); aluMixData(STATIC_CAST(ALCbackend, self)->mDevice, outputBuffer, framesPerBuffer); + ALCportPlayback_unlock(self); return 0; } diff --git a/Alc/backends/qsa.c b/Alc/backends/qsa.c index b7923517..dabe5ee9 100644 --- a/Alc/backends/qsa.c +++ b/Alc/backends/qsa.c @@ -33,6 +33,8 @@ #include "alu.h" #include "threads.h" +#include "backends/base.h" + typedef struct { snd_pcm_t* pcmHandle; @@ -161,13 +163,13 @@ FORCE_ALIGN static int qsa_proc_playback(void* ptr) { ALCdevice* device=(ALCdevice*)ptr; qsa_data* data=(qsa_data*)device->ExtraData; - char* write_ptr; - int avail; snd_pcm_channel_status_t status; struct sched_param param; - fd_set wfds; - int selectret; struct timeval timeout; + char* write_ptr; + fd_set wfds; + ALint len; + int sret; SetRTPriority(); althrd_setname(althrd_current(), MIXER_THREAD_NAME); @@ -177,59 +179,53 @@ FORCE_ALIGN static int qsa_proc_playback(void* ptr) param.sched_priority=param.sched_curpriority+1; SchedSet(0, 0, SCHED_NOCHANGE, ¶m); - ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + const ALint frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); - while (!data->killNow) + V0(device->Backend,lock)(); + while(!data->killNow) { - ALint len=data->size; - write_ptr=data->buffer; - - avail=len/frame_size; - aluMixData(device, write_ptr, avail); + FD_ZERO(&wfds); + FD_SET(data->audio_fd, &wfds); + timeout.tv_sec=2; + timeout.tv_usec=0; - while (len>0 && !data->killNow) + /* Select also works like time slice to OS */ + V0(device->Backend,unlock)(); + sret = select(data->audio_fd+1, NULL, &wfds, NULL, &timeout); + V0(device->Backend,lock)(); + if(sret == -1) { - FD_ZERO(&wfds); - FD_SET(data->audio_fd, &wfds); - timeout.tv_sec=2; - timeout.tv_usec=0; - - /* Select also works like time slice to OS */ - selectret=select(data->audio_fd+1, NULL, &wfds, NULL, &timeout); - switch (selectret) - { - case -1: - aluHandleDisconnect(device); - return 1; - case 0: - break; - default: - if (FD_ISSET(data->audio_fd, &wfds)) - { - break; - } - break; - } - - int wrote=snd_pcm_plugin_write(data->pcmHandle, write_ptr, len); + ERR("select error: %s\n", strerror(errno)); + aluHandleDisconnect(device); + break; + } + if(sret == 0) + { + ERR("select timeout\n"); + continue; + } - if (wrote<=0) + len = data->size; + write_ptr = data->buffer; + aluMixData(device, write_ptr, len/frame_size); + while(len>0 && !data->killNow) + { + int wrote = snd_pcm_plugin_write(data->pcmHandle, write_ptr, len); + if(wrote <= 0) { - if ((errno==EAGAIN) || (errno==EWOULDBLOCK)) - { + if(errno==EAGAIN || errno==EWOULDBLOCK) continue; - } - memset(&status, 0, sizeof (status)); - status.channel=SND_PCM_CHANNEL_PLAYBACK; + memset(&status, 0, sizeof(status)); + status.channel = SND_PCM_CHANNEL_PLAYBACK; snd_pcm_plugin_status(data->pcmHandle, &status); /* we need to reinitialize the sound channel if we've underrun the buffer */ - if ((status.status==SND_PCM_STATUS_UNDERRUN) || - (status.status==SND_PCM_STATUS_READY)) + if(status.status == SND_PCM_STATUS_UNDERRUN || + status.status == SND_PCM_STATUS_READY) { - if ((snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK))<0) + if(snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK) < 0) { aluHandleDisconnect(device); break; @@ -238,11 +234,12 @@ FORCE_ALIGN static int qsa_proc_playback(void* ptr) } else { - write_ptr+=wrote; - len-=wrote; + write_ptr += wrote; + len -= wrote; } } } + V0(device->Backend,unlock)(); return 0; } diff --git a/Alc/backends/sndio.c b/Alc/backends/sndio.c index af519794..00d7c654 100644 --- a/Alc/backends/sndio.c +++ b/Alc/backends/sndio.c @@ -105,7 +105,9 @@ static int ALCsndioBackend_mixerProc(void *ptr) ALsizei len = self->data_size; ALubyte *WritePtr = self->mix_data; + ALCsndioBackend_lock(self); aluMixData(device, WritePtr, len/frameSize); + ALCsndioBackend_unlock(self); while(len > 0 && !self->killNow) { wrote = sio_write(self->sndHandle, WritePtr, len); diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index 9bf5a727..ac0ffd80 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -157,7 +157,9 @@ static int ALCwaveBackend_mixerProc(void *ptr) al_nssleep(restTime); else while(avail-done >= device->UpdateSize) { + ALCwaveBackend_lock(self); aluMixData(device, self->mBuffer, device->UpdateSize); + ALCwaveBackend_unlock(self); done += device->UpdateSize; if(!IS_LITTLE_ENDIAN) diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index 9d8f8e9d..2b6db4ad 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -232,8 +232,10 @@ FORCE_ALIGN static int ALCwinmmPlayback_mixerProc(void *arg) } WaveHdr = ((WAVEHDR*)msg.lParam); + ALCwinmmPlayback_lock(self); aluMixData(device, WaveHdr->lpData, WaveHdr->dwBufferLength / self->Format.nBlockAlign); + ALCwinmmPlayback_unlock(self); // Send buffer back to play more data waveOutWrite(self->OutHdl, WaveHdr, sizeof(WAVEHDR)); -- cgit v1.2.3 From e0e6efbfeac7bb07dce82b63b7688648e1067da3 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 21 Feb 2017 10:17:48 -0800 Subject: Print warnings about missing libraries and functions --- Alc/backends/alsa.c | 9 ++++++++- Alc/backends/jack.c | 9 ++++++++- Alc/backends/pulseaudio.c | 8 ++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 7a9045bb..2fa806ae 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -199,15 +199,21 @@ static ALCboolean alsa_load(void) #ifdef HAVE_DYNLOAD if(!alsa_handle) { + al_string missing_funcs = AL_STRING_INIT_STATIC(); + alsa_handle = LoadLib("libasound.so.2"); if(!alsa_handle) + { + WARN("Failed to load %s\n", "libasound.so.2"); return ALC_FALSE; + } error = ALC_FALSE; #define LOAD_FUNC(f) do { \ p##f = GetSymbol(alsa_handle, #f); \ if(p##f == NULL) { \ error = ALC_TRUE; \ + al_string_append_cstr(&missing_funcs, "\n" #f); \ } \ } while(0) ALSA_FUNCS(LOAD_FUNC); @@ -215,10 +221,11 @@ static ALCboolean alsa_load(void) if(error) { + WARN("Missing expected functions:%s\n", al_string_get_cstr(missing_funcs)); CloseLib(alsa_handle); alsa_handle = NULL; - return ALC_FALSE; } + al_string_deinit(&missing_funcs); } #endif diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index fa04c594..f1cd82bd 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -96,6 +96,8 @@ static ALCboolean jack_load(void) #ifdef HAVE_DYNLOAD if(!jack_handle) { + al_string missing_funcs = AL_STRING_INIT_STATIC(); + #ifdef _WIN32 #define JACKLIB "libjack.dll" #else @@ -103,13 +105,17 @@ static ALCboolean jack_load(void) #endif jack_handle = LoadLib(JACKLIB); if(!jack_handle) + { + WARN("Failed to load %s\n", JACKLIB); return ALC_FALSE; + } error = ALC_FALSE; #define LOAD_FUNC(f) do { \ p##f = GetSymbol(jack_handle, #f); \ if(p##f == NULL) { \ error = ALC_TRUE; \ + al_string_append_cstr(&missing_funcs, "\n" #f); \ } \ } while(0) JACK_FUNCS(LOAD_FUNC); @@ -117,10 +123,11 @@ static ALCboolean jack_load(void) if(error) { + WARN("Missing expected functions:%s\n", al_string_get_cstr(missing_funcs)); CloseLib(jack_handle); jack_handle = NULL; - return ALC_FALSE; } + al_string_deinit(&missing_funcs); } #endif diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index fa07da3e..14b37ee6 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -182,6 +182,8 @@ static ALCboolean pulse_load(void) #ifdef HAVE_DYNLOAD if(!pa_handle) { + al_string missing_funcs = AL_STRING_INIT_STATIC(); + #ifdef _WIN32 #define PALIB "libpulse-0.dll" #elif defined(__APPLE__) && defined(__MACH__) @@ -191,12 +193,16 @@ static ALCboolean pulse_load(void) #endif pa_handle = LoadLib(PALIB); if(!pa_handle) + { + WARN("Failed to load %s\n", PALIB); return ALC_FALSE; + } #define LOAD_FUNC(x) do { \ p##x = GetSymbol(pa_handle, #x); \ if(!(p##x)) { \ ret = ALC_FALSE; \ + al_string_append_cstr(&missing_funcs, "\n" #x); \ } \ } while(0) LOAD_FUNC(pa_context_unref); @@ -270,9 +276,11 @@ static ALCboolean pulse_load(void) if(ret == ALC_FALSE) { + WARN("Missing expected functions:%s\n", al_string_get_cstr(missing_funcs)); CloseLib(pa_handle); pa_handle = NULL; } + al_string_deinit(&missing_funcs); } #endif /* HAVE_DYNLOAD */ return ret; -- cgit v1.2.3 From e720faf2d40e9e4ec27479ffbbcba1a3b3838956 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 22 Feb 2017 15:00:41 -0800 Subject: Fix OpenSL latency calculation --- Alc/backends/opensl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index a667dc70..b8d6d29a 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -694,8 +694,8 @@ static ClockLatency ALCopenslPlayback_getClockLatency(ALCopenslPlayback *self) ALCopenslPlayback_lock(self); ret.ClockTime = GetDeviceClockTime(device); - ret.Latency = ll_ringbuffer_read_space(self->mRing) * DEVICE_CLOCK_RES / - device->Frequency; + ret.Latency = ll_ringbuffer_read_space(self->mRing)*device->UpdateSize * + DEVICE_CLOCK_RES / device->Frequency; ALCopenslPlayback_unlock(self); return ret; -- cgit v1.2.3 From 2e1f1449bc7bd9f50822298577be203693deca7f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 22 Feb 2017 15:44:47 -0800 Subject: Don't remove a period from the OSS buffer Since we're now waiting for space to be available before mixing, the mixing buffer isn't adding another period. --- Alc/backends/oss.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 8934181b..b22e87ba 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -419,17 +419,10 @@ static ALCboolean ALCplaybackOSS_reset(ALCplaybackOSS *self) 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--; + frameSize = numChannels * BytesFromDevFmt(device->FmtType); + /* According to the OSS spec, 16 bytes (log2(16)) is the minimum. */ + log2FragmentSize = maxi(log2i(device->UpdateSize*frameSize), 4); numFragmentsLogSize = (periods << 16) | log2FragmentSize; #define CHECKERR(func) if((func) < 0) { \ @@ -467,7 +460,7 @@ static ALCboolean ALCplaybackOSS_reset(ALCplaybackOSS *self) device->Frequency = ossSpeed; device->UpdateSize = info.fragsize / frameSize; - device->NumUpdates = info.fragments + 1; + device->NumUpdates = info.fragments; SetDefaultChannelOrder(device); -- cgit v1.2.3 From a9610b3607e8dd23f731b614c3b0761c38cb36a8 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 27 Feb 2017 16:11:45 -0800 Subject: Use separate enums for the ambisonic channel order and normalization --- Alc/ALc.c | 24 ++++++++++++++++++------ Alc/backends/wave.c | 3 ++- Alc/panning.c | 8 ++++---- OpenAL32/Include/alMain.h | 20 ++++++++++++++------ 4 files changed, 38 insertions(+), 17 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index bf683ba3..56063bb1 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -3640,7 +3640,8 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) device->FmtType = DevFmtTypeDefault; device->Frequency = DEFAULT_OUTPUT_RATE; device->IsHeadphones = AL_FALSE; - device->AmbiFmt = AmbiFormat_Default; + device->AmbiLayout = AmbiLayout_Default; + device->AmbiScale = AmbiNorm_Default; device->NumUpdates = 3; device->UpdateSize = 1024; @@ -3763,11 +3764,20 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt)) { if(strcasecmp(fmt, "fuma") == 0) - device->AmbiFmt = AmbiFormat_FuMa; + { + device->AmbiLayout = AmbiLayout_FuMa; + device->AmbiScale = AmbiNorm_FuMa; + } else if(strcasecmp(fmt, "acn+sn3d") == 0) - device->AmbiFmt = AmbiFormat_ACN_SN3D; + { + device->AmbiLayout = AmbiLayout_ACN; + device->AmbiScale = AmbiNorm_SN3D; + } else if(strcasecmp(fmt, "acn+n3d") == 0) - device->AmbiFmt = AmbiFormat_ACN_N3D; + { + device->AmbiLayout = AmbiLayout_ACN; + device->AmbiScale = AmbiNorm_N3D; + } else ERR("Unsupported ambi-format: %s\n", fmt); } @@ -3939,7 +3949,8 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, return NULL; } device->IsHeadphones = AL_FALSE; - device->AmbiFmt = AmbiFormat_Default; + device->AmbiLayout = AmbiLayout_Default; + device->AmbiScale = AmbiNorm_Default; device->UpdateSize = samples; device->NumUpdates = 1; @@ -4142,7 +4153,8 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN device->FmtChans = DevFmtChannelsDefault; device->FmtType = DevFmtTypeDefault; device->IsHeadphones = AL_FALSE; - device->AmbiFmt = AmbiFormat_Default; + device->AmbiLayout = AmbiLayout_Default; + device->AmbiScale = AmbiNorm_Default; ConfigValueUInt(NULL, NULL, "sources", &device->SourcesMax); if(device->SourcesMax == 0) device->SourcesMax = 256; diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index ac0ffd80..1b13746e 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -283,7 +283,8 @@ static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self) case DevFmtAmbi2: case DevFmtAmbi3: /* .amb output requires FuMa */ - device->AmbiFmt = AmbiFormat_FuMa; + device->AmbiLayout = AmbiLayout_FuMa; + device->AmbiScale = AmbiNorm_FuMa; isbformat = 1; chanmask = 0; break; diff --git a/Alc/panning.c b/Alc/panning.c index 46f134a6..77f8e31b 100644 --- a/Alc/panning.c +++ b/Alc/panning.c @@ -546,10 +546,10 @@ static void InitPanning(ALCdevice *device) if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3) { - const ALsizei *acnmap = (device->AmbiFmt == AmbiFormat_FuMa) ? FuMa2ACN : ACN2ACN; - const ALfloat *n3dscale = (device->AmbiFmt == AmbiFormat_FuMa) ? FuMa2N3DScale : - (device->AmbiFmt == AmbiFormat_ACN_SN3D) ? SN3D2N3DScale : - /*(device->AmbiFmt == AmbiFormat_ACN_N3D) ?*/ UnitScale; + const ALsizei *acnmap = (device->AmbiLayout == AmbiLayout_FuMa) ? FuMa2ACN : ACN2ACN; + const ALfloat *n3dscale = (device->AmbiScale == AmbiNorm_FuMa) ? FuMa2N3DScale : + (device->AmbiScale == AmbiNorm_SN3D) ? SN3D2N3DScale : + /*(device->AmbiScale == AmbiNorm_N3D) ?*/ UnitScale; count = (device->FmtChans == DevFmtAmbi3) ? 16 : (device->FmtChans == DevFmtAmbi2) ? 9 : diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 0b467403..23572a90 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -510,12 +510,19 @@ inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType ty return ChannelsFromDevFmt(chans) * BytesFromDevFmt(type); } -enum AmbiFormat { - AmbiFormat_FuMa, /* FuMa channel order and normalization */ - AmbiFormat_ACN_SN3D, /* ACN channel order and SN3D normalization */ - AmbiFormat_ACN_N3D, /* ACN channel order and N3D normalization */ +enum AmbiLayout { + AmbiLayout_FuMa, /* FuMa channel order */ + AmbiLayout_ACN, /* ACN channel order */ - AmbiFormat_Default = AmbiFormat_ACN_SN3D + AmbiLayout_Default = AmbiLayout_ACN +}; + +enum AmbiNorm { + AmbiNorm_FuMa, /* FuMa normalization */ + AmbiNorm_SN3D, /* SN3D normalization */ + AmbiNorm_N3D, /* N3D normalization */ + + AmbiNorm_Default = AmbiNorm_SN3D }; @@ -635,7 +642,8 @@ struct ALCdevice_struct /* For DevFmtAmbi* output only, specifies the channel order and * normalization. */ - enum AmbiFormat AmbiFmt; + enum AmbiLayout AmbiLayout; + enum AmbiNorm AmbiScale; al_string DeviceName; -- cgit v1.2.3 From 1cd6617ff6404cfdcc1ccaf1c08c9d763e27366c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 28 Feb 2017 03:50:42 -0800 Subject: Don't use the mutex in the base getClockLatency implementation --- Alc/backends/base.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/base.c b/Alc/backends/base.c index e4305653..902c4310 100644 --- a/Alc/backends/base.c +++ b/Alc/backends/base.c @@ -42,17 +42,22 @@ ALCuint ALCbackend_availableSamples(ALCbackend* UNUSED(self)) ClockLatency ALCbackend_getClockLatency(ALCbackend *self) { ALCdevice *device = self->mDevice; + ALuint refcount; ClockLatency ret; - almtx_lock(&self->mMutex); - ret.ClockTime = GetDeviceClockTime(device); + do { + while(((refcount=ATOMIC_LOAD(&device->MixCount, almemory_order_acquire))&1)) + althrd_yield(); + ret.ClockTime = GetDeviceClockTime(device); + ATOMIC_THREAD_FENCE(almemory_order_acquire); + } while(refcount != ATOMIC_LOAD(&device->MixCount, almemory_order_relaxed)); + /* NOTE: The device will generally have about all but one periods filled at * any given time during playback. Without a more accurate measurement from * the output, this is an okay approximation. */ ret.Latency = device->UpdateSize * DEVICE_CLOCK_RES / device->Frequency * maxu(device->NumUpdates-1, 1); - almtx_unlock(&self->mMutex); return ret; } -- cgit v1.2.3 From 26144ca9dffd935c3e7499b417ccb9a6ef93eea0 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 4 Apr 2017 06:58:53 -0700 Subject: Rename al_string_* functions to alstr_* --- Alc/ALc.c | 38 ++++++------ Alc/alcConfig.c | 38 ++++++------ Alc/alstring.h | 36 +++++------ Alc/ambdec.c | 12 ++-- Alc/backends/alsa.c | 34 +++++------ Alc/backends/coreaudio.c | 4 +- Alc/backends/dsound.c | 26 ++++---- Alc/backends/jack.c | 12 ++-- Alc/backends/loopback.c | 2 +- Alc/backends/mmdevapi.c | 46 +++++++------- Alc/backends/null.c | 2 +- Alc/backends/opensl.c | 2 +- Alc/backends/oss.c | 4 +- Alc/backends/portaudio.c | 4 +- Alc/backends/pulseaudio.c | 80 ++++++++++++------------ Alc/backends/qsa.c | 4 +- Alc/backends/sndio.c | 2 +- Alc/backends/solaris.c | 2 +- Alc/backends/wave.c | 2 +- Alc/backends/winmm.c | 40 ++++++------ Alc/helpers.c | 152 +++++++++++++++++++++++----------------------- Alc/hrtf.c | 108 ++++++++++++++++---------------- Alc/panning.c | 48 +++++++-------- 23 files changed, 348 insertions(+), 350 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index 12d0d608..f248a998 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -1311,7 +1311,7 @@ static void ProbeDevices(al_string *list, struct BackendInfo *backendinfo, enum DO_INITCONFIG(); LockLists(); - al_string_clear(list); + alstr_clear(list); if(backendinfo->Probe) backendinfo->Probe(type); @@ -1331,7 +1331,7 @@ static void AppendDevice(const ALCchar *name, al_string *devnames) { size_t len = strlen(name); if(len > 0) - al_string_append_range(devnames, name, name+len+1); + alstr_append_range(devnames, name, name+len+1); } void AppendAllDevicesList(const ALCchar *name) { AppendDevice(name, &alcAllDevicesList); } @@ -1985,7 +1985,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) } #undef TRACE_ATTR - ConfigValueUInt(al_string_get_cstr(device->DeviceName), NULL, "frequency", &freq); + ConfigValueUInt(alstr_get_cstr(device->DeviceName), NULL, "frequency", &freq); freq = maxu(freq, MIN_OUTPUT_RATE); device->UpdateSize = (ALuint64)device->UpdateSize * freq / @@ -1998,7 +1998,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) device->NumMonoSources = numMono; device->NumStereoSources = numStereo; - if(ConfigValueInt(al_string_get_cstr(device->DeviceName), NULL, "sends", &new_sends)) + if(ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "sends", &new_sends)) new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS)); else new_sends = numSends; @@ -2037,7 +2037,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) if(device->Type != Loopback) { const char *hrtf; - if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "hrtf", &hrtf)) + if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "hrtf", &hrtf)) { if(strcasecmp(hrtf, "true") == 0) hrtf_userreq = Hrtf_Enable; @@ -2869,26 +2869,26 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum para case ALC_ALL_DEVICES_SPECIFIER: if(VerifyDevice(&Device)) { - value = al_string_get_cstr(Device->DeviceName); + value = alstr_get_cstr(Device->DeviceName); ALCdevice_DecRef(Device); } else { ProbeAllDevicesList(); - value = al_string_get_cstr(alcAllDevicesList); + value = alstr_get_cstr(alcAllDevicesList); } break; case ALC_CAPTURE_DEVICE_SPECIFIER: if(VerifyDevice(&Device)) { - value = al_string_get_cstr(Device->DeviceName); + value = alstr_get_cstr(Device->DeviceName); ALCdevice_DecRef(Device); } else { ProbeCaptureDeviceList(); - value = al_string_get_cstr(alcCaptureDeviceList); + value = alstr_get_cstr(alcCaptureDeviceList); } break; @@ -2898,13 +2898,13 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum para break; case ALC_DEFAULT_ALL_DEVICES_SPECIFIER: - if(al_string_empty(alcAllDevicesList)) + if(alstr_empty(alcAllDevicesList)) ProbeAllDevicesList(); VerifyDevice(&Device); free(alcDefaultAllDevicesSpecifier); - alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList)); + alcDefaultAllDevicesSpecifier = strdup(alstr_get_cstr(alcAllDevicesList)); if(!alcDefaultAllDevicesSpecifier) alcSetError(Device, ALC_OUT_OF_MEMORY); @@ -2913,13 +2913,13 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum para break; case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER: - if(al_string_empty(alcCaptureDeviceList)) + if(alstr_empty(alcCaptureDeviceList)) ProbeCaptureDeviceList(); VerifyDevice(&Device); free(alcCaptureDefaultDeviceSpecifier); - alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcCaptureDeviceList)); + alcCaptureDefaultDeviceSpecifier = strdup(alstr_get_cstr(alcCaptureDeviceList)); if(!alcCaptureDefaultDeviceSpecifier) alcSetError(Device, ALC_OUT_OF_MEMORY); @@ -2943,7 +2943,7 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum para else { almtx_lock(&Device->BackendLock); - value = (Device->HrtfHandle ? al_string_get_cstr(Device->HrtfName) : ""); + value = (Device->HrtfHandle ? alstr_get_cstr(Device->HrtfName) : ""); almtx_unlock(&Device->BackendLock); ALCdevice_DecRef(Device); } @@ -3578,7 +3578,7 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin ALCdevice_IncRef(ALContext->Device); InitContext(ALContext); - if(ConfigValueFloat(al_string_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf)) + if(ConfigValueFloat(alstr_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf)) { if(!isfinite(valf)) ERR("volume-adjust must be finite: %f\n", valf); @@ -3937,7 +3937,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) } almtx_init(&device->BackendLock, almtx_plain); - if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt)) + if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt)) { if(strcasecmp(fmt, "fuma") == 0) { @@ -3985,7 +3985,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device)); } - TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName)); + TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName)); return device; } @@ -4155,7 +4155,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device)); } - TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName)); + TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName)); return device; } @@ -4519,7 +4519,7 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum { case ALC_HRTF_SPECIFIER_SOFT: if(index >= 0 && (size_t)index < VECTOR_SIZE(device->HrtfList)) - str = al_string_get_cstr(VECTOR_ELEM(device->HrtfList, index).name); + str = alstr_get_cstr(VECTOR_ELEM(device->HrtfList, index).name); else alcSetError(device, ALC_INVALID_VALUE); break; diff --git a/Alc/alcConfig.c b/Alc/alcConfig.c index 5224f0f5..6fd01746 100644 --- a/Alc/alcConfig.c +++ b/Alc/alcConfig.c @@ -373,25 +373,25 @@ void ReadALConfig(void) if(SHGetSpecialFolderPathW(NULL, buffer, CSIDL_APPDATA, FALSE) != FALSE) { al_string filepath = AL_STRING_INIT_STATIC(); - al_string_copy_wcstr(&filepath, buffer); - al_string_append_cstr(&filepath, "\\alsoft.ini"); + alstr_copy_wcstr(&filepath, buffer); + alstr_append_cstr(&filepath, "\\alsoft.ini"); - TRACE("Loading config %s...\n", al_string_get_cstr(filepath)); - f = al_fopen(al_string_get_cstr(filepath), "rt"); + TRACE("Loading config %s...\n", alstr_get_cstr(filepath)); + f = al_fopen(alstr_get_cstr(filepath), "rt"); if(f) { LoadConfigFromFile(f); fclose(f); } - al_string_deinit(&filepath); + alstr_reset(&filepath); } ppath = GetProcPath(); - if(!al_string_empty(ppath)) + if(!alstr_empty(ppath)) { - al_string_append_cstr(&ppath, "\\alsoft.ini"); - TRACE("Loading config %s...\n", al_string_get_cstr(ppath)); - f = al_fopen(al_string_get_cstr(ppath), "r"); + alstr_append_cstr(&ppath, "\\alsoft.ini"); + TRACE("Loading config %s...\n", alstr_get_cstr(ppath)); + f = al_fopen(alstr_get_cstr(ppath), "r"); if(f) { LoadConfigFromFile(f); @@ -402,19 +402,19 @@ void ReadALConfig(void) if((str=_wgetenv(L"ALSOFT_CONF")) != NULL && *str) { al_string filepath = AL_STRING_INIT_STATIC(); - al_string_copy_wcstr(&filepath, str); + alstr_copy_wcstr(&filepath, str); - TRACE("Loading config %s...\n", al_string_get_cstr(filepath)); - f = al_fopen(al_string_get_cstr(filepath), "rt"); + TRACE("Loading config %s...\n", alstr_get_cstr(filepath)); + f = al_fopen(alstr_get_cstr(filepath), "rt"); if(f) { LoadConfigFromFile(f); fclose(f); } - al_string_deinit(&filepath); + alstr_reset(&filepath); } - al_string_deinit(&ppath); + alstr_reset(&ppath); } #else void ReadALConfig(void) @@ -502,11 +502,11 @@ void ReadALConfig(void) } ppath = GetProcPath(); - if(!al_string_empty(ppath)) + if(!alstr_empty(ppath)) { - al_string_append_cstr(&ppath, "/alsoft.conf"); - TRACE("Loading config %s...\n", al_string_get_cstr(ppath)); - f = al_fopen(al_string_get_cstr(ppath), "r"); + alstr_append_cstr(&ppath, "/alsoft.conf"); + TRACE("Loading config %s...\n", alstr_get_cstr(ppath)); + f = al_fopen(alstr_get_cstr(ppath), "r"); if(f) { LoadConfigFromFile(f); @@ -525,7 +525,7 @@ void ReadALConfig(void) } } - al_string_deinit(&ppath); + alstr_reset(&ppath); } #endif diff --git a/Alc/alstring.h b/Alc/alstring.h index 6167f5ce..a7513516 100644 --- a/Alc/alstring.h +++ b/Alc/alstring.h @@ -10,40 +10,40 @@ typedef char al_string_char_type; TYPEDEF_VECTOR(al_string_char_type, al_string) TYPEDEF_VECTOR(al_string, vector_al_string) -inline void al_string_deinit(al_string *str) +inline void alstr_reset(al_string *str) { VECTOR_DEINIT(*str); } #define AL_STRING_INIT(_x) do { (_x) = (al_string)NULL; } while(0) #define AL_STRING_INIT_STATIC() ((al_string)NULL) -#define AL_STRING_DEINIT(_x) al_string_deinit(&(_x)) +#define AL_STRING_DEINIT(_x) alstr_reset(&(_x)) -inline size_t al_string_length(const_al_string str) +inline size_t alstr_length(const_al_string str) { return VECTOR_SIZE(str); } -inline ALboolean al_string_empty(const_al_string str) -{ return al_string_length(str) == 0; } +inline ALboolean alstr_empty(const_al_string str) +{ return alstr_length(str) == 0; } -inline const al_string_char_type *al_string_get_cstr(const_al_string str) +inline const al_string_char_type *alstr_get_cstr(const_al_string str) { return str ? &VECTOR_FRONT(str) : ""; } -void al_string_clear(al_string *str); +void alstr_clear(al_string *str); -int al_string_cmp(const_al_string str1, const_al_string str2); -int al_string_cmp_cstr(const_al_string str1, const al_string_char_type *str2); +int alstr_cmp(const_al_string str1, const_al_string str2); +int alstr_cmp_cstr(const_al_string str1, const al_string_char_type *str2); -void al_string_copy(al_string *str, const_al_string from); -void al_string_copy_cstr(al_string *str, const al_string_char_type *from); -void al_string_copy_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to); +void alstr_copy(al_string *str, const_al_string from); +void alstr_copy_cstr(al_string *str, const al_string_char_type *from); +void alstr_copy_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to); -void al_string_append_char(al_string *str, const al_string_char_type c); -void al_string_append_cstr(al_string *str, const al_string_char_type *from); -void al_string_append_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to); +void alstr_append_char(al_string *str, const al_string_char_type c); +void alstr_append_cstr(al_string *str, const al_string_char_type *from); +void alstr_append_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to); #ifdef _WIN32 #include /* Windows-only methods to deal with WideChar strings. */ -void al_string_copy_wcstr(al_string *str, const wchar_t *from); -void al_string_append_wcstr(al_string *str, const wchar_t *from); -void al_string_append_wrange(al_string *str, const wchar_t *from, const wchar_t *to); +void alstr_copy_wcstr(al_string *str, const wchar_t *from); +void alstr_append_wcstr(al_string *str, const wchar_t *from); +void alstr_append_wrange(al_string *str, const wchar_t *from, const wchar_t *to); #endif #endif /* ALSTRING_H */ diff --git a/Alc/ambdec.c b/Alc/ambdec.c index 719b509c..da114335 100644 --- a/Alc/ambdec.c +++ b/Alc/ambdec.c @@ -164,7 +164,7 @@ static int load_ambdec_speakers(AmbDecConf *conf, FILE *f, char **buffer, size_t const char *conn = my_strtok_r(NULL, " \t", saveptr); if(!name) WARN("Name not specified for speaker %u\n", cur+1); - else al_string_copy_cstr(&conf->Speakers[cur].Name, name); + else alstr_copy_cstr(&conf->Speakers[cur].Name, name); if(!dist) WARN("Distance not specified for speaker %u\n", cur+1); else read_float(&conf->Speakers[cur].Distance, dist); if(!az) WARN("Azimuth not specified for speaker %u\n", cur+1); @@ -172,7 +172,7 @@ static int load_ambdec_speakers(AmbDecConf *conf, FILE *f, char **buffer, size_t if(!elev) WARN("Elevation not specified for speaker %u\n", cur+1); else read_float(&conf->Speakers[cur].Elevation, elev); if(!conn) TRACE("Connection not specified for speaker %u\n", cur+1); - else al_string_copy_cstr(&conf->Speakers[cur].Connection, conn); + else alstr_copy_cstr(&conf->Speakers[cur].Connection, conn); cur++; } @@ -293,11 +293,11 @@ void ambdec_deinit(AmbDecConf *conf) { ALsizei i; - al_string_deinit(&conf->Description); + alstr_reset(&conf->Description); for(i = 0;i < MAX_OUTPUT_CHANNELS;i++) { - al_string_deinit(&conf->Speakers[i].Name); - al_string_deinit(&conf->Speakers[i].Connection); + alstr_reset(&conf->Speakers[i].Name); + alstr_reset(&conf->Speakers[i].Connection); } memset(conf, 0, sizeof(*conf)); } @@ -331,7 +331,7 @@ int ambdec_load(AmbDecConf *conf, const char *fname) if(strcmp(command, "description") == 0) { char *value = my_strtok_r(NULL, "", &saveptr); - al_string_copy_cstr(&conf->Description, lstrip(value)); + alstr_copy_cstr(&conf->Description, lstrip(value)); } else if(strcmp(command, "version") == 0) { diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 2fa806ae..4a7b81ba 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -213,7 +213,7 @@ static ALCboolean alsa_load(void) p##f = GetSymbol(alsa_handle, #f); \ if(p##f == NULL) { \ error = ALC_TRUE; \ - al_string_append_cstr(&missing_funcs, "\n" #f); \ + alstr_append_cstr(&missing_funcs, "\n" #f); \ } \ } while(0) ALSA_FUNCS(LOAD_FUNC); @@ -221,11 +221,11 @@ static ALCboolean alsa_load(void) if(error) { - WARN("Missing expected functions:%s\n", al_string_get_cstr(missing_funcs)); + WARN("Missing expected functions:%s\n", alstr_get_cstr(missing_funcs)); CloseLib(alsa_handle); alsa_handle = NULL; } - al_string_deinit(&missing_funcs); + alstr_reset(&missing_funcs); } #endif @@ -276,8 +276,8 @@ static void probe_devices(snd_pcm_stream_t stream, vector_DevMap *DeviceList) AL_STRING_INIT(entry.name); AL_STRING_INIT(entry.device_name); - al_string_copy_cstr(&entry.name, alsaDevice); - al_string_copy_cstr(&entry.device_name, GetConfigValue(NULL, "alsa", (stream==SND_PCM_STREAM_PLAYBACK) ? + alstr_copy_cstr(&entry.name, alsaDevice); + alstr_copy_cstr(&entry.device_name, GetConfigValue(NULL, "alsa", (stream==SND_PCM_STREAM_PLAYBACK) ? "device" : "capture", "default")); VECTOR_PUSH_BACK(*DeviceList, entry); @@ -344,8 +344,8 @@ static void probe_devices(snd_pcm_stream_t stream, vector_DevMap *DeviceList) TRACE("Got device \"%s\", \"%s\"\n", name, device); AL_STRING_INIT(entry.name); AL_STRING_INIT(entry.device_name); - al_string_copy_cstr(&entry.name, name); - al_string_copy_cstr(&entry.device_name, device); + alstr_copy_cstr(&entry.name, name); + alstr_copy_cstr(&entry.device_name, device); VECTOR_PUSH_BACK(*DeviceList, entry); } snd_ctl_close(handle); @@ -636,12 +636,12 @@ static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name) if(VECTOR_SIZE(PlaybackDevices) == 0) probe_devices(SND_PCM_STREAM_PLAYBACK, &PlaybackDevices); -#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, name) == 0) +#define MATCH_NAME(i) (alstr_cmp_cstr((i)->name, name) == 0) VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); #undef MATCH_NAME if(iter == VECTOR_END(PlaybackDevices)) return ALC_INVALID_VALUE; - driver = al_string_get_cstr(iter->device_name); + driver = alstr_get_cstr(iter->device_name); } else { @@ -660,7 +660,7 @@ static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name) /* Free alsa's global config tree. Otherwise valgrind reports a ton of leaks. */ snd_config_update_free_global(); - al_string_copy_cstr(&device->DeviceName, name); + alstr_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } @@ -711,7 +711,7 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self) break; } - allowmmap = GetConfigValueBool(al_string_get_cstr(device->DeviceName), "alsa", "mmap", 1); + allowmmap = GetConfigValueBool(alstr_get_cstr(device->DeviceName), "alsa", "mmap", 1); periods = device->NumUpdates; periodLen = (ALuint64)device->UpdateSize * 1000000 / device->Frequency; bufferLen = periodLen * periods; @@ -777,7 +777,7 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self) } CHECK(snd_pcm_hw_params_set_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans))); /* set rate (implicitly constrains period/buffer parameters) */ - if(!GetConfigValueBool(al_string_get_cstr(device->DeviceName), "alsa", "allow-resampler", 0) || + if(!GetConfigValueBool(alstr_get_cstr(device->DeviceName), "alsa", "allow-resampler", 0) || !(device->Flags&DEVICE_FREQUENCY_REQUEST)) { if(snd_pcm_hw_params_set_rate_resample(self->pcmHandle, hp, 0) < 0) @@ -977,12 +977,12 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name) if(VECTOR_SIZE(CaptureDevices) == 0) probe_devices(SND_PCM_STREAM_CAPTURE, &CaptureDevices); -#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, name) == 0) +#define MATCH_NAME(i) (alstr_cmp_cstr((i)->name, name) == 0) VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); #undef MATCH_NAME if(iter == VECTOR_END(CaptureDevices)) return ALC_INVALID_VALUE; - driver = al_string_get_cstr(iter->device_name); + driver = alstr_get_cstr(iter->device_name); } else { @@ -1072,7 +1072,7 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name) } } - al_string_copy_cstr(&device->DeviceName, name); + alstr_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; @@ -1314,9 +1314,9 @@ static ClockLatency ALCcaptureAlsa_getClockLatency(ALCcaptureAlsa *self) static inline void AppendAllDevicesList2(const DevMap *entry) -{ AppendAllDevicesList(al_string_get_cstr(entry->name)); } +{ AppendAllDevicesList(alstr_get_cstr(entry->name)); } static inline void AppendCaptureDeviceList2(const DevMap *entry) -{ AppendCaptureDeviceList(al_string_get_cstr(entry->name)); } +{ AppendCaptureDeviceList(alstr_get_cstr(entry->name)); } typedef struct ALCalsaBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index eb93f9ea..5e0b03bd 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -183,7 +183,7 @@ static ALCenum ca_open_playback(ALCdevice *device, const ALCchar *deviceName) return ALC_INVALID_VALUE; } - al_string_copy_cstr(&device->DeviceName, deviceName); + alstr_copy_cstr(&device->DeviceName, deviceName); device->ExtraData = data; return ALC_NO_ERROR; } @@ -596,7 +596,7 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) ); if(!data->ring) goto error; - al_string_copy_cstr(&device->DeviceName, deviceName); + alstr_copy_cstr(&device->DeviceName, deviceName); return ALC_NO_ERROR; diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index 084d1125..3dc297ff 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -145,16 +145,16 @@ static BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHA { const DevMap *iter; - al_string_copy_cstr(&entry.name, DEVNAME_HEAD); - al_string_append_wcstr(&entry.name, desc); + alstr_copy_cstr(&entry.name, DEVNAME_HEAD); + alstr_append_wcstr(&entry.name, desc); if(count != 0) { char str[64]; snprintf(str, sizeof(str), " #%d", count+1); - al_string_append_cstr(&entry.name, str); + alstr_append_cstr(&entry.name, str); } -#define MATCH_ENTRY(i) (al_string_cmp(entry.name, (i)->name) == 0) +#define MATCH_ENTRY(i) (alstr_cmp(entry.name, (i)->name) == 0) VECTOR_FIND_IF(iter, const DevMap, *devices, MATCH_ENTRY); if(iter == VECTOR_END(*devices)) break; #undef MATCH_ENTRY @@ -165,7 +165,7 @@ static BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHA hr = StringFromCLSID(guid, &guidstr); if(SUCCEEDED(hr)) { - TRACE("Got device \"%s\", GUID \"%ls\"\n", al_string_get_cstr(entry.name), guidstr); + TRACE("Got device \"%s\", GUID \"%ls\"\n", alstr_get_cstr(entry.name), guidstr); CoTaskMemFree(guidstr); } @@ -343,14 +343,14 @@ static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *de if(!deviceName && VECTOR_SIZE(PlaybackDevices) > 0) { - deviceName = al_string_get_cstr(VECTOR_FRONT(PlaybackDevices).name); + deviceName = alstr_get_cstr(VECTOR_FRONT(PlaybackDevices).name); guid = &VECTOR_FRONT(PlaybackDevices).guid; } else { const DevMap *iter; -#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, deviceName) == 0) +#define MATCH_NAME(i) (alstr_cmp_cstr((i)->name, deviceName) == 0) VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); #undef MATCH_NAME if(iter == VECTOR_END(PlaybackDevices)) @@ -381,7 +381,7 @@ static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *de return ALC_INVALID_VALUE; } - al_string_copy_cstr(&device->DeviceName, deviceName); + alstr_copy_cstr(&device->DeviceName, deviceName); return ALC_NO_ERROR; } @@ -706,14 +706,14 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi if(!deviceName && VECTOR_SIZE(CaptureDevices) > 0) { - deviceName = al_string_get_cstr(VECTOR_FRONT(CaptureDevices).name); + deviceName = alstr_get_cstr(VECTOR_FRONT(CaptureDevices).name); guid = &VECTOR_FRONT(CaptureDevices).guid; } else { const DevMap *iter; -#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, deviceName) == 0) +#define MATCH_NAME(i) (alstr_cmp_cstr((i)->name, deviceName) == 0) VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); #undef MATCH_NAME if(iter == VECTOR_END(CaptureDevices)) @@ -855,7 +855,7 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi self->BufferBytes = DSCBDescription.dwBufferBytes; SetDefaultWFXChannelOrder(device); - al_string_copy_cstr(&device->DeviceName, deviceName); + alstr_copy_cstr(&device->DeviceName, deviceName); return ALC_NO_ERROR; } @@ -958,9 +958,9 @@ done: static inline void AppendAllDevicesList2(const DevMap *entry) -{ AppendAllDevicesList(al_string_get_cstr(entry->name)); } +{ AppendAllDevicesList(alstr_get_cstr(entry->name)); } static inline void AppendCaptureDeviceList2(const DevMap *entry) -{ AppendCaptureDeviceList(al_string_get_cstr(entry->name)); } +{ AppendCaptureDeviceList(alstr_get_cstr(entry->name)); } typedef struct ALCdsoundBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index f1cd82bd..cce828e9 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -115,7 +115,7 @@ static ALCboolean jack_load(void) p##f = GetSymbol(jack_handle, #f); \ if(p##f == NULL) { \ error = ALC_TRUE; \ - al_string_append_cstr(&missing_funcs, "\n" #f); \ + alstr_append_cstr(&missing_funcs, "\n" #f); \ } \ } while(0) JACK_FUNCS(LOAD_FUNC); @@ -123,11 +123,11 @@ static ALCboolean jack_load(void) if(error) { - WARN("Missing expected functions:%s\n", al_string_get_cstr(missing_funcs)); + WARN("Missing expected functions:%s\n", alstr_get_cstr(missing_funcs)); CloseLib(jack_handle); jack_handle = NULL; } - al_string_deinit(&missing_funcs); + alstr_reset(&missing_funcs); } #endif @@ -220,7 +220,7 @@ static int ALCjackPlayback_bufferSizeNotify(jack_nframes_t numframes, void *arg) device->NumUpdates = 2; bufsize = device->UpdateSize; - if(ConfigValueUInt(al_string_get_cstr(device->DeviceName), "jack", "buffer-size", &bufsize)) + if(ConfigValueUInt(alstr_get_cstr(device->DeviceName), "jack", "buffer-size", &bufsize)) bufsize = maxu(NextPowerOf2(bufsize), device->UpdateSize); bufsize += device->UpdateSize; device->NumUpdates = bufsize / device->UpdateSize; @@ -373,7 +373,7 @@ static ALCenum ALCjackPlayback_open(ALCjackPlayback *self, const ALCchar *name) jack_set_process_callback(self->Client, ALCjackPlayback_process, self); jack_set_buffer_size_callback(self->Client, ALCjackPlayback_bufferSizeNotify, self); - al_string_copy_cstr(&device->DeviceName, name); + alstr_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } @@ -415,7 +415,7 @@ static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self) device->NumUpdates = 2; bufsize = device->UpdateSize; - if(ConfigValueUInt(al_string_get_cstr(device->DeviceName), "jack", "buffer-size", &bufsize)) + if(ConfigValueUInt(alstr_get_cstr(device->DeviceName), "jack", "buffer-size", &bufsize)) bufsize = maxu(NextPowerOf2(bufsize), device->UpdateSize); bufsize += device->UpdateSize; device->NumUpdates = bufsize / device->UpdateSize; diff --git a/Alc/backends/loopback.c b/Alc/backends/loopback.c index 0164bc5a..8f23aad9 100644 --- a/Alc/backends/loopback.c +++ b/Alc/backends/loopback.c @@ -59,7 +59,7 @@ static ALCenum ALCloopback_open(ALCloopback *self, const ALCchar *name) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - al_string_copy_cstr(&device->DeviceName, name); + alstr_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 6ff9d931..339ea8d3 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -130,14 +130,14 @@ static void get_device_name_and_guid(IMMDevice *device, al_string *name, al_stri PROPVARIANT pvguid; HRESULT hr; - al_string_copy_cstr(name, DEVNAME_HEAD); + alstr_copy_cstr(name, DEVNAME_HEAD); hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps); if(FAILED(hr)) { WARN("OpenPropertyStore failed: 0x%08lx\n", hr); - al_string_append_cstr(name, "Unknown Device Name"); - if(guid!=NULL)al_string_copy_cstr(guid, "Unknown Device GUID"); + alstr_append_cstr(name, "Unknown Device Name"); + if(guid!=NULL)alstr_copy_cstr(guid, "Unknown Device GUID"); return; } @@ -147,14 +147,14 @@ static void get_device_name_and_guid(IMMDevice *device, al_string *name, al_stri if(FAILED(hr)) { WARN("GetValue Device_FriendlyName failed: 0x%08lx\n", hr); - al_string_append_cstr(name, "Unknown Device Name"); + alstr_append_cstr(name, "Unknown Device Name"); } else if(pvname.vt == VT_LPWSTR) - al_string_append_wcstr(name, pvname.pwszVal); + alstr_append_wcstr(name, pvname.pwszVal); else { WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvname.vt); - al_string_append_cstr(name, "Unknown Device Name"); + alstr_append_cstr(name, "Unknown Device Name"); } PropVariantClear(&pvname); @@ -165,14 +165,14 @@ static void get_device_name_and_guid(IMMDevice *device, al_string *name, al_stri if(FAILED(hr)) { WARN("GetValue AudioEndpoint_GUID failed: 0x%08lx\n", hr); - al_string_copy_cstr(guid, "Unknown Device GUID"); + alstr_copy_cstr(guid, "Unknown Device GUID"); } else if(pvguid.vt == VT_LPWSTR) - al_string_copy_wcstr(guid, pvguid.pwszVal); + alstr_copy_wcstr(guid, pvguid.pwszVal); else { WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvguid.vt); - al_string_copy_cstr(guid, "Unknown Device GUID"); + alstr_copy_cstr(guid, "Unknown Device GUID"); } PropVariantClear(&pvguid); @@ -228,22 +228,22 @@ static void add_device(IMMDevice *device, const WCHAR *devid, vector_DevMap *lis { const DevMap *iter; - al_string_copy(&entry.name, tmpname); + alstr_copy(&entry.name, tmpname); if(count != 0) { char str[64]; snprintf(str, sizeof(str), " #%d", count+1); - al_string_append_cstr(&entry.name, str); + alstr_append_cstr(&entry.name, str); } -#define MATCH_ENTRY(i) (al_string_cmp(entry.name, (i)->name) == 0) +#define MATCH_ENTRY(i) (alstr_cmp(entry.name, (i)->name) == 0) VECTOR_FIND_IF(iter, const DevMap, *list, MATCH_ENTRY); if(iter == VECTOR_END(*list)) break; #undef MATCH_ENTRY count++; } - TRACE("Got device \"%s\", \"%s\", \"%ls\"\n", al_string_get_cstr(entry.name), al_string_get_cstr(entry.endpoint_guid), entry.devid); + TRACE("Got device \"%s\", \"%s\", \"%ls\"\n", alstr_get_cstr(entry.name), alstr_get_cstr(entry.endpoint_guid), entry.devid); VECTOR_PUSH_BACK(*list, entry); AL_STRING_DEINIT(tmpname); @@ -716,8 +716,8 @@ static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *devi } hr = E_FAIL; -#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, deviceName) == 0 || \ - al_string_cmp_cstr((i)->endpoint_guid, deviceName) == 0) +#define MATCH_NAME(i) (alstr_cmp_cstr((i)->name, deviceName) == 0 || \ + alstr_cmp_cstr((i)->endpoint_guid, deviceName) == 0) VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); #undef MATCH_NAME if(iter == VECTOR_END(PlaybackDevices)) @@ -739,7 +739,7 @@ static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *devi { ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; self->devid = strdupW(iter->devid); - al_string_copy(&device->DeviceName, iter->name); + alstr_copy(&device->DeviceName, iter->name); hr = S_OK; } } @@ -797,7 +797,7 @@ static HRESULT ALCmmdevPlayback_openProxy(ALCmmdevPlayback *self) if(SUCCEEDED(hr)) { self->client = ptr; - if(al_string_empty(device->DeviceName)) + if(alstr_empty(device->DeviceName)) get_device_name_and_guid(self->mmdev, &device->DeviceName, NULL); } @@ -1377,8 +1377,8 @@ static ALCenum ALCmmdevCapture_open(ALCmmdevCapture *self, const ALCchar *device } hr = E_FAIL; -#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, deviceName) == 0 || \ - al_string_cmp_cstr((i)->endpoint_guid, deviceName) == 0) +#define MATCH_NAME(i) (alstr_cmp_cstr((i)->name, deviceName) == 0 || \ + alstr_cmp_cstr((i)->endpoint_guid, deviceName) == 0) VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); #undef MATCH_NAME if(iter == VECTOR_END(CaptureDevices)) @@ -1400,7 +1400,7 @@ static ALCenum ALCmmdevCapture_open(ALCmmdevCapture *self, const ALCchar *device { ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; self->devid = strdupW(iter->devid); - al_string_copy(&device->DeviceName, iter->name); + alstr_copy(&device->DeviceName, iter->name); hr = S_OK; } } @@ -1476,7 +1476,7 @@ static HRESULT ALCmmdevCapture_openProxy(ALCmmdevCapture *self) if(SUCCEEDED(hr)) { self->client = ptr; - if(al_string_empty(device->DeviceName)) + if(alstr_empty(device->DeviceName)) get_device_name_and_guid(self->mmdev, &device->DeviceName, NULL); } @@ -1777,9 +1777,9 @@ ALCenum ALCmmdevCapture_captureSamples(ALCmmdevCapture *self, ALCvoid *buffer, A static inline void AppendAllDevicesList2(const DevMap *entry) -{ AppendAllDevicesList(al_string_get_cstr(entry->name)); } +{ AppendAllDevicesList(alstr_get_cstr(entry->name)); } static inline void AppendCaptureDeviceList2(const DevMap *entry) -{ AppendCaptureDeviceList(al_string_get_cstr(entry->name)); } +{ AppendCaptureDeviceList(alstr_get_cstr(entry->name)); } typedef struct ALCmmdevBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); diff --git a/Alc/backends/null.c b/Alc/backends/null.c index 41636538..e8c43782 100644 --- a/Alc/backends/null.c +++ b/Alc/backends/null.c @@ -130,7 +130,7 @@ static ALCenum ALCnullBackend_open(ALCnullBackend *self, const ALCchar *name) return ALC_INVALID_VALUE; device = STATIC_CAST(ALCbackend, self)->mDevice; - al_string_copy_cstr(&device->DeviceName, name); + alstr_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index b8d6d29a..41f55120 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -399,7 +399,7 @@ static ALCenum ALCopenslPlayback_open(ALCopenslPlayback *self, const ALCchar *na return ALC_INVALID_VALUE; } - al_string_copy_cstr(&device->DeviceName, name); + alstr_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index b22e87ba..6706405d 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -374,7 +374,7 @@ static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name) return ALC_INVALID_VALUE; } - al_string_copy_cstr(&device->DeviceName, name); + alstr_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } @@ -717,7 +717,7 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) return ALC_OUT_OF_MEMORY; } - al_string_copy_cstr(&device->DeviceName, name); + alstr_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } diff --git a/Alc/backends/portaudio.c b/Alc/backends/portaudio.c index 129b0606..b713f330 100644 --- a/Alc/backends/portaudio.c +++ b/Alc/backends/portaudio.c @@ -245,7 +245,7 @@ retry_open: return ALC_INVALID_VALUE; } - al_string_copy_cstr(&device->DeviceName, name); + alstr_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; @@ -445,7 +445,7 @@ static ALCenum ALCportCapture_open(ALCportCapture *self, const ALCchar *name) return ALC_INVALID_VALUE; } - al_string_copy_cstr(&device->DeviceName, name); + alstr_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index 14b37ee6..79ca38e5 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -202,7 +202,7 @@ static ALCboolean pulse_load(void) p##x = GetSymbol(pa_handle, #x); \ if(!(p##x)) { \ ret = ALC_FALSE; \ - al_string_append_cstr(&missing_funcs, "\n" #x); \ + alstr_append_cstr(&missing_funcs, "\n" #x); \ } \ } while(0) LOAD_FUNC(pa_context_unref); @@ -276,11 +276,11 @@ static ALCboolean pulse_load(void) if(ret == ALC_FALSE) { - WARN("Missing expected functions:%s\n", al_string_get_cstr(missing_funcs)); + WARN("Missing expected functions:%s\n", alstr_get_cstr(missing_funcs)); CloseLib(pa_handle); pa_handle = NULL; } - al_string_deinit(&missing_funcs); + alstr_reset(&missing_funcs); } #endif /* HAVE_DYNLOAD */ return ret; @@ -533,7 +533,7 @@ static void ALCpulsePlayback_deviceCallback(pa_context *UNUSED(context), const p return; } -#define MATCH_INFO_NAME(iter) (al_string_cmp_cstr((iter)->device_name, info->name) == 0) +#define MATCH_INFO_NAME(iter) (alstr_cmp_cstr((iter)->device_name, info->name) == 0) VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_INFO_NAME); if(iter != VECTOR_END(PlaybackDevices)) return; #undef MATCH_INFO_NAME @@ -541,27 +541,27 @@ static void ALCpulsePlayback_deviceCallback(pa_context *UNUSED(context), const p AL_STRING_INIT(entry.name); AL_STRING_INIT(entry.device_name); - al_string_copy_cstr(&entry.device_name, info->name); + alstr_copy_cstr(&entry.device_name, info->name); count = 0; while(1) { - al_string_copy_cstr(&entry.name, info->description); + alstr_copy_cstr(&entry.name, info->description); if(count != 0) { char str[64]; snprintf(str, sizeof(str), " #%d", count+1); - al_string_append_cstr(&entry.name, str); + alstr_append_cstr(&entry.name, str); } -#define MATCH_ENTRY(i) (al_string_cmp(entry.name, (i)->name) == 0) +#define MATCH_ENTRY(i) (alstr_cmp(entry.name, (i)->name) == 0) VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_ENTRY); if(iter == VECTOR_END(PlaybackDevices)) break; #undef MATCH_ENTRY count++; } - TRACE("Got device \"%s\", \"%s\"\n", al_string_get_cstr(entry.name), al_string_get_cstr(entry.device_name)); + TRACE("Got device \"%s\", \"%s\"\n", alstr_get_cstr(entry.name), alstr_get_cstr(entry.device_name)); VECTOR_PUSH_BACK(PlaybackDevices, entry); } @@ -737,7 +737,7 @@ static void ALCpulsePlayback_sinkNameCallback(pa_context *UNUSED(context), const return; } - al_string_copy_cstr(&device->DeviceName, info->description); + alstr_copy_cstr(&device->DeviceName, info->description); } @@ -745,9 +745,9 @@ static void ALCpulsePlayback_streamMovedCallback(pa_stream *stream, void *pdata) { ALCpulsePlayback *self = pdata; - al_string_copy_cstr(&self->device_name, pa_stream_get_device_name(stream)); + alstr_copy_cstr(&self->device_name, pa_stream_get_device_name(stream)); - TRACE("Stream moved to %s\n", al_string_get_cstr(self->device_name)); + TRACE("Stream moved to %s\n", alstr_get_cstr(self->device_name)); } @@ -866,12 +866,12 @@ static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name if(VECTOR_SIZE(PlaybackDevices) == 0) ALCpulsePlayback_probeDevices(); -#define MATCH_NAME(iter) (al_string_cmp_cstr((iter)->name, name) == 0) +#define MATCH_NAME(iter) (alstr_cmp_cstr((iter)->name, name) == 0) VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); #undef MATCH_NAME if(iter == VECTOR_END(PlaybackDevices)) return ALC_INVALID_VALUE; - pulse_name = al_string_get_cstr(iter->device_name); + pulse_name = alstr_get_cstr(iter->device_name); dev_name = iter->name; } @@ -902,11 +902,11 @@ static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name } pa_stream_set_moved_callback(self->stream, ALCpulsePlayback_streamMovedCallback, self); - al_string_copy_cstr(&self->device_name, pa_stream_get_device_name(self->stream)); - if(al_string_empty(dev_name)) + alstr_copy_cstr(&self->device_name, pa_stream_get_device_name(self->stream)); + if(alstr_empty(dev_name)) { pa_operation *o = pa_context_get_sink_info_by_name( - self->context, al_string_get_cstr(self->device_name), + self->context, alstr_get_cstr(self->device_name), ALCpulsePlayback_sinkNameCallback, self ); wait_for_operation(o, self->loop); @@ -914,7 +914,7 @@ static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name else { ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; - al_string_copy(&device->DeviceName, dev_name); + alstr_copy(&device->DeviceName, dev_name); } pa_threaded_mainloop_unlock(self->loop); @@ -929,7 +929,7 @@ static void ALCpulsePlayback_close(ALCpulsePlayback *self) self->context = NULL; self->stream = NULL; - al_string_clear(&self->device_name); + alstr_clear(&self->device_name); } static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) @@ -954,11 +954,11 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) self->stream = NULL; } - o = pa_context_get_sink_info_by_name(self->context, al_string_get_cstr(self->device_name), + o = pa_context_get_sink_info_by_name(self->context, alstr_get_cstr(self->device_name), ALCpulsePlayback_sinkInfoCallback, self); wait_for_operation(o, self->loop); - if(GetConfigValueBool(al_string_get_cstr(device->DeviceName), "pulse", "fix-rate", 0) || + if(GetConfigValueBool(alstr_get_cstr(device->DeviceName), "pulse", "fix-rate", 0) || !(device->Flags&DEVICE_FREQUENCY_REQUEST)) flags |= PA_STREAM_FIX_RATE; flags |= PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE; @@ -1044,7 +1044,7 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) self->attr.tlength = self->attr.minreq * maxu(device->NumUpdates, 2); self->attr.maxlength = -1; - self->stream = ALCpulsePlayback_connectStream(al_string_get_cstr(self->device_name), + self->stream = ALCpulsePlayback_connectStream(alstr_get_cstr(self->device_name), self->loop, self->context, flags, &self->attr, &self->spec, &chanmap); if(!self->stream) @@ -1261,7 +1261,7 @@ static void ALCpulseCapture_deviceCallback(pa_context *UNUSED(context), const pa return; } -#define MATCH_INFO_NAME(iter) (al_string_cmp_cstr((iter)->device_name, info->name) == 0) +#define MATCH_INFO_NAME(iter) (alstr_cmp_cstr((iter)->device_name, info->name) == 0) VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_INFO_NAME); if(iter != VECTOR_END(CaptureDevices)) return; #undef MATCH_INFO_NAME @@ -1269,27 +1269,27 @@ static void ALCpulseCapture_deviceCallback(pa_context *UNUSED(context), const pa AL_STRING_INIT(entry.name); AL_STRING_INIT(entry.device_name); - al_string_copy_cstr(&entry.device_name, info->name); + alstr_copy_cstr(&entry.device_name, info->name); count = 0; while(1) { - al_string_copy_cstr(&entry.name, info->description); + alstr_copy_cstr(&entry.name, info->description); if(count != 0) { char str[64]; snprintf(str, sizeof(str), " #%d", count+1); - al_string_append_cstr(&entry.name, str); + alstr_append_cstr(&entry.name, str); } -#define MATCH_ENTRY(i) (al_string_cmp(entry.name, (i)->name) == 0) +#define MATCH_ENTRY(i) (alstr_cmp(entry.name, (i)->name) == 0) VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_ENTRY); if(iter == VECTOR_END(CaptureDevices)) break; #undef MATCH_ENTRY count++; } - TRACE("Got device \"%s\", \"%s\"\n", al_string_get_cstr(entry.name), al_string_get_cstr(entry.device_name)); + TRACE("Got device \"%s\", \"%s\"\n", alstr_get_cstr(entry.name), alstr_get_cstr(entry.device_name)); VECTOR_PUSH_BACK(CaptureDevices, entry); } @@ -1382,7 +1382,7 @@ static void ALCpulseCapture_sourceNameCallback(pa_context *UNUSED(context), cons return; } - al_string_copy_cstr(&device->DeviceName, info->description); + alstr_copy_cstr(&device->DeviceName, info->description); } @@ -1390,9 +1390,9 @@ static void ALCpulseCapture_streamMovedCallback(pa_stream *stream, void *pdata) { ALCpulseCapture *self = pdata; - al_string_copy_cstr(&self->device_name, pa_stream_get_device_name(stream)); + alstr_copy_cstr(&self->device_name, pa_stream_get_device_name(stream)); - TRACE("Stream moved to %s\n", al_string_get_cstr(self->device_name)); + TRACE("Stream moved to %s\n", alstr_get_cstr(self->device_name)); } @@ -1452,13 +1452,13 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name) if(VECTOR_SIZE(CaptureDevices) == 0) ALCpulseCapture_probeDevices(); -#define MATCH_NAME(iter) (al_string_cmp_cstr((iter)->name, name) == 0) +#define MATCH_NAME(iter) (alstr_cmp_cstr((iter)->name, name) == 0) VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); #undef MATCH_NAME if(iter == VECTOR_END(CaptureDevices)) return ALC_INVALID_VALUE; - pulse_name = al_string_get_cstr(iter->device_name); - al_string_copy(&device->DeviceName, iter->name); + pulse_name = alstr_get_cstr(iter->device_name); + alstr_copy(&device->DeviceName, iter->name); } if(!pulse_open(&self->loop, &self->context, ALCpulseCapture_contextStateCallback, self)) @@ -1531,11 +1531,11 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name) pa_stream_set_moved_callback(self->stream, ALCpulseCapture_streamMovedCallback, self); pa_stream_set_state_callback(self->stream, ALCpulseCapture_streamStateCallback, self); - al_string_copy_cstr(&self->device_name, pa_stream_get_device_name(self->stream)); - if(al_string_empty(device->DeviceName)) + alstr_copy_cstr(&self->device_name, pa_stream_get_device_name(self->stream)); + if(alstr_empty(device->DeviceName)) { pa_operation *o = pa_context_get_source_info_by_name( - self->context, al_string_get_cstr(self->device_name), + self->context, alstr_get_cstr(self->device_name), ALCpulseCapture_sourceNameCallback, self ); wait_for_operation(o, self->loop); @@ -1560,7 +1560,7 @@ static void ALCpulseCapture_close(ALCpulseCapture *self) self->context = NULL; self->stream = NULL; - al_string_clear(&self->device_name); + alstr_clear(&self->device_name); } static ALCboolean ALCpulseCapture_start(ALCpulseCapture *self) @@ -1785,14 +1785,14 @@ static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory* UNUSED(self), e { case ALL_DEVICE_PROBE: ALCpulsePlayback_probeDevices(); -#define APPEND_ALL_DEVICES_LIST(e) AppendAllDevicesList(al_string_get_cstr((e)->name)) +#define APPEND_ALL_DEVICES_LIST(e) AppendAllDevicesList(alstr_get_cstr((e)->name)) VECTOR_FOR_EACH(const DevMap, PlaybackDevices, APPEND_ALL_DEVICES_LIST); #undef APPEND_ALL_DEVICES_LIST break; case CAPTURE_DEVICE_PROBE: ALCpulseCapture_probeDevices(); -#define APPEND_CAPTURE_DEVICE_LIST(e) AppendCaptureDeviceList(al_string_get_cstr((e)->name)) +#define APPEND_CAPTURE_DEVICE_LIST(e) AppendCaptureDeviceList(alstr_get_cstr((e)->name)) VECTOR_FOR_EACH(const DevMap, CaptureDevices, APPEND_CAPTURE_DEVICE_LIST); #undef APPEND_CAPTURE_DEVICE_LIST break; diff --git a/Alc/backends/qsa.c b/Alc/backends/qsa.c index dabe5ee9..9563a918 100644 --- a/Alc/backends/qsa.c +++ b/Alc/backends/qsa.c @@ -296,7 +296,7 @@ static ALCenum qsa_open_playback(ALCdevice* device, const ALCchar* deviceName) return ALC_INVALID_DEVICE; } - al_string_copy_cstr(&device->DeviceName, deviceName); + alstr_copy_cstr(&device->DeviceName, deviceName); device->ExtraData = data; return ALC_NO_ERROR; @@ -643,7 +643,7 @@ static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName) return ALC_INVALID_DEVICE; } - al_string_copy_cstr(&device->DeviceName, deviceName); + alstr_copy_cstr(&device->DeviceName, deviceName); device->ExtraData = data; switch (device->FmtType) diff --git a/Alc/backends/sndio.c b/Alc/backends/sndio.c index 00d7c654..ac2dc03f 100644 --- a/Alc/backends/sndio.c +++ b/Alc/backends/sndio.c @@ -145,7 +145,7 @@ static ALCenum ALCsndioBackend_open(ALCsndioBackend *self, const ALCchar *name) return ALC_INVALID_VALUE; } - al_string_copy_cstr(&device->DeviceName, name); + alstr_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c index c70e0b46..98c00525 100644 --- a/Alc/backends/solaris.c +++ b/Alc/backends/solaris.c @@ -185,7 +185,7 @@ static ALCenum ALCsolarisBackend_open(ALCsolarisBackend *self, const ALCchar *na } device = STATIC_CAST(ALCbackend,self)->mDevice; - al_string_copy_cstr(&device->DeviceName, name); + alstr_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index 1b13746e..36d7cbca 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -228,7 +228,7 @@ static ALCenum ALCwaveBackend_open(ALCwaveBackend *self, const ALCchar *name) } device = STATIC_CAST(ALCbackend, self)->mDevice; - al_string_copy_cstr(&device->DeviceName, name); + alstr_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index 2b6db4ad..da0d67a1 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -45,7 +45,7 @@ static vector_al_string CaptureDevices; static void clear_devlist(vector_al_string *list) { - VECTOR_FOR_EACH(al_string, *list, al_string_deinit); + VECTOR_FOR_EACH(al_string, *list, alstr_reset); VECTOR_RESIZE(*list, 0, 0); } @@ -71,23 +71,23 @@ static void ProbePlaybackDevices(void) ALuint count = 0; while(1) { - al_string_copy_cstr(&dname, DEVNAME_HEAD); - al_string_append_wcstr(&dname, WaveCaps.szPname); + alstr_copy_cstr(&dname, DEVNAME_HEAD); + alstr_append_wcstr(&dname, WaveCaps.szPname); if(count != 0) { char str[64]; snprintf(str, sizeof(str), " #%d", count+1); - al_string_append_cstr(&dname, str); + alstr_append_cstr(&dname, str); } count++; -#define MATCH_ENTRY(i) (al_string_cmp(dname, *(i)) == 0) +#define MATCH_ENTRY(i) (alstr_cmp(dname, *(i)) == 0) VECTOR_FIND_IF(iter, const al_string, PlaybackDevices, MATCH_ENTRY); if(iter == VECTOR_END(PlaybackDevices)) break; #undef MATCH_ENTRY } - TRACE("Got device \"%s\", ID %u\n", al_string_get_cstr(dname), i); + TRACE("Got device \"%s\", ID %u\n", alstr_get_cstr(dname), i); } VECTOR_PUSH_BACK(PlaybackDevices, dname); } @@ -114,23 +114,23 @@ static void ProbeCaptureDevices(void) ALuint count = 0; while(1) { - al_string_copy_cstr(&dname, DEVNAME_HEAD); - al_string_append_wcstr(&dname, WaveCaps.szPname); + alstr_copy_cstr(&dname, DEVNAME_HEAD); + alstr_append_wcstr(&dname, WaveCaps.szPname); if(count != 0) { char str[64]; snprintf(str, sizeof(str), " #%d", count+1); - al_string_append_cstr(&dname, str); + alstr_append_cstr(&dname, str); } count++; -#define MATCH_ENTRY(i) (al_string_cmp(dname, *(i)) == 0) +#define MATCH_ENTRY(i) (alstr_cmp(dname, *(i)) == 0) VECTOR_FIND_IF(iter, const al_string, CaptureDevices, MATCH_ENTRY); if(iter == VECTOR_END(CaptureDevices)) break; #undef MATCH_ENTRY } - TRACE("Got device \"%s\", ID %u\n", al_string_get_cstr(dname), i); + TRACE("Got device \"%s\", ID %u\n", alstr_get_cstr(dname), i); } VECTOR_PUSH_BACK(CaptureDevices, dname); } @@ -257,8 +257,8 @@ static ALCenum ALCwinmmPlayback_open(ALCwinmmPlayback *self, const ALCchar *devi ProbePlaybackDevices(); // Find the Device ID matching the deviceName if valid -#define MATCH_DEVNAME(iter) (!al_string_empty(*(iter)) && \ - (!deviceName || al_string_cmp_cstr(*(iter), deviceName) == 0)) +#define MATCH_DEVNAME(iter) (!alstr_empty(*(iter)) && \ + (!deviceName || alstr_cmp_cstr(*(iter), deviceName) == 0)) VECTOR_FIND_IF(iter, const al_string, PlaybackDevices, MATCH_DEVNAME); if(iter == VECTOR_END(PlaybackDevices)) return ALC_INVALID_VALUE; @@ -300,7 +300,7 @@ retry_open: goto failure; } - al_string_copy(&device->DeviceName, VECTOR_ELEM(PlaybackDevices, DeviceID)); + alstr_copy(&device->DeviceName, VECTOR_ELEM(PlaybackDevices, DeviceID)); return ALC_NO_ERROR; failure: @@ -544,7 +544,7 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name) ProbeCaptureDevices(); // Find the Device ID matching the deviceName if valid -#define MATCH_DEVNAME(iter) (!al_string_empty(*(iter)) && (!name || al_string_cmp_cstr(*iter, name) == 0)) +#define MATCH_DEVNAME(iter) (!alstr_empty(*(iter)) && (!name || alstr_cmp_cstr(*iter, name) == 0)) VECTOR_FIND_IF(iter, const al_string, CaptureDevices, MATCH_DEVNAME); if(iter == VECTOR_END(CaptureDevices)) return ALC_INVALID_VALUE; @@ -638,7 +638,7 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name) if(althrd_create(&self->thread, ALCwinmmCapture_captureProc, self) != althrd_success) goto failure; - al_string_copy(&device->DeviceName, VECTOR_ELEM(CaptureDevices, DeviceID)); + alstr_copy(&device->DeviceName, VECTOR_ELEM(CaptureDevices, DeviceID)); return ALC_NO_ERROR; failure: @@ -715,13 +715,13 @@ static ALCuint ALCwinmmCapture_availableSamples(ALCwinmmCapture *self) static inline void AppendAllDevicesList2(const al_string *name) { - if(!al_string_empty(*name)) - AppendAllDevicesList(al_string_get_cstr(*name)); + if(!alstr_empty(*name)) + AppendAllDevicesList(alstr_get_cstr(*name)); } static inline void AppendCaptureDeviceList2(const al_string *name) { - if(!al_string_empty(*name)) - AppendCaptureDeviceList(al_string_get_cstr(*name)); + if(!alstr_empty(*name)) + AppendCaptureDeviceList(alstr_get_cstr(*name)); } typedef struct ALCwinmmBackendFactory { diff --git a/Alc/helpers.c b/Alc/helpers.c index 1ce567b2..5d23c3a7 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -358,7 +358,7 @@ void RestoreFPUMode(const FPUCtl *ctl) static int StringSortCompare(const void *str1, const void *str2) { - return al_string_cmp(*(const_al_string*)str1, *(const_al_string*)str2); + return alstr_cmp(*(const_al_string*)str1, *(const_al_string*)str2); } #ifdef _WIN32 @@ -406,10 +406,10 @@ al_string GetProcPath(void) } else if((sep = strrchrW(pathname, '/'))) *sep = 0; - al_string_copy_wcstr(&ret, pathname); + alstr_copy_wcstr(&ret, pathname); free(pathname); - TRACE("Got: %s\n", al_string_get_cstr(ret)); + TRACE("Got: %s\n", alstr_get_cstr(ret)); return ret; } @@ -526,13 +526,13 @@ static void DirectorySearch(const char *path, const char *ext, vector_al_string WCHAR *wpath; HANDLE hdl; - al_string_copy_cstr(&pathstr, path); - al_string_append_cstr(&pathstr, "\\*"); - al_string_append_cstr(&pathstr, ext); + alstr_copy_cstr(&pathstr, path); + alstr_append_cstr(&pathstr, "\\*"); + alstr_append_cstr(&pathstr, ext); - TRACE("Searching %s\n", al_string_get_cstr(pathstr)); + TRACE("Searching %s\n", alstr_get_cstr(pathstr)); - wpath = FromUTF8(al_string_get_cstr(pathstr)); + wpath = FromUTF8(alstr_get_cstr(pathstr)); hdl = FindFirstFileW(wpath, &fdata); if(hdl != INVALID_HANDLE_VALUE) @@ -540,10 +540,10 @@ static void DirectorySearch(const char *path, const char *ext, vector_al_string size_t base = VECTOR_SIZE(*results); do { al_string str = AL_STRING_INIT_STATIC(); - al_string_copy_cstr(&str, path); - al_string_append_char(&str, '\\'); - al_string_append_wcstr(&str, fdata.cFileName); - TRACE("Got result %s\n", al_string_get_cstr(str)); + alstr_copy_cstr(&str, path); + alstr_append_char(&str, '\\'); + alstr_append_wcstr(&str, fdata.cFileName); + TRACE("Got result %s\n", alstr_get_cstr(str)); VECTOR_PUSH_BACK(*results, str); } while(FindNextFileW(hdl, &fdata)); FindClose(hdl); @@ -554,7 +554,7 @@ static void DirectorySearch(const char *path, const char *ext, vector_al_string } free(wpath); - al_string_deinit(&pathstr); + alstr_reset(&pathstr); } vector_al_string SearchDataFiles(const char *ext, const char *subdir) @@ -571,14 +571,14 @@ vector_al_string SearchDataFiles(const char *ext, const char *subdir) if(isalpha(subdir[0]) && subdir[1] == ':' && is_slash(subdir[2])) { al_string path = AL_STRING_INIT_STATIC(); - al_string_copy_cstr(&path, subdir); + alstr_copy_cstr(&path, subdir); #define FIX_SLASH(i) do { if(*(i) == '/') *(i) = '\\'; } while(0) VECTOR_FOR_EACH(char, path, FIX_SLASH); #undef FIX_SLASH - DirectorySearch(al_string_get_cstr(path), ext, &results); + DirectorySearch(alstr_get_cstr(path), ext, &results); - al_string_deinit(&path); + alstr_reset(&path); } else if(subdir[0] == '\\' && subdir[1] == '\\' && subdir[2] == '?' && subdir[3] == '\\') DirectorySearch(subdir, ext, &results); @@ -590,7 +590,7 @@ vector_al_string SearchDataFiles(const char *ext, const char *subdir) /* Search the app-local directory. */ if((cwdbuf=_wgetenv(L"ALSOFT_LOCAL_PATH")) && *cwdbuf != '\0') { - al_string_copy_wcstr(&path, cwdbuf); + alstr_copy_wcstr(&path, cwdbuf); if(is_slash(VECTOR_BACK(path))) { VECTOR_POP_BACK(path); @@ -598,10 +598,10 @@ vector_al_string SearchDataFiles(const char *ext, const char *subdir) } } else if(!(cwdbuf=_wgetcwd(NULL, 0))) - al_string_copy_cstr(&path, "."); + alstr_copy_cstr(&path, "."); else { - al_string_copy_wcstr(&path, cwdbuf); + alstr_copy_wcstr(&path, cwdbuf); if(is_slash(VECTOR_BACK(path))) { VECTOR_POP_BACK(path); @@ -612,7 +612,7 @@ vector_al_string SearchDataFiles(const char *ext, const char *subdir) #define FIX_SLASH(i) do { if(*(i) == '/') *(i) = '\\'; } while(0) VECTOR_FOR_EACH(char, path, FIX_SLASH); #undef FIX_SLASH - DirectorySearch(al_string_get_cstr(path), ext, &results); + DirectorySearch(alstr_get_cstr(path), ext, &results); /* Search the local and global data dirs. */ for(i = 0;i < COUNTOF(ids);i++) @@ -620,19 +620,19 @@ vector_al_string SearchDataFiles(const char *ext, const char *subdir) WCHAR buffer[PATH_MAX]; if(SHGetSpecialFolderPathW(NULL, buffer, ids[i], FALSE) != FALSE) { - al_string_copy_wcstr(&path, buffer); + alstr_copy_wcstr(&path, buffer); if(!is_slash(VECTOR_BACK(path))) - al_string_append_char(&path, '\\'); - al_string_append_cstr(&path, subdir); + alstr_append_char(&path, '\\'); + alstr_append_cstr(&path, subdir); #define FIX_SLASH(i) do { if(*(i) == '/') *(i) = '\\'; } while(0) VECTOR_FOR_EACH(char, path, FIX_SLASH); #undef FIX_SLASH - DirectorySearch(al_string_get_cstr(path), ext, &results); + DirectorySearch(alstr_get_cstr(path), ext, &results); } } - al_string_deinit(&path); + alstr_reset(&path); } ATOMIC_STORE_SEQ(&search_lock, 0); @@ -740,12 +740,12 @@ al_string GetProcPath(void) pathname[len] = 0; sep = strrchr(pathname, '/'); if(sep) - al_string_copy_range(&ret, pathname, sep); + alstr_copy_range(&ret, pathname, sep); else - al_string_copy_cstr(&ret, pathname); + alstr_copy_cstr(&ret, pathname); free(pathname); - TRACE("Got: %s\n", al_string_get_cstr(ret)); + TRACE("Got: %s\n", alstr_get_cstr(ret)); return ret; } @@ -820,11 +820,11 @@ static void DirectorySearch(const char *path, const char *ext, vector_al_string continue; AL_STRING_INIT(str); - al_string_copy_cstr(&str, path); + alstr_copy_cstr(&str, path); if(VECTOR_BACK(str) != '/') - al_string_append_char(&str, '/'); - al_string_append_cstr(&str, dirent->d_name); - TRACE("Got result %s\n", al_string_get_cstr(str)); + alstr_append_char(&str, '/'); + alstr_append_cstr(&str, dirent->d_name); + TRACE("Got result %s\n", alstr_get_cstr(str)); VECTOR_PUSH_BACK(*results, str); } closedir(dir); @@ -862,23 +862,23 @@ vector_al_string SearchDataFiles(const char *ext, const char *subdir) // Search local data dir if((str=getenv("XDG_DATA_HOME")) != NULL && str[0] != '\0') { - al_string_copy_cstr(&path, str); + alstr_copy_cstr(&path, str); if(VECTOR_BACK(path) != '/') - al_string_append_char(&path, '/'); - al_string_append_cstr(&path, subdir); - DirectorySearch(al_string_get_cstr(path), ext, &results); + alstr_append_char(&path, '/'); + alstr_append_cstr(&path, subdir); + DirectorySearch(alstr_get_cstr(path), ext, &results); } else if((str=getenv("HOME")) != NULL && str[0] != '\0') { - al_string_copy_cstr(&path, str); + alstr_copy_cstr(&path, str); if(VECTOR_BACK(path) == '/') { VECTOR_POP_BACK(path); *VECTOR_END(path) = 0; } - al_string_append_cstr(&path, "/.local/share/"); - al_string_append_cstr(&path, subdir); - DirectorySearch(al_string_get_cstr(path), ext, &results); + alstr_append_cstr(&path, "/.local/share/"); + alstr_append_cstr(&path, subdir); + DirectorySearch(alstr_get_cstr(path), ext, &results); } // Search global data dirs @@ -890,23 +890,23 @@ vector_al_string SearchDataFiles(const char *ext, const char *subdir) { next = strchr(str, ':'); if(!next) - al_string_copy_cstr(&path, str); + alstr_copy_cstr(&path, str); else { - al_string_copy_range(&path, str, next); + alstr_copy_range(&path, str, next); ++next; } - if(!al_string_empty(path)) + if(!alstr_empty(path)) { if(VECTOR_BACK(path) != '/') - al_string_append_char(&path, '/'); - al_string_append_cstr(&path, subdir); + alstr_append_char(&path, '/'); + alstr_append_cstr(&path, subdir); - DirectorySearch(al_string_get_cstr(path), ext, &results); + DirectorySearch(alstr_get_cstr(path), ext, &results); } } - al_string_deinit(&path); + alstr_reset(&path); } ATOMIC_STORE_SEQ(&search_lock, 0); @@ -983,14 +983,14 @@ void SetRTPriority(void) } -extern inline void al_string_deinit(al_string *str); -extern inline size_t al_string_length(const_al_string str); -extern inline ALboolean al_string_empty(const_al_string str); -extern inline const al_string_char_type *al_string_get_cstr(const_al_string str); +extern inline void alstr_reset(al_string *str); +extern inline size_t alstr_length(const_al_string str); +extern inline ALboolean alstr_empty(const_al_string str); +extern inline const al_string_char_type *alstr_get_cstr(const_al_string str); -void al_string_clear(al_string *str) +void alstr_clear(al_string *str) { - if(!al_string_empty(*str)) + if(!alstr_empty(*str)) { /* Reserve one more character than the total size of the string. This * is to ensure we have space to add a null terminator in the string @@ -1001,8 +1001,8 @@ void al_string_clear(al_string *str) } } -static inline int al_string_compare(const al_string_char_type *str1, size_t str1len, - const al_string_char_type *str2, size_t str2len) +static inline int alstr_compare(const al_string_char_type *str1, size_t str1len, + const al_string_char_type *str2, size_t str2len) { size_t complen = (str1len < str2len) ? str1len : str2len; int ret = memcmp(str1, str2, complen); @@ -1013,20 +1013,20 @@ static inline int al_string_compare(const al_string_char_type *str1, size_t str1 } return ret; } -int al_string_cmp(const_al_string str1, const_al_string str2) +int alstr_cmp(const_al_string str1, const_al_string str2) { - return al_string_compare(&VECTOR_FRONT(str1), al_string_length(str1), - &VECTOR_FRONT(str2), al_string_length(str2)); + return alstr_compare(&VECTOR_FRONT(str1), alstr_length(str1), + &VECTOR_FRONT(str2), alstr_length(str2)); } -int al_string_cmp_cstr(const_al_string str1, const al_string_char_type *str2) +int alstr_cmp_cstr(const_al_string str1, const al_string_char_type *str2) { - return al_string_compare(&VECTOR_FRONT(str1), al_string_length(str1), - str2, strlen(str2)); + return alstr_compare(&VECTOR_FRONT(str1), alstr_length(str1), + str2, strlen(str2)); } -void al_string_copy(al_string *str, const_al_string from) +void alstr_copy(al_string *str, const_al_string from) { - size_t len = al_string_length(from); + size_t len = alstr_length(from); size_t i; VECTOR_RESIZE(*str, len, len+1); @@ -1035,7 +1035,7 @@ void al_string_copy(al_string *str, const_al_string from) VECTOR_ELEM(*str, i) = 0; } -void al_string_copy_cstr(al_string *str, const al_string_char_type *from) +void alstr_copy_cstr(al_string *str, const al_string_char_type *from) { size_t len = strlen(from); size_t i; @@ -1046,7 +1046,7 @@ void al_string_copy_cstr(al_string *str, const al_string_char_type *from) VECTOR_ELEM(*str, i) = 0; } -void al_string_copy_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to) +void alstr_copy_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to) { size_t len = to - from; size_t i; @@ -1057,20 +1057,20 @@ void al_string_copy_range(al_string *str, const al_string_char_type *from, const VECTOR_ELEM(*str, i) = 0; } -void al_string_append_char(al_string *str, const al_string_char_type c) +void alstr_append_char(al_string *str, const al_string_char_type c) { - size_t len = al_string_length(*str); + size_t len = alstr_length(*str); VECTOR_RESIZE(*str, len, len+2); VECTOR_PUSH_BACK(*str, c); VECTOR_ELEM(*str, len+1) = 0; } -void al_string_append_cstr(al_string *str, const al_string_char_type *from) +void alstr_append_cstr(al_string *str, const al_string_char_type *from) { size_t len = strlen(from); if(len != 0) { - size_t base = al_string_length(*str); + size_t base = alstr_length(*str); size_t i; VECTOR_RESIZE(*str, base+len, base+len+1); @@ -1080,12 +1080,12 @@ void al_string_append_cstr(al_string *str, const al_string_char_type *from) } } -void al_string_append_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to) +void alstr_append_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to) { size_t len = to - from; if(len != 0) { - size_t base = al_string_length(*str); + size_t base = alstr_length(*str); size_t i; VECTOR_RESIZE(*str, base+len, base+len+1); @@ -1096,7 +1096,7 @@ void al_string_append_range(al_string *str, const al_string_char_type *from, con } #ifdef _WIN32 -void al_string_copy_wcstr(al_string *str, const wchar_t *from) +void alstr_copy_wcstr(al_string *str, const wchar_t *from) { int len; if((len=WideCharToMultiByte(CP_UTF8, 0, from, -1, NULL, 0, NULL, NULL)) > 0) @@ -1107,24 +1107,24 @@ void al_string_copy_wcstr(al_string *str, const wchar_t *from) } } -void al_string_append_wcstr(al_string *str, const wchar_t *from) +void alstr_append_wcstr(al_string *str, const wchar_t *from) { int len; if((len=WideCharToMultiByte(CP_UTF8, 0, from, -1, NULL, 0, NULL, NULL)) > 0) { - size_t base = al_string_length(*str); + size_t base = alstr_length(*str); VECTOR_RESIZE(*str, base+len-1, base+len); WideCharToMultiByte(CP_UTF8, 0, from, -1, &VECTOR_ELEM(*str, base), len, NULL, NULL); VECTOR_ELEM(*str, base+len-1) = 0; } } -void al_string_append_wrange(al_string *str, const wchar_t *from, const wchar_t *to) +void alstr_append_wrange(al_string *str, const wchar_t *from, const wchar_t *to) { int len; if((len=WideCharToMultiByte(CP_UTF8, 0, from, (int)(to-from), NULL, 0, NULL, NULL)) > 0) { - size_t base = al_string_length(*str); + size_t base = alstr_length(*str); VECTOR_RESIZE(*str, base+len, base+len+1); WideCharToMultiByte(CP_UTF8, 0, from, (int)(to-from), &VECTOR_ELEM(*str, base), len+1, NULL, NULL); VECTOR_ELEM(*str, base+len) = 0; diff --git a/Alc/hrtf.c b/Alc/hrtf.c index 2f6e9983..4634e6eb 100644 --- a/Alc/hrtf.c +++ b/Alc/hrtf.c @@ -252,7 +252,7 @@ static struct Hrtf *CreateHrtfStore(ALuint rate, ALsizei irSize, ALsizei evCount total = RoundUp(total, sizeof(ALfloat)); /* Align for float fields */ total += sizeof(Hrtf->coeffs[0])*irSize*irCount; total += sizeof(Hrtf->delays[0])*irCount; - total += al_string_length(filename)+1; + total += alstr_length(filename)+1; Hrtf = al_calloc(16, total); if(Hrtf == NULL) @@ -288,7 +288,7 @@ static struct Hrtf *CreateHrtfStore(ALuint rate, ALsizei irSize, ALsizei evCount offset += sizeof(_delays[0])*irCount; _name = (char*)(base + offset); Hrtf->filename = _name; - offset += sizeof(_name[0])*(al_string_length(filename)+1); + offset += sizeof(_name[0])*(alstr_length(filename)+1); Hrtf->next = NULL; @@ -298,7 +298,7 @@ static struct Hrtf *CreateHrtfStore(ALuint rate, ALsizei irSize, ALsizei evCount for(i = 0;i < irSize*irCount;i++) _coeffs[i] = coeffs[i] / 32768.0f; for(i = 0;i < irCount;i++) _delays[i] = delays[i]; - for(i = 0;i < (ALsizei)al_string_length(filename);i++) + for(i = 0;i < (ALsizei)alstr_length(filename);i++) _name[i] = VECTOR_ELEM(filename, i); _name[i] = '\0'; @@ -325,7 +325,7 @@ static struct Hrtf *LoadHrtf00(const ALubyte *data, size_t datalen, const_al_str if(datalen < 9) { ERR("Unexpected end of %s data (req %d, rem "SZFMT")\n", - al_string_get_cstr(filename), 9, datalen); + alstr_get_cstr(filename), 9, datalen); return NULL; } @@ -364,7 +364,7 @@ static struct Hrtf *LoadHrtf00(const ALubyte *data, size_t datalen, const_al_str if(datalen < evCount*2) { ERR("Unexpected end of %s data (req %d, rem "SZFMT")\n", - al_string_get_cstr(filename), evCount*2, datalen); + alstr_get_cstr(filename), evCount*2, datalen); return NULL; } @@ -433,7 +433,7 @@ static struct Hrtf *LoadHrtf00(const ALubyte *data, size_t datalen, const_al_str if(datalen < reqsize) { ERR("Unexpected end of %s data (req "SZFMT", rem "SZFMT")\n", - al_string_get_cstr(filename), reqsize, datalen); + alstr_get_cstr(filename), reqsize, datalen); failed = AL_TRUE; } } @@ -489,7 +489,7 @@ static struct Hrtf *LoadHrtf01(const ALubyte *data, size_t datalen, const_al_str if(datalen < 6) { ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n", - al_string_get_cstr(filename), 6, datalen); + alstr_get_cstr(filename), 6, datalen); return NULL; } @@ -523,7 +523,7 @@ static struct Hrtf *LoadHrtf01(const ALubyte *data, size_t datalen, const_al_str if(datalen < evCount) { ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n", - al_string_get_cstr(filename), evCount, datalen); + alstr_get_cstr(filename), evCount, datalen); return NULL; } @@ -575,7 +575,7 @@ static struct Hrtf *LoadHrtf01(const ALubyte *data, size_t datalen, const_al_str if(datalen < reqsize) { ERR("Unexpected end of %s data (req "SZFMT", rem "SZFMT"\n", - al_string_get_cstr(filename), reqsize, datalen); + alstr_get_cstr(filename), reqsize, datalen); failed = AL_TRUE; } } @@ -626,11 +626,11 @@ static void AddFileEntry(vector_HrtfEntry *list, const_al_string filename) const char *ext; int i; -#define MATCH_FNAME(i) (al_string_cmp_cstr(filename, (i)->hrtf->filename) == 0) +#define MATCH_FNAME(i) (alstr_cmp_cstr(filename, (i)->hrtf->filename) == 0) VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_FNAME); if(iter != VECTOR_END(*list)) { - TRACE("Skipping duplicate file entry %s\n", al_string_get_cstr(filename)); + TRACE("Skipping duplicate file entry %s\n", alstr_get_cstr(filename)); return; } #undef MATCH_FNAME @@ -638,24 +638,24 @@ static void AddFileEntry(vector_HrtfEntry *list, const_al_string filename) entry.hrtf = LoadedHrtfs; while(entry.hrtf) { - if(al_string_cmp_cstr(filename, entry.hrtf->filename) == 0) + if(alstr_cmp_cstr(filename, entry.hrtf->filename) == 0) { - TRACE("Skipping load of already-loaded file %s\n", al_string_get_cstr(filename)); + TRACE("Skipping load of already-loaded file %s\n", alstr_get_cstr(filename)); goto skip_load; } entry.hrtf = entry.hrtf->next; } - TRACE("Loading %s...\n", al_string_get_cstr(filename)); - fmap = MapFileToMem(al_string_get_cstr(filename)); + TRACE("Loading %s...\n", alstr_get_cstr(filename)); + fmap = MapFileToMem(alstr_get_cstr(filename)); if(fmap.ptr == NULL) { - ERR("Could not open %s\n", al_string_get_cstr(filename)); + ERR("Could not open %s\n", alstr_get_cstr(filename)); return; } if(fmap.len < sizeof(magicMarker01)) - ERR("%s data is too short ("SZFMT" bytes)\n", al_string_get_cstr(filename), fmap.len); + ERR("%s data is too short ("SZFMT" bytes)\n", alstr_get_cstr(filename), fmap.len); else if(memcmp(fmap.ptr, magicMarker01, sizeof(magicMarker01)) == 0) { TRACE("Detected data set format v1\n"); @@ -671,12 +671,12 @@ static void AddFileEntry(vector_HrtfEntry *list, const_al_string filename) ); } else - ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(filename), (const char*)fmap.ptr); + ERR("Invalid header in %s: \"%.8s\"\n", alstr_get_cstr(filename), (const char*)fmap.ptr); UnmapFileMem(&fmap); if(!hrtf) { - ERR("Failed to load %s\n", al_string_get_cstr(filename)); + ERR("Failed to load %s\n", alstr_get_cstr(filename)); return; } @@ -689,9 +689,9 @@ static void AddFileEntry(vector_HrtfEntry *list, const_al_string filename) skip_load: /* TODO: Get a human-readable name from the HRTF data (possibly coming in a * format update). */ - name = strrchr(al_string_get_cstr(filename), '/'); - if(!name) name = strrchr(al_string_get_cstr(filename), '\\'); - if(!name) name = al_string_get_cstr(filename); + name = strrchr(alstr_get_cstr(filename), '/'); + if(!name) name = strrchr(alstr_get_cstr(filename), '\\'); + if(!name) name = alstr_get_cstr(filename); else ++name; ext = strrchr(name, '.'); @@ -699,24 +699,24 @@ skip_load: i = 0; do { if(!ext) - al_string_copy_cstr(&entry.name, name); + alstr_copy_cstr(&entry.name, name); else - al_string_copy_range(&entry.name, name, ext); + alstr_copy_range(&entry.name, name, ext); if(i != 0) { char str[64]; snprintf(str, sizeof(str), " #%d", i+1); - al_string_append_cstr(&entry.name, str); + alstr_append_cstr(&entry.name, str); } ++i; -#define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0) +#define MATCH_NAME(i) (alstr_cmp(entry.name, (i)->name) == 0) VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_NAME); #undef MATCH_NAME } while(iter != VECTOR_END(*list)); - TRACE("Adding entry \"%s\" from file \"%s\"\n", al_string_get_cstr(entry.name), - al_string_get_cstr(filename)); + TRACE("Adding entry \"%s\" from file \"%s\"\n", alstr_get_cstr(entry.name), + alstr_get_cstr(filename)); VECTOR_PUSH_BACK(*list, entry); } @@ -730,11 +730,11 @@ static void AddBuiltInEntry(vector_HrtfEntry *list, const ALubyte *data, size_t const HrtfEntry *iter; int i; -#define MATCH_FNAME(i) (al_string_cmp_cstr(filename, (i)->hrtf->filename) == 0) +#define MATCH_FNAME(i) (alstr_cmp_cstr(filename, (i)->hrtf->filename) == 0) VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_FNAME); if(iter != VECTOR_END(*list)) { - TRACE("Skipping duplicate file entry %s\n", al_string_get_cstr(filename)); + TRACE("Skipping duplicate file entry %s\n", alstr_get_cstr(filename)); return; } #undef MATCH_FNAME @@ -742,18 +742,18 @@ static void AddBuiltInEntry(vector_HrtfEntry *list, const ALubyte *data, size_t entry.hrtf = LoadedHrtfs; while(entry.hrtf) { - if(al_string_cmp_cstr(filename, entry.hrtf->filename) == 0) + if(alstr_cmp_cstr(filename, entry.hrtf->filename) == 0) { - TRACE("Skipping load of already-loaded file %s\n", al_string_get_cstr(filename)); + TRACE("Skipping load of already-loaded file %s\n", alstr_get_cstr(filename)); goto skip_load; } entry.hrtf = entry.hrtf->next; } - TRACE("Loading %s...\n", al_string_get_cstr(filename)); + TRACE("Loading %s...\n", alstr_get_cstr(filename)); if(datalen < sizeof(magicMarker01)) { - ERR("%s data is too short ("SZFMT" bytes)\n", al_string_get_cstr(filename), datalen); + ERR("%s data is too short ("SZFMT" bytes)\n", alstr_get_cstr(filename), datalen); return; } @@ -772,11 +772,11 @@ static void AddBuiltInEntry(vector_HrtfEntry *list, const ALubyte *data, size_t ); } else - ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(filename), data); + ERR("Invalid header in %s: \"%.8s\"\n", alstr_get_cstr(filename), data); if(!hrtf) { - ERR("Failed to load %s\n", al_string_get_cstr(filename)); + ERR("Failed to load %s\n", alstr_get_cstr(filename)); return; } @@ -789,21 +789,21 @@ static void AddBuiltInEntry(vector_HrtfEntry *list, const ALubyte *data, size_t skip_load: i = 0; do { - al_string_copy(&entry.name, filename); + alstr_copy(&entry.name, filename); if(i != 0) { char str[64]; snprintf(str, sizeof(str), " #%d", i+1); - al_string_append_cstr(&entry.name, str); + alstr_append_cstr(&entry.name, str); } ++i; -#define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0) +#define MATCH_NAME(i) (alstr_cmp(entry.name, (i)->name) == 0) VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_NAME); #undef MATCH_NAME } while(iter != VECTOR_END(*list)); - TRACE("Adding built-in entry \"%s\"\n", al_string_get_cstr(entry.name)); + TRACE("Adding built-in entry \"%s\"\n", alstr_get_cstr(entry.name)); VECTOR_PUSH_BACK(*list, entry); } @@ -909,7 +909,7 @@ vector_HrtfEntry EnumerateHrtf(const_al_string devname) const char *pathlist = ""; bool usedefaults = true; - if(ConfigValueStr(al_string_get_cstr(devname), NULL, "hrtf-paths", &pathlist)) + if(ConfigValueStr(alstr_get_cstr(devname), NULL, "hrtf-paths", &pathlist)) { al_string pname = AL_STRING_INIT_STATIC(); while(pathlist && *pathlist) @@ -937,21 +937,21 @@ vector_HrtfEntry EnumerateHrtf(const_al_string devname) vector_al_string flist; size_t i; - al_string_append_range(&pname, pathlist, end); + alstr_append_range(&pname, pathlist, end); - flist = SearchDataFiles(".mhr", al_string_get_cstr(pname)); + flist = SearchDataFiles(".mhr", alstr_get_cstr(pname)); for(i = 0;i < VECTOR_SIZE(flist);i++) AddFileEntry(&list, VECTOR_ELEM(flist, i)); - VECTOR_FOR_EACH(al_string, flist, al_string_deinit); + VECTOR_FOR_EACH(al_string, flist, alstr_reset); VECTOR_DEINIT(flist); } pathlist = next; } - al_string_deinit(&pname); + alstr_reset(&pname); } - else if(ConfigValueExists(al_string_get_cstr(devname), NULL, "hrtf_tables")) + else if(ConfigValueExists(alstr_get_cstr(devname), NULL, "hrtf_tables")) ERR("The hrtf_tables option is deprecated, please use hrtf-paths instead.\n"); if(usedefaults) @@ -964,30 +964,30 @@ vector_HrtfEntry EnumerateHrtf(const_al_string devname) flist = SearchDataFiles(".mhr", "openal/hrtf"); for(i = 0;i < VECTOR_SIZE(flist);i++) AddFileEntry(&list, VECTOR_ELEM(flist, i)); - VECTOR_FOR_EACH(al_string, flist, al_string_deinit); + VECTOR_FOR_EACH(al_string, flist, alstr_reset); VECTOR_DEINIT(flist); rdata = GetResource(IDR_DEFAULT_44100_MHR, &rsize); if(rdata != NULL && rsize > 0) { - al_string_copy_cstr(&ename, "Built-In 44100hz"); + alstr_copy_cstr(&ename, "Built-In 44100hz"); AddBuiltInEntry(&list, rdata, rsize, ename); } rdata = GetResource(IDR_DEFAULT_48000_MHR, &rsize); if(rdata != NULL && rsize > 0) { - al_string_copy_cstr(&ename, "Built-In 48000hz"); + alstr_copy_cstr(&ename, "Built-In 48000hz"); AddBuiltInEntry(&list, rdata, rsize, ename); } - al_string_deinit(&ename); + alstr_reset(&ename); } - if(VECTOR_SIZE(list) > 1 && ConfigValueStr(al_string_get_cstr(devname), NULL, "default-hrtf", &defaulthrtf)) + if(VECTOR_SIZE(list) > 1 && ConfigValueStr(alstr_get_cstr(devname), NULL, "default-hrtf", &defaulthrtf)) { const HrtfEntry *iter; /* Find the preferred HRTF and move it to the front of the list. */ -#define FIND_ENTRY(i) (al_string_cmp_cstr((i)->name, defaulthrtf) == 0) +#define FIND_ENTRY(i) (alstr_cmp_cstr((i)->name, defaulthrtf) == 0) VECTOR_FIND_IF(iter, const HrtfEntry, list, FIND_ENTRY); #undef FIND_ENTRY if(iter == VECTOR_END(list)) @@ -1006,9 +1006,7 @@ vector_HrtfEntry EnumerateHrtf(const_al_string devname) void FreeHrtfList(vector_HrtfEntry *list) { -#define CLEAR_ENTRY(i) do { \ - al_string_deinit(&(i)->name); \ -} while(0) +#define CLEAR_ENTRY(i) alstr_reset(&(i)->name) VECTOR_FOR_EACH(HrtfEntry, *list, CLEAR_ENTRY); VECTOR_DEINIT(*list); #undef CLEAR_ENTRY diff --git a/Alc/panning.c b/Alc/panning.c index 0ff58c3a..ce86a561 100644 --- a/Alc/panning.c +++ b/Alc/panning.c @@ -386,45 +386,45 @@ static bool MakeSpeakerMap(ALCdevice *device, const AmbDecConf *conf, ALsizei sp * use the side channels when the device is configured for back, * and vice-versa. */ - if(al_string_cmp_cstr(conf->Speakers[i].Name, "LF") == 0) + if(alstr_cmp_cstr(conf->Speakers[i].Name, "LF") == 0) c = GetChannelIdxByName(device->RealOut, FrontLeft); - else if(al_string_cmp_cstr(conf->Speakers[i].Name, "RF") == 0) + else if(alstr_cmp_cstr(conf->Speakers[i].Name, "RF") == 0) c = GetChannelIdxByName(device->RealOut, FrontRight); - else if(al_string_cmp_cstr(conf->Speakers[i].Name, "CE") == 0) + else if(alstr_cmp_cstr(conf->Speakers[i].Name, "CE") == 0) c = GetChannelIdxByName(device->RealOut, FrontCenter); - else if(al_string_cmp_cstr(conf->Speakers[i].Name, "LS") == 0) + else if(alstr_cmp_cstr(conf->Speakers[i].Name, "LS") == 0) { if(device->FmtChans == DevFmtX51Rear) c = GetChannelIdxByName(device->RealOut, BackLeft); else c = GetChannelIdxByName(device->RealOut, SideLeft); } - else if(al_string_cmp_cstr(conf->Speakers[i].Name, "RS") == 0) + else if(alstr_cmp_cstr(conf->Speakers[i].Name, "RS") == 0) { if(device->FmtChans == DevFmtX51Rear) c = GetChannelIdxByName(device->RealOut, BackRight); else c = GetChannelIdxByName(device->RealOut, SideRight); } - else if(al_string_cmp_cstr(conf->Speakers[i].Name, "LB") == 0) + else if(alstr_cmp_cstr(conf->Speakers[i].Name, "LB") == 0) { if(device->FmtChans == DevFmtX51) c = GetChannelIdxByName(device->RealOut, SideLeft); else c = GetChannelIdxByName(device->RealOut, BackLeft); } - else if(al_string_cmp_cstr(conf->Speakers[i].Name, "RB") == 0) + else if(alstr_cmp_cstr(conf->Speakers[i].Name, "RB") == 0) { if(device->FmtChans == DevFmtX51) c = GetChannelIdxByName(device->RealOut, SideRight); else c = GetChannelIdxByName(device->RealOut, BackRight); } - else if(al_string_cmp_cstr(conf->Speakers[i].Name, "CB") == 0) + else if(alstr_cmp_cstr(conf->Speakers[i].Name, "CB") == 0) c = GetChannelIdxByName(device->RealOut, BackCenter); else { - const char *name = al_string_get_cstr(conf->Speakers[i].Name); + const char *name = alstr_get_cstr(conf->Speakers[i].Name); unsigned int n; char ch; @@ -439,7 +439,7 @@ static bool MakeSpeakerMap(ALCdevice *device, const AmbDecConf *conf, ALsizei sp if(c == -1) { ERR("Failed to lookup AmbDec speaker label %s\n", - al_string_get_cstr(conf->Speakers[i].Name)); + alstr_get_cstr(conf->Speakers[i].Name)); return false; } speakermap[i] = c; @@ -489,7 +489,7 @@ static const ChannelMap MonoCfg[1] = { static void InitNearFieldCtrl(ALCdevice *device, ALfloat ctrl_dist, ALsizei order, bool periphonic) { - const char *devname = al_string_get_cstr(device->DeviceName); + const char *devname = alstr_get_cstr(device->DeviceName); ALsizei i; if(GetConfigValueBool(devname, "decoder", "nfc", 1) && ctrl_dist > 0.0f) @@ -514,7 +514,7 @@ static void InitNearFieldCtrl(ALCdevice *device, ALfloat ctrl_dist, ALsizei orde static void InitDistanceComp(ALCdevice *device, const AmbDecConf *conf, const ALsizei speakermap[MAX_OUTPUT_CHANNELS]) { - const char *devname = al_string_get_cstr(device->DeviceName); + const char *devname = alstr_get_cstr(device->DeviceName); ALfloat maxdist = 0.0f; ALsizei total = 0; ALsizei i; @@ -540,14 +540,14 @@ static void InitDistanceComp(ALCdevice *device, const AmbDecConf *conf, const AL srate + 0.5f); if(delay >= (ALfloat)MAX_DELAY_LENGTH) ERR("Delay for speaker \"%s\" exceeds buffer length (%f >= %u)\n", - al_string_get_cstr(conf->Speakers[i].Name), delay, MAX_DELAY_LENGTH); + alstr_get_cstr(conf->Speakers[i].Name), delay, MAX_DELAY_LENGTH); device->ChannelDelay[chan].Length = (ALsizei)clampf( delay, 0.0f, (ALfloat)(MAX_DELAY_LENGTH-1) ); device->ChannelDelay[chan].Gain = conf->Speakers[i].Distance / maxdist; TRACE("Channel %u \"%s\" distance compensation: %d samples, %f gain\n", chan, - al_string_get_cstr(conf->Speakers[i].Name), device->ChannelDelay[chan].Length, + alstr_get_cstr(conf->Speakers[i].Name), device->ChannelDelay[chan].Length, device->ChannelDelay[chan].Gain ); @@ -628,7 +628,7 @@ static void InitPanning(ALCdevice *device) if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3) { - const char *devname = al_string_get_cstr(device->DeviceName); + const char *devname = alstr_get_cstr(device->DeviceName); const ALsizei *acnmap = (device->AmbiLayout == AmbiLayout_FuMa) ? FuMa2ACN : ACN2ACN; const ALfloat *n3dscale = (device->AmbiScale == AmbiNorm_FuMa) ? FuMa2N3DScale : (device->AmbiScale == AmbiNorm_SN3D) ? SN3D2N3DScale : @@ -1005,7 +1005,7 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf al_free(device->Hrtf); device->Hrtf = NULL; device->HrtfHandle = NULL; - al_string_clear(&device->HrtfName); + alstr_clear(&device->HrtfName); device->Render_Mode = NormalRender; memset(&device->Dry.Ambi, 0, sizeof(device->Dry.Ambi)); @@ -1033,7 +1033,7 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf ambdec_init(&conf); - devname = al_string_get_cstr(device->DeviceName); + devname = alstr_get_cstr(device->DeviceName); switch(device->FmtChans) { case DevFmtQuad: layout = "quad"; break; @@ -1110,7 +1110,7 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf if(device->Type != Loopback) { const char *mode; - if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "stereo-mode", &mode)) + if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "stereo-mode", &mode)) { if(strcasecmp(mode, "headphones") == 0) headphones = true; @@ -1154,7 +1154,7 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf if(entry->hrtf->sampleRate == device->Frequency) { device->HrtfHandle = entry->hrtf; - al_string_copy(&device->HrtfName, entry->name); + alstr_copy(&device->HrtfName, entry->name); } } @@ -1164,7 +1164,7 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf if(entry->hrtf->sampleRate == device->Frequency) { device->HrtfHandle = entry->hrtf; - al_string_copy(&device->HrtfName, entry->name); + alstr_copy(&device->HrtfName, entry->name); } } @@ -1173,7 +1173,7 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf bool hoa_mode; device->Render_Mode = HrtfRender; - if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "hrtf-mode", &mode)) + if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "hrtf-mode", &mode)) { if(strcasecmp(mode, "full") == 0) device->Render_Mode = HrtfRender; @@ -1201,7 +1201,7 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf TRACE("%s HRTF rendering enabled, using \"%s\"\n", ((device->Render_Mode == HrtfRender) ? "Full" : "Basic"), - al_string_get_cstr(device->HrtfName) + alstr_get_cstr(device->HrtfName) ); InitHrtfPanning(device, hoa_mode); return; @@ -1219,7 +1219,7 @@ no_hrtf: bs2blevel = ((headphones && hrtf_appreq != Hrtf_Disable) || (hrtf_appreq == Hrtf_Enable)) ? 5 : 0; if(device->Type != Loopback) - ConfigValueInt(al_string_get_cstr(device->DeviceName), NULL, "cf_level", &bs2blevel); + ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "cf_level", &bs2blevel); if(bs2blevel > 0 && bs2blevel <= 6) { device->Bs2b = al_calloc(16, sizeof(*device->Bs2b)); @@ -1231,7 +1231,7 @@ no_hrtf: TRACE("BS2B disabled\n"); - if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "stereo-encoding", &mode)) + if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "stereo-encoding", &mode)) { if(strcasecmp(mode, "uhj") == 0) device->Render_Mode = NormalRender; -- cgit v1.2.3 From 1f64f9d016790797ecd81e00f0392b34abdddcb6 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 8 Apr 2017 10:01:04 -0700 Subject: Try to write the full configured buffer length with PulseAudio This basically ignores tlength even if it's smaller than what was requested. It keeps up-to-date with minreq changes too now, in case that happens. --- Alc/backends/pulseaudio.c | 52 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 15 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index 79ca38e5..0eda2abd 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -626,6 +626,11 @@ static void ALCpulsePlayback_bufferAttrCallback(pa_stream *stream, void *pdata) self->attr = *pa_stream_get_buffer_attr(stream); TRACE("minreq=%d, tlength=%d, prebuf=%d\n", self->attr.minreq, self->attr.tlength, self->attr.prebuf); + /* FIXME: Update the device's UpdateSize (and/or NumUpdates) using the new + * buffer attributes? Changing UpdateSize will change the ALC_REFRESH + * property, which probably shouldn't change between device resets. But + * leaving it alone means ALC_REFRESH will be off. + */ } static void ALCpulsePlayback_contextStateCallback(pa_context *context, void *pdata) @@ -797,7 +802,6 @@ static int ALCpulsePlayback_mixerProc(void *ptr) ALCpulsePlayback *self = ptr; ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; ALuint buffer_size; - ALint update_size; size_t frame_size; ssize_t len; @@ -806,18 +810,30 @@ static int ALCpulsePlayback_mixerProc(void *ptr) pa_threaded_mainloop_lock(self->loop); frame_size = pa_frame_size(&self->spec); - update_size = device->UpdateSize * frame_size; - - /* Sanitize buffer metrics, in case we actually have less than what we - * asked for. */ - buffer_size = minu(update_size*device->NumUpdates, self->attr.tlength); - update_size = minu(update_size, buffer_size/2); - do { - len = pa_stream_writable_size(self->stream) - self->attr.tlength + - buffer_size; - if(len < update_size) + buffer_size = device->UpdateSize * device->NumUpdates * frame_size; + + while(!self->killNow && device->Connected) + { + len = pa_stream_writable_size(self->stream); + if(len < 0) { - if(pa_stream_is_corked(self->stream) == 1) + ERR("Failed to get writable size: %ld", (long)len); + aluHandleDisconnect(device); + break; + } + + /* Make sure we're going to write at least 2 'periods' (minreqs), in + * case the server increased it since starting playback. + */ + buffer_size = maxu(buffer_size, self->attr.minreq*2); + + /* NOTE: This assumes pa_stream_writable_size returns between 0 and + * tlength, else there will be more latency than intended. + */ + len = mini(len - (ssize_t)self->attr.tlength, 0) + buffer_size; + if(len < self->attr.minreq) + { + if(pa_stream_is_corked(self->stream)) { pa_operation *o; o = pa_stream_cork(self->stream, 0, NULL, NULL); @@ -826,11 +842,12 @@ static int ALCpulsePlayback_mixerProc(void *ptr) pa_threaded_mainloop_wait(self->loop); continue; } - len -= len%update_size; + len -= len%self->attr.minreq; while(len > 0) { size_t newlen = len; + int ret; void *buf; pa_free_cb_t free_func = NULL; @@ -842,10 +859,15 @@ static int ALCpulsePlayback_mixerProc(void *ptr) aluMixData(device, buf, newlen/frame_size); - pa_stream_write(self->stream, buf, newlen, free_func, 0, PA_SEEK_RELATIVE); + ret = pa_stream_write(self->stream, buf, newlen, free_func, 0, PA_SEEK_RELATIVE); + if(ret != PA_OK) + { + ERR("Failed to write to stream: %d, %s\n", ret, pa_strerror(ret)); + break; + } len -= newlen; } - } while(!self->killNow && device->Connected); + } pa_threaded_mainloop_unlock(self->loop); return 0; -- cgit v1.2.3 From 5ef7d8fe6248bccc8edf895afece8e1b44b0f4ea Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 8 Apr 2017 12:27:30 -0700 Subject: Clean up some formatting --- Alc/backends/pulseaudio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index 0eda2abd..26557ea8 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -1067,8 +1067,8 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) self->attr.maxlength = -1; self->stream = ALCpulsePlayback_connectStream(alstr_get_cstr(self->device_name), - self->loop, self->context, flags, - &self->attr, &self->spec, &chanmap); + self->loop, self->context, flags, &self->attr, &self->spec, &chanmap + ); if(!self->stream) { pa_threaded_mainloop_unlock(self->loop); @@ -1542,9 +1542,9 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name) flags |= PA_STREAM_DONT_MOVE; TRACE("Connecting to \"%s\"\n", pulse_name ? pulse_name : "(default)"); - self->stream = ALCpulseCapture_connectStream(pulse_name, self->loop, self->context, - flags, &self->attr, &self->spec, - &chanmap); + self->stream = ALCpulseCapture_connectStream(pulse_name, + self->loop, self->context, flags, &self->attr, &self->spec, &chanmap + ); if(!self->stream) { pa_threaded_mainloop_unlock(self->loop); -- cgit v1.2.3 From 81527cdbddc52338f5fb3c8b79139bf9d9186d3a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 9 Apr 2017 11:21:02 -0700 Subject: Convert the CoreAudio backend to the updated backend API --- Alc/ALc.c | 2 +- Alc/backends/base.h | 1 + Alc/backends/coreaudio.c | 460 ++++++++++++++++++++++++++++------------------ OpenAL32/Include/alMain.h | 3 - 4 files changed, 284 insertions(+), 182 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index 0cc36cad..7d4f4de3 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -72,7 +72,7 @@ static struct BackendInfo BackendList[] = { { "alsa", ALCalsaBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, #endif #ifdef HAVE_COREAUDIO - { "core", NULL, alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs }, + { "core", ALCcoreAudioBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, #endif #ifdef HAVE_OSS { "oss", ALCossBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, diff --git a/Alc/backends/base.h b/Alc/backends/base.h index 4f398047..961a4d1a 100644 --- a/Alc/backends/base.h +++ b/Alc/backends/base.h @@ -137,6 +137,7 @@ static const struct ALCbackendFactoryVtable T##_ALCbackendFactory_vtable = { \ ALCbackendFactory *ALCpulseBackendFactory_getFactory(void); ALCbackendFactory *ALCalsaBackendFactory_getFactory(void); +ALCbackendFactory *ALCcoreAudioBackendFactory_getFactory(void); ALCbackendFactory *ALCossBackendFactory_getFactory(void); ALCbackendFactory *ALCjackBackendFactory_getFactory(void); ALCbackendFactory *ALCsolarisBackendFactory_getFactory(void); diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index 5e0b03bd..435c0fae 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -33,6 +33,8 @@ #include #include +#include "backends/base.h" + typedef struct { AudioUnit audioUnit; @@ -51,17 +53,6 @@ typedef struct { 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; @@ -83,70 +74,85 @@ static AudioBufferList* allocate_buffer_list(UInt32 channelCount, UInt32 byteSiz return list; } -static OSStatus ca_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, - UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) +static void destroy_buffer_list(AudioBufferList* list) { - ALCdevice *device = (ALCdevice*)inRefCon; - ca_data *data = (ca_data*)device->ExtraData; - - ALCdevice_Lock(device); - aluMixData(device, ioData->mBuffers[0].mData, - ioData->mBuffers[0].mDataByteSize / data->frameSize); - ALCdevice_Unlock(device); - - return noErr; + if(list) + { + UInt32 i; + for(i = 0;i < list->mNumberBuffers;i++) + free(list->mBuffers[i].mData); + free(list); + } } -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 - ll_ringbuffer_read(data->ring, data->resampleBuffer, *ioNumberDataPackets); +typedef struct ALCcoreAudioPlayback { + DERIVE_FROM_TYPE(ALCbackend); - // 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; + AudioUnit audioUnit; - return noErr; + ALuint frameSize; + AudioStreamBasicDescription format; // This is the OpenAL format as a CoreAudio ASBD +} ALCcoreAudioPlayback; + +static void ALCcoreAudioPlayback_Construct(ALCcoreAudioPlayback *self, ALCdevice *device); +static void ALCcoreAudioPlayback_Destruct(ALCcoreAudioPlayback *self); +static ALCenum ALCcoreAudioPlayback_open(ALCcoreAudioPlayback *self, const ALCchar *name); +static void ALCcoreAudioPlayback_close(ALCcoreAudioPlayback *self); +static ALCboolean ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback *self); +static ALCboolean ALCcoreAudioPlayback_start(ALCcoreAudioPlayback *self); +static void ALCcoreAudioPlayback_stop(ALCcoreAudioPlayback *self); +static DECLARE_FORWARD2(ALCcoreAudioPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint) +static DECLARE_FORWARD(ALCcoreAudioPlayback, ALCbackend, ALCuint, availableSamples) +static DECLARE_FORWARD(ALCcoreAudioPlayback, ALCbackend, ClockLatency, getClockLatency) +static DECLARE_FORWARD(ALCcoreAudioPlayback, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCcoreAudioPlayback, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCcoreAudioPlayback) + +DEFINE_ALCBACKEND_VTABLE(ALCcoreAudioPlayback); + + +static void ALCcoreAudioPlayback_Construct(ALCcoreAudioPlayback *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCcoreAudioPlayback, ALCbackend, self); + + self->frameSize = 0; + memset(&self->format, 0, sizeof(self->format)); } -static OSStatus ca_capture_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, - UInt32 inNumberFrames, AudioBufferList *ioData) +static void ALCcoreAudioPlayback_Destruct(ALCcoreAudioPlayback *self) { - ALCdevice *device = (ALCdevice*)inRefCon; - ca_data *data = (ca_data*)device->ExtraData; - AudioUnitRenderActionFlags flags = 0; - OSStatus err; + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} - // 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; - } - ll_ringbuffer_write(data->ring, data->bufferList->mBuffers[0].mData, inNumberFrames); +static OSStatus ALCcoreAudioPlayback_MixerProc(void *inRefCon, + AudioUnitRenderActionFlags* UNUSED(ioActionFlags), const AudioTimeStamp* UNUSED(inTimeStamp), + UInt32 UNUSED(inBusNumber), UInt32 UNUSED(inNumberFrames), AudioBufferList *ioData) +{ + ALCcoreAudioPlayback *self = inRefCon; + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + + ALCdevice_Lock(device); + aluMixData(device, ioData->mBuffers[0].mData, + ioData->mBuffers[0].mDataByteSize / self->frameSize); + ALCdevice_Unlock(device); return noErr; } -static ALCenum ca_open_playback(ALCdevice *device, const ALCchar *deviceName) + +static ALCenum ALCcoreAudioPlayback_open(ALCcoreAudioPlayback *self, const ALCchar *name) { + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; AudioComponentDescription desc; AudioComponent comp; - ca_data *data; OSStatus err; - if(!deviceName) - deviceName = ca_device; - else if(strcmp(deviceName, ca_device) != 0) + if(!name) + name = ca_device; + else if(strcmp(name, ca_device) != 0) return ALC_INVALID_VALUE; /* open the default output unit */ @@ -163,57 +169,47 @@ static ALCenum ca_open_playback(ALCdevice *device, const ALCchar *deviceName) return ALC_INVALID_VALUE; } - data = calloc(1, sizeof(*data)); - - err = AudioComponentInstanceNew(comp, &data->audioUnit); + err = AudioComponentInstanceNew(comp, &self->audioUnit); if(err != noErr) { ERR("AudioComponentInstanceNew failed\n"); - free(data); return ALC_INVALID_VALUE; } /* init and start the default audio unit... */ - err = AudioUnitInitialize(data->audioUnit); + err = AudioUnitInitialize(self->audioUnit); if(err != noErr) { ERR("AudioUnitInitialize failed\n"); - AudioComponentInstanceDispose(data->audioUnit); - free(data); + AudioComponentInstanceDispose(self->audioUnit); return ALC_INVALID_VALUE; } - alstr_copy_cstr(&device->DeviceName, deviceName); - device->ExtraData = data; + alstr_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } -static void ca_close_playback(ALCdevice *device) +static void ALCcoreAudioPlayback_close(ALCcoreAudioPlayback *self) { - ca_data *data = (ca_data*)device->ExtraData; - - AudioUnitUninitialize(data->audioUnit); - AudioComponentInstanceDispose(data->audioUnit); - - free(data); - device->ExtraData = NULL; + AudioUnitUninitialize(self->audioUnit); + AudioComponentInstanceDispose(self->audioUnit); } -static ALCboolean ca_reset_playback(ALCdevice *device) +static ALCboolean ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback *self) { - ca_data *data = (ca_data*)device->ExtraData; + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; AudioStreamBasicDescription streamFormat; AURenderCallbackStruct input; OSStatus err; UInt32 size; - err = AudioUnitUninitialize(data->audioUnit); + err = AudioUnitUninitialize(self->audioUnit); if(err != noErr) ERR("-- AudioUnitUninitialize failed.\n"); /* retrieve default output unit's properties (output side) */ size = sizeof(AudioStreamBasicDescription); - err = AudioUnitGetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &streamFormat, &size); + err = AudioUnitGetProperty(self->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &streamFormat, &size); if(err != noErr || size != sizeof(AudioStreamBasicDescription)) { ERR("AudioUnitGetProperty failed\n"); @@ -231,7 +227,7 @@ static ALCboolean ca_reset_playback(ALCdevice *device) #endif /* set default output unit's input side to match output side */ - err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, size); + err = AudioUnitSetProperty(self->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, size); if(err != noErr) { ERR("AudioUnitSetProperty failed\n"); @@ -315,7 +311,7 @@ static ALCboolean ca_reset_playback(ALCdevice *device) streamFormat.mFormatFlags |= kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsPacked; - err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, sizeof(AudioStreamBasicDescription)); + err = AudioUnitSetProperty(self->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, sizeof(AudioStreamBasicDescription)); if(err != noErr) { ERR("AudioUnitSetProperty failed\n"); @@ -323,11 +319,11 @@ static ALCboolean ca_reset_playback(ALCdevice *device) } /* setup callback */ - data->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); - input.inputProc = ca_callback; - input.inputProcRefCon = device; + self->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + input.inputProc = ALCcoreAudioPlayback_MixerProc; + input.inputProcRefCon = self; - err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(AURenderCallbackStruct)); + err = AudioUnitSetProperty(self->audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(AURenderCallbackStruct)); if(err != noErr) { ERR("AudioUnitSetProperty failed\n"); @@ -335,7 +331,7 @@ static ALCboolean ca_reset_playback(ALCdevice *device) } /* init the default audio unit... */ - err = AudioUnitInitialize(data->audioUnit); + err = AudioUnitInitialize(self->audioUnit); if(err != noErr) { ERR("AudioUnitInitialize failed\n"); @@ -345,12 +341,9 @@ static ALCboolean ca_reset_playback(ALCdevice *device) return ALC_TRUE; } -static ALCboolean ca_start_playback(ALCdevice *device) +static ALCboolean ALCcoreAudioPlayback_start(ALCcoreAudioPlayback *self) { - ca_data *data = (ca_data*)device->ExtraData; - OSStatus err; - - err = AudioOutputUnitStart(data->audioUnit); + OSStatus err = AudioOutputUnitStart(self->audioUnit); if(err != noErr) { ERR("AudioOutputUnitStart failed\n"); @@ -360,18 +353,107 @@ static ALCboolean ca_start_playback(ALCdevice *device) return ALC_TRUE; } -static void ca_stop_playback(ALCdevice *device) +static void ALCcoreAudioPlayback_stop(ALCcoreAudioPlayback *self) { - ca_data *data = (ca_data*)device->ExtraData; + OSStatus err = AudioOutputUnitStop(self->audioUnit); + if(err != noErr) + ERR("AudioOutputUnitStop failed\n"); +} + + + + +typedef struct ALCcoreAudioCapture { + DERIVE_FROM_TYPE(ALCbackend); + + 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 + + ll_ringbuffer_t *ring; +} ALCcoreAudioCapture; + +static void ALCcoreAudioCapture_Construct(ALCcoreAudioCapture *self, ALCdevice *device); +static void ALCcoreAudioCapture_Destruct(ALCcoreAudioCapture *self); +static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar *name); +static void ALCcoreAudioCapture_close(ALCcoreAudioCapture *self); +static DECLARE_FORWARD(ALCcoreAudioCapture, ALCbackend, ALCboolean, reset) +static ALCboolean ALCcoreAudioCapture_start(ALCcoreAudioCapture *self); +static void ALCcoreAudioCapture_stop(ALCcoreAudioCapture *self); +static ALCenum ALCcoreAudioCapture_captureSamples(ALCcoreAudioCapture *self, ALCvoid *buffer, ALCuint samples); +static ALCuint ALCcoreAudioCapture_availableSamples(ALCcoreAudioCapture *self); +static DECLARE_FORWARD(ALCcoreAudioCapture, ALCbackend, ClockLatency, getClockLatency) +static DECLARE_FORWARD(ALCcoreAudioCapture, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCcoreAudioCapture, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCcoreAudioCapture) + +DEFINE_ALCBACKEND_VTABLE(ALCcoreAudioCapture); + + +static void ALCcoreAudioCapture_Construct(ALCcoreAudioCapture *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCcoreAudioCapture, ALCbackend, self); + +} + +static void ALCcoreAudioCapture_Destruct(ALCcoreAudioCapture *self) +{ + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + + +static OSStatus ALCcoreAudioCapture_RecordProc(void *inRefCon, + AudioUnitRenderActionFlags* UNUSED(ioActionFlags), + const AudioTimeStamp *inTimeStamp, UInt32 UNUSED(inBusNumber), + UInt32 inNumberFrames, AudioBufferList* UNUSED(ioData)) +{ + ALCcoreAudioCapture *self = inRefCon; + AudioUnitRenderActionFlags flags = 0; OSStatus err; - err = AudioOutputUnitStop(data->audioUnit); + // fill the bufferList with data from the input device + err = AudioUnitRender(self->audioUnit, &flags, inTimeStamp, 1, inNumberFrames, self->bufferList); if(err != noErr) - ERR("AudioOutputUnitStop failed\n"); + { + ERR("AudioUnitRender error: %d\n", err); + return err; + } + + ll_ringbuffer_write(self->ring, self->bufferList->mBuffers[0].mData, inNumberFrames); + + return noErr; +} + +static OSStatus ALCcoreAudioCapture_ConvertCallback(AudioConverterRef UNUSED(inAudioConverter), + UInt32 *ioNumberDataPackets, AudioBufferList *ioData, + AudioStreamPacketDescription** UNUSED(outDataPacketDescription), + void *inUserData) +{ + ALCcoreAudioCapture *self = inUserData; + + // Read from the ring buffer and store temporarily in a large buffer + ll_ringbuffer_read(self->ring, self->resampleBuffer, *ioNumberDataPackets); + + // Set the input data + ioData->mNumberBuffers = 1; + ioData->mBuffers[0].mNumberChannels = self->format.mChannelsPerFrame; + ioData->mBuffers[0].mData = self->resampleBuffer; + ioData->mBuffers[0].mDataByteSize = (*ioNumberDataPackets) * self->format.mBytesPerFrame; + + return noErr; } -static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) + +static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar *name) { + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; AudioStreamBasicDescription requestedFormat; // The application requested format AudioStreamBasicDescription hardwareFormat; // The hardware format AudioStreamBasicDescription outputFormat; // The AudioUnit output format @@ -383,12 +465,11 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) AudioObjectPropertyAddress propertyAddress; UInt32 enableIO; AudioComponent comp; - ca_data *data; OSStatus err; - if(!deviceName) - deviceName = ca_device; - else if(strcmp(deviceName, ca_device) != 0) + if(!name) + name = ca_device; + else if(strcmp(name, ca_device) != 0) return ALC_INVALID_VALUE; desc.componentType = kAudioUnitType_Output; @@ -405,11 +486,8 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) return ALC_INVALID_VALUE; } - data = calloc(1, sizeof(*data)); - device->ExtraData = data; - // Open the component - err = AudioComponentInstanceNew(comp, &data->audioUnit); + err = AudioComponentInstanceNew(comp, &self->audioUnit); if(err != noErr) { ERR("AudioComponentInstanceNew failed\n"); @@ -418,7 +496,7 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) // Turn off AudioUnit output enableIO = 0; - err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(ALuint)); + err = AudioUnitSetProperty(self->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(ALuint)); if(err != noErr) { ERR("AudioUnitSetProperty failed\n"); @@ -427,7 +505,7 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) // Turn on AudioUnit input enableIO = 1; - err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(ALuint)); + err = AudioUnitSetProperty(self->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(ALuint)); if(err != noErr) { ERR("AudioUnitSetProperty failed\n"); @@ -455,7 +533,7 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) } // Track the input device - err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &inputDevice, sizeof(AudioDeviceID)); + err = AudioUnitSetProperty(self->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &inputDevice, sizeof(AudioDeviceID)); if(err != noErr) { ERR("AudioUnitSetProperty failed\n"); @@ -463,10 +541,10 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) } // set capture callback - input.inputProc = ca_capture_callback; - input.inputProcRefCon = device; + input.inputProc = ALCcoreAudioCapture_RecordProc; + input.inputProcRefCon = self; - err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &input, sizeof(AURenderCallbackStruct)); + err = AudioUnitSetProperty(self->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &input, sizeof(AURenderCallbackStruct)); if(err != noErr) { ERR("AudioUnitSetProperty failed\n"); @@ -474,7 +552,7 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) } // Initialize the device - err = AudioUnitInitialize(data->audioUnit); + err = AudioUnitInitialize(self->audioUnit); if(err != noErr) { ERR("AudioUnitInitialize failed\n"); @@ -483,7 +561,7 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) // Get the hardware format propertySize = sizeof(AudioStreamBasicDescription); - err = AudioUnitGetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &hardwareFormat, &propertySize); + err = AudioUnitGetProperty(self->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &hardwareFormat, &propertySize); if(err != noErr || propertySize != sizeof(AudioStreamBasicDescription)) { ERR("AudioUnitGetProperty failed\n"); @@ -545,8 +623,8 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) requestedFormat.mFramesPerPacket = 1; // save requested format description for later use - data->format = requestedFormat; - data->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + self->format = requestedFormat; + self->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 @@ -554,11 +632,11 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) outputFormat.mSampleRate = hardwareFormat.mSampleRate; // Determine sample rate ratio for resampling - data->sampleRateRatio = outputFormat.mSampleRate / device->Frequency; + self->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)); + err = AudioUnitSetProperty(self->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, (void *)&outputFormat, sizeof(outputFormat)); if(err != noErr) { ERR("AudioUnitSetProperty failed\n"); @@ -566,8 +644,8 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) } // Set the AudioUnit output format frame count - outputFrameCount = device->UpdateSize * data->sampleRateRatio; - err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Output, 0, &outputFrameCount, sizeof(outputFrameCount)); + outputFrameCount = device->UpdateSize * self->sampleRateRatio; + err = AudioUnitSetProperty(self->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Output, 0, &outputFrameCount, sizeof(outputFrameCount)); if(err != noErr) { ERR("AudioUnitSetProperty failed: %d\n", err); @@ -575,7 +653,7 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) } // Set up sample converter - err = AudioConverterNew(&outputFormat, &requestedFormat, &data->audioConverter); + err = AudioConverterNew(&outputFormat, &requestedFormat, &self->audioConverter); if(err != noErr) { ERR("AudioConverterNew failed: %d\n", err); @@ -583,75 +661,71 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) } // Create a buffer for use in the resample callback - data->resampleBuffer = malloc(device->UpdateSize * data->frameSize * data->sampleRateRatio); + self->resampleBuffer = malloc(device->UpdateSize * self->frameSize * self->sampleRateRatio); // Allocate buffer for the AudioUnit output - data->bufferList = allocate_buffer_list(outputFormat.mChannelsPerFrame, device->UpdateSize * data->frameSize * data->sampleRateRatio); - if(data->bufferList == NULL) + self->bufferList = allocate_buffer_list(outputFormat.mChannelsPerFrame, device->UpdateSize * self->frameSize * self->sampleRateRatio); + if(self->bufferList == NULL) goto error; - data->ring = ll_ringbuffer_create( - device->UpdateSize*data->sampleRateRatio*device->NumUpdates + 1, - data->frameSize + self->ring = ll_ringbuffer_create( + device->UpdateSize*self->sampleRateRatio*device->NumUpdates + 1, + self->frameSize ); - if(!data->ring) goto error; + if(!self->ring) goto error; - alstr_copy_cstr(&device->DeviceName, deviceName); + alstr_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; error: - ll_ringbuffer_free(data->ring); - data->ring = NULL; - free(data->resampleBuffer); - destroy_buffer_list(data->bufferList); - - if(data->audioConverter) - AudioConverterDispose(data->audioConverter); - if(data->audioUnit) - AudioComponentInstanceDispose(data->audioUnit); + ll_ringbuffer_free(self->ring); + self->ring = NULL; + free(self->resampleBuffer); + destroy_buffer_list(self->bufferList); - free(data); - device->ExtraData = NULL; + if(self->audioConverter) + AudioConverterDispose(self->audioConverter); + if(self->audioUnit) + AudioComponentInstanceDispose(self->audioUnit); return ALC_INVALID_VALUE; } -static void ca_close_capture(ALCdevice *device) + +static void ALCcoreAudioCapture_close(ALCcoreAudioCapture *self) { - ca_data *data = (ca_data*)device->ExtraData; + ll_ringbuffer_free(self->ring); + self->ring = NULL; - ll_ringbuffer_free(data->ring); - data->ring = NULL; - free(data->resampleBuffer); - destroy_buffer_list(data->bufferList); + free(self->resampleBuffer); - AudioConverterDispose(data->audioConverter); - AudioComponentInstanceDispose(data->audioUnit); + destroy_buffer_list(self->bufferList); - free(data); - device->ExtraData = NULL; + AudioConverterDispose(self->audioConverter); + AudioComponentInstanceDispose(self->audioUnit); } -static void ca_start_capture(ALCdevice *device) +static ALCboolean ALCcoreAudioCapture_start(ALCcoreAudioCapture *self) { - ca_data *data = (ca_data*)device->ExtraData; - OSStatus err = AudioOutputUnitStart(data->audioUnit); + OSStatus err = AudioOutputUnitStart(self->audioUnit); if(err != noErr) + { ERR("AudioOutputUnitStart failed\n"); + return ALC_FALSE; + } + return ALC_TRUE; } -static void ca_stop_capture(ALCdevice *device) +static void ALCcoreAudioCapture_stop(ALCcoreAudioCapture *self) { - ca_data *data = (ca_data*)device->ExtraData; - OSStatus err = AudioOutputUnitStop(data->audioUnit); + OSStatus err = AudioOutputUnitStop(self->audioUnit); if(err != noErr) ERR("AudioOutputUnitStop failed\n"); } -static ALCenum ca_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples) +static ALCenum ALCcoreAudioCapture_captureSamples(ALCcoreAudioCapture *self, ALCvoid *buffer, ALCuint samples) { - ca_data *data = (ca_data*)device->ExtraData; AudioBufferList *list; UInt32 frameCount; OSStatus err; @@ -665,14 +739,15 @@ static ALCenum ca_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint sa // 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].mNumberChannels = self->format.mChannelsPerFrame; + list->mBuffers[0].mDataByteSize = samples * self->frameSize; list->mBuffers[0].mData = buffer; // Resample into another AudioBufferList frameCount = samples; - err = AudioConverterFillComplexBuffer(data->audioConverter, ca_capture_conversion_callback, - device, &frameCount, list, NULL); + err = AudioConverterFillComplexBuffer(self->audioConverter, + ALCcoreAudioCapture_ConvertCallback, self, &frameCount, list, NULL + ); if(err != noErr) { ERR("AudioConverterFillComplexBuffer error: %d\n", err); @@ -681,38 +756,47 @@ static ALCenum ca_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint sa return ALC_NO_ERROR; } -static ALCuint ca_available_samples(ALCdevice *device) +static ALCuint ALCcoreAudioCapture_availableSamples(ALCcoreAudioCapture *self) { - ca_data *data = device->ExtraData; - return ll_ringbuffer_read_space(data->ring) / data->sampleRateRatio; + return ll_ringbuffer_read_space(self->ring) / self->sampleRateRatio; } -static const BackendFuncs ca_funcs = { - ca_open_playback, - ca_close_playback, - ca_reset_playback, - ca_start_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) +typedef struct ALCcoreAudioBackendFactory { + DERIVE_FROM_TYPE(ALCbackendFactory); +} ALCcoreAudioBackendFactory; +#define ALCCOREAUDIOBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCcoreAudioBackendFactory, ALCbackendFactory) } } + +ALCbackendFactory *ALCcoreAudioBackendFactory_getFactory(void); + +static ALCboolean ALCcoreAudioBackendFactory_init(ALCcoreAudioBackendFactory *self); +static DECLARE_FORWARD(ALCcoreAudioBackendFactory, ALCbackendFactory, void, deinit) +static ALCboolean ALCcoreAudioBackendFactory_querySupport(ALCcoreAudioBackendFactory *self, ALCbackend_Type type); +static void ALCcoreAudioBackendFactory_probe(ALCcoreAudioBackendFactory *self, enum DevProbe type); +static ALCbackend* ALCcoreAudioBackendFactory_createBackend(ALCcoreAudioBackendFactory *self, ALCdevice *device, ALCbackend_Type type); +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCcoreAudioBackendFactory); + + +ALCbackendFactory *ALCcoreAudioBackendFactory_getFactory(void) +{ + static ALCcoreAudioBackendFactory factory = ALCCOREAUDIOBACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); +} + + +static ALCboolean ALCcoreAudioBackendFactory_init(ALCcoreAudioBackendFactory* UNUSED(self)) { - *func_list = ca_funcs; return ALC_TRUE; } -void alc_ca_deinit(void) +static ALCboolean ALCcoreAudioBackendFactory_querySupport(ALCcoreAudioBackendFactory* UNUSED(self), ALCbackend_Type type) { + if(type == ALCbackend_Playback || ALCbackend_Capture) + return ALC_TRUE; + return ALC_FALSE; } -void alc_ca_probe(enum DevProbe type) +static void ALCcoreAudioBackendFactory_probe(ALCcoreAudioBackendFactory* UNUSED(self), enum DevProbe type) { switch(type) { @@ -724,3 +808,23 @@ void alc_ca_probe(enum DevProbe type) break; } } + +static ALCbackend* ALCcoreAudioBackendFactory_createBackend(ALCcoreAudioBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + { + ALCcoreAudioPlayback *backend; + NEW_OBJ(backend, ALCcoreAudioPlayback)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + if(type == ALCbackend_Capture) + { + ALCcoreAudioCapture *backend; + NEW_OBJ(backend, ALCcoreAudioCapture)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + + return NULL; +} diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 7add9310..1919a257 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -429,9 +429,6 @@ typedef struct { ALCuint (*AvailableSamples)(ALCdevice*); } BackendFuncs; -ALCboolean alc_ca_init(BackendFuncs *func_list); -void alc_ca_deinit(void); -void alc_ca_probe(enum DevProbe type); ALCboolean alc_qsa_init(BackendFuncs *func_list); void alc_qsa_deinit(void); void alc_qsa_probe(enum DevProbe type); -- cgit v1.2.3 From 78d5492d2c66ab6bb0141b5034a0b95b18fbf69a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 11 Apr 2017 09:41:23 -0700 Subject: Use the converters to enable mmdevapi capture --- Alc/backends/mmdevapi.c | 213 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 171 insertions(+), 42 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 339ea8d3..a70607e4 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -44,6 +44,7 @@ #include "threads.h" #include "compat.h" #include "alstring.h" +#include "converter.h" #include "backends/base.h" @@ -1206,6 +1207,8 @@ typedef struct ALCmmdevCapture { HANDLE MsgEvent; + ChannelConverter *ChannelConv; + SampleConverter *SampleConv; ll_ringbuffer_t *Ring; volatile int killNow; @@ -1253,6 +1256,8 @@ static void ALCmmdevCapture_Construct(ALCmmdevCapture *self, ALCdevice *device) self->MsgEvent = NULL; + self->ChannelConv = NULL; + self->SampleConv = NULL; self->Ring = NULL; self->killNow = 0; @@ -1263,6 +1268,9 @@ static void ALCmmdevCapture_Destruct(ALCmmdevCapture *self) ll_ringbuffer_free(self->Ring); self->Ring = NULL; + DestroySampleConverter(&self->SampleConv); + DestroyChannelConverter(&self->ChannelConv); + if(self->NotifyEvent != NULL) CloseHandle(self->NotifyEvent); self->NotifyEvent = NULL; @@ -1282,6 +1290,8 @@ FORCE_ALIGN int ALCmmdevCapture_recordProc(void *arg) { ALCmmdevCapture *self = arg; ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + ALfloat *samples = NULL; + size_t samplesmax = 0; HRESULT hr; hr = CoInitialize(NULL); @@ -1304,33 +1314,74 @@ FORCE_ALIGN int ALCmmdevCapture_recordProc(void *arg) hr = IAudioCaptureClient_GetNextPacketSize(self->capture, &avail); if(FAILED(hr)) ERR("Failed to get next packet size: 0x%08lx\n", hr); - else while(avail > 0 && SUCCEEDED(hr)) + else if(avail > 0) { UINT32 numsamples; DWORD flags; - BYTE *data; + BYTE *rdata; hr = IAudioCaptureClient_GetBuffer(self->capture, - &data, &numsamples, &flags, NULL, NULL + &rdata, &numsamples, &flags, NULL, NULL ); if(FAILED(hr)) - { ERR("Failed to get capture buffer: 0x%08lx\n", hr); - break; - } + else + { + ll_ringbuffer_data_t data[2]; + size_t dstframes = 0; - ll_ringbuffer_write(self->Ring, (char*)data, numsamples); + if(self->ChannelConv) + { + if(samplesmax < numsamples) + { + size_t newmax = RoundUp(numsamples, 4096); + ALfloat *tmp = al_calloc(DEF_ALIGN, newmax*2*sizeof(ALfloat)); + al_free(samples); + samples = tmp; + samplesmax = newmax; + } + ChannelConverterInput(self->ChannelConv, rdata, samples, numsamples); + rdata = (BYTE*)samples; + } - hr = IAudioCaptureClient_ReleaseBuffer(self->capture, numsamples); - if(FAILED(hr)) - { - ERR("Failed to release capture buffer: 0x%08lx\n", hr); - break; - } + ll_ringbuffer_get_write_vector(self->Ring, data); - hr = IAudioCaptureClient_GetNextPacketSize(self->capture, &avail); - if(FAILED(hr)) - ERR("Failed to get next packet size: 0x%08lx\n", hr); + if(self->SampleConv) + { + const ALvoid *srcdata = rdata; + ALsizei srcframes = numsamples; + + dstframes = SampleConverterInput(self->SampleConv, + &srcdata, &srcframes, data[0].buf, data[0].len + ); + if(srcframes > 0 && dstframes == data[0].len && data[1].len > 0) + { + /* If some source samples remain, all of the first dest + * block was filled, and there's space in the second + * dest block, do another run for the second block. + */ + dstframes += SampleConverterInput(self->SampleConv, + &srcdata, &srcframes, data[1].buf, data[1].len + ); + } + } + else + { + size_t framesize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + ALuint len1 = minu(data[0].len, numsamples); + ALuint len2 = minu(data[1].len, numsamples-len1); + + memcpy(data[0].buf, rdata, len1*framesize); + if(len2 > 0) + memcpy(data[1].buf, rdata+len1*framesize, len2*framesize); + dstframes = len1 + len2; + } + + ll_ringbuffer_write_advance(self->Ring, dstframes); + + hr = IAudioCaptureClient_ReleaseBuffer(self->capture, numsamples); + if(FAILED(hr)) ERR("Failed to release capture buffer: 0x%08lx\n", hr); + } } if(FAILED(hr)) @@ -1346,6 +1397,10 @@ FORCE_ALIGN int ALCmmdevCapture_recordProc(void *arg) ERR("WaitForSingleObjectEx error: 0x%lx\n", res); } + al_free(samples); + samples = NULL; + samplesmax = 0; + CoUninitialize(); return 0; } @@ -1528,6 +1583,7 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; WAVEFORMATEXTENSIBLE OutputType; WAVEFORMATEX *wfx = NULL; + enum DevFmtType srcType; REFERENCE_TIME buf_time; UINT32 buffer_len; void *ptr = NULL; @@ -1587,33 +1643,28 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) } switch(device->FmtType) { + /* NOTE: Signedness doesn't matter, the converter will handle it. */ + case DevFmtByte: case DevFmtUByte: OutputType.Format.wBitsPerSample = 8; - OutputType.Samples.wValidBitsPerSample = 8; OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; break; case DevFmtShort: + case DevFmtUShort: OutputType.Format.wBitsPerSample = 16; - OutputType.Samples.wValidBitsPerSample = 16; OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; break; case DevFmtInt: + case DevFmtUInt: OutputType.Format.wBitsPerSample = 32; - OutputType.Samples.wValidBitsPerSample = 32; OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; break; case DevFmtFloat: OutputType.Format.wBitsPerSample = 32; - OutputType.Samples.wValidBitsPerSample = 32; OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; break; - - case DevFmtByte: - case DevFmtUShort: - case DevFmtUInt: - WARN("%s capture samples not supported\n", DevFmtTypeString(device->FmtType)); - return E_FAIL; } + OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; OutputType.Format.nSamplesPerSec = device->Frequency; OutputType.Format.nBlockAlign = OutputType.Format.nChannels * @@ -1631,27 +1682,103 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) return hr; } - /* FIXME: We should do conversion/resampling if we didn't get a matching format. */ - if(wfx->nSamplesPerSec != OutputType.Format.nSamplesPerSec || - wfx->wBitsPerSample != OutputType.Format.wBitsPerSample || - wfx->nChannels != OutputType.Format.nChannels || - wfx->nBlockAlign != OutputType.Format.nBlockAlign) + DestroySampleConverter(&self->SampleConv); + DestroyChannelConverter(&self->ChannelConv); + + if(wfx != NULL) { - ERR("Failed to get matching format, wanted: %s %s %uhz, got: %d channel%s %d-bit %luhz\n", - DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), - device->Frequency, wfx->nChannels, (wfx->nChannels==1)?"":"s", wfx->wBitsPerSample, - wfx->nSamplesPerSec); + if(!(wfx->nChannels == OutputType.Format.nChannels || + (wfx->nChannels == 1 && OutputType.Format.nChannels == 2) || + (wfx->nChannels == 2 && OutputType.Format.nChannels == 1))) + { + ERR("Failed to get matching format, wanted: %s %s %uhz, got: %d channel%s %d-bit %luhz\n", + DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), + device->Frequency, wfx->nChannels, (wfx->nChannels==1)?"":"s", wfx->wBitsPerSample, + wfx->nSamplesPerSec); + CoTaskMemFree(wfx); + return E_FAIL; + } + + if(!MakeExtensible(&OutputType, wfx)) + { + CoTaskMemFree(wfx); + return E_FAIL; + } CoTaskMemFree(wfx); - return E_FAIL; + wfx = NULL; } - if(!MakeExtensible(&OutputType, wfx)) + if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) { - CoTaskMemFree(wfx); + if(OutputType.Format.wBitsPerSample == 8) + srcType = DevFmtUByte; + else if(OutputType.Format.wBitsPerSample == 16) + srcType = DevFmtShort; + else if(OutputType.Format.wBitsPerSample == 32) + srcType = DevFmtInt; + else + { + ERR("Unhandled integer bit depth: %d\n", OutputType.Format.wBitsPerSample); + return E_FAIL; + } + } + else if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) + { + if(OutputType.Format.wBitsPerSample == 32) + srcType = DevFmtFloat; + else + { + ERR("Unhandled float bit depth: %d\n", OutputType.Format.wBitsPerSample); + return E_FAIL; + } + } + else + { + ERR("Unhandled format sub-type\n"); return E_FAIL; } - CoTaskMemFree(wfx); - wfx = NULL; + + if(device->FmtChans == DevFmtMono && OutputType.Format.nChannels == 2) + { + self->ChannelConv = CreateChannelConverter(srcType, DevFmtStereo, + device->FmtChans); + if(!self->ChannelConv) + { + ERR("Failed to create stereo-to-mono converter\n"); + return E_FAIL; + } + /* The channel converter always outputs float, so change the input type + * for the resampler/type-converter. + */ + srcType = DevFmtFloat; + } + else if(device->FmtChans == DevFmtStereo && OutputType.Format.nChannels == 1) + { + self->ChannelConv = CreateChannelConverter(srcType, DevFmtMono, + device->FmtChans); + if(!self->ChannelConv) + { + ERR("Failed to create mono-to-stereo converter\n"); + return E_FAIL; + } + srcType = DevFmtFloat; + } + + if(device->Frequency != OutputType.Format.nSamplesPerSec || device->FmtType != srcType) + { + self->SampleConv = CreateSampleConverter( + srcType, device->FmtType, ChannelsFromDevFmt(device->FmtChans), + OutputType.Format.nSamplesPerSec, device->Frequency + ); + if(!self->SampleConv) + { + ERR("Failed to create converter for format, dst: %s %s %uhz, src: %d-bit %luhz\n", + DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), + device->Frequency, OutputType.Format.wBitsPerSample, + OutputType.Format.nSamplesPerSec); + return E_FAIL; + } + } hr = IAudioClient_Initialize(self->client, AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, @@ -1672,7 +1799,9 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) buffer_len = maxu(device->UpdateSize*device->NumUpdates + 1, buffer_len); ll_ringbuffer_free(self->Ring); - self->Ring = ll_ringbuffer_create(buffer_len, OutputType.Format.nBlockAlign); + self->Ring = ll_ringbuffer_create(buffer_len, + FrameSizeFromDevFmt(device->FmtChans, device->FmtType) + ); if(!self->Ring) { ERR("Failed to allocate capture ring buffer\n"); @@ -1851,7 +1980,7 @@ static ALCboolean ALCmmdevBackendFactory_querySupport(ALCmmdevBackendFactory* UN * stereo input, for example, and the app asks for 22050hz mono, * initialization will fail. */ - if(type == ALCbackend_Playback /*|| type == ALCbackend_Capture*/) + if(type == ALCbackend_Playback || type == ALCbackend_Capture) return ALC_TRUE; return ALC_FALSE; } -- cgit v1.2.3 From 901804d724d49f316cd2bf51ec1cd2cd9fb9eb91 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 12 Apr 2017 18:26:07 -0700 Subject: Store the ambisonic order separate from the channel enum --- Alc/ALc.c | 157 +++++++++++++++++------------------------ Alc/backends/alsa.c | 11 +-- Alc/backends/coreaudio.c | 8 +-- Alc/backends/dsound.c | 176 ++++++++++++++++++++++------------------------ Alc/backends/jack.c | 10 ++- Alc/backends/mmdevapi.c | 15 ++-- Alc/backends/opensl.c | 10 ++- Alc/backends/oss.c | 16 +++-- Alc/backends/portaudio.c | 4 +- Alc/backends/pulseaudio.c | 48 +++++++++++-- Alc/backends/qsa.c | 20 +++--- Alc/backends/sndio.c | 6 +- Alc/backends/solaris.c | 12 ++-- Alc/backends/wave.c | 25 ++++--- Alc/backends/winmm.c | 8 +-- Alc/converter.c | 2 +- Alc/panning.c | 31 ++++---- OpenAL32/Include/alMain.h | 13 ++-- 18 files changed, 285 insertions(+), 287 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index 47bd19e4..2a636c59 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -1367,14 +1367,12 @@ const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans) case DevFmtX51Rear: return "5.1 Surround (Rear)"; case DevFmtX61: return "6.1 Surround"; case DevFmtX71: return "7.1 Surround"; - case DevFmtAmbi1: return "Ambisonic (1st Order)"; - case DevFmtAmbi2: return "Ambisonic (2nd Order)"; - case DevFmtAmbi3: return "Ambisonic (3rd Order)"; + case DevFmtAmbi3D: return "Ambisonic 3D"; } return "(unknown channels)"; } -extern inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type); +extern inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type, ALsizei ambiorder); ALsizei BytesFromDevFmt(enum DevFmtType type) { switch(type) @@ -1389,7 +1387,7 @@ ALsizei BytesFromDevFmt(enum DevFmtType type) } return 0; } -ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans) +ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder) { switch(chans) { @@ -1400,9 +1398,9 @@ ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans) case DevFmtX51Rear: return 6; case DevFmtX61: return 7; case DevFmtX71: return 8; - case DevFmtAmbi1: return 4; - case DevFmtAmbi2: return 9; - case DevFmtAmbi3: return 16; + case DevFmtAmbi3D: return (ambiorder >= 3) ? 16 : + (ambiorder == 2) ? 9 : + (ambiorder == 1) ? 4 : 1; } return 0; } @@ -1585,40 +1583,32 @@ void SetDefaultWFXChannelOrder(ALCdevice *device) device->RealOut.ChannelName[6] = SideLeft; device->RealOut.ChannelName[7] = SideRight; break; - case DevFmtAmbi1: + case DevFmtAmbi3D: device->RealOut.ChannelName[0] = Aux0; - device->RealOut.ChannelName[1] = Aux1; - device->RealOut.ChannelName[2] = Aux2; - device->RealOut.ChannelName[3] = Aux3; - break; - case DevFmtAmbi2: - device->RealOut.ChannelName[0] = Aux0; - device->RealOut.ChannelName[1] = Aux1; - device->RealOut.ChannelName[2] = Aux2; - device->RealOut.ChannelName[3] = Aux3; - device->RealOut.ChannelName[4] = Aux4; - device->RealOut.ChannelName[5] = Aux5; - device->RealOut.ChannelName[6] = Aux6; - device->RealOut.ChannelName[7] = Aux7; - device->RealOut.ChannelName[8] = Aux8; - break; - case DevFmtAmbi3: - device->RealOut.ChannelName[0] = Aux0; - device->RealOut.ChannelName[1] = Aux1; - device->RealOut.ChannelName[2] = Aux2; - device->RealOut.ChannelName[3] = Aux3; - device->RealOut.ChannelName[4] = Aux4; - device->RealOut.ChannelName[5] = Aux5; - device->RealOut.ChannelName[6] = Aux6; - device->RealOut.ChannelName[7] = Aux7; - device->RealOut.ChannelName[8] = Aux8; - device->RealOut.ChannelName[9] = Aux9; - device->RealOut.ChannelName[10] = Aux10; - device->RealOut.ChannelName[11] = Aux11; - device->RealOut.ChannelName[12] = Aux12; - device->RealOut.ChannelName[13] = Aux13; - device->RealOut.ChannelName[14] = Aux14; - device->RealOut.ChannelName[15] = Aux15; + if(device->AmbiOrder > 0) + { + device->RealOut.ChannelName[1] = Aux1; + device->RealOut.ChannelName[2] = Aux2; + device->RealOut.ChannelName[3] = Aux3; + } + if(device->AmbiOrder > 1) + { + device->RealOut.ChannelName[4] = Aux4; + device->RealOut.ChannelName[5] = Aux5; + device->RealOut.ChannelName[6] = Aux6; + device->RealOut.ChannelName[7] = Aux7; + device->RealOut.ChannelName[8] = Aux8; + } + if(device->AmbiOrder > 2) + { + device->RealOut.ChannelName[9] = Aux9; + device->RealOut.ChannelName[10] = Aux10; + device->RealOut.ChannelName[11] = Aux11; + device->RealOut.ChannelName[12] = Aux12; + device->RealOut.ChannelName[13] = Aux13; + device->RealOut.ChannelName[14] = Aux14; + device->RealOut.ChannelName[15] = Aux15; + } break; } } @@ -1661,9 +1651,7 @@ void SetDefaultChannelOrder(ALCdevice *device) case DevFmtQuad: case DevFmtX51: case DevFmtX61: - case DevFmtAmbi1: - case DevFmtAmbi2: - case DevFmtAmbi3: + case DevFmtAmbi3D: SetDefaultWFXChannelOrder(device); break; } @@ -1901,16 +1889,15 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) UpdateClockBase(device); + device->Frequency = freq; + device->FmtChans = schans; + device->FmtType = stype; if(schans == ALC_BFORMAT3D_SOFT) { - device->FmtChans = DevFmtAmbi1 + (aorder-1); + device->AmbiOrder = aorder; device->AmbiLayout = alayout; device->AmbiScale = ascale; } - else - device->FmtChans = schans; - device->Frequency = freq; - device->FmtType = stype; device->NumMonoSources = numMono; device->NumStereoSources = numStereo; @@ -2944,8 +2931,7 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum para static inline ALCsizei NumAttrsForDevice(ALCdevice *device) { - if(device->Type == Loopback && device->FmtChans >= DevFmtAmbi1 && - device->FmtChans <= DevFmtAmbi3) + if(device->Type == Loopback && device->FmtChans == DevFmtAmbi3D) return 23; return 17; } @@ -3060,7 +3046,7 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC } else { - if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3) + if(device->FmtChans == DevFmtAmbi3D) { values[i++] = ALC_AMBISONIC_LAYOUT_SOFT; values[i++] = device->AmbiLayout; @@ -3069,17 +3055,12 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC values[i++] = device->AmbiScale; values[i++] = ALC_AMBISONIC_ORDER_SOFT; - values[i++] = device->FmtChans-DevFmtAmbi1+1; - - values[i++] = ALC_FORMAT_CHANNELS_SOFT; - values[i++] = ALC_BFORMAT3D_SOFT; - } - else - { - values[i++] = ALC_FORMAT_CHANNELS_SOFT; - values[i++] = device->FmtChans; + values[i++] = device->AmbiOrder; } + values[i++] = ALC_FORMAT_CHANNELS_SOFT; + values[i++] = device->FmtChans; + values[i++] = ALC_FORMAT_TYPE_SOFT; values[i++] = device->FmtType; } @@ -3133,10 +3114,7 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC alcSetError(device, ALC_INVALID_DEVICE); return 0; } - if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3) - values[0] = ALC_BFORMAT3D_SOFT; - else - values[0] = device->FmtChans; + values[0] = device->FmtChans; return 1; case ALC_FORMAT_TYPE_SOFT: @@ -3149,8 +3127,7 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC return 1; case ALC_AMBISONIC_LAYOUT_SOFT: - if(device->Type != Loopback || !(device->FmtChans >= DevFmtAmbi1 && - device->FmtChans <= DevFmtAmbi3)) + if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D) { alcSetError(device, ALC_INVALID_DEVICE); return 0; @@ -3159,8 +3136,7 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC return 1; case ALC_AMBISONIC_SCALING_SOFT: - if(device->Type != Loopback || !(device->FmtChans >= DevFmtAmbi1 && - device->FmtChans <= DevFmtAmbi3)) + if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D) { alcSetError(device, ALC_INVALID_DEVICE); return 0; @@ -3169,13 +3145,12 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC return 1; case ALC_AMBISONIC_ORDER_SOFT: - if(device->Type != Loopback || !(device->FmtChans >= DevFmtAmbi1 && - device->FmtChans <= DevFmtAmbi3)) + if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D) { alcSetError(device, ALC_INVALID_DEVICE); return 0; } - values[0] = device->FmtChans - DevFmtAmbi1 + 1; + values[0] = device->AmbiOrder; return 1; case ALC_MONO_SOURCES: @@ -3280,7 +3255,7 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, } else { - if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3) + if(device->FmtChans == DevFmtAmbi3D) { values[i++] = ALC_AMBISONIC_LAYOUT_SOFT; values[i++] = device->AmbiLayout; @@ -3289,17 +3264,12 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, values[i++] = device->AmbiScale; values[i++] = ALC_AMBISONIC_ORDER_SOFT; - values[i++] = device->FmtChans-DevFmtAmbi1+1; - - values[i++] = ALC_FORMAT_CHANNELS_SOFT; - values[i++] = ALC_BFORMAT3D_SOFT; - } - else - { - values[i++] = ALC_FORMAT_CHANNELS_SOFT; - values[i++] = device->FmtChans; + values[i++] = device->AmbiOrder; } + values[i++] = ALC_FORMAT_CHANNELS_SOFT; + values[i++] = device->FmtChans; + values[i++] = ALC_FORMAT_TYPE_SOFT; values[i++] = device->FmtType; } @@ -3825,17 +3795,18 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) static const struct { const char name[16]; enum DevFmtChannels chans; + ALsizei order; } chanlist[] = { - { "mono", DevFmtMono }, - { "stereo", DevFmtStereo }, - { "quad", DevFmtQuad }, - { "surround51", DevFmtX51 }, - { "surround61", DevFmtX61 }, - { "surround71", DevFmtX71 }, - { "surround51rear", DevFmtX51Rear }, - { "ambi1", DevFmtAmbi1 }, - { "ambi2", DevFmtAmbi2 }, - { "ambi3", DevFmtAmbi3 }, + { "mono", DevFmtMono, 0 }, + { "stereo", DevFmtStereo, 0 }, + { "quad", DevFmtQuad, 0 }, + { "surround51", DevFmtX51, 0 }, + { "surround61", DevFmtX61, 0 }, + { "surround71", DevFmtX71, 0 }, + { "surround51rear", DevFmtX51Rear, 0 }, + { "ambi1", DevFmtAmbi3D, 1 }, + { "ambi2", DevFmtAmbi3D, 2 }, + { "ambi3", DevFmtAmbi3D, 3 }, }; size_t i; @@ -3844,6 +3815,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) if(strcasecmp(chanlist[i].name, fmt) == 0) { device->FmtChans = chanlist[i].chans; + device->AmbiOrder = chanlist[i].order; device->Flags |= DEVICE_CHANNELS_REQUEST; break; } @@ -4118,6 +4090,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, return NULL; } device->IsHeadphones = AL_FALSE; + device->AmbiOrder = 0; device->AmbiLayout = AmbiLayout_Default; device->AmbiScale = AmbiNorm_Default; diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 4a7b81ba..40b68779 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -755,7 +755,7 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self) } CHECK(snd_pcm_hw_params_set_format(self->pcmHandle, hp, format)); /* test and set channels (implicitly sets frame bits) */ - if(snd_pcm_hw_params_test_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans)) < 0) + if(snd_pcm_hw_params_test_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder)) < 0) { static const enum DevFmtChannels channellist[] = { DevFmtStereo, @@ -768,14 +768,15 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self) for(k = 0;k < COUNTOF(channellist);k++) { - if(snd_pcm_hw_params_test_channels(self->pcmHandle, hp, ChannelsFromDevFmt(channellist[k])) >= 0) + if(snd_pcm_hw_params_test_channels(self->pcmHandle, hp, ChannelsFromDevFmt(channellist[k], 0)) >= 0) { device->FmtChans = channellist[k]; + device->AmbiOrder = 0; break; } } } - CHECK(snd_pcm_hw_params_set_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans))); + CHECK(snd_pcm_hw_params_set_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder))); /* set rate (implicitly constrains period/buffer parameters) */ if(!GetConfigValueBool(alstr_get_cstr(device->DeviceName), "alsa", "allow-resampler", 0) || !(device->Flags&DEVICE_FREQUENCY_REQUEST)) @@ -1039,7 +1040,7 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name) /* set format (implicitly sets sample bits) */ CHECK(snd_pcm_hw_params_set_format(self->pcmHandle, hp, format)); /* set channels (implicitly sets frame bits) */ - CHECK(snd_pcm_hw_params_set_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans))); + CHECK(snd_pcm_hw_params_set_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder))); /* set rate (implicitly constrains period/buffer parameters) */ CHECK(snd_pcm_hw_params_set_rate(self->pcmHandle, hp, device->Frequency, 0)); /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */ @@ -1063,7 +1064,7 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name) { self->ring = ll_ringbuffer_create( device->UpdateSize*device->NumUpdates + 1, - FrameSizeFromDevFmt(device->FmtChans, device->FmtType) + FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder) ); if(!self->ring) { diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index 435c0fae..ec926d3d 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -319,7 +319,7 @@ static ALCboolean ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback *self) } /* setup callback */ - self->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + self->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); input.inputProc = ALCcoreAudioPlayback_MixerProc; input.inputProcRefCon = self; @@ -608,9 +608,7 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar case DevFmtX51Rear: case DevFmtX61: case DevFmtX71: - case DevFmtAmbi1: - case DevFmtAmbi2: - case DevFmtAmbi3: + case DevFmtAmbi3D: ERR("%s not supported\n", DevFmtChannelsString(device->FmtChans)); goto error; } @@ -624,7 +622,7 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar // save requested format description for later use self->format = requestedFormat; - self->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + self->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); // Use intermediate format for sample rate conversion (outputFormat) // Set sample rate to the same as hardware for resampling later diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index 3dc297ff..f730dc95 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -244,7 +244,7 @@ FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr) return 1; } - FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); FragSize = device->UpdateSize * FrameSize; IDirectSoundBuffer_GetCurrentPosition(self->Buffer, &LastCursor, NULL); @@ -474,9 +474,7 @@ static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self) case DevFmtMono: OutputType.dwChannelMask = SPEAKER_FRONT_CENTER; break; - case DevFmtAmbi1: - case DevFmtAmbi2: - case DevFmtAmbi3: + case DevFmtAmbi3D: device->FmtChans = DevFmtStereo; /*fall-through*/ case DevFmtStereo: @@ -529,7 +527,7 @@ static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self) retry_open: hr = S_OK; OutputType.Format.wFormatTag = WAVE_FORMAT_PCM; - OutputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans); + OutputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); OutputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8; OutputType.Format.nBlockAlign = OutputType.Format.nChannels*OutputType.Format.wBitsPerSample/8; OutputType.Format.nSamplesPerSec = device->Frequency; @@ -736,98 +734,94 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi break; } - //DirectSoundCapture Init code - hr = DirectSoundCaptureCreate(guid, &self->DSC, NULL); - if(SUCCEEDED(hr)) + memset(&InputType, 0, sizeof(InputType)); + switch(device->FmtChans) { - memset(&InputType, 0, sizeof(InputType)); - - switch(device->FmtChans) - { - case DevFmtMono: - InputType.dwChannelMask = SPEAKER_FRONT_CENTER; - break; - case DevFmtStereo: - InputType.dwChannelMask = SPEAKER_FRONT_LEFT | - SPEAKER_FRONT_RIGHT; - break; - case DevFmtQuad: - InputType.dwChannelMask = SPEAKER_FRONT_LEFT | - SPEAKER_FRONT_RIGHT | - SPEAKER_BACK_LEFT | - SPEAKER_BACK_RIGHT; - break; - case DevFmtX51: - InputType.dwChannelMask = SPEAKER_FRONT_LEFT | - SPEAKER_FRONT_RIGHT | - SPEAKER_FRONT_CENTER | - SPEAKER_LOW_FREQUENCY | - SPEAKER_SIDE_LEFT | - SPEAKER_SIDE_RIGHT; - break; - case DevFmtX51Rear: - InputType.dwChannelMask = SPEAKER_FRONT_LEFT | - SPEAKER_FRONT_RIGHT | - SPEAKER_FRONT_CENTER | - SPEAKER_LOW_FREQUENCY | - SPEAKER_BACK_LEFT | - SPEAKER_BACK_RIGHT; - break; - case DevFmtX61: - InputType.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: - InputType.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; - case DevFmtAmbi1: - case DevFmtAmbi2: - case DevFmtAmbi3: - break; - } + case DevFmtMono: + InputType.dwChannelMask = SPEAKER_FRONT_CENTER; + break; + case DevFmtStereo: + InputType.dwChannelMask = SPEAKER_FRONT_LEFT | + SPEAKER_FRONT_RIGHT; + break; + case DevFmtQuad: + InputType.dwChannelMask = SPEAKER_FRONT_LEFT | + SPEAKER_FRONT_RIGHT | + SPEAKER_BACK_LEFT | + SPEAKER_BACK_RIGHT; + break; + case DevFmtX51: + InputType.dwChannelMask = SPEAKER_FRONT_LEFT | + SPEAKER_FRONT_RIGHT | + SPEAKER_FRONT_CENTER | + SPEAKER_LOW_FREQUENCY | + SPEAKER_SIDE_LEFT | + SPEAKER_SIDE_RIGHT; + break; + case DevFmtX51Rear: + InputType.dwChannelMask = SPEAKER_FRONT_LEFT | + SPEAKER_FRONT_RIGHT | + SPEAKER_FRONT_CENTER | + SPEAKER_LOW_FREQUENCY | + SPEAKER_BACK_LEFT | + SPEAKER_BACK_RIGHT; + break; + case DevFmtX61: + InputType.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: + InputType.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; + case DevFmtAmbi3D: + WARN("%s capture not supported\n", DevFmtChannelsString(device->FmtChans)); + return ALC_INVALID_ENUM; + } - InputType.Format.wFormatTag = WAVE_FORMAT_PCM; - InputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans); - InputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8; - InputType.Format.nBlockAlign = InputType.Format.nChannels*InputType.Format.wBitsPerSample/8; - InputType.Format.nSamplesPerSec = device->Frequency; - InputType.Format.nAvgBytesPerSec = InputType.Format.nSamplesPerSec*InputType.Format.nBlockAlign; - InputType.Format.cbSize = 0; + InputType.Format.wFormatTag = WAVE_FORMAT_PCM; + InputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); + InputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8; + InputType.Format.nBlockAlign = InputType.Format.nChannels*InputType.Format.wBitsPerSample/8; + InputType.Format.nSamplesPerSec = device->Frequency; + InputType.Format.nAvgBytesPerSec = InputType.Format.nSamplesPerSec*InputType.Format.nBlockAlign; + InputType.Format.cbSize = 0; + InputType.Samples.wValidBitsPerSample = InputType.Format.wBitsPerSample; + if(device->FmtType == DevFmtFloat) + InputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; + else + InputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - if(InputType.Format.nChannels > 2 || device->FmtType == DevFmtFloat) - { - InputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; - InputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); - InputType.Samples.wValidBitsPerSample = InputType.Format.wBitsPerSample; - if(device->FmtType == DevFmtFloat) - InputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; - else - InputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - } + if(InputType.Format.nChannels > 2 || device->FmtType == DevFmtFloat) + { + InputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + InputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); + } - samples = device->UpdateSize * device->NumUpdates; - samples = maxu(samples, 100 * device->Frequency / 1000); + samples = device->UpdateSize * device->NumUpdates; + samples = maxu(samples, 100 * device->Frequency / 1000); - memset(&DSCBDescription, 0, sizeof(DSCBUFFERDESC)); - DSCBDescription.dwSize = sizeof(DSCBUFFERDESC); - DSCBDescription.dwFlags = 0; - DSCBDescription.dwBufferBytes = samples * InputType.Format.nBlockAlign; - DSCBDescription.lpwfxFormat = &InputType.Format; + memset(&DSCBDescription, 0, sizeof(DSCBUFFERDESC)); + DSCBDescription.dwSize = sizeof(DSCBUFFERDESC); + DSCBDescription.dwFlags = 0; + DSCBDescription.dwBufferBytes = samples * InputType.Format.nBlockAlign; + DSCBDescription.lpwfxFormat = &InputType.Format; + //DirectSoundCapture Init code + hr = DirectSoundCaptureCreate(guid, &self->DSC, NULL); + if(SUCCEEDED(hr)) hr = IDirectSoundCapture_CreateCaptureBuffer(self->DSC, &DSCBDescription, &self->DSCbuffer, NULL); - } if(SUCCEEDED(hr)) { self->Ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates + 1, @@ -921,7 +915,7 @@ static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self) if(!device->Connected) goto done; - FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); BufferBytes = self->BufferBytes; LastCursor = self->Cursor; diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index cce828e9..f43f8527 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -228,7 +228,9 @@ static int ALCjackPlayback_bufferSizeNotify(jack_nframes_t numframes, void *arg) TRACE("%u update size x%u\n", device->UpdateSize, device->NumUpdates); ll_ringbuffer_free(self->Ring); - self->Ring = ll_ringbuffer_create(bufsize, FrameSizeFromDevFmt(device->FmtChans, device->FmtType)); + self->Ring = ll_ringbuffer_create(bufsize, + FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder) + ); if(!self->Ring) { ERR("Failed to reallocate ringbuffer\n"); @@ -423,7 +425,7 @@ static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self) /* Force 32-bit float output. */ device->FmtType = DevFmtFloat; - numchans = ChannelsFromDevFmt(device->FmtChans); + numchans = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); for(i = 0;i < numchans;i++) { char name[64]; @@ -452,7 +454,9 @@ static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self) } ll_ringbuffer_free(self->Ring); - self->Ring = ll_ringbuffer_create(bufsize, FrameSizeFromDevFmt(device->FmtChans, device->FmtType)); + self->Ring = ll_ringbuffer_create(bufsize, + FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder) + ); if(!self->Ring) { ERR("Failed to allocate ringbuffer\n"); diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index a70607e4..43d8429d 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -922,9 +922,7 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self) OutputType.Format.nChannels = 1; OutputType.dwChannelMask = MONO; break; - case DevFmtAmbi1: - case DevFmtAmbi2: - case DevFmtAmbi3: + case DevFmtAmbi3D: device->FmtChans = DevFmtStereo; /*fall-through*/ case DevFmtStereo: @@ -1367,7 +1365,8 @@ FORCE_ALIGN int ALCmmdevCapture_recordProc(void *arg) } else { - size_t framesize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + size_t framesize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, + device->AmbiOrder); ALuint len1 = minu(data[0].len, numsamples); ALuint len2 = minu(data[1].len, numsamples-len1); @@ -1636,9 +1635,7 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) OutputType.dwChannelMask = X7DOT1; break; - case DevFmtAmbi1: - case DevFmtAmbi2: - case DevFmtAmbi3: + case DevFmtAmbi3D: return E_FAIL; } switch(device->FmtType) @@ -1767,7 +1764,7 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) if(device->Frequency != OutputType.Format.nSamplesPerSec || device->FmtType != srcType) { self->SampleConv = CreateSampleConverter( - srcType, device->FmtType, ChannelsFromDevFmt(device->FmtChans), + srcType, device->FmtType, ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder), OutputType.Format.nSamplesPerSec, device->Frequency ); if(!self->SampleConv) @@ -1800,7 +1797,7 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) buffer_len = maxu(device->UpdateSize*device->NumUpdates + 1, buffer_len); ll_ringbuffer_free(self->Ring); self->Ring = ll_ringbuffer_create(buffer_len, - FrameSizeFromDevFmt(device->FmtChans, device->FmtType) + FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder) ); if(!self->Ring) { diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 41f55120..622437b8 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -65,9 +65,7 @@ static SLuint32 GetChannelMask(enum DevFmtChannels chans) 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 DevFmtAmbi1: - case DevFmtAmbi2: - case DevFmtAmbi3: + case DevFmtAmbi3D: break; } return 0; @@ -513,7 +511,7 @@ static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self) device->FmtType = DevFmtShort; SetDefaultWFXChannelOrder(device); - self->mFrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + self->mFrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; @@ -522,7 +520,7 @@ static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self) #ifdef SL_DATAFORMAT_PCM_EX SLDataFormat_PCM_EX format_pcm; format_pcm.formatType = SL_DATAFORMAT_PCM_EX; - format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans); + format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); format_pcm.sampleRate = device->Frequency * 1000; format_pcm.bitsPerSample = BytesFromDevFmt(device->FmtType) * 8; format_pcm.containerSize = format_pcm.bitsPerSample; @@ -533,7 +531,7 @@ static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self) #else SLDataFormat_PCM format_pcm; format_pcm.formatType = SL_DATAFORMAT_PCM; - format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans); + format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); format_pcm.samplesPerSec = device->Frequency * 1000; format_pcm.bitsPerSample = BytesFromDevFmt(device->FmtType) * 8; format_pcm.containerSize = format_pcm.bitsPerSample; diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 6706405d..6774a789 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -280,7 +280,7 @@ static int ALCplaybackOSS_mixerProc(void *ptr) SetRTPriority(); althrd_setname(althrd_current(), MIXER_THREAD_NAME); - frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); ALCplaybackOSS_lock(self); while(!ATOMIC_LOAD_SEQ(&self->killNow) && device->Connected) @@ -418,7 +418,7 @@ static ALCboolean ALCplaybackOSS_reset(ALCplaybackOSS *self) } periods = device->NumUpdates; - numChannels = ChannelsFromDevFmt(device->FmtChans); + numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); ossSpeed = device->Frequency; frameSize = numChannels * BytesFromDevFmt(device->FmtType); /* According to the OSS spec, 16 bytes (log2(16)) is the minimum. */ @@ -444,7 +444,7 @@ static ALCboolean ALCplaybackOSS_reset(ALCplaybackOSS *self) } #undef CHECKERR - if((int)ChannelsFromDevFmt(device->FmtChans) != numChannels) + if((int)ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder) != numChannels) { ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(device->FmtChans), numChannels); return ALC_FALSE; @@ -471,7 +471,9 @@ static ALCboolean ALCplaybackOSS_start(ALCplaybackOSS *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - self->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + self->data_size = device->UpdateSize * FrameSizeFromDevFmt( + device->FmtChans, device->FmtType, device->AmbiOrder + ); self->mix_data = calloc(1, self->data_size); ATOMIC_STORE_SEQ(&self->killNow, AL_FALSE); @@ -543,7 +545,7 @@ static int ALCcaptureOSS_recordProc(void *ptr) SetRTPriority(); althrd_setname(althrd_current(), RECORD_THREAD_NAME); - frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); while(!ATOMIC_LOAD_SEQ(&self->killNow)) { @@ -660,7 +662,7 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) } periods = 4; - numChannels = ChannelsFromDevFmt(device->FmtChans); + numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); frameSize = numChannels * BytesFromDevFmt(device->FmtType); ossSpeed = device->Frequency; log2FragmentSize = log2i(device->UpdateSize * device->NumUpdates * @@ -690,7 +692,7 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) } #undef CHECKERR - if((int)ChannelsFromDevFmt(device->FmtChans) != numChannels) + if((int)ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder) != numChannels) { ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(device->FmtChans), numChannels); close(self->fd); diff --git a/Alc/backends/portaudio.c b/Alc/backends/portaudio.c index b713f330..807e8000 100644 --- a/Alc/backends/portaudio.c +++ b/Alc/backends/portaudio.c @@ -399,7 +399,7 @@ static ALCenum ALCportCapture_open(ALCportCapture *self, const ALCchar *name) samples = device->UpdateSize * device->NumUpdates; samples = maxu(samples, 100 * device->Frequency / 1000); - frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); self->ring = ll_ringbuffer_create(samples, frame_size); if(self->ring == NULL) return ALC_INVALID_VALUE; @@ -433,7 +433,7 @@ static ALCenum ALCportCapture_open(ALCportCapture *self, const ALCchar *name) ERR("%s samples not supported\n", DevFmtTypeString(device->FmtType)); return ALC_INVALID_VALUE; } - self->params.channelCount = ChannelsFromDevFmt(device->FmtChans); + self->params.channelCount = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); err = Pa_OpenStream(&self->stream, &self->params, NULL, device->Frequency, paFramesPerBufferUnspecified, paNoFlag, diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index 26557ea8..9e2d4f73 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -1014,7 +1014,7 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) break; } self->spec.rate = device->Frequency; - self->spec.channels = ChannelsFromDevFmt(device->FmtChans); + self->spec.channels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); if(pa_sample_spec_valid(&self->spec) == 0) { @@ -1028,9 +1028,7 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) case DevFmtMono: mapname = "mono"; break; - case DevFmtAmbi1: - case DevFmtAmbi2: - case DevFmtAmbi3: + case DevFmtAmbi3D: device->FmtChans = DevFmtStereo; /*fall-through*/ case DevFmtStereo: @@ -1464,6 +1462,7 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name) ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; const char *pulse_name = NULL; pa_stream_flags_t flags = 0; + const char *mapname = NULL; pa_channel_map chanmap; ALuint samples; @@ -1488,9 +1487,6 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name) pa_threaded_mainloop_lock(self->loop); - self->spec.rate = device->Frequency; - self->spec.channels = ChannelsFromDevFmt(device->FmtChans); - switch(device->FmtType) { case DevFmtUByte: @@ -1513,6 +1509,44 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name) goto fail; } + switch(device->FmtChans) + { + case DevFmtMono: + mapname = "mono"; + break; + case DevFmtStereo: + mapname = "front-left,front-right"; + break; + case DevFmtQuad: + mapname = "front-left,front-right,rear-left,rear-right"; + break; + case DevFmtX51: + mapname = "front-left,front-right,front-center,lfe,side-left,side-right"; + break; + case DevFmtX51Rear: + mapname = "front-left,front-right,front-center,lfe,rear-left,rear-right"; + break; + case DevFmtX61: + mapname = "front-left,front-right,front-center,lfe,rear-center,side-left,side-right"; + break; + case DevFmtX71: + mapname = "front-left,front-right,front-center,lfe,rear-left,rear-right,side-left,side-right"; + break; + case DevFmtAmbi3D: + ERR("%s capture samples not supported\n", DevFmtChannelsString(device->FmtChans)); + pa_threaded_mainloop_unlock(self->loop); + goto fail; + } + if(!pa_channel_map_parse(&chanmap, mapname)) + { + ERR("Failed to build channel map for %s\n", DevFmtChannelsString(device->FmtChans)); + pa_threaded_mainloop_unlock(self->loop); + return ALC_FALSE; + } + + self->spec.rate = device->Frequency; + self->spec.channels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); + if(pa_sample_spec_valid(&self->spec) == 0) { ERR("Invalid sample format\n"); diff --git a/Alc/backends/qsa.c b/Alc/backends/qsa.c index 9563a918..9da55b59 100644 --- a/Alc/backends/qsa.c +++ b/Alc/backends/qsa.c @@ -179,7 +179,9 @@ FORCE_ALIGN static int qsa_proc_playback(void* ptr) param.sched_priority=param.sched_curpriority+1; SchedSet(0, 0, SCHED_NOCHANGE, ¶m); - const ALint frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + const ALint frame_size = FrameSizeFromDevFmt( + device->FmtChans, device->FmtType, device->AmbiOrder + ); V0(device->Backend,lock)(); while(!data->killNow) @@ -361,14 +363,14 @@ static ALCboolean qsa_reset_playback(ALCdevice* device) data->cparams.start_mode=SND_PCM_START_FULL; data->cparams.stop_mode=SND_PCM_STOP_STOP; - data->cparams.buf.block.frag_size=device->UpdateSize* - ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType); + data->cparams.buf.block.frag_size=device->UpdateSize * + FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); data->cparams.buf.block.frags_max=device->NumUpdates; data->cparams.buf.block.frags_min=device->NumUpdates; data->cparams.format.interleave=1; data->cparams.format.rate=device->Frequency; - data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans); + data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); data->cparams.format.format=format; if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0) @@ -552,7 +554,7 @@ static ALCboolean qsa_reset_playback(ALCdevice* device) SetDefaultChannelOrder(device); device->UpdateSize=data->csetup.buf.block.frag_size/ - (ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType)); + FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); device->NumUpdates=data->csetup.buf.block.frags; data->size=data->csetup.buf.block.frag_size; @@ -684,13 +686,13 @@ static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName) data->cparams.stop_mode=SND_PCM_STOP_STOP; data->cparams.buf.block.frag_size=device->UpdateSize* - ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType); + FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); data->cparams.buf.block.frags_max=device->NumUpdates; data->cparams.buf.block.frags_min=device->NumUpdates; data->cparams.format.interleave=1; data->cparams.format.rate=device->Frequency; - data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans); + data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); data->cparams.format.format=format; if(snd_pcm_plugin_params(data->pcmHandle, &data->cparams) < 0) @@ -749,7 +751,7 @@ static ALCuint qsa_available_samples(ALCdevice* device) { qsa_data* data=(qsa_data*)device->ExtraData; snd_pcm_channel_status_t status; - ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + ALint frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); ALint free_size; int rstatus; @@ -785,7 +787,7 @@ static ALCenum qsa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint s int selectret; struct timeval timeout; int bytes_read; - ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); ALint len=samples*frame_size; int rstatus; diff --git a/Alc/backends/sndio.c b/Alc/backends/sndio.c index ac2dc03f..47e05353 100644 --- a/Alc/backends/sndio.c +++ b/Alc/backends/sndio.c @@ -98,7 +98,7 @@ static int ALCsndioBackend_mixerProc(void *ptr) SetRTPriority(); althrd_setname(althrd_current(), MIXER_THREAD_NAME); - frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); while(!self->killNow && device->Connected) { @@ -245,7 +245,9 @@ static ALCboolean ALCsndioBackend_start(ALCsndioBackend *self) { ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; - self->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + self->data_size = device->UpdateSize * FrameSizeFromDevFmt( + device->FmtChans, device->FmtType, device->AmbiOrder + ); al_free(self->mix_data); self->mix_data = al_calloc(16, self->data_size); diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c index 98c00525..5b3f6136 100644 --- a/Alc/backends/solaris.c +++ b/Alc/backends/solaris.c @@ -116,7 +116,7 @@ static int ALCsolarisBackend_mixerProc(void *ptr) SetRTPriority(); althrd_setname(althrd_current(), MIXER_THREAD_NAME); - frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); ALCsolarisBackend_lock(self); while(!ATOMIC_LOAD_SEQ(&self->killNow) && device->Connected) @@ -209,7 +209,7 @@ static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self) if(device->FmtChans != DevFmtMono) device->FmtChans = DevFmtStereo; - numChannels = ChannelsFromDevFmt(device->FmtChans); + numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); info.play.channels = numChannels; switch(device->FmtType) @@ -243,9 +243,9 @@ static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self) return ALC_FALSE; } - if(ChannelsFromDevFmt(device->FmtChans) != (ALsizei)info.play.channels) + if(ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder) != (ALsizei)info.play.channels) { - ERR("Could not set %d channels, got %d instead\n", ChannelsFromDevFmt(device->FmtChans), info.play.channels); + ERR("Failed to set %s, got %u channels instead\n", DevFmtChannelsString(device->FmtChans), info.play.channels); return ALC_FALSE; } @@ -265,7 +265,9 @@ static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self) SetDefaultChannelOrder(device); free(self->mix_data); - self->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + self->data_size = device->UpdateSize * FrameSizeFromDevFmt( + device->FmtChans, device->FmtType, device->AmbiOrder + ); self->mix_data = calloc(1, self->data_size); return ALC_TRUE; diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index 36d7cbca..c72a632b 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -127,7 +127,7 @@ static int ALCwaveBackend_mixerProc(void *ptr) althrd_setname(althrd_current(), MIXER_THREAD_NAME); - frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); done = 0; if(altimespec_get(&start, AL_TIME_UTC) != AL_TIME_UTC) @@ -251,7 +251,10 @@ static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self) clearerr(self->mFile); if(GetConfigValueBool(NULL, "wave", "bformat", 0)) - device->FmtChans = DevFmtAmbi1; + { + device->FmtChans = DevFmtAmbi3D; + device->AmbiOrder = 1; + } switch(device->FmtType) { @@ -279,9 +282,7 @@ static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self) case DevFmtX51Rear: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020; break; case DevFmtX61: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x100 | 0x200 | 0x400; break; case DevFmtX71: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x200 | 0x400; break; - case DevFmtAmbi1: - case DevFmtAmbi2: - case DevFmtAmbi3: + case DevFmtAmbi3D: /* .amb output requires FuMa */ device->AmbiLayout = AmbiLayout_FuMa; device->AmbiScale = AmbiNorm_FuMa; @@ -290,14 +291,14 @@ static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self) break; } bits = BytesFromDevFmt(device->FmtType) * 8; - channels = ChannelsFromDevFmt(device->FmtChans); + channels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); - fprintf(self->mFile, "RIFF"); + fputs("RIFF", self->mFile); fwrite32le(0xFFFFFFFF, self->mFile); // 'RIFF' header len; filled in at close - fprintf(self->mFile, "WAVE"); + fputs("WAVE", self->mFile); - fprintf(self->mFile, "fmt "); + fputs("fmt ", self->mFile); fwrite32le(40, self->mFile); // 'fmt ' header len; 40 bytes for EXTENSIBLE // 16-bit val, format type id (extensible: 0xFFFE) @@ -323,7 +324,7 @@ static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self) (isbformat ? SUBTYPE_BFORMAT_PCM : SUBTYPE_PCM)), 1, 16, self->mFile); (void)val; - fprintf(self->mFile, "data"); + fputs("data", self->mFile); fwrite32le(0xFFFFFFFF, self->mFile); // 'data' header len; filled in at close if(ferror(self->mFile)) @@ -342,7 +343,9 @@ static ALCboolean ALCwaveBackend_start(ALCwaveBackend *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - self->mSize = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + self->mSize = device->UpdateSize * FrameSizeFromDevFmt( + device->FmtChans, device->FmtType, device->AmbiOrder + ); self->mBuffer = malloc(self->mSize); if(!self->mBuffer) { diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index da0d67a1..b5b3cdb6 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -382,7 +382,7 @@ static ALCboolean ALCwinmmPlayback_start(ALCwinmmPlayback *self) // Create 4 Buffers BufferSize = device->UpdateSize*device->NumUpdates / 4; - BufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + BufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); BufferData = calloc(4, BufferSize); for(i = 0;i < 4;i++) @@ -563,9 +563,7 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name) case DevFmtX51Rear: case DevFmtX61: case DevFmtX71: - case DevFmtAmbi1: - case DevFmtAmbi2: - case DevFmtAmbi3: + case DevFmtAmbi3D: return ALC_INVALID_ENUM; } @@ -586,7 +584,7 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name) memset(&self->Format, 0, sizeof(WAVEFORMATEX)); self->Format.wFormatTag = ((device->FmtType == DevFmtFloat) ? WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM); - self->Format.nChannels = ChannelsFromDevFmt(device->FmtChans); + self->Format.nChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); self->Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8; self->Format.nBlockAlign = self->Format.wBitsPerSample * self->Format.nChannels / 8; diff --git a/Alc/converter.c b/Alc/converter.c index 38d51d47..56af8ff0 100644 --- a/Alc/converter.c +++ b/Alc/converter.c @@ -389,7 +389,7 @@ void ChannelConverterInput(ChannelConverter *converter, const ALvoid *src, ALflo if(converter->mSrcChans == converter->mDstChans) { LoadSamples(dst, src, 1, converter->mSrcType, - frames*ChannelsFromDevFmt(converter->mSrcChans)); + frames*ChannelsFromDevFmt(converter->mSrcChans, 0)); return; } diff --git a/Alc/panning.c b/Alc/panning.c index dcdcf36d..e4941720 100644 --- a/Alc/panning.c +++ b/Alc/panning.c @@ -620,13 +620,11 @@ static void InitPanning(ALCdevice *device) coeffcount = 16; break; - case DevFmtAmbi1: - case DevFmtAmbi2: - case DevFmtAmbi3: + case DevFmtAmbi3D: break; } - if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3) + if(device->FmtChans == DevFmtAmbi3D) { const char *devname = alstr_get_cstr(device->DeviceName); const ALsizei *acnmap = (device->AmbiLayout == AmbiLayout_FuMa) ? FuMa2ACN : ACN2ACN; @@ -635,9 +633,9 @@ static void InitPanning(ALCdevice *device) /*(device->AmbiScale == AmbiNorm_N3D) ?*/ UnitScale; ALfloat nfc_delay = 0.0f; - count = (device->FmtChans == DevFmtAmbi3) ? 16 : - (device->FmtChans == DevFmtAmbi2) ? 9 : - (device->FmtChans == DevFmtAmbi1) ? 4 : 1; + count = (device->AmbiOrder == 3) ? 16 : + (device->AmbiOrder == 2) ? 9 : + (device->AmbiOrder == 1) ? 4 : 1; for(i = 0;i < count;i++) { ALsizei acn = acnmap[i]; @@ -647,7 +645,7 @@ static void InitPanning(ALCdevice *device) device->Dry.CoeffCount = 0; device->Dry.NumChannels = count; - if(device->FmtChans == DevFmtAmbi1) + if(device->AmbiOrder < 2) { device->FOAOut.Ambi = device->Dry.Ambi; device->FOAOut.CoeffCount = device->Dry.CoeffCount; @@ -674,10 +672,7 @@ static void InitPanning(ALCdevice *device) { nfc_delay = clampf(nfc_delay, 0.001f, 1000.0f); InitNearFieldCtrl(device, nfc_delay * SPEEDOFSOUNDMETRESPERSEC, - (device->FmtChans == DevFmtAmbi3) ? 3 : - (device->FmtChans == DevFmtAmbi2) ? 2 : 1, - true - ); + device->AmbiOrder, true); } } else @@ -861,7 +856,7 @@ static void InitHQPanning(ALCdevice *device, const AmbDecConf *conf, const ALsiz device->FOAOut.NumChannels = count; } - device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans); + device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); avg_dist = 0.0f; for(i = 0;i < conf->NumSpeakers;i++) @@ -963,7 +958,7 @@ static void InitHrtfPanning(ALCdevice *device, bool hoa_mode) ambiup_reset(device->AmbiUp, device); } - device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans); + device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); device->Hrtf->IrSize = BuildBFormatHrtf(device->HrtfHandle, device->Hrtf, device->Dry.NumChannels, @@ -992,7 +987,7 @@ static void InitUhjPanning(ALCdevice *device) device->FOAOut.CoeffCount = device->Dry.CoeffCount; device->FOAOut.NumChannels = 0; - device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans); + device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); } void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq) @@ -1049,9 +1044,7 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf /* Mono, Stereo, and Ambisonics output don't use custom decoders. */ case DevFmtMono: case DevFmtStereo: - case DevFmtAmbi1: - case DevFmtAmbi2: - case DevFmtAmbi3: + case DevFmtAmbi3D: break; } if(layout) @@ -1085,7 +1078,7 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf { bformatdec_free(device->AmbiDecoder); device->AmbiDecoder = NULL; - if(device->FmtChans > DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3) + if(device->FmtChans == DevFmtAmbi3D && device->AmbiOrder == 1) { if(!device->AmbiUp) device->AmbiUp = ambiup_alloc(); diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 1919a257..fc2c5e8f 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -508,24 +508,20 @@ enum DevFmtChannels { DevFmtX51 = ALC_5POINT1_SOFT, DevFmtX61 = ALC_6POINT1_SOFT, DevFmtX71 = ALC_7POINT1_SOFT, + DevFmtAmbi3D = ALC_BFORMAT3D_SOFT, /* Similar to 5.1, except using rear channels instead of sides */ DevFmtX51Rear = 0x80000000, - /* Ambisonic formats should be kept together */ - DevFmtAmbi1, - DevFmtAmbi2, - DevFmtAmbi3, - DevFmtChannelsDefault = DevFmtStereo }; #define MAX_OUTPUT_CHANNELS (16) ALsizei BytesFromDevFmt(enum DevFmtType type); -ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans); -inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type) +ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder); +inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type, ALsizei ambiorder) { - return ChannelsFromDevFmt(chans) * BytesFromDevFmt(type); + return ChannelsFromDevFmt(chans, ambiorder) * BytesFromDevFmt(type); } enum AmbiLayout { @@ -668,6 +664,7 @@ struct ALCdevice_struct enum DevFmtChannels FmtChans; enum DevFmtType FmtType; ALboolean IsHeadphones; + ALsizei AmbiOrder; /* For DevFmtAmbi* output only, specifies the channel order and * normalization. */ -- cgit v1.2.3 From f94fa5d5cfb78ab5438a53b2ad17f033660103c9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 14 Apr 2017 17:47:55 -0700 Subject: Use separate atomic macros for pointers --- Alc/ALc.c | 36 ++++++------ Alc/ALu.c | 12 ++-- Alc/backends/opensl.c | 4 +- Alc/backends/oss.c | 4 +- Alc/backends/solaris.c | 2 +- Alc/helpers.c | 4 +- OpenAL32/alAuxEffectSlot.c | 18 +++--- OpenAL32/alError.c | 4 +- OpenAL32/alListener.c | 7 +-- OpenAL32/alSource.c | 19 +++---- include/atomic.h | 133 ++++++++++++++++++++++++++++----------------- 11 files changed, 135 insertions(+), 108 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index 2a636c59..cc9aa5c3 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -1247,7 +1247,7 @@ static void alc_cleanup(void) free(alcCaptureDefaultDeviceSpecifier); alcCaptureDefaultDeviceSpecifier = NULL; - if((dev=ATOMIC_EXCHANGE_SEQ(ALCdevice*, &DeviceList, NULL)) != NULL) + if((dev=ATOMIC_EXCHANGE_PTR_SEQ(&DeviceList, NULL)) != NULL) { ALCuint num = 0; do { @@ -1678,7 +1678,7 @@ void ALCcontext_DeferUpdates(ALCcontext *context) void ALCcontext_ProcessUpdates(ALCcontext *context) { ReadLock(&context->PropLock); - if(ATOMIC_EXCHANGE_SEQ(ALenum, &context->DeferUpdates, AL_FALSE)) + if(ATOMIC_EXCHANGE_SEQ(&context->DeferUpdates, AL_FALSE)) { /* Tell the mixer to stop applying updates, then wait for any active * updating to finish, before providing updates. @@ -2225,11 +2225,10 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) * number of auxiliary sends changed. Playing (or paused) sources * will have updates respecified in UpdateAllSourceProps. */ - props = ATOMIC_EXCHANGE_SEQ(struct ALsourceProps*, &source->Update, NULL); + props = ATOMIC_EXCHANGE_PTR_SEQ(&source->Update, NULL); al_free(props); - props = ATOMIC_EXCHANGE(struct ALsourceProps*, &source->FreeList, NULL, - almemory_order_relaxed); + props = ATOMIC_EXCHANGE_PTR(&source->FreeList, NULL, almemory_order_relaxed); while(props) { struct ALsourceProps *next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); @@ -2489,8 +2488,7 @@ static void FreeContext(ALCcontext *context) TRACE("%p\n", context); - auxslots = ATOMIC_EXCHANGE(struct ALeffectslotArray*, &context->ActiveAuxSlots, - NULL, almemory_order_relaxed); + auxslots = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, NULL, almemory_order_relaxed); al_free(auxslots); if(context->SourceMap.size > 0) @@ -2557,13 +2555,13 @@ static bool ReleaseContext(ALCcontext *context, ALCdevice *device) } origctx = context; - if(ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext*, &GlobalContext, &origctx, NULL)) + if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext, &origctx, NULL)) ALCcontext_DecRef(context); ALCdevice_Lock(device); origctx = context; newhead = context->next; - if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext*, &device->ContextList, &origctx, newhead)) + if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device->ContextList, &origctx, newhead)) { ALCcontext *volatile*list = &origctx->next; while(*list) @@ -2750,11 +2748,11 @@ ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device) if(VerifyDevice(&device)) { - errorCode = ATOMIC_EXCHANGE_SEQ(ALCenum, &device->LastError, ALC_NO_ERROR); + errorCode = ATOMIC_EXCHANGE_SEQ(&device->LastError, ALC_NO_ERROR); ALCdevice_DecRef(device); } else - errorCode = ATOMIC_EXCHANGE_SEQ(ALCenum, &LastNullDeviceError, ALC_NO_ERROR); + errorCode = ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError, ALC_NO_ERROR); return errorCode; } @@ -3549,8 +3547,8 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin ALCcontext *head = ATOMIC_LOAD_SEQ(&device->ContextList); do { ALContext->next = head; - } while(ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCcontext*, - &device->ContextList, &head, ALContext) == 0); + } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device->ContextList, &head, + ALContext) == 0); } almtx_unlock(&device->BackendLock); @@ -3628,7 +3626,7 @@ ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context) return ALC_FALSE; } /* context's reference count is already incremented */ - context = ATOMIC_EXCHANGE_SEQ(ALCcontext*, &GlobalContext, context); + context = ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext, context); if(context) ALCcontext_DecRef(context); if((context=altss_get(LocalContext)) != NULL) @@ -3937,7 +3935,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList); do { device->next = head; - } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device)); + } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device)); } TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName)); @@ -3968,7 +3966,7 @@ ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device) almtx_lock(&device->BackendLock); origdev = device; - if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice*, &DeviceList, &origdev, device->next)) + if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, device->next)) { ALCdevice *volatile*list = &origdev->next; while(*list) @@ -4113,7 +4111,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList); do { device->next = head; - } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device)); + } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device)); } TRACE("Created device %p, \"%s\"\n", device, alstr_get_cstr(device->DeviceName)); @@ -4138,7 +4136,7 @@ ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device) } origdev = device; - if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice*, &DeviceList, &origdev, device->next)) + if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList, &origdev, device->next)) { ALCdevice *volatile*list = &origdev->next; while(*list) @@ -4334,7 +4332,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN ALCdevice *head = ATOMIC_LOAD_SEQ(&DeviceList); do { device->next = head; - } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice*, &DeviceList, &head, device)); + } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList, &head, device)); } TRACE("Created device %p\n", device); diff --git a/Alc/ALu.c b/Alc/ALu.c index 4f41d012..89689fba 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -241,7 +241,7 @@ static ALboolean CalcListenerParams(ALCcontext *Context) struct ALlistenerProps *props; aluVector vel; - props = ATOMIC_EXCHANGE(struct ALlistenerProps*, &Listener->Update, NULL, almemory_order_acq_rel); + props = ATOMIC_EXCHANGE_PTR(&Listener->Update, NULL, almemory_order_acq_rel); if(!props) return AL_FALSE; /* AT then UP */ @@ -291,7 +291,7 @@ static ALboolean CalcEffectSlotParams(ALeffectslot *slot, ALCdevice *device) struct ALeffectslotProps *props; ALeffectState *state; - props = ATOMIC_EXCHANGE(struct ALeffectslotProps*, &slot->Update, NULL, almemory_order_acq_rel); + props = ATOMIC_EXCHANGE_PTR(&slot->Update, NULL, almemory_order_acq_rel); if(!props) return AL_FALSE; slot->Params.Gain = props->Gain; @@ -1252,7 +1252,7 @@ static void CalcSourceParams(ALvoice *voice, ALsource *source, ALCcontext *conte const ALbufferlistitem *BufferListItem; struct ALsourceProps *props; - props = ATOMIC_EXCHANGE(struct ALsourceProps*, &source->Update, NULL, almemory_order_acq_rel); + props = ATOMIC_EXCHANGE_PTR(&source->Update, NULL, almemory_order_acq_rel); if(!props && !force) return; if(props) @@ -1607,14 +1607,14 @@ void aluHandleDisconnect(ALCdevice *device) voice_end = voice + Context->VoiceCount; while(voice != voice_end) { - ALsource *source = ATOMIC_EXCHANGE(ALsource*, &(*voice)->Source, NULL, - almemory_order_acq_rel); + ALsource *source = ATOMIC_EXCHANGE_PTR(&(*voice)->Source, NULL, + almemory_order_acq_rel); ATOMIC_STORE(&(*voice)->Playing, false, almemory_order_release); if(source) { ALenum playing = AL_PLAYING; - ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALenum, &source->state, &playing, AL_STOPPED); + (void)(ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(&source->state, &playing, AL_STOPPED)); } voice++; diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 622437b8..4e295f23 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -149,7 +149,7 @@ typedef struct ALCopenslPlayback { ALsizei mFrameSize; - ATOMIC(ALboolean) mKillNow; + ATOMIC(ALenum) mKillNow; althrd_t mThread; } ALCopenslPlayback; @@ -637,7 +637,7 @@ static void ALCopenslPlayback_stop(ALCopenslPlayback *self) SLresult result; int res; - if(ATOMIC_EXCHANGE_SEQ(ALboolean, &self->mKillNow, AL_TRUE)) + if(ATOMIC_EXCHANGE_SEQ(&self->mKillNow, AL_TRUE)) return; /* Lock the backend to ensure we don't flag the mixer to die and signal the diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 6774a789..33ea55eb 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -491,7 +491,7 @@ static void ALCplaybackOSS_stop(ALCplaybackOSS *self) { int res; - if(ATOMIC_EXCHANGE_SEQ(ALenum, &self->killNow, AL_TRUE)) + if(ATOMIC_EXCHANGE_SEQ(&self->killNow, AL_TRUE)) return; althrd_join(self->thread, &res); @@ -745,7 +745,7 @@ static void ALCcaptureOSS_stop(ALCcaptureOSS *self) { int res; - if(ATOMIC_EXCHANGE_SEQ(ALenum, &self->killNow, AL_TRUE)) + if(ATOMIC_EXCHANGE_SEQ(&self->killNow, AL_TRUE)) return; althrd_join(self->thread, &res); diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c index 5b3f6136..5dfb5084 100644 --- a/Alc/backends/solaris.c +++ b/Alc/backends/solaris.c @@ -285,7 +285,7 @@ static void ALCsolarisBackend_stop(ALCsolarisBackend *self) { int res; - if(ATOMIC_EXCHANGE_SEQ(int, &self->killNow, AL_TRUE)) + if(ATOMIC_EXCHANGE_SEQ(&self->killNow, AL_TRUE)) return; althrd_join(self->thread, &res); diff --git a/Alc/helpers.c b/Alc/helpers.c index 5d23c3a7..8e685c75 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -564,7 +564,7 @@ vector_al_string SearchDataFiles(const char *ext, const char *subdir) vector_al_string results = VECTOR_INIT_STATIC(); size_t i; - while(ATOMIC_EXCHANGE_SEQ(uint, &search_lock, 1) == 1) + while(ATOMIC_EXCHANGE_SEQ(&search_lock, 1) == 1) althrd_yield(); /* If the path is absolute, use it directly. */ @@ -840,7 +840,7 @@ vector_al_string SearchDataFiles(const char *ext, const char *subdir) static RefCount search_lock; vector_al_string results = VECTOR_INIT_STATIC(); - while(ATOMIC_EXCHANGE_SEQ(uint, &search_lock, 1) == 1) + while(ATOMIC_EXCHANGE_SEQ(&search_lock, 1) == 1) althrd_yield(); if(subdir[0] == '/') diff --git a/OpenAL32/alAuxEffectSlot.c b/OpenAL32/alAuxEffectSlot.c index 743fac14..de7de943 100644 --- a/OpenAL32/alAuxEffectSlot.c +++ b/OpenAL32/alAuxEffectSlot.c @@ -126,9 +126,8 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo if(curarray) memcpy(newarray->slot+n, curarray->slot, sizeof(ALeffectslot*)*curarray->count); - newarray = ATOMIC_EXCHANGE(struct ALeffectslotArray*, - &context->ActiveAuxSlots, newarray, almemory_order_acq_rel - ); + newarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray, + almemory_order_acq_rel); device = context->Device; while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1)) althrd_yield(); @@ -187,9 +186,8 @@ AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint * newarray->slot[i++] = slot; } - newarray = ATOMIC_EXCHANGE(struct ALeffectslotArray*, - &context->ActiveAuxSlots, newarray, almemory_order_acq_rel - ); + newarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray, + almemory_order_acq_rel); device = context->Device; while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1)) althrd_yield(); @@ -668,9 +666,8 @@ void UpdateEffectSlotProps(ALeffectslot *slot) struct ALeffectslotProps *next; do { next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); - } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALeffectslotProps*, - &slot->FreeList, &props, next, almemory_order_seq_cst, - almemory_order_acquire) == 0); + } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&slot->FreeList, &props, next, + almemory_order_seq_cst, almemory_order_acquire) == 0); } /* Copy in current property values. */ @@ -687,8 +684,7 @@ void UpdateEffectSlotProps(ALeffectslot *slot) props->State = slot->Effect.State; /* Set the new container for updating internal parameters. */ - props = ATOMIC_EXCHANGE(struct ALeffectslotProps*, &slot->Update, props, - almemory_order_acq_rel); + props = ATOMIC_EXCHANGE_PTR(&slot->Update, props, almemory_order_acq_rel); if(props) { /* If there was an unused update container, put it back in the diff --git a/OpenAL32/alError.c b/OpenAL32/alError.c index 19fcaa6d..6c953977 100644 --- a/OpenAL32/alError.c +++ b/OpenAL32/alError.c @@ -49,7 +49,7 @@ ALvoid alSetError(ALCcontext *Context, ALenum errorCode) #endif } - ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALenum, &Context->LastError, &curerr, errorCode); + (void)(ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(&Context->LastError, &curerr, errorCode)); } AL_API ALenum AL_APIENTRY alGetError(void) @@ -74,7 +74,7 @@ AL_API ALenum AL_APIENTRY alGetError(void) return AL_INVALID_OPERATION; } - errorCode = ATOMIC_EXCHANGE_SEQ(ALenum, &Context->LastError, AL_NO_ERROR); + errorCode = ATOMIC_EXCHANGE_SEQ(&Context->LastError, AL_NO_ERROR); ALCcontext_DecRef(Context); diff --git a/OpenAL32/alListener.c b/OpenAL32/alListener.c index e3d71435..d117c0ca 100644 --- a/OpenAL32/alListener.c +++ b/OpenAL32/alListener.c @@ -468,9 +468,8 @@ void UpdateListenerProps(ALCcontext *context) struct ALlistenerProps *next; do { next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); - } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALlistenerProps*, - &listener->FreeList, &props, next, almemory_order_seq_cst, - almemory_order_acquire) == 0); + } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&listener->FreeList, &props, next, + almemory_order_seq_cst, almemory_order_acquire) == 0); } /* Copy in current property values. */ @@ -500,7 +499,7 @@ void UpdateListenerProps(ALCcontext *context) props->DistanceModel = context->DistanceModel;; /* Set the new container for updating internal parameters. */ - props = ATOMIC_EXCHANGE(struct ALlistenerProps*, &listener->Update, props, almemory_order_acq_rel); + props = ATOMIC_EXCHANGE_PTR(&listener->Update, props, almemory_order_acq_rel); if(props) { /* If there was an unused update container, put it back in the diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index a8c4ce2f..040078df 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -158,7 +158,7 @@ static inline ALenum GetSourceState(ALsource *source, ALvoice *voice) if(!voice) { ALenum state = AL_PLAYING; - if(ATOMIC_COMPARE_EXCHANGE_STRONG(ALenum, &source->state, &state, AL_STOPPED, + if(ATOMIC_COMPARE_EXCHANGE_STRONG(&source->state, &state, AL_STOPPED, almemory_order_acq_rel, almemory_order_acquire)) return AL_STOPPED; return state; @@ -747,7 +747,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p Source->SourceType = AL_UNDETERMINED; newlist = NULL; } - oldlist = ATOMIC_EXCHANGE_SEQ(ALbufferlistitem*, &Source->queue, newlist); + oldlist = ATOMIC_EXCHANGE_PTR_SEQ(&Source->queue, newlist); WriteUnlock(&Source->queue_lock); UnlockBuffersRead(device); @@ -2784,8 +2784,8 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu source->SourceType = AL_STREAMING; BufferList = NULL; - if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALbufferlistitem*, &source->queue, - &BufferList, BufferListStart)) + if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&source->queue, &BufferList, + BufferListStart)) { /* Queue head is not NULL, append to the end of the queue */ while(BufferList->next != NULL) @@ -2854,7 +2854,7 @@ AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint } /* Swap it, and cut the new head from the old. */ - OldHead = ATOMIC_EXCHANGE_SEQ(ALbufferlistitem*, &source->queue, OldTail->next); + OldHead = ATOMIC_EXCHANGE_PTR_SEQ(&source->queue, OldTail->next); if(OldTail->next) { ALCdevice *device = context->Device; @@ -3003,7 +3003,7 @@ static void DeinitSource(ALsource *source, ALsizei num_sends) if(count > 3) WARN("Freed "SZFMT" Source property objects\n", count); - BufferList = ATOMIC_EXCHANGE_SEQ(ALbufferlistitem*, &source->queue, NULL); + BufferList = ATOMIC_EXCHANGE_PTR_SEQ(&source->queue, NULL); while(BufferList != NULL) { ALbufferlistitem *next = BufferList->next; @@ -3040,9 +3040,8 @@ static void UpdateSourceProps(ALsource *source, ALsizei num_sends) struct ALsourceProps *next; do { next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); - } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALsourceProps*, - &source->FreeList, &props, next, almemory_order_acq_rel, - almemory_order_acquire) == 0); + } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&source->FreeList, &props, next, + almemory_order_acq_rel, almemory_order_acquire) == 0); } /* Copy in current property values. */ @@ -3103,7 +3102,7 @@ static void UpdateSourceProps(ALsource *source, ALsizei num_sends) } /* Set the new container for updating internal parameters. */ - props = ATOMIC_EXCHANGE(struct ALsourceProps*, &source->Update, props, almemory_order_acq_rel); + props = ATOMIC_EXCHANGE_PTR(&source->Update, props, almemory_order_acq_rel); if(props) { /* If there was an unused update container, put it back in the diff --git a/include/atomic.h b/include/atomic.h index 57609c33..a42cfa4a 100644 --- a/include/atomic.h +++ b/include/atomic.h @@ -34,10 +34,10 @@ extern "C" { #define ATOMIC_ADD(_val, _incr, _MO) atomic_fetch_add_explicit(_val, _incr, _MO) #define ATOMIC_SUB(_val, _decr, _MO) atomic_fetch_sub_explicit(_val, _decr, _MO) -#define ATOMIC_EXCHANGE(T, _val, _newval, _MO) atomic_exchange_explicit(_val, _newval, _MO) -#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _orig, _newval, _MO1, _MO2) \ +#define ATOMIC_EXCHANGE(_val, _newval, _MO) atomic_exchange_explicit(_val, _newval, _MO) +#define ATOMIC_COMPARE_EXCHANGE_STRONG(_val, _orig, _newval, _MO1, _MO2) \ atomic_compare_exchange_strong_explicit(_val, _orig, _newval, _MO1, _MO2) -#define ATOMIC_COMPARE_EXCHANGE_WEAK(T, _val, _orig, _newval, _MO1, _MO2) \ +#define ATOMIC_COMPARE_EXCHANGE_WEAK(_val, _orig, _newval, _MO1, _MO2) \ atomic_compare_exchange_weak_explicit(_val, _orig, _newval, _MO1, _MO2) #define ATOMIC_FLAG_TEST_AND_SET(_val, _MO) atomic_flag_test_and_set_explicit(_val, _MO) @@ -77,14 +77,12 @@ enum almemory_order { #define ATOMIC_ADD(_val, _incr, _MO) __sync_fetch_and_add(&(_val)->value, (_incr)) #define ATOMIC_SUB(_val, _decr, _MO) __sync_fetch_and_sub(&(_val)->value, (_decr)) -#define ATOMIC_EXCHANGE(T, _val, _newval, _MO) __extension__({ \ - static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \ +#define ATOMIC_EXCHANGE(_val, _newval, _MO) __extension__({ \ __asm__ __volatile__("" ::: "memory"); \ __sync_lock_test_and_set(&(_val)->value, (_newval)); \ }) -#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval, _MO1, _MO2) __extension__({ \ - static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \ - T _o = *(_oldval); \ +#define ATOMIC_COMPARE_EXCHANGE_STRONG(_val, _oldval, _newval, _MO1, _MO2) __extension__({ \ + __typeof(*(_oldval)) _o = *(_oldval); \ *(_oldval) = __sync_val_compare_and_swap(&(_val)->value, _o, (_newval)); \ *(_oldval) == _o; \ }) @@ -175,20 +173,29 @@ enum almemory_order { _r; \ }) -#define ATOMIC_EXCHANGE(T, _val, _newval, _MO) __extension__({ \ - static_assert(sizeof(T)==4 || sizeof(T)==8, "Type "#T" has incorrect size!"); \ - static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \ - T _r; \ - if(sizeof(T) == 4) WRAP_XCHG("l", _r, &(_val)->value, (T)(_newval)); \ - else if(sizeof(T) == 8) WRAP_XCHG("q", _r, &(_val)->value, (T)(_newval)); \ +#define ATOMIC_EXCHANGE(_val, _newval, _MO) __extension__({ \ + __typeof((_val)->value) _r; \ + if(sizeof((_val)->value) == 4) WRAP_XCHG("l", _r, &(_val)->value, (_newval)); \ + else if(sizeof((_val)->value) == 8) WRAP_XCHG("q", _r, &(_val)->value, (_newval)); \ _r; \ }) -#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval, _MO1, _MO2) __extension__({ \ - static_assert(sizeof(T)==4 || sizeof(T)==8, "Type "#T" has incorrect size!"); \ - static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \ - T _old = *(_oldval); \ - if(sizeof(T) == 4) WRAP_CMPXCHG("l", *(_oldval), &(_val)->value, _old, (T)(_newval)); \ - else if(sizeof(T) == 8) WRAP_CMPXCHG("q", *(_oldval), &(_val)->value, _old, (T)(_newval)); \ +#define ATOMIC_COMPARE_EXCHANGE_STRONG(_val, _oldval, _newval, _MO1, _MO2) __extension__({ \ + __typeof(*(_oldval)) _old = *(_oldval); \ + if(sizeof((_val)->value) == 4) WRAP_CMPXCHG("l", *(_oldval), &(_val)->value, _old, (_newval)); \ + else if(sizeof((_val)->value) == 8) WRAP_CMPXCHG("q", *(_oldval), &(_val)->value, _old, (_newval)); \ + *(_oldval) == _old; \ +}) + +#define ATOMIC_EXCHANGE_PTR(_val, _newval, _MO) __extension__({ \ + void *_r; \ + if(sizeof(void*) == 4) WRAP_XCHG("l", _r, &(_val)->value, (_newval)); \ + else if(sizeof(void*) == 8) WRAP_XCHG("q", _r, &(_val)->value, (_newval));\ + _r; \ +}) +#define ATOMIC_COMPARE_EXCHANGE_PTR_STRONG(_val, _oldval, _newval, _MO1, _MO2) __extension__({ \ + void *_old = *(_oldval); \ + if(sizeof(void*) == 4) WRAP_CMPXCHG("l", *(_oldval), &(_val)->value, _old, (_newval)); \ + else if(sizeof(void*) == 8) WRAP_CMPXCHG("q", *(_oldval), &(_val)->value, _old, (_newval)); \ *(_oldval) == _old; \ }) @@ -205,14 +212,13 @@ enum almemory_order { #define WIN32_LEAN_AND_MEAN #include -/* NOTE: This mess is *extremely* noisy, at least on GCC. It works by wrapping - * Windows' 32-bit and 64-bit atomic methods, which are then casted to use the - * given type based on its size (e.g. int and float use 32-bit atomics). This - * is fine for the swap and compare-and-swap methods, although the add and - * subtract methods only work properly for integer types. +/* NOTE: This mess is *extremely* touchy. It lacks quite a bit of safety + * checking due to the lack of multi-statement expressions, typeof(), and C99 + * compound literals. It is incapable of properly exchanging floats, which get + * casted to LONG/int, and could cast away potential warnings. * - * Despite how noisy it is, it's unfortunately the only way that doesn't rely - * on C99 (damn MSVC). + * Unfortunately, it's the only semi-safe way that doesn't rely on C99 (because + * MSVC). */ inline LONG AtomicAdd32(volatile LONG *dest, LONG incr) @@ -240,6 +246,10 @@ inline LONGLONG AtomicSwap64(volatile LONGLONG *dest, LONGLONG newval) { return InterlockedExchange64(dest, newval); } +inline void *AtomicSwapPtr(void *volatile *dest, void *newval) +{ + return InterlockedExchangePointer(dest, newval); +} inline bool CompareAndSwap32(volatile LONG *dest, LONG newval, LONG *oldval) { @@ -253,10 +263,16 @@ inline bool CompareAndSwap64(volatile LONGLONG *dest, LONGLONG newval, LONGLONG *oldval = InterlockedCompareExchange64(dest, newval, *oldval); return old == *oldval; } +inline bool CompareAndSwapPtr(void *volatile *dest, void *newval, void **oldval) +{ + void *old = *oldval; + *oldval = InterlockedCompareExchangePointer(dest, newval, *oldval); + return old == *oldval; +} #define WRAP_ADDSUB(T, _func, _ptr, _amnt) _func((T volatile*)(_ptr), (_amnt)) -#define WRAP_XCHG(T, _func, _ptr, _newval) ((T(*)(T volatile*,T))_func)((_ptr), (_newval)) -#define WRAP_CMPXCHG(T, _func, _ptr, _newval, _oldval) ((bool(*)(T volatile*,T,T*))_func)((_ptr), (_newval), (_oldval)) +#define WRAP_XCHG(T, _func, _ptr, _newval) _func((T volatile*)(_ptr), (_newval)) +#define WRAP_CMPXCHG(T, _func, _ptr, _newval, _oldval) _func((T volatile*)(_ptr), (_newval), (T*)(_oldval)) enum almemory_order { @@ -289,13 +305,20 @@ int _al_invalid_atomic_size(); /* not defined */ (sizeof((_val)->value)==8) ? WRAP_ADDSUB(LONGLONG, AtomicSub64, &(_val)->value, (_decr)) : \ _al_invalid_atomic_size()) -#define ATOMIC_EXCHANGE(T, _val, _newval, _MO) \ - ((sizeof(T)==4) ? WRAP_XCHG(T, AtomicSwap32, &(_val)->value, (_newval)) : \ - (sizeof(T)==8) ? WRAP_XCHG(T, AtomicSwap64, &(_val)->value, (_newval)) : \ - (T)_al_invalid_atomic_size()) -#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval, _MO1, _MO2) \ - ((sizeof(T)==4) ? WRAP_CMPXCHG(T, CompareAndSwap32, &(_val)->value, (_newval), (_oldval)) : \ - (sizeof(T)==8) ? WRAP_CMPXCHG(T, CompareAndSwap64, &(_val)->value, (_newval), (_oldval)) : \ +#define ATOMIC_EXCHANGE(_val, _newval, _MO) \ + ((sizeof((_val)->value)==4) ? WRAP_XCHG(LONG, AtomicSwap32, &(_val)->value, (_newval)) : \ + (sizeof((_val)->value)==8) ? WRAP_XCHG(LONGLONG, AtomicSwap64, &(_val)->value, (_newval)) : \ + (LONG)_al_invalid_atomic_size()) +#define ATOMIC_COMPARE_EXCHANGE_STRONG(_val, _oldval, _newval, _MO1, _MO2) \ + ((sizeof((_val)->value)==4) ? WRAP_CMPXCHG(LONG, CompareAndSwap32, &(_val)->value, (_newval), (_oldval)) : \ + (sizeof((_val)->value)==8) ? WRAP_CMPXCHG(LONGLONG, CompareAndSwap64, &(_val)->value, (_newval), (_oldval)) : \ + (bool)_al_invalid_atomic_size()) + +#define ATOMIC_EXCHANGE_PTR(_val, _newval, _MO) \ + ((sizeof((_val)->value)==sizeof(void*)) ? AtomicSwapPtr((void*volatile*)&(_val)->value, (_newval)) : \ + (void*)_al_invalid_atomic_size()) +#define ATOMIC_COMPARE_EXCHANGE_PTR_STRONG(_val, _oldval, _newval, _MO1, _MO2)\ + ((sizeof((_val)->value)==sizeof(void*)) ? CompareAndSwapPtr((void*volatile*)&(_val)->value, (_newval), (void**)(_oldval)) : \ (bool)_al_invalid_atomic_size()) #define ATOMIC_THREAD_FENCE(order) do { \ @@ -320,21 +343,27 @@ int _al_invalid_atomic_size(); /* not defined */ #define ATOMIC_ADD(...) (0) #define ATOMIC_SUB(...) (0) -#define ATOMIC_EXCHANGE(T, ...) (0) -#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, ...) (0) -#define ATOMIC_COMPARE_EXCHANGE_WEAK(T, ...) (0) - -#define ATOMIC_FLAG_TEST_AND_SET(...) (0) -#define ATOMIC_FLAG_CLEAR(...) ((void)0) +#define ATOMIC_EXCHANGE(...) (0) +#define ATOMIC_COMPARE_EXCHANGE_STRONG(...) (0) #define ATOMIC_THREAD_FENCE(...) ((void)0) #endif +/* If no PTR xchg variants are provided, the normal ones can handle it. */ +#ifndef ATOMIC_EXCHANGE_PTR +#define ATOMIC_EXCHANGE_PTR ATOMIC_EXCHANGE +#define ATOMIC_COMPARE_EXCHANGE_PTR_STRONG ATOMIC_COMPARE_EXCHANGE_STRONG +#define ATOMIC_COMPARE_EXCHANGE_PTR_WEAK ATOMIC_COMPARE_EXCHANGE_WEAK +#endif + /* If no weak cmpxchg is provided (not all systems will have one), substitute a * strong cmpxchg. */ #ifndef ATOMIC_COMPARE_EXCHANGE_WEAK #define ATOMIC_COMPARE_EXCHANGE_WEAK ATOMIC_COMPARE_EXCHANGE_STRONG #endif +#ifndef ATOMIC_COMPARE_EXCHANGE_PTR_WEAK +#define ATOMIC_COMPARE_EXCHANGE_PTR_WEAK ATOMIC_COMPARE_EXCHANGE_PTR_STRONG +#endif /* If no ATOMIC_FLAG is defined, simulate one with an atomic int using exchange * and store ops. @@ -342,7 +371,7 @@ int _al_invalid_atomic_size(); /* not defined */ #ifndef ATOMIC_FLAG #define ATOMIC_FLAG ATOMIC(int) #define ATOMIC_FLAG_INIT ATOMIC_INIT_STATIC(0) -#define ATOMIC_FLAG_TEST_AND_SET(_val, _MO) ATOMIC_EXCHANGE(int, _val, 1, _MO) +#define ATOMIC_FLAG_TEST_AND_SET(_val, _MO) ATOMIC_EXCHANGE(_val, 1, _MO) #define ATOMIC_FLAG_CLEAR(_val, _MO) ATOMIC_STORE(_val, 0, _MO) #endif @@ -353,11 +382,17 @@ int _al_invalid_atomic_size(); /* not defined */ #define ATOMIC_ADD_SEQ(_val, _incr) ATOMIC_ADD(_val, _incr, almemory_order_seq_cst) #define ATOMIC_SUB_SEQ(_val, _decr) ATOMIC_SUB(_val, _decr, almemory_order_seq_cst) -#define ATOMIC_EXCHANGE_SEQ(T, _val, _newval) ATOMIC_EXCHANGE(T, _val, _newval, almemory_order_seq_cst) -#define ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(T, _val, _oldval, _newval) \ - ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval, almemory_order_seq_cst, almemory_order_seq_cst) -#define ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(T, _val, _oldval, _newval) \ - ATOMIC_COMPARE_EXCHANGE_WEAK(T, _val, _oldval, _newval, almemory_order_seq_cst, almemory_order_seq_cst) +#define ATOMIC_EXCHANGE_SEQ(_val, _newval) ATOMIC_EXCHANGE(_val, _newval, almemory_order_seq_cst) +#define ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(_val, _oldval, _newval) \ + ATOMIC_COMPARE_EXCHANGE_STRONG(_val, _oldval, _newval, almemory_order_seq_cst, almemory_order_seq_cst) +#define ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(_val, _oldval, _newval) \ + ATOMIC_COMPARE_EXCHANGE_WEAK(_val, _oldval, _newval, almemory_order_seq_cst, almemory_order_seq_cst) + +#define ATOMIC_EXCHANGE_PTR_SEQ(_val, _newval) ATOMIC_EXCHANGE_PTR(_val, _newval, almemory_order_seq_cst) +#define ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(_val, _oldval, _newval) \ + ATOMIC_COMPARE_EXCHANGE_PTR_STRONG(_val, _oldval, _newval, almemory_order_seq_cst, almemory_order_seq_cst) +#define ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(_val, _oldval, _newval) \ + ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(_val, _oldval, _newval, almemory_order_seq_cst, almemory_order_seq_cst) typedef unsigned int uint; @@ -381,7 +416,7 @@ inline uint DecrementRef(RefCount *ptr) T _first = ATOMIC_LOAD(_head, almemory_order_acquire); \ do { \ ATOMIC_STORE(&(_entry)->next, _first, almemory_order_relaxed); \ - } while(ATOMIC_COMPARE_EXCHANGE_WEAK(T, _head, &_first, _entry, \ + } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(_head, &_first, _entry, \ almemory_order_acq_rel, almemory_order_acquire) == 0); \ } while(0) -- cgit v1.2.3 From fca83263f46c8934b58d17997362eeecd6a79905 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 15 Apr 2017 18:08:52 -0700 Subject: Implement capture support in the OpenSL backend --- Alc/backends/opensl.c | 380 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 379 insertions(+), 1 deletion(-) (limited to 'Alc/backends') diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 4e295f23..aa1ff991 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -700,6 +700,376 @@ static ClockLatency ALCopenslPlayback_getClockLatency(ALCopenslPlayback *self) } +typedef struct ALCopenslCapture { + DERIVE_FROM_TYPE(ALCbackend); + + /* engine interfaces */ + SLObjectItf mEngineObj; + SLEngineItf mEngine; + + /* recording interfaces */ + SLObjectItf mRecordObj; + + ll_ringbuffer_t *mRing; + ALCuint mSplOffset; + + ALsizei mFrameSize; +} ALCopenslCapture; + +static void ALCopenslCapture_process(SLAndroidSimpleBufferQueueItf bq, void *context); + +static void ALCopenslCapture_Construct(ALCopenslCapture *self, ALCdevice *device); +static void ALCopenslCapture_Destruct(ALCopenslCapture *self); +static ALCenum ALCopenslCapture_open(ALCopenslCapture *self, const ALCchar *name); +static void ALCopenslCapture_close(ALCopenslCapture *self); +static DECLARE_FORWARD(ALCopenslCapture, ALCbackend, ALCboolean, reset) +static ALCboolean ALCopenslCapture_start(ALCopenslCapture *self); +static void ALCopenslCapture_stop(ALCopenslCapture *self); +static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid *buffer, ALCuint samples); +static ALCuint ALCopenslCapture_availableSamples(ALCopenslCapture *self); +static DECLARE_FORWARD(ALCopenslCapture, ALCbackend, ClockLatency, getClockLatency) +static DECLARE_FORWARD(ALCopenslCapture, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCopenslCapture, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCopenslCapture) +DEFINE_ALCBACKEND_VTABLE(ALCopenslCapture); + + +static void ALCopenslCapture_process(SLAndroidSimpleBufferQueueItf UNUSED(bq), void *context) +{ + ALCopenslCapture *self = context; + /* A new chunk has been written into the ring buffer, advance it. */ + ll_ringbuffer_write_advance(self->mRing, 1); +} + + +static void ALCopenslCapture_Construct(ALCopenslCapture *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCopenslCapture, ALCbackend, self); + + self->mEngineObj = NULL; + self->mEngine = NULL; + + self->mRecordObj = NULL; + + self->mRing = NULL; + self->mSplOffset = 0; + + self->mFrameSize = 0; +} + +static void ALCopenslCapture_Destruct(ALCopenslCapture *self) +{ + ll_ringbuffer_free(self->mRing); + self->mRing = NULL; + + if(self->mRecordObj != NULL) + VCALL0(self->mRecordObj,Destroy)(); + self->mRecordObj = NULL; + + if(self->mEngineObj != NULL) + VCALL0(self->mEngineObj,Destroy)(); + self->mEngineObj = NULL; + self->mEngine = NULL; + + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + +static ALCenum ALCopenslCapture_open(ALCopenslCapture *self, const ALCchar *name) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + SLDataLocator_AndroidSimpleBufferQueue loc_bq; + SLAndroidSimpleBufferQueueItf bufferQueue; + SLDataLocator_IODevice loc_dev; + SLDataSource audioSrc; + SLDataSink audioSnk; + SLresult result; + + if(!name) + name = opensl_device; + else if(strcmp(name, opensl_device) != 0) + return ALC_INVALID_VALUE; + + result = slCreateEngine(&self->mEngineObj, 0, NULL, 0, NULL, NULL); + PRINTERR(result, "slCreateEngine"); + if(SL_RESULT_SUCCESS == result) + { + result = VCALL(self->mEngineObj,Realize)(SL_BOOLEAN_FALSE); + PRINTERR(result, "engine->Realize"); + } + if(SL_RESULT_SUCCESS == result) + { + result = VCALL(self->mEngineObj,GetInterface)(SL_IID_ENGINE, &self->mEngine); + PRINTERR(result, "engine->GetInterface"); + } + if(SL_RESULT_SUCCESS == result) + { + /* Ensure the total length is at least 100ms */ + ALsizei length = maxi(device->NumUpdates * device->UpdateSize, + device->Frequency / 10); + /* Ensure the per-chunk length is at least 10ms, and no more than 50ms. */ + ALsizei update_len = clampi(device->NumUpdates*device->UpdateSize / 3, + device->Frequency / 100, + device->Frequency / 100 * 5); + + device->UpdateSize = update_len; + device->NumUpdates = (length+update_len-1) / update_len; + + self->mFrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); + } + loc_dev.locatorType = SL_DATALOCATOR_IODEVICE; + loc_dev.deviceType = SL_IODEVICE_AUDIOINPUT; + loc_dev.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT; + loc_dev.device = NULL; + + audioSrc.pLocator = &loc_dev; + audioSrc.pFormat = NULL; + + loc_bq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; + loc_bq.numBuffers = device->NumUpdates; + +#ifdef SL_DATAFORMAT_PCM_EX + SLDataFormat_PCM_EX format_pcm; + format_pcm.formatType = SL_DATAFORMAT_PCM_EX; + format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); + format_pcm.sampleRate = 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 = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : + SL_BYTEORDER_BIGENDIAN; + format_pcm.representation = GetTypeRepresentation(device->FmtType); +#else + SLDataFormat_PCM format_pcm; + format_pcm.formatType = SL_DATAFORMAT_PCM; + format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); + 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 = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : + SL_BYTEORDER_BIGENDIAN; +#endif + + audioSnk.pLocator = &loc_bq; + audioSnk.pFormat = &format_pcm; + + if(SL_RESULT_SUCCESS == result) + { + const SLInterfaceID ids[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION }; + const SLboolean reqs[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_FALSE }; + + result = VCALL(self->mEngine,CreateAudioRecorder)(&self->mRecordObj, + &audioSrc, &audioSnk, COUNTOF(ids), ids, reqs + ); + PRINTERR(result, "engine->CreateAudioRecorder"); + } + if(SL_RESULT_SUCCESS == result) + { + /* Set the record preset to "generic", if possible. */ + SLAndroidConfigurationItf config; + result = VCALL(self->mRecordObj,GetInterface)(SL_IID_ANDROIDCONFIGURATION, &config); + PRINTERR(result, "recordObj->GetInterface SL_IID_ANDROIDCONFIGURATION"); + if(SL_RESULT_SUCCESS == result) + { + SLuint32 preset = SL_ANDROID_RECORDING_PRESET_GENERIC; + result = VCALL(config,SetConfiguration)(SL_ANDROID_KEY_RECORDING_PRESET, + &preset, sizeof(preset) + ); + PRINTERR(result, "config->SetConfiguration"); + } + + /* Clear any error since this was optional. */ + result = SL_RESULT_SUCCESS; + } + if(SL_RESULT_SUCCESS == result) + { + result = VCALL(self->mRecordObj,Realize)(SL_BOOLEAN_FALSE); + PRINTERR(result, "recordObj->Realize"); + } + + if(SL_RESULT_SUCCESS == result) + { + self->mRing = ll_ringbuffer_create(device->NumUpdates + 1, + device->UpdateSize * self->mFrameSize); + + result = VCALL(self->mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, + &bufferQueue); + PRINTERR(result, "recordObj->GetInterface"); + } + if(SL_RESULT_SUCCESS == result) + { + result = VCALL(bufferQueue,RegisterCallback)(ALCopenslCapture_process, self); + PRINTERR(result, "bufferQueue->RegisterCallback"); + } + if(SL_RESULT_SUCCESS == result) + { + ALsizei chunk_size = device->UpdateSize * self->mFrameSize; + ll_ringbuffer_data_t data[2]; + size_t i; + + ll_ringbuffer_get_write_vector(self->mRing, data); + for(i = 0;i < data[0].len && SL_RESULT_SUCCESS == result;i++) + { + result = VCALL(bufferQueue,Enqueue)(data[0].buf + chunk_size*i, chunk_size); + PRINTERR(result, "bufferQueue->Enqueue"); + } + for(i = 0;i < data[1].len && SL_RESULT_SUCCESS == result;i++) + { + result = VCALL(bufferQueue,Enqueue)(data[1].buf + chunk_size*i, chunk_size); + PRINTERR(result, "bufferQueue->Enqueue"); + } + } + + if(SL_RESULT_SUCCESS != result) + { + if(self->mRecordObj != NULL) + VCALL0(self->mRecordObj,Destroy)(); + self->mRecordObj = NULL; + + if(self->mEngineObj != NULL) + VCALL0(self->mEngineObj,Destroy)(); + self->mEngineObj = NULL; + self->mEngine = NULL; + + return ALC_INVALID_VALUE; + } + + alstr_copy_cstr(&device->DeviceName, name); + + return ALC_NO_ERROR; +} + +static void ALCopenslCapture_close(ALCopenslCapture *self) +{ + ll_ringbuffer_free(self->mRing); + self->mRing = NULL; + + if(self->mRecordObj != NULL) + VCALL0(self->mRecordObj,Destroy)(); + self->mRecordObj = NULL; + + if(self->mEngineObj != NULL) + VCALL0(self->mEngineObj,Destroy)(); + self->mEngineObj = NULL; + self->mEngine = NULL; +} + +static ALCboolean ALCopenslCapture_start(ALCopenslCapture *self) +{ + SLRecordItf record; + SLresult result; + + result = VCALL(self->mRecordObj,GetInterface)(SL_IID_RECORD, &record); + PRINTERR(result, "recordObj->GetInterface"); + + if(SL_RESULT_SUCCESS == result) + { + result = VCALL(record,SetRecordState)(SL_RECORDSTATE_RECORDING); + PRINTERR(result, "record->SetRecordState"); + } + + if(SL_RESULT_SUCCESS != result) + { + ALCopenslCapture_lock(self); + aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice); + ALCopenslCapture_unlock(self); + return ALC_FALSE; + } + + return ALC_TRUE; +} + +static void ALCopenslCapture_stop(ALCopenslCapture *self) +{ + SLRecordItf record; + SLresult result; + + result = VCALL(self->mRecordObj,GetInterface)(SL_IID_RECORD, &record); + PRINTERR(result, "recordObj->GetInterface"); + + if(SL_RESULT_SUCCESS == result) + { + result = VCALL(record,SetRecordState)(SL_RECORDSTATE_PAUSED); + PRINTERR(result, "record->SetRecordState"); + } +} + +static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid *buffer, ALCuint samples) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + ALsizei chunk_size = device->UpdateSize * self->mFrameSize; + SLAndroidSimpleBufferQueueItf bufferQueue; + ll_ringbuffer_data_t data[2]; + SLresult result; + size_t advance; + ALCuint i; + + /* Read the desired samples from the ring buffer then advance its read + * pointer. + */ + ll_ringbuffer_get_read_vector(self->mRing, data); + advance = 0; + for(i = 0;i < samples;) + { + ALCuint rem = minu(samples - i, device->UpdateSize - self->mSplOffset); + memcpy((ALCbyte*)buffer + i*self->mFrameSize, + data[0].buf + self->mSplOffset*self->mFrameSize, + rem * self->mFrameSize); + + self->mSplOffset += rem; + if(self->mSplOffset == device->UpdateSize) + { + /* Finished a chunk, reset the offset and advance the read pointer. */ + self->mSplOffset = 0; + advance++; + + data[0].len--; + if(!data[0].len) + data[0] = data[1]; + else + data[0].buf += chunk_size; + } + + i += rem; + } + ll_ringbuffer_read_advance(self->mRing, advance); + + result = VCALL(self->mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, + &bufferQueue); + PRINTERR(result, "recordObj->GetInterface"); + + /* Enqueue any newly-writable chunks in the ring buffer. */ + ll_ringbuffer_get_write_vector(self->mRing, data); + for(i = 0;i < data[0].len && SL_RESULT_SUCCESS == result;i++) + { + result = VCALL(bufferQueue,Enqueue)(data[0].buf + chunk_size*i, chunk_size); + PRINTERR(result, "bufferQueue->Enqueue"); + } + for(i = 0;i < data[1].len && SL_RESULT_SUCCESS == result;i++) + { + result = VCALL(bufferQueue,Enqueue)(data[1].buf + chunk_size*i, chunk_size); + PRINTERR(result, "bufferQueue->Enqueue"); + } + + if(SL_RESULT_SUCCESS != result) + { + ALCopenslCapture_lock(self); + aluHandleDisconnect(device); + ALCopenslCapture_unlock(self); + return ALC_INVALID_DEVICE; + } + + return ALC_NO_ERROR; +} + +static ALCuint ALCopenslCapture_availableSamples(ALCopenslCapture *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + return ll_ringbuffer_read_space(self->mRing) * device->UpdateSize; +} + + typedef struct ALCopenslBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); } ALCopenslBackendFactory; @@ -716,7 +1086,7 @@ static void ALCopenslBackendFactory_deinit(ALCopenslBackendFactory* UNUSED(self) static ALCboolean ALCopenslBackendFactory_querySupport(ALCopenslBackendFactory* UNUSED(self), ALCbackend_Type type) { - if(type == ALCbackend_Playback) + if(type == ALCbackend_Playback || type == ALCbackend_Capture) return ALC_TRUE; return ALC_FALSE; } @@ -730,6 +1100,7 @@ static void ALCopenslBackendFactory_probe(ALCopenslBackendFactory* UNUSED(self), break; case CAPTURE_DEVICE_PROBE: + AppendAllDevicesList(opensl_device); break; } } @@ -743,6 +1114,13 @@ static ALCbackend* ALCopenslBackendFactory_createBackend(ALCopenslBackendFactory if(!backend) return NULL; return STATIC_CAST(ALCbackend, backend); } + if(type == ALCbackend_Capture) + { + ALCopenslCapture *backend; + NEW_OBJ(backend, ALCopenslCapture)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } return NULL; } -- cgit v1.2.3 From 45d52f7124312c91ec0259fbb0c72346ee36e03b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 17 Apr 2017 21:31:20 -0700 Subject: Remove unnecessary functions in the JACK backend --- Alc/backends/jack.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index f43f8527..85d5d9c5 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -163,8 +163,8 @@ static void ALCjackPlayback_stop(ALCjackPlayback *self); static DECLARE_FORWARD2(ALCjackPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint) static DECLARE_FORWARD(ALCjackPlayback, ALCbackend, ALCuint, availableSamples) static ClockLatency ALCjackPlayback_getClockLatency(ALCjackPlayback *self); -static void ALCjackPlayback_lock(ALCjackPlayback *self); -static void ALCjackPlayback_unlock(ALCjackPlayback *self); +static DECLARE_FORWARD(ALCjackPlayback, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCjackPlayback, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCjackPlayback) DEFINE_ALCBACKEND_VTABLE(ALCjackPlayback); @@ -248,7 +248,7 @@ static int ALCjackPlayback_process(jack_nframes_t numframes, void *arg) ll_ringbuffer_data_t data[2]; jack_nframes_t total = 0; jack_nframes_t todo; - ALuint i, c, numchans; + ALsizei i, c, numchans; ll_ringbuffer_get_read_vector(self->Ring, data); @@ -260,7 +260,7 @@ static int ALCjackPlayback_process(jack_nframes_t numframes, void *arg) for(c = 0;c < numchans;c++) { const ALfloat *restrict in = ((ALfloat*)data[0].buf) + c; - for(i = 0;i < todo;i++) + for(i = 0;(jack_nframes_t)i < todo;i++) out[c][i] = in[i*numchans]; out[c] += todo; } @@ -272,7 +272,7 @@ static int ALCjackPlayback_process(jack_nframes_t numframes, void *arg) for(c = 0;c < numchans;c++) { const ALfloat *restrict in = ((ALfloat*)data[1].buf) + c; - for(i = 0;i < todo;i++) + for(i = 0;(jack_nframes_t)i < todo;i++) out[c][i] = in[i*numchans]; out[c] += todo; } @@ -287,7 +287,7 @@ static int ALCjackPlayback_process(jack_nframes_t numframes, void *arg) todo = numframes-total; for(c = 0;c < numchans;c++) { - for(i = 0;i < todo;i++) + for(i = 0;(jack_nframes_t)i < todo;i++) out[c][i] = 0.0f; } } @@ -397,7 +397,7 @@ static void ALCjackPlayback_close(ALCjackPlayback *self) static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - ALuint numchans, i; + ALsizei numchans, i; ALuint bufsize; for(i = 0;i < MAX_OUTPUT_CHANNELS;i++) @@ -471,7 +471,7 @@ static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self) static ALCboolean ALCjackPlayback_start(ALCjackPlayback *self) { const char **ports; - ALuint i; + ALsizei i; if(jack_activate(self->Client)) { @@ -544,17 +544,6 @@ static ClockLatency ALCjackPlayback_getClockLatency(ALCjackPlayback *self) } -static void ALCjackPlayback_lock(ALCjackPlayback *self) -{ - almtx_lock(&STATIC_CAST(ALCbackend,self)->mMutex); -} - -static void ALCjackPlayback_unlock(ALCjackPlayback *self) -{ - almtx_unlock(&STATIC_CAST(ALCbackend,self)->mMutex); -} - - static void jack_msg_handler(const char *message) { WARN("%s\n", message); -- cgit v1.2.3 From a49e2ebbc56e8694a03a150e4210f4070203e43d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 16 May 2017 16:50:43 -0700 Subject: Add an env var to specify a default pulse device Some apps don't allow selecting an audio device, and due to problems with KDE, PulseAudio isn't allowed to move the stream after being created by default. --- Alc/backends/pulseaudio.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'Alc/backends') diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index 9e2d4f73..43761e23 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -764,6 +764,13 @@ static pa_stream *ALCpulsePlayback_connectStream(const char *device_name, pa_stream_state_t state; pa_stream *stream; + if(!device_name) + { + device_name = getenv("ALSOFT_PULSE_DEFAULT"); + if(device_name && !device_name[0]) + device_name = NULL; + } + stream = pa_stream_new_with_proplist(context, "Playback Stream", spec, chanmap, prop_filter); if(!stream) { -- cgit v1.2.3 From 2266fb76b9c7e75d513a8eee871063b667f1d815 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 23 May 2017 18:12:45 -0700 Subject: Add a config option to specify custom ALSA devices --- Alc/backends/alsa.c | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 40b68779..79f2795a 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -277,10 +277,44 @@ static void probe_devices(snd_pcm_stream_t stream, vector_DevMap *DeviceList) AL_STRING_INIT(entry.name); AL_STRING_INIT(entry.device_name); alstr_copy_cstr(&entry.name, alsaDevice); - alstr_copy_cstr(&entry.device_name, GetConfigValue(NULL, "alsa", (stream==SND_PCM_STREAM_PLAYBACK) ? - "device" : "capture", "default")); + alstr_copy_cstr(&entry.device_name, GetConfigValue( + NULL, "alsa", (stream==SND_PCM_STREAM_PLAYBACK) ? "device" : "capture", "default" + )); VECTOR_PUSH_BACK(*DeviceList, entry); + if(stream == SND_PCM_STREAM_PLAYBACK) + { + const char *customdevs, *sep, *next; + next = GetConfigValue(NULL, "alsa", "custom-devices", ""); + while((customdevs=next) != NULL && customdevs[0]) + { + next = strchr(customdevs, ';'); + sep = strchr(customdevs, '='); + if(!sep) + { + al_string spec = AL_STRING_INIT_STATIC(); + if(next) + alstr_copy_range(&spec, customdevs, next++); + else + alstr_copy_cstr(&spec, customdevs); + ERR("Invalid ALSA device specification \"%s\"\n", alstr_get_cstr(spec)); + alstr_reset(&spec); + continue; + } + + AL_STRING_INIT(entry.name); + AL_STRING_INIT(entry.device_name); + alstr_copy_range(&entry.name, customdevs, sep++); + if(next) + alstr_copy_range(&entry.device_name, sep, next++); + else + alstr_copy_cstr(&entry.device_name, sep); + TRACE("Got device \"%s\", \"%s\"\n", alstr_get_cstr(entry.name), + alstr_get_cstr(entry.device_name)); + VECTOR_PUSH_BACK(*DeviceList, entry); + } + } + card = -1; if((err=snd_card_next(&card)) < 0) ERR("Failed to find a card: %s\n", snd_strerror(err)); @@ -325,7 +359,8 @@ static void probe_devices(snd_pcm_stream_t stream, vector_DevMap *DeviceList) 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 = snd_ctl_pcm_info(handle, pcminfo)) < 0) + { if(err != -ENOENT) ERR("control digital audio info (hw:%d): %s\n", card, snd_strerror(err)); continue; @@ -337,9 +372,9 @@ static void probe_devices(snd_pcm_stream_t stream, vector_DevMap *DeviceList) ConfigValueStr(NULL, "alsa", name, &device_prefix); snprintf(name, sizeof(name), "%s, %s (CARD=%s,DEV=%d)", - cardname, devname, cardid, dev); + cardname, devname, cardid, dev); snprintf(device, sizeof(device), "%sCARD=%s,DEV=%d", - device_prefix, cardid, dev); + device_prefix, cardid, dev); TRACE("Got device \"%s\", \"%s\"\n", name, device); AL_STRING_INIT(entry.name); -- cgit v1.2.3 From d4f3490a880f779f460332689a396ade69840f50 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 15 Jun 2017 21:39:09 -0700 Subject: Limit device buffer based on PulseAudio's tlength Unfortunately PulseAudio has a habit of limiting tlength, and trying to calculate the device's buffer length to write regardless of tlength could result in some amount always being writable. --- Alc/backends/pulseaudio.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index 43761e23..8c5469b2 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -817,7 +817,6 @@ static int ALCpulsePlayback_mixerProc(void *ptr) pa_threaded_mainloop_lock(self->loop); frame_size = pa_frame_size(&self->spec); - buffer_size = device->UpdateSize * device->NumUpdates * frame_size; while(!self->killNow && device->Connected) { @@ -830,15 +829,17 @@ static int ALCpulsePlayback_mixerProc(void *ptr) } /* Make sure we're going to write at least 2 'periods' (minreqs), in - * case the server increased it since starting playback. + * case the server increased it since starting playback. Also round up + * the number of writable periods if it's not an integer count. */ - buffer_size = maxu(buffer_size, self->attr.minreq*2); + buffer_size = maxu((self->attr.tlength + self->attr.minreq/2) / self->attr.minreq, 2) * + self->attr.minreq; /* NOTE: This assumes pa_stream_writable_size returns between 0 and * tlength, else there will be more latency than intended. */ len = mini(len - (ssize_t)self->attr.tlength, 0) + buffer_size; - if(len < self->attr.minreq) + if(len < (int32_t)self->attr.minreq) { if(pa_stream_is_corked(self->stream)) { @@ -968,7 +969,6 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) const char *mapname = NULL; pa_channel_map chanmap; pa_operation *o; - ALuint len; pa_threaded_mainloop_lock(self->loop); @@ -1107,11 +1107,10 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) pa_stream_set_buffer_attr_callback(self->stream, ALCpulsePlayback_bufferAttrCallback, self); ALCpulsePlayback_bufferAttrCallback(self->stream, self); - len = self->attr.minreq / pa_frame_size(&self->spec); - device->NumUpdates = (ALuint)clampd( - (ALdouble)device->NumUpdates/len*device->UpdateSize + 0.5, 2.0, 16.0 + device->NumUpdates = (ALuint)clampu64( + (self->attr.tlength + self->attr.minreq/2) / self->attr.minreq, 2, 16 ); - device->UpdateSize = len; + device->UpdateSize = self->attr.minreq / pa_frame_size(&self->spec); /* HACK: prebuf should be 0 as that's what we set it to. However on some * systems it comes back as non-0, so we have to make sure the device will @@ -1121,7 +1120,7 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) */ if(self->attr.prebuf != 0) { - len = self->attr.prebuf / pa_frame_size(&self->spec); + ALuint len = self->attr.prebuf / pa_frame_size(&self->spec); if(len <= device->UpdateSize*device->NumUpdates) ERR("Non-0 prebuf, %u samples (%u bytes), device has %u samples\n", len, self->attr.prebuf, device->UpdateSize*device->NumUpdates); -- cgit v1.2.3 From 0a361fa9e27b9d9533dffe34663efc3669205b86 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 18 Jun 2017 03:07:02 -0700 Subject: "Convert" the QSA backend to the new API I say "convert" because it takes the lazy way and essentially just embeds the wrappers into the backend. It's done this way because I lack the means to check any changes, even syntactically. This also means the device's ExtraData field is still needed. However, this does mean all the backends are now using the new API. Code related to the old interface can now be removed. --- Alc/ALc.c | 109 ++++++++------------------- Alc/backends/base.c | 154 -------------------------------------- Alc/backends/base.h | 3 +- Alc/backends/qsa.c | 185 +++++++++++++++++++++++++++++++++++++++++----- OpenAL32/Include/alMain.h | 19 ----- 5 files changed, 201 insertions(+), 269 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index 7f6cf279..6642c334 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -54,57 +54,52 @@ struct BackendInfo { const char *name; ALCbackendFactory* (*getFactory)(void); - ALCboolean (*Init)(BackendFuncs*); - void (*Deinit)(void); - void (*Probe)(enum DevProbe); - BackendFuncs Funcs; }; -#define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } static struct BackendInfo BackendList[] = { #ifdef HAVE_JACK - { "jack", ALCjackBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, + { "jack", ALCjackBackendFactory_getFactory }, #endif #ifdef HAVE_PULSEAUDIO - { "pulse", ALCpulseBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, + { "pulse", ALCpulseBackendFactory_getFactory }, #endif #ifdef HAVE_ALSA - { "alsa", ALCalsaBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, + { "alsa", ALCalsaBackendFactory_getFactory }, #endif #ifdef HAVE_COREAUDIO - { "core", ALCcoreAudioBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, + { "core", ALCcoreAudioBackendFactory_getFactory }, #endif #ifdef HAVE_OSS - { "oss", ALCossBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, + { "oss", ALCossBackendFactory_getFactory }, #endif #ifdef HAVE_SOLARIS - { "solaris", ALCsolarisBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, + { "solaris", ALCsolarisBackendFactory_getFactory }, #endif #ifdef HAVE_SNDIO - { "sndio", ALCsndioBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, + { "sndio", ALCsndioBackendFactory_getFactory }, #endif #ifdef HAVE_QSA - { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs }, + { "qsa", ALCqsaBackendFactory_getFactory }, #endif #ifdef HAVE_MMDEVAPI - { "mmdevapi", ALCmmdevBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, + { "mmdevapi", ALCmmdevBackendFactory_getFactory }, #endif #ifdef HAVE_DSOUND - { "dsound", ALCdsoundBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, + { "dsound", ALCdsoundBackendFactory_getFactory }, #endif #ifdef HAVE_WINMM - { "winmm", ALCwinmmBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, + { "winmm", ALCwinmmBackendFactory_getFactory }, #endif #ifdef HAVE_PORTAUDIO - { "port", ALCportBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, + { "port", ALCportBackendFactory_getFactory }, #endif #ifdef HAVE_OPENSL - { "opensl", ALCopenslBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, + { "opensl", ALCopenslBackendFactory_getFactory }, #endif - { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, + { "null", ALCnullBackendFactory_getFactory }, #ifdef HAVE_WAVE - { "wave", ALCwaveBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, + { "wave", ALCwaveBackendFactory_getFactory }, #endif }; static ALsizei BackendListSize = COUNTOF(BackendList); @@ -1091,43 +1086,20 @@ static void alc_initconfig(void) for(i = 0;i < BackendListSize && (!PlaybackBackend.name || !CaptureBackend.name);i++) { - if(BackendList[i].getFactory) - { - ALCbackendFactory *factory = BackendList[i].getFactory(); - if(!V0(factory,init)()) - { - WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name); - continue; - } - - TRACE("Initialized backend \"%s\"\n", BackendList[i].name); - if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback)) - { - PlaybackBackend = BackendList[i]; - TRACE("Added \"%s\" for playback\n", PlaybackBackend.name); - } - if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture)) - { - CaptureBackend = BackendList[i]; - TRACE("Added \"%s\" for capture\n", CaptureBackend.name); - } - - continue; - } - - if(!BackendList[i].Init(&BackendList[i].Funcs)) + ALCbackendFactory *factory = BackendList[i].getFactory(); + if(!V0(factory,init)()) { WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name); continue; } TRACE("Initialized backend \"%s\"\n", BackendList[i].name); - if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name) + if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback)) { PlaybackBackend = BackendList[i]; TRACE("Added \"%s\" for playback\n", PlaybackBackend.name); } - if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name) + if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture)) { CaptureBackend = BackendList[i]; TRACE("Added \"%s\" for capture\n", CaptureBackend.name); @@ -1299,13 +1271,8 @@ static void alc_deinit(void) for(i = 0;i < BackendListSize;i++) { - if(!BackendList[i].getFactory) - BackendList[i].Deinit(); - else - { - ALCbackendFactory *factory = BackendList[i].getFactory(); - V0(factory,deinit)(); - } + ALCbackendFactory *factory = BackendList[i].getFactory(); + V0(factory,deinit)(); } { ALCbackendFactory *factory = ALCloopbackFactory_getFactory(); @@ -1321,18 +1288,16 @@ static void alc_deinit(void) ************************************************/ static void ProbeDevices(al_string *list, struct BackendInfo *backendinfo, enum DevProbe type) { + ALCbackendFactory *factory; + DO_INITCONFIG(); LockLists(); alstr_clear(list); - if(backendinfo->Probe) - backendinfo->Probe(type); - else if(backendinfo->getFactory) - { - ALCbackendFactory *factory = backendinfo->getFactory(); - V(factory,probe)(type); - } + factory = backendinfo->getFactory(); + V(factory,probe)(type); + UnlockLists(); } static void ProbeAllDevicesList(void) @@ -3830,6 +3795,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context) */ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) { + ALCbackendFactory *factory; const ALCchar *fmt; ALCdevice *device; ALCenum err; @@ -3916,14 +3882,8 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) device->NumUpdates = 3; device->UpdateSize = 1024; - if(!PlaybackBackend.getFactory) - device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs, - ALCbackend_Playback); - else - { - ALCbackendFactory *factory = PlaybackBackend.getFactory(); - device->Backend = V(factory,createBackend)(device, ALCbackend_Playback); - } + factory = PlaybackBackend.getFactory(); + device->Backend = V(factory,createBackend)(device, ALCbackend_Playback); if(!device->Backend) { al_free(device); @@ -4151,6 +4111,7 @@ ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device) ************************************************/ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples) { + ALCbackendFactory *factory; ALCdevice *device = NULL; ALCenum err; ALCsizei i; @@ -4208,14 +4169,8 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, device->ChannelDelay[i].Buffer = NULL; } - if(!CaptureBackend.getFactory) - device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs, - ALCbackend_Capture); - else - { - ALCbackendFactory *factory = CaptureBackend.getFactory(); - device->Backend = V(factory,createBackend)(device, ALCbackend_Capture); - } + factory = CaptureBackend.getFactory(); + device->Backend = V(factory,createBackend)(device, ALCbackend_Capture); if(!device->Backend) { al_free(device); diff --git a/Alc/backends/base.c b/Alc/backends/base.c index 902c4310..5f568d8e 100644 --- a/Alc/backends/base.c +++ b/Alc/backends/base.c @@ -79,157 +79,3 @@ void ALCbackend_unlock(ALCbackend *self) void ALCbackendFactory_deinit(ALCbackendFactory* UNUSED(self)) { } - - -/* Wrappers to use an old-style backend with the new interface. */ -typedef struct PlaybackWrapper { - DERIVE_FROM_TYPE(ALCbackend); - - const BackendFuncs *Funcs; -} PlaybackWrapper; - -static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device, const BackendFuncs *funcs); -static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, Destruct) -static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name); -static void PlaybackWrapper_close(PlaybackWrapper *self); -static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self); -static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self); -static void PlaybackWrapper_stop(PlaybackWrapper *self); -static DECLARE_FORWARD2(PlaybackWrapper, ALCbackend, ALCenum, captureSamples, void*, ALCuint) -static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ALCuint, availableSamples) -static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ClockLatency, getClockLatency) -static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, lock) -static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, unlock) -DECLARE_DEFAULT_ALLOCATORS(PlaybackWrapper) -DEFINE_ALCBACKEND_VTABLE(PlaybackWrapper); - -static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device, const BackendFuncs *funcs) -{ - ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); - SET_VTABLE2(PlaybackWrapper, ALCbackend, self); - - self->Funcs = funcs; -} - -static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return self->Funcs->OpenPlayback(device, name); -} - -static void PlaybackWrapper_close(PlaybackWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - self->Funcs->ClosePlayback(device); -} - -static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return self->Funcs->ResetPlayback(device); -} - -static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return self->Funcs->StartPlayback(device); -} - -static void PlaybackWrapper_stop(PlaybackWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - self->Funcs->StopPlayback(device); -} - - -typedef struct CaptureWrapper { - DERIVE_FROM_TYPE(ALCbackend); - - const BackendFuncs *Funcs; -} CaptureWrapper; - -static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device, const BackendFuncs *funcs); -static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, Destruct) -static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name); -static void CaptureWrapper_close(CaptureWrapper *self); -static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ALCboolean, reset) -static ALCboolean CaptureWrapper_start(CaptureWrapper *self); -static void CaptureWrapper_stop(CaptureWrapper *self); -static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples); -static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self); -static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ClockLatency, getClockLatency) -static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, lock) -static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, unlock) -DECLARE_DEFAULT_ALLOCATORS(CaptureWrapper) -DEFINE_ALCBACKEND_VTABLE(CaptureWrapper); - -static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device, const BackendFuncs *funcs) -{ - ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); - SET_VTABLE2(CaptureWrapper, ALCbackend, self); - - self->Funcs = funcs; -} - -static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return self->Funcs->OpenCapture(device, name); -} - -static void CaptureWrapper_close(CaptureWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - self->Funcs->CloseCapture(device); -} - -static ALCboolean CaptureWrapper_start(CaptureWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - self->Funcs->StartCapture(device); - return ALC_TRUE; -} - -static void CaptureWrapper_stop(CaptureWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - self->Funcs->StopCapture(device); -} - -static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return self->Funcs->CaptureSamples(device, buffer, samples); -} - -static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return self->Funcs->AvailableSamples(device); -} - - -ALCbackend *create_backend_wrapper(ALCdevice *device, const BackendFuncs *funcs, ALCbackend_Type type) -{ - if(type == ALCbackend_Playback) - { - PlaybackWrapper *backend; - - NEW_OBJ(backend, PlaybackWrapper)(device, funcs); - if(!backend) return NULL; - - return STATIC_CAST(ALCbackend, backend); - } - - if(type == ALCbackend_Capture) - { - CaptureWrapper *backend; - - NEW_OBJ(backend, CaptureWrapper)(device, funcs); - if(!backend) return NULL; - - return STATIC_CAST(ALCbackend, backend); - } - - return NULL; -} diff --git a/Alc/backends/base.h b/Alc/backends/base.h index 961a4d1a..8464fdee 100644 --- a/Alc/backends/base.h +++ b/Alc/backends/base.h @@ -142,6 +142,7 @@ ALCbackendFactory *ALCossBackendFactory_getFactory(void); ALCbackendFactory *ALCjackBackendFactory_getFactory(void); ALCbackendFactory *ALCsolarisBackendFactory_getFactory(void); ALCbackendFactory *ALCsndioBackendFactory_getFactory(void); +ALCbackendFactory *ALCqsaBackendFactory_getFactory(void); ALCbackendFactory *ALCmmdevBackendFactory_getFactory(void); ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void); ALCbackendFactory *ALCwinmmBackendFactory_getFactory(void); @@ -151,6 +152,4 @@ ALCbackendFactory *ALCnullBackendFactory_getFactory(void); ALCbackendFactory *ALCwaveBackendFactory_getFactory(void); ALCbackendFactory *ALCloopbackFactory_getFactory(void); -ALCbackend *create_backend_wrapper(ALCdevice *device, const BackendFuncs *funcs, ALCbackend_Type type); - #endif /* AL_BACKENDS_BASE_H */ diff --git a/Alc/backends/qsa.c b/Alc/backends/qsa.c index 9da55b59..15c264aa 100644 --- a/Alc/backends/qsa.c +++ b/Alc/backends/qsa.c @@ -853,27 +853,145 @@ static ALCenum qsa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint s return ALC_NO_ERROR; } -static const BackendFuncs qsa_funcs= { - qsa_open_playback, - qsa_close_playback, - qsa_reset_playback, - qsa_start_playback, - qsa_stop_playback, - qsa_open_capture, - qsa_close_capture, - qsa_start_capture, - qsa_stop_capture, - qsa_capture_samples, - qsa_available_samples -}; -ALCboolean alc_qsa_init(BackendFuncs* func_list) +/* Wrappers to use an old-style backend with the new interface. */ +typedef struct PlaybackWrapper { + DERIVE_FROM_TYPE(ALCbackend); +} PlaybackWrapper; + +static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device); +static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, Destruct) +static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name); +static void PlaybackWrapper_close(PlaybackWrapper *self); +static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self); +static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self); +static void PlaybackWrapper_stop(PlaybackWrapper *self); +static DECLARE_FORWARD2(PlaybackWrapper, ALCbackend, ALCenum, captureSamples, void*, ALCuint) +static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ALCuint, availableSamples) +static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ClockLatency, getClockLatency) +static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, lock) +static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(PlaybackWrapper) +DEFINE_ALCBACKEND_VTABLE(PlaybackWrapper); + +static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(PlaybackWrapper, ALCbackend, self); +} + +static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + return qsa_open_playback(device, name); +} + +static void PlaybackWrapper_close(PlaybackWrapper *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + qsa_close_playback(device); +} + +static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + return qsa_reset_playback(device); +} + +static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + return qsa_start_playback(device); +} + +static void PlaybackWrapper_stop(PlaybackWrapper *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + qsa_stop_playback(device); +} + + +typedef struct CaptureWrapper { + DERIVE_FROM_TYPE(ALCbackend); +} CaptureWrapper; + +static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device); +static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, Destruct) +static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name); +static void CaptureWrapper_close(CaptureWrapper *self); +static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ALCboolean, reset) +static ALCboolean CaptureWrapper_start(CaptureWrapper *self); +static void CaptureWrapper_stop(CaptureWrapper *self); +static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples); +static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self); +static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ClockLatency, getClockLatency) +static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, lock) +static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(CaptureWrapper) +DEFINE_ALCBACKEND_VTABLE(CaptureWrapper); + +static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(CaptureWrapper, ALCbackend, self); +} + +static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name) { - *func_list = qsa_funcs; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + return qsa_open_capture(device, name); +} + +static void CaptureWrapper_close(CaptureWrapper *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + qsa_close_capture(device); +} + +static ALCboolean CaptureWrapper_start(CaptureWrapper *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + qsa_start_capture(device); return ALC_TRUE; } -void alc_qsa_deinit(void) +static void CaptureWrapper_stop(CaptureWrapper *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + qsa_stop_capture(device); +} + +static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + return qsa_capture_samples(device, buffer, samples); +} + +static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + return qsa_available_samples(device); +} + + +typedef struct ALCqsaBackendFactory { + DERIVE_FROM_TYPE(ALCbackendFactory); +} ALCqsaBackendFactory; +#define ALCQSABACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCqsaBackendFactory, ALCbackendFactory) } } + +static ALCboolean ALCqsaBackendFactory_init(ALCqsaBackendFactory* UNUSED(self)); +static void ALCqsaBackendFactory_deinit(ALCqsaBackendFactory* UNUSED(self)); +static ALCboolean ALCqsaBackendFactory_querySupport(ALCqsaBackendFactory* UNUSED(self), ALCbackend_Type type); +static void ALCqsaBackendFactory_probe(ALCqsaBackendFactory* UNUSED(self), enum DevProbe type); +static ALCbackend* ALCqsaBackendFactory_createBackend(ALCqsaBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type); +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCqsaBackendFactory); + +static ALCboolean ALCqsaBackendFactory_init(ALCqsaBackendFactory* UNUSED(self)) +{ + return ALC_TRUE; +} + +static void ALCqsaBackendFactory_deinit(ALCqsaBackendFactory* UNUSED(self)) { #define FREE_NAME(iter) free((iter)->name) VECTOR_FOR_EACH(DevMap, DeviceNameMap, FREE_NAME); @@ -884,7 +1002,14 @@ void alc_qsa_deinit(void) #undef FREE_NAME } -void alc_qsa_probe(enum DevProbe type) +static ALCboolean ALCqsaBackendFactory_querySupport(ALCqsaBackendFactory* UNUSED(self), ALCbackend_Type type) +{ + if(type == ALCbackend_Playback || type == ALCbackend_Capture) + return ALC_TRUE; + return ALC_FALSE; +} + +static void ALCqsaBackendFactory_probe(ALCqsaBackendFactory* UNUSED(self), enum DevProbe type) { switch (type) { @@ -913,3 +1038,29 @@ void alc_qsa_probe(enum DevProbe type) break; } } + +static ALCbackend* ALCqsaBackendFactory_createBackend(ALCqsaBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + { + PlaybackWrapper *backend; + NEW_OBJ(backend, PlaybackWrapper)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + if(type == ALCbackend_Capture) + { + CaptureWrapper *backend; + NEW_OBJ(backend, CaptureWrapper)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + + return NULL; +} + +ALCbackendFactory *ALCqsaBackendFactory_getFactory(void) +{ + static ALCqsaBackendFactory factory = ALCQSABACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); +} diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index e5dd8c26..8cedee94 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -436,25 +436,6 @@ enum DevProbe { CAPTURE_DEVICE_PROBE }; -typedef struct { - ALCenum (*OpenPlayback)(ALCdevice*, const ALCchar*); - void (*ClosePlayback)(ALCdevice*); - ALCboolean (*ResetPlayback)(ALCdevice*); - ALCboolean (*StartPlayback)(ALCdevice*); - void (*StopPlayback)(ALCdevice*); - - ALCenum (*OpenCapture)(ALCdevice*, const ALCchar*); - void (*CloseCapture)(ALCdevice*); - void (*StartCapture)(ALCdevice*); - void (*StopCapture)(ALCdevice*); - ALCenum (*CaptureSamples)(ALCdevice*, void*, ALCuint); - ALCuint (*AvailableSamples)(ALCdevice*); -} BackendFuncs; - -ALCboolean alc_qsa_init(BackendFuncs *func_list); -void alc_qsa_deinit(void); -void alc_qsa_probe(enum DevProbe type); - struct ALCbackend; -- cgit v1.2.3 From 31b02e044f689e9d586a935c924e4a989371823e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 22 Jun 2017 13:58:32 -0700 Subject: Trace the capture converter formats for mmdevapi --- Alc/backends/mmdevapi.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'Alc/backends') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 43d8429d..875a3e4d 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -1744,6 +1744,7 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) ERR("Failed to create stereo-to-mono converter\n"); return E_FAIL; } + TRACE("Created stereo-to-mono converter\n"); /* The channel converter always outputs float, so change the input type * for the resampler/type-converter. */ @@ -1758,6 +1759,7 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) ERR("Failed to create mono-to-stereo converter\n"); return E_FAIL; } + TRACE("Created mono-to-stereo converter\n"); srcType = DevFmtFloat; } @@ -1775,6 +1777,10 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) OutputType.Format.nSamplesPerSec); return E_FAIL; } + TRACE("Created converter for format, dst: %s %s %uhz, src: %d-bit %luhz\n", + DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), + device->Frequency, OutputType.Format.wBitsPerSample, + OutputType.Format.nSamplesPerSec); } hr = IAudioClient_Initialize(self->client, -- cgit v1.2.3 From d1bb04d588f444d4e1f7318fcd05eb7c298a129e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 23 Jun 2017 09:54:26 -0700 Subject: Improve traces for the mmdevapi capture conversions --- Alc/backends/mmdevapi.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 875a3e4d..75370489 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -1741,10 +1741,10 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) device->FmtChans); if(!self->ChannelConv) { - ERR("Failed to create stereo-to-mono converter\n"); + ERR("Failed to create %s stereo-to-mono converter\n", DevFmtTypeString(srcType)); return E_FAIL; } - TRACE("Created stereo-to-mono converter\n"); + TRACE("Created %s stereo-to-mono converter\n", DevFmtTypeString(srcType)); /* The channel converter always outputs float, so change the input type * for the resampler/type-converter. */ @@ -1756,10 +1756,10 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) device->FmtChans); if(!self->ChannelConv) { - ERR("Failed to create mono-to-stereo converter\n"); + ERR("Failed to create %s mono-to-stereo converter\n", DevFmtTypeString(srcType)); return E_FAIL; } - TRACE("Created mono-to-stereo converter\n"); + TRACE("Created %s mono-to-stereo converter\n", DevFmtTypeString(srcType)); srcType = DevFmtFloat; } @@ -1771,16 +1771,14 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) ); if(!self->SampleConv) { - ERR("Failed to create converter for format, dst: %s %s %uhz, src: %d-bit %luhz\n", + ERR("Failed to create converter for %s format, dst: %s %uhz, src: %s %luhz\n", DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), - device->Frequency, OutputType.Format.wBitsPerSample, - OutputType.Format.nSamplesPerSec); + device->Frequency, DevFmtTypeString(srcType), OutputType.Format.nSamplesPerSec); return E_FAIL; } - TRACE("Created converter for format, dst: %s %s %uhz, src: %d-bit %luhz\n", + TRACE("Created converter for %s format, dst: %s %uhz, src: %s %luhz\n", DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), - device->Frequency, OutputType.Format.wBitsPerSample, - OutputType.Format.nSamplesPerSec); + device->Frequency, DevFmtTypeString(srcType), OutputType.Format.nSamplesPerSec); } hr = IAudioClient_Initialize(self->client, -- cgit v1.2.3 From 5d5eff7502a41fbb8b2dbe27239ec860770fe1bb Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 26 Jun 2017 06:14:11 -0700 Subject: Ensure the mmdevapi capture buffer is at least 100ms --- Alc/backends/mmdevapi.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Alc/backends') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 75370489..860515be 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -1602,6 +1602,10 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) buf_time = ((REFERENCE_TIME)device->UpdateSize*device->NumUpdates*10000000 + device->Frequency-1) / device->Frequency; + // Make sure buffer is at least 100ms in size + buf_time = maxu64(buf_time, U64(1000000)); + device->UpdateSize = (buf_time*device->Frequency + 10000000-1)/10000000 / + device->NumUpdates; OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; switch(device->FmtChans) -- cgit v1.2.3 From 55c329b462ce3df1d5417331f835f6474d0c7e13 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 26 Jun 2017 06:54:45 -0700 Subject: Clean up some messy rounding code --- Alc/backends/mmdevapi.c | 16 +++++++++------- Alc/helpers.c | 3 +++ OpenAL32/Include/alMain.h | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+), 7 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 860515be..f341c1b0 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -65,6 +65,8 @@ DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x #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) #define X7DOT1_WIDE (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_FRONT_LEFT_OF_CENTER|SPEAKER_FRONT_RIGHT_OF_CENTER) +#define REFTIME_PER_SEC ((REFERENCE_TIME)10000000) + #define DEVNAME_HEAD "OpenAL Soft on " @@ -891,8 +893,8 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self) CoTaskMemFree(wfx); wfx = NULL; - buf_time = ((REFERENCE_TIME)device->UpdateSize*device->NumUpdates*10000000 + - device->Frequency-1) / device->Frequency; + buf_time = ScaleCeil(device->UpdateSize*device->NumUpdates, REFTIME_PER_SEC, + device->Frequency); if(!(device->Flags&DEVICE_FREQUENCY_REQUEST)) device->Frequency = OutputType.Format.nSamplesPerSec; @@ -1081,7 +1083,7 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self) hr = IAudioClient_GetDevicePeriod(self->client, &min_per, NULL); if(SUCCEEDED(hr)) { - min_len = (UINT32)((min_per*device->Frequency + 10000000-1) / 10000000); + min_len = (UINT32)ScaleCeil(min_per, device->Frequency, REFTIME_PER_SEC); /* Find the nearest multiple of the period size to the update size */ if(min_len < device->UpdateSize) min_len *= (device->UpdateSize + min_len/2)/min_len; @@ -1600,11 +1602,11 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) } self->client = ptr; - buf_time = ((REFERENCE_TIME)device->UpdateSize*device->NumUpdates*10000000 + - device->Frequency-1) / device->Frequency; + buf_time = ScaleCeil(device->UpdateSize*device->NumUpdates, REFTIME_PER_SEC, + device->Frequency); // Make sure buffer is at least 100ms in size - buf_time = maxu64(buf_time, U64(1000000)); - device->UpdateSize = (buf_time*device->Frequency + 10000000-1)/10000000 / + buf_time = maxu64(buf_time, REFTIME_PER_SEC/10); + device->UpdateSize = ScaleCeil(buf_time, device->Frequency, REFTIME_PER_SEC) / device->NumUpdates; OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; diff --git a/Alc/helpers.c b/Alc/helpers.c index f1cd1f66..53623d85 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -117,6 +117,9 @@ DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x extern inline ALuint NextPowerOf2(ALuint value); extern inline size_t RoundUp(size_t value, size_t r); +extern inline ALuint64 ScaleRound(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale); +extern inline ALuint64 ScaleFloor(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale); +extern inline ALuint64 ScaleCeil(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale); extern inline ALint fastf2i(ALfloat f); extern inline ALuint fastf2u(ALfloat f); diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 8cedee94..9460a3f1 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -409,6 +409,24 @@ inline size_t RoundUp(size_t value, size_t r) return value - (value%r); } +/* Scales the given value using 64-bit integer math, rounding the result. */ +inline ALuint64 ScaleRound(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale) +{ + return (val*new_scale + old_scale/2) / old_scale; +} + +/* Scales the given value using 64-bit integer math, flooring the result. */ +inline ALuint64 ScaleFloor(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale) +{ + return val * new_scale / old_scale; +} + +/* Scales the given value using 64-bit integer math, ceiling the result. */ +inline ALuint64 ScaleCeil(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale) +{ + return (val*new_scale + old_scale-1) / old_scale; +} + /* Fast float-to-int conversion. Assumes the FPU is already in round-to-zero * mode. */ inline ALint fastf2i(ALfloat f) -- cgit v1.2.3 From 2f2d941edb61767689a1a80940ea539681648807 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 26 Jun 2017 08:57:29 -0700 Subject: Trace the message name in the message handler loop --- Alc/backends/mmdevapi.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'Alc/backends') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index f341c1b0..668d2fe5 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -111,6 +111,15 @@ typedef struct { #define WM_USER_Enumerate (WM_USER+5) #define WM_USER_Last (WM_USER+5) +static const char MessageStr[WM_USER_Last+1-WM_USER][20] = { + "Open Device", + "Reset Device", + "Start Device", + "Stop Device", + "Close Device", + "Enumerate Devices", +}; + static inline void ReturnMsgResponse(ThreadRequest *req, HRESULT res) { req->result = res; @@ -405,7 +414,11 @@ static DWORD CALLBACK ALCmmdevProxy_messageHandler(void *ptr) TRACE("Starting message loop\n"); while(GetMessage(&msg, NULL, WM_USER_First, WM_USER_Last)) { - TRACE("Got message %u (lparam=%p, wparam=%p)\n", msg.message, (void*)msg.lParam, (void*)msg.wParam); + TRACE("Got message \"%s\" (0x%04x, lparam=%p, wparam=%p)\n", + (msg.message >= WM_USER && msg.message <= WM_USER_Last) ? + MessageStr[msg.message-WM_USER] : "Unknown", + msg.message, (void*)msg.lParam, (void*)msg.wParam + ); switch(msg.message) { case WM_USER_OpenDevice: -- cgit v1.2.3 From ec13cf6c9cefa709db9fb9099e3ce5f502931161 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 29 Jun 2017 10:25:33 -0700 Subject: Add casts to silence MSVC --- Alc/backends/mmdevapi.c | 2 +- common/threads.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 668d2fe5..9afb62f0 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -1619,7 +1619,7 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) device->Frequency); // Make sure buffer is at least 100ms in size buf_time = maxu64(buf_time, REFTIME_PER_SEC/10); - device->UpdateSize = ScaleCeil(buf_time, device->Frequency, REFTIME_PER_SEC) / + device->UpdateSize = (ALuint)ScaleCeil(buf_time, device->Frequency, REFTIME_PER_SEC) / device->NumUpdates; OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; diff --git a/common/threads.c b/common/threads.c index 0a019d03..0761a324 100644 --- a/common/threads.c +++ b/common/threads.c @@ -257,7 +257,7 @@ int alcnd_timedwait(alcnd_t *cond, almtx_t *mtx, const struct timespec *time_poi else { sleeptime = (time_point->tv_nsec - curtime.tv_nsec + 999999)/1000000; - sleeptime += (time_point->tv_sec - curtime.tv_sec)*1000; + sleeptime += (DWORD)(time_point->tv_sec - curtime.tv_sec)*1000; if(SleepConditionVariableCS(cond, mtx, sleeptime) != 0) return althrd_success; } @@ -364,7 +364,7 @@ int alcnd_timedwait(alcnd_t *cond, almtx_t *mtx, const struct timespec *time_poi else { sleeptime = (time_point->tv_nsec - curtime.tv_nsec + 999999)/1000000; - sleeptime += (time_point->tv_sec - curtime.tv_sec)*1000; + sleeptime += (DWORD)(time_point->tv_sec - curtime.tv_sec)*1000; } IncrementRef(&icond->wait_count); -- cgit v1.2.3 From 8a0d1e5191973999dd1d406f57a874e25918e549 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 29 Jun 2017 17:38:38 -0700 Subject: Store the QSA backend's ExtraData in the wrapper struct --- Alc/backends/qsa.c | 239 +++++++++++++++++++++++----------------------- OpenAL32/Include/alMain.h | 2 - 2 files changed, 121 insertions(+), 120 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/qsa.c b/Alc/backends/qsa.c index 15c264aa..58193c96 100644 --- a/Alc/backends/qsa.c +++ b/Alc/backends/qsa.c @@ -159,10 +159,33 @@ static void deviceList(int type, vector_DevMap *devmap) } -FORCE_ALIGN static int qsa_proc_playback(void* ptr) +/* Wrappers to use an old-style backend with the new interface. */ +typedef struct PlaybackWrapper { + DERIVE_FROM_TYPE(ALCbackend); + qsa_data *ExtraData; +} PlaybackWrapper; + +static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device); +static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, Destruct) +static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name); +static void PlaybackWrapper_close(PlaybackWrapper *self); +static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self); +static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self); +static void PlaybackWrapper_stop(PlaybackWrapper *self); +static DECLARE_FORWARD2(PlaybackWrapper, ALCbackend, ALCenum, captureSamples, void*, ALCuint) +static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ALCuint, availableSamples) +static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ClockLatency, getClockLatency) +static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, lock) +static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(PlaybackWrapper) +DEFINE_ALCBACKEND_VTABLE(PlaybackWrapper); + + +FORCE_ALIGN static int qsa_proc_playback(void *ptr) { - ALCdevice* device=(ALCdevice*)ptr; - qsa_data* data=(qsa_data*)device->ExtraData; + PlaybackWrapper *self = ptr; + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + qsa_data *data = self->ExtraData; snd_pcm_channel_status_t status; struct sched_param param; struct timeval timeout; @@ -250,8 +273,9 @@ FORCE_ALIGN static int qsa_proc_playback(void* ptr) /* Playback */ /************/ -static ALCenum qsa_open_playback(ALCdevice* device, const ALCchar* deviceName) +static ALCenum qsa_open_playback(PlaybackWrapper *self, const ALCchar* deviceName) { + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; qsa_data *data; int card, dev; int status; @@ -299,14 +323,14 @@ static ALCenum qsa_open_playback(ALCdevice* device, const ALCchar* deviceName) } alstr_copy_cstr(&device->DeviceName, deviceName); - device->ExtraData = data; + self->ExtraData = data; return ALC_NO_ERROR; } -static void qsa_close_playback(ALCdevice* device) +static void qsa_close_playback(PlaybackWrapper *self) { - qsa_data* data=(qsa_data*)device->ExtraData; + qsa_data *data = self->ExtraData; if (data->buffer!=NULL) { @@ -317,12 +341,13 @@ static void qsa_close_playback(ALCdevice* device) snd_pcm_close(data->pcmHandle); free(data); - device->ExtraData=NULL; + self->ExtraData = NULL; } -static ALCboolean qsa_reset_playback(ALCdevice* device) +static ALCboolean qsa_reset_playback(PlaybackWrapper *self) { - qsa_data* data=(qsa_data*)device->ExtraData; + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + qsa_data *data = self->ExtraData; int32_t format=-1; switch(device->FmtType) @@ -567,20 +592,20 @@ static ALCboolean qsa_reset_playback(ALCdevice* device) return ALC_TRUE; } -static ALCboolean qsa_start_playback(ALCdevice* device) +static ALCboolean qsa_start_playback(PlaybackWrapper *self) { - qsa_data *data = (qsa_data*)device->ExtraData; + qsa_data *data = self->ExtraData; data->killNow = 0; - if(althrd_create(&data->thread, qsa_proc_playback, device) != althrd_success) + if(althrd_create(&data->thread, qsa_proc_playback, self) != althrd_success) return ALC_FALSE; return ALC_TRUE; } -static void qsa_stop_playback(ALCdevice* device) +static void qsa_stop_playback(PlaybackWrapper *self) { - qsa_data *data = (qsa_data*)device->ExtraData; + qsa_data *data = self->ExtraData; int res; if(data->killNow) @@ -590,12 +615,70 @@ static void qsa_stop_playback(ALCdevice* device) althrd_join(data->thread, &res); } + +static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(PlaybackWrapper, ALCbackend, self); + + self->ExtraData = NULL; +} + +static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name) +{ + return qsa_open_playback(self, name); +} + +static void PlaybackWrapper_close(PlaybackWrapper *self) +{ + qsa_close_playback(self); +} + +static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self) +{ + return qsa_reset_playback(self); +} + +static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self) +{ + return qsa_start_playback(self); +} + +static void PlaybackWrapper_stop(PlaybackWrapper *self) +{ + qsa_stop_playback(self); +} + + + /***********/ /* Capture */ /***********/ -static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName) +typedef struct CaptureWrapper { + DERIVE_FROM_TYPE(ALCbackend); + qsa_data *ExtraData; +} CaptureWrapper; + +static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device); +static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, Destruct) +static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name); +static void CaptureWrapper_close(CaptureWrapper *self); +static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ALCboolean, reset) +static ALCboolean CaptureWrapper_start(CaptureWrapper *self); +static void CaptureWrapper_stop(CaptureWrapper *self); +static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples); +static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self); +static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ClockLatency, getClockLatency) +static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, lock) +static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(CaptureWrapper) +DEFINE_ALCBACKEND_VTABLE(CaptureWrapper); + + +static ALCenum qsa_open_capture(CaptureWrapper *self, const ALCchar *deviceName) { + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; qsa_data *data; int card, dev; int format=-1; @@ -646,7 +729,7 @@ static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName) } alstr_copy_cstr(&device->DeviceName, deviceName); - device->ExtraData = data; + self->ExtraData = data; switch (device->FmtType) { @@ -699,7 +782,6 @@ static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName) { snd_pcm_close(data->pcmHandle); free(data); - device->ExtraData=NULL; return ALC_INVALID_VALUE; } @@ -707,20 +789,20 @@ static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName) return ALC_NO_ERROR; } -static void qsa_close_capture(ALCdevice* device) +static void qsa_close_capture(CaptureWrapper *self) { - qsa_data* data=(qsa_data*)device->ExtraData; + qsa_data *data = self->ExtraData; if (data->pcmHandle!=NULL) snd_pcm_close(data->pcmHandle); free(data); - device->ExtraData=NULL; + self->ExtraData = NULL; } -static void qsa_start_capture(ALCdevice* device) +static void qsa_start_capture(CaptureWrapper *self) { - qsa_data* data=(qsa_data*)device->ExtraData; + qsa_data *data = self->ExtraData; int rstatus; if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0) @@ -740,16 +822,16 @@ static void qsa_start_capture(ALCdevice* device) snd_pcm_capture_go(data->pcmHandle); } -static void qsa_stop_capture(ALCdevice* device) +static void qsa_stop_capture(CaptureWrapper *self) { - qsa_data* data=(qsa_data*)device->ExtraData; - + qsa_data *data = self->ExtraData; snd_pcm_capture_flush(data->pcmHandle); } -static ALCuint qsa_available_samples(ALCdevice* device) +static ALCuint qsa_available_samples(CaptureWrapper *self) { - qsa_data* data=(qsa_data*)device->ExtraData; + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + qsa_data *data = self->ExtraData; snd_pcm_channel_status_t status; ALint frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); ALint free_size; @@ -778,9 +860,10 @@ static ALCuint qsa_available_samples(ALCdevice* device) return free_size/frame_size; } -static ALCenum qsa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples) +static ALCenum qsa_capture_samples(CaptureWrapper *self, ALCvoid *buffer, ALCuint samples) { - qsa_data* data=(qsa_data*)device->ExtraData; + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + qsa_data *data = self->ExtraData; char* read_ptr; snd_pcm_channel_status_t status; fd_set rfds; @@ -854,123 +937,43 @@ static ALCenum qsa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint s } -/* Wrappers to use an old-style backend with the new interface. */ -typedef struct PlaybackWrapper { - DERIVE_FROM_TYPE(ALCbackend); -} PlaybackWrapper; - -static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device); -static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, Destruct) -static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name); -static void PlaybackWrapper_close(PlaybackWrapper *self); -static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self); -static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self); -static void PlaybackWrapper_stop(PlaybackWrapper *self); -static DECLARE_FORWARD2(PlaybackWrapper, ALCbackend, ALCenum, captureSamples, void*, ALCuint) -static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ALCuint, availableSamples) -static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ClockLatency, getClockLatency) -static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, lock) -static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, unlock) -DECLARE_DEFAULT_ALLOCATORS(PlaybackWrapper) -DEFINE_ALCBACKEND_VTABLE(PlaybackWrapper); - -static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device) -{ - ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); - SET_VTABLE2(PlaybackWrapper, ALCbackend, self); -} - -static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return qsa_open_playback(device, name); -} - -static void PlaybackWrapper_close(PlaybackWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - qsa_close_playback(device); -} - -static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return qsa_reset_playback(device); -} - -static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return qsa_start_playback(device); -} - -static void PlaybackWrapper_stop(PlaybackWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - qsa_stop_playback(device); -} - - -typedef struct CaptureWrapper { - DERIVE_FROM_TYPE(ALCbackend); -} CaptureWrapper; - -static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device); -static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, Destruct) -static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name); -static void CaptureWrapper_close(CaptureWrapper *self); -static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ALCboolean, reset) -static ALCboolean CaptureWrapper_start(CaptureWrapper *self); -static void CaptureWrapper_stop(CaptureWrapper *self); -static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples); -static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self); -static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ClockLatency, getClockLatency) -static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, lock) -static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, unlock) -DECLARE_DEFAULT_ALLOCATORS(CaptureWrapper) -DEFINE_ALCBACKEND_VTABLE(CaptureWrapper); - static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device) { ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(CaptureWrapper, ALCbackend, self); + + self->ExtraData = NULL; } static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name) { - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return qsa_open_capture(device, name); + return qsa_open_capture(self, name); } static void CaptureWrapper_close(CaptureWrapper *self) { - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - qsa_close_capture(device); + qsa_close_capture(self); } static ALCboolean CaptureWrapper_start(CaptureWrapper *self) { - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - qsa_start_capture(device); + qsa_start_capture(self); return ALC_TRUE; } static void CaptureWrapper_stop(CaptureWrapper *self) { - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - qsa_stop_capture(device); + qsa_stop_capture(self); } static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples) { - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return qsa_capture_samples(device, buffer, samples); + return qsa_capture_samples(self, buffer, samples); } static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self) { - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return qsa_available_samples(device); + return qsa_available_samples(self); } diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index be80020b..6bb328e1 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -807,8 +807,6 @@ struct ALCdevice_struct almtx_t BackendLock; struct ALCbackend *Backend; - void *ExtraData; // For the backend's use - ALCdevice *volatile next; /* Memory space used by the default slot (Playback devices only) */ -- cgit v1.2.3 From ff696bc1fe06bd042d5a1dc2fbfd88efd0161b84 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 15 Jul 2017 01:45:48 -0700 Subject: Set the float PCM GUID for wave files only when outputting float --- Alc/backends/wave.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index c72a632b..bdf76edc 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -320,8 +320,9 @@ static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self) // 32-bit val, channel mask fwrite32le(chanmask, self->mFile); // 16 byte GUID, sub-type format - val = fwrite(((bits==32) ? (isbformat ? SUBTYPE_BFORMAT_FLOAT : SUBTYPE_FLOAT) : - (isbformat ? SUBTYPE_BFORMAT_PCM : SUBTYPE_PCM)), 1, 16, self->mFile); + val = fwrite((device->FmtType == DevFmtFloat) ? + (isbformat ? SUBTYPE_BFORMAT_FLOAT : SUBTYPE_FLOAT) : + (isbformat ? SUBTYPE_BFORMAT_PCM : SUBTYPE_PCM), 1, 16, self->mFile); (void)val; fputs("data", self->mFile); -- cgit v1.2.3 From 5ab4e584eec469708a14df9effe1e038df805f8b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 23 Jul 2017 16:38:54 -0700 Subject: Make sure OSS device files exist before adding them --- Alc/backends/oss.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 33ea55eb..f99ca0d2 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -821,7 +821,11 @@ void ALCossBackendFactory_probe(ALCossBackendFactory* UNUSED(self), enum DevProb cur = &oss_playback; while(cur != NULL) { - AppendAllDevicesList(cur->handle); +#ifdef HAVE_STAT + struct stat buf; + if(stat(cur->path, &buf) == 0) +#endif + AppendAllDevicesList(cur->handle); cur = cur->next; } break; @@ -832,7 +836,11 @@ void ALCossBackendFactory_probe(ALCossBackendFactory* UNUSED(self), enum DevProb cur = &oss_capture; while(cur != NULL) { - AppendCaptureDeviceList(cur->handle); +#ifdef HAVE_STAT + struct stat buf; + if(stat(cur->path, &buf) == 0) +#endif + AppendCaptureDeviceList(cur->handle); cur = cur->next; } break; -- cgit v1.2.3 From 82a990e08e3bb16063485d13491274de55889664 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 23 Jul 2017 16:43:39 -0700 Subject: Downgrade some ERRs to TRACEs These don't exist outside OSSv4, e.g. with OSS/Free, padsp, or aoss, so no need to be concerned. --- Alc/backends/oss.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index f99ca0d2..9c63d9d2 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -163,12 +163,12 @@ static void ALCossListPopulate(struct oss_device *devlist, int type_flag) if((fd=open("/dev/mixer", O_RDONLY)) < 0) { - ERR("Could not open /dev/mixer\n"); + TRACE("Could not open /dev/mixer: %s\n", strerror(errno)); return; } if(ioctl(fd, SNDCTL_SYSINFO, &si) == -1) { - ERR("SNDCTL_SYSINFO failed: %s\n", strerror(errno)); + TRACE("SNDCTL_SYSINFO failed: %s\n", strerror(errno)); goto done; } for(i = 0;i < si.numaudios;i++) -- cgit v1.2.3 From c5a917b4019c878c50b52127f4c08736415267de Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 23 Sep 2017 03:56:45 -0700 Subject: Restore the original JACK message callback when possible --- Alc/backends/jack.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'Alc/backends') diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index 85d5d9c5..ceff0b3a 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -63,6 +63,7 @@ static const ALCchar jackDevice[] = "JACK Default"; static void *jack_handle; #define MAKE_FUNC(f) static __typeof(f) * p##f JACK_FUNCS(MAKE_FUNC); +static __typeof(jack_error_callback) * pjack_error_callback; #undef MAKE_FUNC #define jack_client_open pjack_client_open @@ -84,6 +85,7 @@ JACK_FUNCS(MAKE_FUNC); #define jack_set_buffer_size_callback pjack_set_buffer_size_callback #define jack_set_buffer_size pjack_set_buffer_size #define jack_get_buffer_size pjack_get_buffer_size +#define jack_error_callback (*pjack_error_callback) #endif @@ -120,6 +122,10 @@ static ALCboolean jack_load(void) } while(0) JACK_FUNCS(LOAD_FUNC); #undef LOAD_FUNC + /* Optional symbols. These don't exist in all versions of JACK. */ +#define LOAD_SYM(f) p##f = GetSymbol(jack_handle, #f) + LOAD_SYM(jack_error_callback); +#undef LOAD_SYM if(error) { @@ -556,6 +562,7 @@ typedef struct ALCjackBackendFactory { static ALCboolean ALCjackBackendFactory_init(ALCjackBackendFactory* UNUSED(self)) { + void (*old_error_cb)(const char*); jack_client_t *client; jack_status_t status; @@ -565,9 +572,10 @@ static ALCboolean ALCjackBackendFactory_init(ALCjackBackendFactory* UNUSED(self) if(!GetConfigValueBool(NULL, "jack", "spawn-server", 0)) ClientOptions |= JackNoStartServer; + old_error_cb = (&jack_error_callback ? jack_error_callback : NULL); jack_set_error_function(jack_msg_handler); client = jack_client_open("alsoft", ClientOptions, &status, NULL); - jack_set_error_function(NULL); + jack_set_error_function(old_error_cb); if(client == NULL) { WARN("jack_client_open() failed, 0x%02x\n", status); -- cgit v1.2.3 From 8aa9e35f8c743c1336142a0a49eaeee19a6d33d3 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 11 Jan 2018 07:56:54 -0800 Subject: Move the config function declarations to their own header And rename alcConfig.c to alconfig.c for consistency. --- Alc/ALc.c | 1 + Alc/alcConfig.c | 652 --------------------------------------------- Alc/alconfig.c | 653 ++++++++++++++++++++++++++++++++++++++++++++++ Alc/alconfig.h | 17 ++ Alc/backends/alsa.c | 1 + Alc/backends/jack.c | 1 + Alc/backends/oss.c | 1 + Alc/backends/portaudio.c | 1 + Alc/backends/pulseaudio.c | 1 + Alc/backends/solaris.c | 1 + Alc/backends/wave.c | 1 + Alc/hrtf.c | 1 + Alc/mixer.c | 1 + Alc/panning.c | 1 + CMakeLists.txt | 2 +- OpenAL32/Include/alMain.h | 10 - 16 files changed, 682 insertions(+), 663 deletions(-) delete mode 100644 Alc/alcConfig.c create mode 100644 Alc/alconfig.c create mode 100644 Alc/alconfig.h (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index 34cb63d4..5297af30 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -40,6 +40,7 @@ #include "mastering.h" #include "bformatdec.h" #include "alu.h" +#include "alconfig.h" #include "cpu_caps.h" #include "compat.h" diff --git a/Alc/alcConfig.c b/Alc/alcConfig.c deleted file mode 100644 index 6fd01746..00000000 --- a/Alc/alcConfig.c +++ /dev/null @@ -1,652 +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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#ifdef _WIN32 -#ifdef __MINGW32__ -#define _WIN32_IE 0x501 -#else -#define _WIN32_IE 0x400 -#endif -#endif - -#include "config.h" - -#include -#include -#include -#include -#ifdef _WIN32_IE -#include -#include -#endif - -#include "alMain.h" -#include "compat.h" -#include "bool.h" - - -typedef struct ConfigEntry { - char *key; - char *value; -} ConfigEntry; - -typedef struct ConfigBlock { - ConfigEntry *entries; - unsigned int entryCount; -} ConfigBlock; -static ConfigBlock cfgBlock; - - -static char *lstrip(char *line) -{ - while(isspace(line[0])) - line++; - return line; -} - -static char *rstrip(char *line) -{ - size_t len = strlen(line); - while(len > 0 && isspace(line[len-1])) - len--; - line[len] = 0; - return line; -} - -static int readline(FILE *f, char **output, size_t *maxlen) -{ - size_t len = 0; - int c; - - while((c=fgetc(f)) != EOF && (c == '\r' || c == '\n')) - ; - if(c == EOF) - return 0; - - do { - if(len+1 >= *maxlen) - { - void *temp = NULL; - size_t newmax; - - newmax = (*maxlen ? (*maxlen)<<1 : 32); - if(newmax > *maxlen) - temp = realloc(*output, newmax); - if(!temp) - { - ERR("Failed to realloc "SZFMT" bytes from "SZFMT"!\n", newmax, *maxlen); - return 0; - } - - *output = temp; - *maxlen = newmax; - } - (*output)[len++] = c; - (*output)[len] = '\0'; - } while((c=fgetc(f)) != EOF && c != '\r' && c != '\n'); - - return 1; -} - - -static char *expdup(const char *str) -{ - char *output = NULL; - size_t maxlen = 0; - size_t len = 0; - - while(*str != '\0') - { - const char *addstr; - size_t addstrlen; - size_t i; - - if(str[0] != '$') - { - const char *next = strchr(str, '$'); - addstr = str; - addstrlen = next ? (size_t)(next-str) : strlen(str); - - str += addstrlen; - } - else - { - str++; - if(*str == '$') - { - const char *next = strchr(str+1, '$'); - addstr = str; - addstrlen = next ? (size_t)(next-str) : strlen(str); - - str += addstrlen; - } - else - { - bool hasbraces; - char envname[1024]; - size_t k = 0; - - hasbraces = (*str == '{'); - if(hasbraces) str++; - - while((isalnum(*str) || *str == '_') && k < sizeof(envname)-1) - envname[k++] = *(str++); - envname[k++] = '\0'; - - if(hasbraces && *str != '}') - continue; - - if(hasbraces) str++; - if((addstr=getenv(envname)) == NULL) - continue; - addstrlen = strlen(addstr); - } - } - if(addstrlen == 0) - continue; - - if(addstrlen >= maxlen-len) - { - void *temp = NULL; - size_t newmax; - - newmax = len+addstrlen+1; - if(newmax > maxlen) - temp = realloc(output, newmax); - if(!temp) - { - ERR("Failed to realloc "SZFMT" bytes from "SZFMT"!\n", newmax, maxlen); - return output; - } - - output = temp; - maxlen = newmax; - } - - for(i = 0;i < addstrlen;i++) - output[len++] = addstr[i]; - output[len] = '\0'; - } - - return output ? output : calloc(1, 1); -} - - -static void LoadConfigFromFile(FILE *f) -{ - char curSection[128] = ""; - char *buffer = NULL; - size_t maxlen = 0; - ConfigEntry *ent; - - while(readline(f, &buffer, &maxlen)) - { - char *line, *comment; - char key[256] = ""; - char value[256] = ""; - - line = rstrip(lstrip(buffer)); - if(!line[0]) continue; - - if(line[0] == '[') - { - char *section = line+1; - char *endsection; - - endsection = strchr(section, ']'); - if(!endsection || section == endsection) - { - ERR("config parse error: bad line \"%s\"\n", line); - continue; - } - if(endsection[1] != 0) - { - char *end = endsection+1; - while(isspace(*end)) - ++end; - if(*end != 0 && *end != '#') - { - ERR("config parse error: bad line \"%s\"\n", line); - continue; - } - } - *endsection = 0; - - if(strcasecmp(section, "general") == 0) - curSection[0] = 0; - else - { - size_t len, p = 0; - do { - char *nextp = strchr(section, '%'); - if(!nextp) - { - strncpy(curSection+p, section, sizeof(curSection)-1-p); - break; - } - - len = nextp - section; - if(len > sizeof(curSection)-1-p) - len = sizeof(curSection)-1-p; - strncpy(curSection+p, section, len); - p += len; - section = nextp; - - if(((section[1] >= '0' && section[1] <= '9') || - (section[1] >= 'a' && section[1] <= 'f') || - (section[1] >= 'A' && section[1] <= 'F')) && - ((section[2] >= '0' && section[2] <= '9') || - (section[2] >= 'a' && section[2] <= 'f') || - (section[2] >= 'A' && section[2] <= 'F'))) - { - unsigned char b = 0; - if(section[1] >= '0' && section[1] <= '9') - b = (section[1]-'0') << 4; - else if(section[1] >= 'a' && section[1] <= 'f') - b = (section[1]-'a'+0xa) << 4; - else if(section[1] >= 'A' && section[1] <= 'F') - b = (section[1]-'A'+0x0a) << 4; - if(section[2] >= '0' && section[2] <= '9') - b |= (section[2]-'0'); - else if(section[2] >= 'a' && section[2] <= 'f') - b |= (section[2]-'a'+0xa); - else if(section[2] >= 'A' && section[2] <= 'F') - b |= (section[2]-'A'+0x0a); - if(p < sizeof(curSection)-1) - curSection[p++] = b; - section += 3; - } - else if(section[1] == '%') - { - if(p < sizeof(curSection)-1) - curSection[p++] = '%'; - section += 2; - } - else - { - if(p < sizeof(curSection)-1) - curSection[p++] = '%'; - section += 1; - } - if(p < sizeof(curSection)-1) - curSection[p] = 0; - } while(p < sizeof(curSection)-1 && *section != 0); - curSection[sizeof(curSection)-1] = 0; - } - - continue; - } - - comment = strchr(line, '#'); - if(comment) *(comment++) = 0; - if(!line[0]) continue; - - if(sscanf(line, "%255[^=] = \"%255[^\"]\"", key, value) == 2 || - sscanf(line, "%255[^=] = '%255[^\']'", key, value) == 2 || - sscanf(line, "%255[^=] = %255[^\n]", key, value) == 2) - { - /* sscanf doesn't handle '' or "" as empty values, so clip it - * manually. */ - if(strcmp(value, "\"\"") == 0 || strcmp(value, "''") == 0) - value[0] = 0; - } - else if(sscanf(line, "%255[^=] %255[=]", key, value) == 2) - { - /* Special case for 'key =' */ - value[0] = 0; - } - else - { - ERR("config parse error: malformed option line: \"%s\"\n\n", line); - continue; - } - rstrip(key); - - if(curSection[0] != 0) - { - size_t len = strlen(curSection); - memmove(&key[len+1], key, sizeof(key)-1-len); - key[len] = '/'; - memcpy(key, curSection, len); - } - - /* Check if we already have this option set */ - ent = cfgBlock.entries; - while((unsigned int)(ent-cfgBlock.entries) < cfgBlock.entryCount) - { - if(strcasecmp(ent->key, key) == 0) - break; - ent++; - } - - if((unsigned int)(ent-cfgBlock.entries) >= cfgBlock.entryCount) - { - /* Allocate a new option entry */ - ent = realloc(cfgBlock.entries, (cfgBlock.entryCount+1)*sizeof(ConfigEntry)); - if(!ent) - { - ERR("config parse error: error reallocating config entries\n"); - continue; - } - cfgBlock.entries = ent; - ent = cfgBlock.entries + cfgBlock.entryCount; - cfgBlock.entryCount++; - - ent->key = strdup(key); - ent->value = NULL; - } - - free(ent->value); - ent->value = expdup(value); - - TRACE("found '%s' = '%s'\n", ent->key, ent->value); - } - - free(buffer); -} - -#ifdef _WIN32 -void ReadALConfig(void) -{ - WCHAR buffer[PATH_MAX]; - const WCHAR *str; - al_string ppath; - FILE *f; - - if(SHGetSpecialFolderPathW(NULL, buffer, CSIDL_APPDATA, FALSE) != FALSE) - { - al_string filepath = AL_STRING_INIT_STATIC(); - alstr_copy_wcstr(&filepath, buffer); - alstr_append_cstr(&filepath, "\\alsoft.ini"); - - TRACE("Loading config %s...\n", alstr_get_cstr(filepath)); - f = al_fopen(alstr_get_cstr(filepath), "rt"); - if(f) - { - LoadConfigFromFile(f); - fclose(f); - } - alstr_reset(&filepath); - } - - ppath = GetProcPath(); - if(!alstr_empty(ppath)) - { - alstr_append_cstr(&ppath, "\\alsoft.ini"); - TRACE("Loading config %s...\n", alstr_get_cstr(ppath)); - f = al_fopen(alstr_get_cstr(ppath), "r"); - if(f) - { - LoadConfigFromFile(f); - fclose(f); - } - } - - if((str=_wgetenv(L"ALSOFT_CONF")) != NULL && *str) - { - al_string filepath = AL_STRING_INIT_STATIC(); - alstr_copy_wcstr(&filepath, str); - - TRACE("Loading config %s...\n", alstr_get_cstr(filepath)); - f = al_fopen(alstr_get_cstr(filepath), "rt"); - if(f) - { - LoadConfigFromFile(f); - fclose(f); - } - alstr_reset(&filepath); - } - - alstr_reset(&ppath); -} -#else -void ReadALConfig(void) -{ - char buffer[PATH_MAX]; - const char *str; - al_string ppath; - FILE *f; - - str = "/etc/openal/alsoft.conf"; - - TRACE("Loading config %s...\n", str); - f = al_fopen(str, "r"); - if(f) - { - LoadConfigFromFile(f); - fclose(f); - } - - if(!(str=getenv("XDG_CONFIG_DIRS")) || str[0] == 0) - str = "/etc/xdg"; - strncpy(buffer, str, sizeof(buffer)-1); - buffer[sizeof(buffer)-1] = 0; - /* Go through the list in reverse, since "the order of base directories - * denotes their importance; the first directory listed is the most - * important". Ergo, we need to load the settings from the later dirs - * first so that the settings in the earlier dirs override them. - */ - while(1) - { - char *next = strrchr(buffer, ':'); - if(next) *(next++) = 0; - else next = buffer; - - if(next[0] != '/') - WARN("Ignoring XDG config dir: %s\n", next); - else - { - size_t len = strlen(next); - strncpy(next+len, "/alsoft.conf", buffer+sizeof(buffer)-next-len); - buffer[sizeof(buffer)-1] = 0; - - TRACE("Loading config %s...\n", next); - f = al_fopen(next, "r"); - if(f) - { - LoadConfigFromFile(f); - fclose(f); - } - } - if(next == buffer) - break; - } - - if((str=getenv("HOME")) != NULL && *str) - { - snprintf(buffer, sizeof(buffer), "%s/.alsoftrc", str); - - TRACE("Loading config %s...\n", buffer); - f = al_fopen(buffer, "r"); - if(f) - { - LoadConfigFromFile(f); - fclose(f); - } - } - - if((str=getenv("XDG_CONFIG_HOME")) != NULL && str[0] != 0) - snprintf(buffer, sizeof(buffer), "%s/%s", str, "alsoft.conf"); - else - { - buffer[0] = 0; - if((str=getenv("HOME")) != NULL && str[0] != 0) - snprintf(buffer, sizeof(buffer), "%s/.config/%s", str, "alsoft.conf"); - } - if(buffer[0] != 0) - { - TRACE("Loading config %s...\n", buffer); - f = al_fopen(buffer, "r"); - if(f) - { - LoadConfigFromFile(f); - fclose(f); - } - } - - ppath = GetProcPath(); - if(!alstr_empty(ppath)) - { - alstr_append_cstr(&ppath, "/alsoft.conf"); - TRACE("Loading config %s...\n", alstr_get_cstr(ppath)); - f = al_fopen(alstr_get_cstr(ppath), "r"); - if(f) - { - LoadConfigFromFile(f); - fclose(f); - } - } - - if((str=getenv("ALSOFT_CONF")) != NULL && *str) - { - TRACE("Loading config %s...\n", str); - f = al_fopen(str, "r"); - if(f) - { - LoadConfigFromFile(f); - fclose(f); - } - } - - alstr_reset(&ppath); -} -#endif - -void FreeALConfig(void) -{ - unsigned int i; - - for(i = 0;i < cfgBlock.entryCount;i++) - { - free(cfgBlock.entries[i].key); - free(cfgBlock.entries[i].value); - } - free(cfgBlock.entries); -} - -const char *GetConfigValue(const char *devName, const char *blockName, const char *keyName, const char *def) -{ - unsigned int i; - char key[256]; - - if(!keyName) - return def; - - if(blockName && strcasecmp(blockName, "general") != 0) - { - if(devName) - snprintf(key, sizeof(key), "%s/%s/%s", blockName, devName, keyName); - else - snprintf(key, sizeof(key), "%s/%s", blockName, keyName); - } - else - { - if(devName) - snprintf(key, sizeof(key), "%s/%s", devName, keyName); - else - { - strncpy(key, keyName, sizeof(key)-1); - key[sizeof(key)-1] = 0; - } - } - - for(i = 0;i < cfgBlock.entryCount;i++) - { - if(strcmp(cfgBlock.entries[i].key, key) == 0) - { - TRACE("Found %s = \"%s\"\n", key, cfgBlock.entries[i].value); - if(cfgBlock.entries[i].value[0]) - return cfgBlock.entries[i].value; - return def; - } - } - - if(!devName) - { - TRACE("Key %s not found\n", key); - return def; - } - return GetConfigValue(NULL, blockName, keyName, def); -} - -int ConfigValueExists(const char *devName, const char *blockName, const char *keyName) -{ - const char *val = GetConfigValue(devName, blockName, keyName, ""); - return !!val[0]; -} - -int ConfigValueStr(const char *devName, const char *blockName, const char *keyName, const char **ret) -{ - const char *val = GetConfigValue(devName, blockName, keyName, ""); - if(!val[0]) return 0; - - *ret = val; - return 1; -} - -int ConfigValueInt(const char *devName, const char *blockName, const char *keyName, int *ret) -{ - const char *val = GetConfigValue(devName, blockName, keyName, ""); - if(!val[0]) return 0; - - *ret = strtol(val, NULL, 0); - return 1; -} - -int ConfigValueUInt(const char *devName, const char *blockName, const char *keyName, unsigned int *ret) -{ - const char *val = GetConfigValue(devName, blockName, keyName, ""); - if(!val[0]) return 0; - - *ret = strtoul(val, NULL, 0); - return 1; -} - -int ConfigValueFloat(const char *devName, const char *blockName, const char *keyName, float *ret) -{ - const char *val = GetConfigValue(devName, blockName, keyName, ""); - if(!val[0]) return 0; - -#ifdef HAVE_STRTOF - *ret = strtof(val, NULL); -#else - *ret = (float)strtod(val, NULL); -#endif - return 1; -} - -int ConfigValueBool(const char *devName, const char *blockName, const char *keyName, int *ret) -{ - const char *val = GetConfigValue(devName, blockName, keyName, ""); - if(!val[0]) return 0; - - *ret = (strcasecmp(val, "true") == 0 || strcasecmp(val, "yes") == 0 || - strcasecmp(val, "on") == 0 || atoi(val) != 0); - return 1; -} - -int GetConfigValueBool(const char *devName, const char *blockName, const char *keyName, int def) -{ - const char *val = GetConfigValue(devName, blockName, keyName, ""); - - if(!val[0]) return !!def; - return (strcasecmp(val, "true") == 0 || strcasecmp(val, "yes") == 0 || - strcasecmp(val, "on") == 0 || atoi(val) != 0); -} diff --git a/Alc/alconfig.c b/Alc/alconfig.c new file mode 100644 index 00000000..1115bf30 --- /dev/null +++ b/Alc/alconfig.c @@ -0,0 +1,653 @@ +/** + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#ifdef _WIN32 +#ifdef __MINGW32__ +#define _WIN32_IE 0x501 +#else +#define _WIN32_IE 0x400 +#endif +#endif + +#include "config.h" + +#include +#include +#include +#include +#ifdef _WIN32_IE +#include +#include +#endif + +#include "alMain.h" +#include "alconfig.h" +#include "compat.h" +#include "bool.h" + + +typedef struct ConfigEntry { + char *key; + char *value; +} ConfigEntry; + +typedef struct ConfigBlock { + ConfigEntry *entries; + unsigned int entryCount; +} ConfigBlock; +static ConfigBlock cfgBlock; + + +static char *lstrip(char *line) +{ + while(isspace(line[0])) + line++; + return line; +} + +static char *rstrip(char *line) +{ + size_t len = strlen(line); + while(len > 0 && isspace(line[len-1])) + len--; + line[len] = 0; + return line; +} + +static int readline(FILE *f, char **output, size_t *maxlen) +{ + size_t len = 0; + int c; + + while((c=fgetc(f)) != EOF && (c == '\r' || c == '\n')) + ; + if(c == EOF) + return 0; + + do { + if(len+1 >= *maxlen) + { + void *temp = NULL; + size_t newmax; + + newmax = (*maxlen ? (*maxlen)<<1 : 32); + if(newmax > *maxlen) + temp = realloc(*output, newmax); + if(!temp) + { + ERR("Failed to realloc "SZFMT" bytes from "SZFMT"!\n", newmax, *maxlen); + return 0; + } + + *output = temp; + *maxlen = newmax; + } + (*output)[len++] = c; + (*output)[len] = '\0'; + } while((c=fgetc(f)) != EOF && c != '\r' && c != '\n'); + + return 1; +} + + +static char *expdup(const char *str) +{ + char *output = NULL; + size_t maxlen = 0; + size_t len = 0; + + while(*str != '\0') + { + const char *addstr; + size_t addstrlen; + size_t i; + + if(str[0] != '$') + { + const char *next = strchr(str, '$'); + addstr = str; + addstrlen = next ? (size_t)(next-str) : strlen(str); + + str += addstrlen; + } + else + { + str++; + if(*str == '$') + { + const char *next = strchr(str+1, '$'); + addstr = str; + addstrlen = next ? (size_t)(next-str) : strlen(str); + + str += addstrlen; + } + else + { + bool hasbraces; + char envname[1024]; + size_t k = 0; + + hasbraces = (*str == '{'); + if(hasbraces) str++; + + while((isalnum(*str) || *str == '_') && k < sizeof(envname)-1) + envname[k++] = *(str++); + envname[k++] = '\0'; + + if(hasbraces && *str != '}') + continue; + + if(hasbraces) str++; + if((addstr=getenv(envname)) == NULL) + continue; + addstrlen = strlen(addstr); + } + } + if(addstrlen == 0) + continue; + + if(addstrlen >= maxlen-len) + { + void *temp = NULL; + size_t newmax; + + newmax = len+addstrlen+1; + if(newmax > maxlen) + temp = realloc(output, newmax); + if(!temp) + { + ERR("Failed to realloc "SZFMT" bytes from "SZFMT"!\n", newmax, maxlen); + return output; + } + + output = temp; + maxlen = newmax; + } + + for(i = 0;i < addstrlen;i++) + output[len++] = addstr[i]; + output[len] = '\0'; + } + + return output ? output : calloc(1, 1); +} + + +static void LoadConfigFromFile(FILE *f) +{ + char curSection[128] = ""; + char *buffer = NULL; + size_t maxlen = 0; + ConfigEntry *ent; + + while(readline(f, &buffer, &maxlen)) + { + char *line, *comment; + char key[256] = ""; + char value[256] = ""; + + line = rstrip(lstrip(buffer)); + if(!line[0]) continue; + + if(line[0] == '[') + { + char *section = line+1; + char *endsection; + + endsection = strchr(section, ']'); + if(!endsection || section == endsection) + { + ERR("config parse error: bad line \"%s\"\n", line); + continue; + } + if(endsection[1] != 0) + { + char *end = endsection+1; + while(isspace(*end)) + ++end; + if(*end != 0 && *end != '#') + { + ERR("config parse error: bad line \"%s\"\n", line); + continue; + } + } + *endsection = 0; + + if(strcasecmp(section, "general") == 0) + curSection[0] = 0; + else + { + size_t len, p = 0; + do { + char *nextp = strchr(section, '%'); + if(!nextp) + { + strncpy(curSection+p, section, sizeof(curSection)-1-p); + break; + } + + len = nextp - section; + if(len > sizeof(curSection)-1-p) + len = sizeof(curSection)-1-p; + strncpy(curSection+p, section, len); + p += len; + section = nextp; + + if(((section[1] >= '0' && section[1] <= '9') || + (section[1] >= 'a' && section[1] <= 'f') || + (section[1] >= 'A' && section[1] <= 'F')) && + ((section[2] >= '0' && section[2] <= '9') || + (section[2] >= 'a' && section[2] <= 'f') || + (section[2] >= 'A' && section[2] <= 'F'))) + { + unsigned char b = 0; + if(section[1] >= '0' && section[1] <= '9') + b = (section[1]-'0') << 4; + else if(section[1] >= 'a' && section[1] <= 'f') + b = (section[1]-'a'+0xa) << 4; + else if(section[1] >= 'A' && section[1] <= 'F') + b = (section[1]-'A'+0x0a) << 4; + if(section[2] >= '0' && section[2] <= '9') + b |= (section[2]-'0'); + else if(section[2] >= 'a' && section[2] <= 'f') + b |= (section[2]-'a'+0xa); + else if(section[2] >= 'A' && section[2] <= 'F') + b |= (section[2]-'A'+0x0a); + if(p < sizeof(curSection)-1) + curSection[p++] = b; + section += 3; + } + else if(section[1] == '%') + { + if(p < sizeof(curSection)-1) + curSection[p++] = '%'; + section += 2; + } + else + { + if(p < sizeof(curSection)-1) + curSection[p++] = '%'; + section += 1; + } + if(p < sizeof(curSection)-1) + curSection[p] = 0; + } while(p < sizeof(curSection)-1 && *section != 0); + curSection[sizeof(curSection)-1] = 0; + } + + continue; + } + + comment = strchr(line, '#'); + if(comment) *(comment++) = 0; + if(!line[0]) continue; + + if(sscanf(line, "%255[^=] = \"%255[^\"]\"", key, value) == 2 || + sscanf(line, "%255[^=] = '%255[^\']'", key, value) == 2 || + sscanf(line, "%255[^=] = %255[^\n]", key, value) == 2) + { + /* sscanf doesn't handle '' or "" as empty values, so clip it + * manually. */ + if(strcmp(value, "\"\"") == 0 || strcmp(value, "''") == 0) + value[0] = 0; + } + else if(sscanf(line, "%255[^=] %255[=]", key, value) == 2) + { + /* Special case for 'key =' */ + value[0] = 0; + } + else + { + ERR("config parse error: malformed option line: \"%s\"\n\n", line); + continue; + } + rstrip(key); + + if(curSection[0] != 0) + { + size_t len = strlen(curSection); + memmove(&key[len+1], key, sizeof(key)-1-len); + key[len] = '/'; + memcpy(key, curSection, len); + } + + /* Check if we already have this option set */ + ent = cfgBlock.entries; + while((unsigned int)(ent-cfgBlock.entries) < cfgBlock.entryCount) + { + if(strcasecmp(ent->key, key) == 0) + break; + ent++; + } + + if((unsigned int)(ent-cfgBlock.entries) >= cfgBlock.entryCount) + { + /* Allocate a new option entry */ + ent = realloc(cfgBlock.entries, (cfgBlock.entryCount+1)*sizeof(ConfigEntry)); + if(!ent) + { + ERR("config parse error: error reallocating config entries\n"); + continue; + } + cfgBlock.entries = ent; + ent = cfgBlock.entries + cfgBlock.entryCount; + cfgBlock.entryCount++; + + ent->key = strdup(key); + ent->value = NULL; + } + + free(ent->value); + ent->value = expdup(value); + + TRACE("found '%s' = '%s'\n", ent->key, ent->value); + } + + free(buffer); +} + +#ifdef _WIN32 +void ReadALConfig(void) +{ + WCHAR buffer[PATH_MAX]; + const WCHAR *str; + al_string ppath; + FILE *f; + + if(SHGetSpecialFolderPathW(NULL, buffer, CSIDL_APPDATA, FALSE) != FALSE) + { + al_string filepath = AL_STRING_INIT_STATIC(); + alstr_copy_wcstr(&filepath, buffer); + alstr_append_cstr(&filepath, "\\alsoft.ini"); + + TRACE("Loading config %s...\n", alstr_get_cstr(filepath)); + f = al_fopen(alstr_get_cstr(filepath), "rt"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + alstr_reset(&filepath); + } + + ppath = GetProcPath(); + if(!alstr_empty(ppath)) + { + alstr_append_cstr(&ppath, "\\alsoft.ini"); + TRACE("Loading config %s...\n", alstr_get_cstr(ppath)); + f = al_fopen(alstr_get_cstr(ppath), "r"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + } + + if((str=_wgetenv(L"ALSOFT_CONF")) != NULL && *str) + { + al_string filepath = AL_STRING_INIT_STATIC(); + alstr_copy_wcstr(&filepath, str); + + TRACE("Loading config %s...\n", alstr_get_cstr(filepath)); + f = al_fopen(alstr_get_cstr(filepath), "rt"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + alstr_reset(&filepath); + } + + alstr_reset(&ppath); +} +#else +void ReadALConfig(void) +{ + char buffer[PATH_MAX]; + const char *str; + al_string ppath; + FILE *f; + + str = "/etc/openal/alsoft.conf"; + + TRACE("Loading config %s...\n", str); + f = al_fopen(str, "r"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + + if(!(str=getenv("XDG_CONFIG_DIRS")) || str[0] == 0) + str = "/etc/xdg"; + strncpy(buffer, str, sizeof(buffer)-1); + buffer[sizeof(buffer)-1] = 0; + /* Go through the list in reverse, since "the order of base directories + * denotes their importance; the first directory listed is the most + * important". Ergo, we need to load the settings from the later dirs + * first so that the settings in the earlier dirs override them. + */ + while(1) + { + char *next = strrchr(buffer, ':'); + if(next) *(next++) = 0; + else next = buffer; + + if(next[0] != '/') + WARN("Ignoring XDG config dir: %s\n", next); + else + { + size_t len = strlen(next); + strncpy(next+len, "/alsoft.conf", buffer+sizeof(buffer)-next-len); + buffer[sizeof(buffer)-1] = 0; + + TRACE("Loading config %s...\n", next); + f = al_fopen(next, "r"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + } + if(next == buffer) + break; + } + + if((str=getenv("HOME")) != NULL && *str) + { + snprintf(buffer, sizeof(buffer), "%s/.alsoftrc", str); + + TRACE("Loading config %s...\n", buffer); + f = al_fopen(buffer, "r"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + } + + if((str=getenv("XDG_CONFIG_HOME")) != NULL && str[0] != 0) + snprintf(buffer, sizeof(buffer), "%s/%s", str, "alsoft.conf"); + else + { + buffer[0] = 0; + if((str=getenv("HOME")) != NULL && str[0] != 0) + snprintf(buffer, sizeof(buffer), "%s/.config/%s", str, "alsoft.conf"); + } + if(buffer[0] != 0) + { + TRACE("Loading config %s...\n", buffer); + f = al_fopen(buffer, "r"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + } + + ppath = GetProcPath(); + if(!alstr_empty(ppath)) + { + alstr_append_cstr(&ppath, "/alsoft.conf"); + TRACE("Loading config %s...\n", alstr_get_cstr(ppath)); + f = al_fopen(alstr_get_cstr(ppath), "r"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + } + + if((str=getenv("ALSOFT_CONF")) != NULL && *str) + { + TRACE("Loading config %s...\n", str); + f = al_fopen(str, "r"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + } + + alstr_reset(&ppath); +} +#endif + +void FreeALConfig(void) +{ + unsigned int i; + + for(i = 0;i < cfgBlock.entryCount;i++) + { + free(cfgBlock.entries[i].key); + free(cfgBlock.entries[i].value); + } + free(cfgBlock.entries); +} + +const char *GetConfigValue(const char *devName, const char *blockName, const char *keyName, const char *def) +{ + unsigned int i; + char key[256]; + + if(!keyName) + return def; + + if(blockName && strcasecmp(blockName, "general") != 0) + { + if(devName) + snprintf(key, sizeof(key), "%s/%s/%s", blockName, devName, keyName); + else + snprintf(key, sizeof(key), "%s/%s", blockName, keyName); + } + else + { + if(devName) + snprintf(key, sizeof(key), "%s/%s", devName, keyName); + else + { + strncpy(key, keyName, sizeof(key)-1); + key[sizeof(key)-1] = 0; + } + } + + for(i = 0;i < cfgBlock.entryCount;i++) + { + if(strcmp(cfgBlock.entries[i].key, key) == 0) + { + TRACE("Found %s = \"%s\"\n", key, cfgBlock.entries[i].value); + if(cfgBlock.entries[i].value[0]) + return cfgBlock.entries[i].value; + return def; + } + } + + if(!devName) + { + TRACE("Key %s not found\n", key); + return def; + } + return GetConfigValue(NULL, blockName, keyName, def); +} + +int ConfigValueExists(const char *devName, const char *blockName, const char *keyName) +{ + const char *val = GetConfigValue(devName, blockName, keyName, ""); + return !!val[0]; +} + +int ConfigValueStr(const char *devName, const char *blockName, const char *keyName, const char **ret) +{ + const char *val = GetConfigValue(devName, blockName, keyName, ""); + if(!val[0]) return 0; + + *ret = val; + return 1; +} + +int ConfigValueInt(const char *devName, const char *blockName, const char *keyName, int *ret) +{ + const char *val = GetConfigValue(devName, blockName, keyName, ""); + if(!val[0]) return 0; + + *ret = strtol(val, NULL, 0); + return 1; +} + +int ConfigValueUInt(const char *devName, const char *blockName, const char *keyName, unsigned int *ret) +{ + const char *val = GetConfigValue(devName, blockName, keyName, ""); + if(!val[0]) return 0; + + *ret = strtoul(val, NULL, 0); + return 1; +} + +int ConfigValueFloat(const char *devName, const char *blockName, const char *keyName, float *ret) +{ + const char *val = GetConfigValue(devName, blockName, keyName, ""); + if(!val[0]) return 0; + +#ifdef HAVE_STRTOF + *ret = strtof(val, NULL); +#else + *ret = (float)strtod(val, NULL); +#endif + return 1; +} + +int ConfigValueBool(const char *devName, const char *blockName, const char *keyName, int *ret) +{ + const char *val = GetConfigValue(devName, blockName, keyName, ""); + if(!val[0]) return 0; + + *ret = (strcasecmp(val, "true") == 0 || strcasecmp(val, "yes") == 0 || + strcasecmp(val, "on") == 0 || atoi(val) != 0); + return 1; +} + +int GetConfigValueBool(const char *devName, const char *blockName, const char *keyName, int def) +{ + const char *val = GetConfigValue(devName, blockName, keyName, ""); + + if(!val[0]) return !!def; + return (strcasecmp(val, "true") == 0 || strcasecmp(val, "yes") == 0 || + strcasecmp(val, "on") == 0 || atoi(val) != 0); +} diff --git a/Alc/alconfig.h b/Alc/alconfig.h new file mode 100644 index 00000000..1e493e2e --- /dev/null +++ b/Alc/alconfig.h @@ -0,0 +1,17 @@ +#ifndef ALCONFIG_H +#define ALCONFIG_H + +void ReadALConfig(void); +void FreeALConfig(void); + +int ConfigValueExists(const char *devName, const char *blockName, const char *keyName); +const char *GetConfigValue(const char *devName, const char *blockName, const char *keyName, const char *def); +int GetConfigValueBool(const char *devName, const char *blockName, const char *keyName, int def); + +int ConfigValueStr(const char *devName, const char *blockName, const char *keyName, const char **ret); +int ConfigValueInt(const char *devName, const char *blockName, const char *keyName, int *ret); +int ConfigValueUInt(const char *devName, const char *blockName, const char *keyName, unsigned int *ret); +int ConfigValueFloat(const char *devName, const char *blockName, const char *keyName, float *ret); +int ConfigValueBool(const char *devName, const char *blockName, const char *keyName, int *ret); + +#endif /* ALCONFIG_H */ diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 79f2795a..f941ce4b 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -26,6 +26,7 @@ #include "alMain.h" #include "alu.h" +#include "alconfig.h" #include "threads.h" #include "compat.h" diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index ceff0b3a..4ef9006c 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -26,6 +26,7 @@ #include "alMain.h" #include "alu.h" +#include "alconfig.h" #include "threads.h" #include "compat.h" diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 9c63d9d2..196432e1 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -35,6 +35,7 @@ #include "alMain.h" #include "alu.h" +#include "alconfig.h" #include "threads.h" #include "compat.h" diff --git a/Alc/backends/portaudio.c b/Alc/backends/portaudio.c index 807e8000..0f4672c4 100644 --- a/Alc/backends/portaudio.c +++ b/Alc/backends/portaudio.c @@ -26,6 +26,7 @@ #include "alMain.h" #include "alu.h" +#include "alconfig.h" #include "compat.h" #include "backends/base.h" diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index 8c5469b2..9f3c4762 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -25,6 +25,7 @@ #include "alMain.h" #include "alu.h" +#include "alconfig.h" #include "threads.h" #include "compat.h" diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c index 5dfb5084..59cc5ddc 100644 --- a/Alc/backends/solaris.c +++ b/Alc/backends/solaris.c @@ -34,6 +34,7 @@ #include "alMain.h" #include "alu.h" +#include "alconfig.h" #include "threads.h" #include "compat.h" diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index bdf76edc..1c502fd9 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -27,6 +27,7 @@ #include "alMain.h" #include "alu.h" +#include "alconfig.h" #include "threads.h" #include "compat.h" diff --git a/Alc/hrtf.c b/Alc/hrtf.c index 54537a05..9d5e2ca9 100644 --- a/Alc/hrtf.c +++ b/Alc/hrtf.c @@ -30,6 +30,7 @@ #include "alu.h" #include "bformatdec.h" #include "hrtf.h" +#include "alconfig.h" #include "compat.h" #include "almalloc.h" diff --git a/Alc/mixer.c b/Alc/mixer.c index 3d1da58f..b1d859c6 100644 --- a/Alc/mixer.c +++ b/Alc/mixer.c @@ -34,6 +34,7 @@ #include "alListener.h" #include "alAuxEffectSlot.h" #include "alu.h" +#include "alconfig.h" #include "cpu_caps.h" #include "mixer_defs.h" diff --git a/Alc/panning.c b/Alc/panning.c index 37bf3ac9..dfb71918 100644 --- a/Alc/panning.c +++ b/Alc/panning.c @@ -29,6 +29,7 @@ #include "alMain.h" #include "alAuxEffectSlot.h" #include "alu.h" +#include "alconfig.h" #include "bool.h" #include "ambdec.h" #include "bformatdec.h" diff --git a/CMakeLists.txt b/CMakeLists.txt index 95b73c25..929b5517 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -713,7 +713,7 @@ SET(OPENAL_OBJS OpenAL32/alAuxEffectSlot.c ) SET(ALC_OBJS Alc/ALc.c Alc/ALu.c - Alc/alcConfig.c + Alc/alconfig.c Alc/alcRing.c Alc/bs2b.c Alc/converter.c diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 6556da37..ea797053 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -850,16 +850,6 @@ size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const char *src, size_t cnt); void ll_ringbuffer_write_advance(ll_ringbuffer_t *rb, size_t cnt); size_t ll_ringbuffer_write_space(const ll_ringbuffer_t *rb); -void ReadALConfig(void); -void FreeALConfig(void); -int ConfigValueExists(const char *devName, const char *blockName, const char *keyName); -const char *GetConfigValue(const char *devName, const char *blockName, const char *keyName, const char *def); -int GetConfigValueBool(const char *devName, const char *blockName, const char *keyName, int def); -int ConfigValueStr(const char *devName, const char *blockName, const char *keyName, const char **ret); -int ConfigValueInt(const char *devName, const char *blockName, const char *keyName, int *ret); -int ConfigValueUInt(const char *devName, const char *blockName, const char *keyName, unsigned int *ret); -int ConfigValueFloat(const char *devName, const char *blockName, const char *keyName, float *ret); -int ConfigValueBool(const char *devName, const char *blockName, const char *keyName, int *ret); void SetRTPriority(void); -- cgit v1.2.3 From 3832b25f308279539a3748bafdc5056d16e4b291 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 11 Jan 2018 09:16:28 -0800 Subject: Move the ringbuffer declarations to a separate header And rename alcRing.c to ringbuffer.c for consistency. --- Alc/alcRing.c | 317 ---------------------------------------------- Alc/backends/alsa.c | 1 + Alc/backends/coreaudio.c | 1 + Alc/backends/dsound.c | 1 + Alc/backends/jack.c | 1 + Alc/backends/mmdevapi.c | 1 + Alc/backends/opensl.c | 3 +- Alc/backends/oss.c | 1 + Alc/backends/portaudio.c | 1 + Alc/backends/winmm.c | 1 + Alc/ringbuffer.c | 298 +++++++++++++++++++++++++++++++++++++++++++ Alc/ringbuffer.h | 29 +++++ CMakeLists.txt | 2 +- OpenAL32/Include/alMain.h | 20 --- 14 files changed, 338 insertions(+), 339 deletions(-) delete mode 100644 Alc/alcRing.c create mode 100644 Alc/ringbuffer.c create mode 100644 Alc/ringbuffer.h (limited to 'Alc/backends') diff --git a/Alc/alcRing.c b/Alc/alcRing.c deleted file mode 100644 index d72b34f1..00000000 --- a/Alc/alcRing.c +++ /dev/null @@ -1,317 +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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#include "config.h" - -#include -#include - -#include "alMain.h" -#include "threads.h" -#include "almalloc.h" -#include "compat.h" - - -/* NOTE: This lockless ringbuffer implementation is copied from JACK, extended - * to include an element size. Consequently, parameters and return values for a - * size or count is in 'elements', not bytes. Additionally, it only supports - * single-consumer/single-provider operation. */ -struct ll_ringbuffer { - ATOMIC(size_t) write_ptr; - ATOMIC(size_t) read_ptr; - size_t size; - size_t size_mask; - size_t elem_size; - int mlocked; - - alignas(16) char buf[]; -}; - -/* Create a new ringbuffer to hold at least `sz' elements of `elem_sz' bytes. - * The number of elements is rounded up to the next power of two. */ -ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz) -{ - ll_ringbuffer_t *rb; - ALuint power_of_two; - - power_of_two = NextPowerOf2(sz); - if(power_of_two < sz) - return NULL; - - rb = al_malloc(16, sizeof(*rb) + power_of_two*elem_sz); - if(!rb) return NULL; - - ATOMIC_INIT(&rb->write_ptr, 0); - ATOMIC_INIT(&rb->read_ptr, 0); - rb->size = power_of_two; - rb->size_mask = rb->size - 1; - rb->elem_size = elem_sz; - rb->mlocked = 0; - return rb; -} - -/* Free all data associated with the ringbuffer `rb'. */ -void ll_ringbuffer_free(ll_ringbuffer_t *rb) -{ - if(rb) - { -#ifdef USE_MLOCK - if(rb->mlocked) - munlock(rb, sizeof(*rb) + rb->size*rb->elem_size); -#endif /* USE_MLOCK */ - al_free(rb); - } -} - -/* Lock the data block of `rb' using the system call 'mlock'. */ -int ll_ringbuffer_mlock(ll_ringbuffer_t *rb) -{ -#ifdef USE_MLOCK - if(!rb->mlocked && mlock(rb, sizeof(*rb) + rb->size*rb->elem_size)) - return -1; -#endif /* USE_MLOCK */ - rb->mlocked = 1; - return 0; -} - -/* Reset the read and write pointers to zero. This is not thread safe. */ -void ll_ringbuffer_reset(ll_ringbuffer_t *rb) -{ - ATOMIC_STORE(&rb->write_ptr, 0, almemory_order_release); - ATOMIC_STORE(&rb->read_ptr, 0, almemory_order_release); - memset(rb->buf, 0, rb->size*rb->elem_size); -} - -/* Return the number of elements available for reading. This is the number of - * elements in front of the read pointer and behind the write pointer. */ -size_t ll_ringbuffer_read_space(const ll_ringbuffer_t *rb) -{ - size_t w = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->write_ptr, almemory_order_acquire); - size_t r = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->read_ptr, almemory_order_acquire); - return (w-r) & rb->size_mask; -} -/* Return the number of elements available for writing. This is the number of - * elements in front of the write pointer and behind the read pointer. */ -size_t ll_ringbuffer_write_space(const ll_ringbuffer_t *rb) -{ - size_t w = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->write_ptr, almemory_order_acquire); - size_t r = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->read_ptr, almemory_order_acquire); - return (r-w-1) & rb->size_mask; -} - -/* The copying data reader. Copy at most `cnt' elements from `rb' to `dest'. - * Returns the actual number of elements copied. */ -size_t ll_ringbuffer_read(ll_ringbuffer_t *rb, char *dest, size_t cnt) -{ - size_t read_ptr; - size_t free_cnt; - size_t cnt2; - size_t to_read; - size_t n1, n2; - - free_cnt = ll_ringbuffer_read_space(rb); - if(free_cnt == 0) return 0; - - to_read = (cnt > free_cnt) ? free_cnt : cnt; - read_ptr = ATOMIC_LOAD(&rb->read_ptr, almemory_order_relaxed) & rb->size_mask; - - cnt2 = read_ptr + to_read; - if(cnt2 > rb->size) - { - n1 = rb->size - read_ptr; - n2 = cnt2 & rb->size_mask; - } - else - { - n1 = to_read; - n2 = 0; - } - - memcpy(dest, &rb->buf[read_ptr*rb->elem_size], n1*rb->elem_size); - read_ptr += n1; - if(n2) - { - memcpy(dest + n1*rb->elem_size, &rb->buf[(read_ptr&rb->size_mask)*rb->elem_size], - n2*rb->elem_size); - read_ptr += n2; - } - ATOMIC_STORE(&rb->read_ptr, read_ptr, almemory_order_release); - return to_read; -} - -/* The copying data reader w/o read pointer advance. Copy at most `cnt' - * elements from `rb' to `dest'. Returns the actual number of elements copied. - */ -size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, char *dest, size_t cnt) -{ - size_t free_cnt; - size_t cnt2; - size_t to_read; - size_t n1, n2; - size_t read_ptr; - - free_cnt = ll_ringbuffer_read_space(rb); - if(free_cnt == 0) return 0; - - to_read = (cnt > free_cnt) ? free_cnt : cnt; - read_ptr = ATOMIC_LOAD(&rb->read_ptr, almemory_order_relaxed) & rb->size_mask; - - cnt2 = read_ptr + to_read; - if(cnt2 > rb->size) - { - n1 = rb->size - read_ptr; - n2 = cnt2 & rb->size_mask; - } - else - { - n1 = to_read; - n2 = 0; - } - - memcpy(dest, &rb->buf[read_ptr*rb->elem_size], n1*rb->elem_size); - if(n2) - { - read_ptr += n1; - memcpy(dest + n1*rb->elem_size, &rb->buf[(read_ptr&rb->size_mask)*rb->elem_size], - n2*rb->elem_size); - } - return to_read; -} - -/* The copying data writer. Copy at most `cnt' elements to `rb' from `src'. - * Returns the actual number of elements copied. */ -size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const char *src, size_t cnt) -{ - size_t write_ptr; - size_t free_cnt; - size_t cnt2; - size_t to_write; - size_t n1, n2; - - free_cnt = ll_ringbuffer_write_space(rb); - if(free_cnt == 0) return 0; - - to_write = (cnt > free_cnt) ? free_cnt : cnt; - write_ptr = ATOMIC_LOAD(&rb->write_ptr, almemory_order_relaxed) & rb->size_mask; - - cnt2 = write_ptr + to_write; - if(cnt2 > rb->size) - { - n1 = rb->size - write_ptr; - n2 = cnt2 & rb->size_mask; - } - else - { - n1 = to_write; - n2 = 0; - } - - memcpy(&rb->buf[write_ptr*rb->elem_size], src, n1*rb->elem_size); - write_ptr += n1; - if(n2) - { - memcpy(&rb->buf[(write_ptr&rb->size_mask)*rb->elem_size], src + n1*rb->elem_size, - n2*rb->elem_size); - write_ptr += n2; - } - ATOMIC_STORE(&rb->write_ptr, write_ptr, almemory_order_release); - return to_write; -} - -/* Advance the read pointer `cnt' places. */ -void ll_ringbuffer_read_advance(ll_ringbuffer_t *rb, size_t cnt) -{ - ATOMIC_ADD(&rb->read_ptr, cnt, almemory_order_acq_rel); -} - -/* Advance the write pointer `cnt' places. */ -void ll_ringbuffer_write_advance(ll_ringbuffer_t *rb, size_t cnt) -{ - ATOMIC_ADD(&rb->write_ptr, cnt, almemory_order_acq_rel); -} - -/* The non-copying data reader. `vec' is an array of two places. Set the values - * at `vec' to hold the current readable data at `rb'. If the readable data is - * in one segment the second segment has zero length. */ -void ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t * vec) -{ - size_t free_cnt; - size_t cnt2; - size_t w, r; - - w = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->write_ptr, almemory_order_acquire); - r = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->read_ptr, almemory_order_acquire); - w &= rb->size_mask; - r &= rb->size_mask; - free_cnt = (w-r) & rb->size_mask; - - cnt2 = r + free_cnt; - if(cnt2 > rb->size) - { - /* Two part vector: the rest of the buffer after the current write ptr, - * plus some from the start of the buffer. */ - vec[0].buf = (char*)&rb->buf[r*rb->elem_size]; - vec[0].len = rb->size - r; - vec[1].buf = (char*)rb->buf; - vec[1].len = cnt2 & rb->size_mask; - } - else - { - /* Single part vector: just the rest of the buffer */ - vec[0].buf = (char*)&rb->buf[r*rb->elem_size]; - vec[0].len = free_cnt; - vec[1].buf = NULL; - vec[1].len = 0; - } -} - -/* The non-copying data writer. `vec' is an array of two places. Set the values - * at `vec' to hold the current writeable data at `rb'. If the writeable data - * is in one segment the second segment has zero length. */ -void ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t *vec) -{ - size_t free_cnt; - size_t cnt2; - size_t w, r; - - w = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->write_ptr, almemory_order_acquire); - r = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->read_ptr, almemory_order_acquire); - w &= rb->size_mask; - r &= rb->size_mask; - free_cnt = (r-w-1) & rb->size_mask; - - cnt2 = w + free_cnt; - if(cnt2 > rb->size) - { - /* Two part vector: the rest of the buffer after the current write ptr, - * plus some from the start of the buffer. */ - vec[0].buf = (char*)&rb->buf[w*rb->elem_size]; - vec[0].len = rb->size - w; - vec[1].buf = (char*)rb->buf; - vec[1].len = cnt2 & rb->size_mask; - } - else - { - vec[0].buf = (char*)&rb->buf[w*rb->elem_size]; - vec[0].len = free_cnt; - vec[1].buf = NULL; - vec[1].len = 0; - } -} diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index f941ce4b..fb5a4446 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -27,6 +27,7 @@ #include "alMain.h" #include "alu.h" #include "alconfig.h" +#include "ringbuffer.h" #include "threads.h" #include "compat.h" diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index ec926d3d..ba73ab82 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -27,6 +27,7 @@ #include "alMain.h" #include "alu.h" +#include "ringbuffer.h" #include #include diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index f730dc95..f88a50c1 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -34,6 +34,7 @@ #include "alMain.h" #include "alu.h" +#include "ringbuffer.h" #include "threads.h" #include "compat.h" #include "alstring.h" diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index 4ef9006c..0dc01ae7 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -27,6 +27,7 @@ #include "alMain.h" #include "alu.h" #include "alconfig.h" +#include "ringbuffer.h" #include "threads.h" #include "compat.h" diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 9afb62f0..ecd7eb5d 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -41,6 +41,7 @@ #include "alMain.h" #include "alu.h" +#include "ringbuffer.h" #include "threads.h" #include "compat.h" #include "alstring.h" diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index aa1ff991..4ec003d8 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -26,8 +26,9 @@ #include "alMain.h" #include "alu.h" -#include "compat.h" +#include "ringbuffer.h" #include "threads.h" +#include "compat.h" #include "backends/base.h" diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 196432e1..2ff7c72b 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -36,6 +36,7 @@ #include "alMain.h" #include "alu.h" #include "alconfig.h" +#include "ringbuffer.h" #include "threads.h" #include "compat.h" diff --git a/Alc/backends/portaudio.c b/Alc/backends/portaudio.c index 0f4672c4..b793486f 100644 --- a/Alc/backends/portaudio.c +++ b/Alc/backends/portaudio.c @@ -27,6 +27,7 @@ #include "alMain.h" #include "alu.h" #include "alconfig.h" +#include "ringbuffer.h" #include "compat.h" #include "backends/base.h" diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index b5b3cdb6..4e4d0c06 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -29,6 +29,7 @@ #include "alMain.h" #include "alu.h" +#include "ringbuffer.h" #include "threads.h" #include "backends/base.h" diff --git a/Alc/ringbuffer.c b/Alc/ringbuffer.c new file mode 100644 index 00000000..63add593 --- /dev/null +++ b/Alc/ringbuffer.c @@ -0,0 +1,298 @@ +/** + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include +#include + +#include "ringbuffer.h" +#include "alMain.h" +#include "threads.h" +#include "almalloc.h" +#include "compat.h" + + +/* NOTE: This lockless ringbuffer implementation is copied from JACK, extended + * to include an element size. Consequently, parameters and return values for a + * size or count is in 'elements', not bytes. Additionally, it only supports + * single-consumer/single-provider operation. */ +struct ll_ringbuffer { + ATOMIC(size_t) write_ptr; + ATOMIC(size_t) read_ptr; + size_t size; + size_t size_mask; + size_t elem_size; + + alignas(16) char buf[]; +}; + +/* Create a new ringbuffer to hold at least `sz' elements of `elem_sz' bytes. + * The number of elements is rounded up to the next power of two. */ +ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz) +{ + ll_ringbuffer_t *rb; + size_t power_of_two; + + power_of_two = NextPowerOf2(sz); + if(power_of_two < sz) + return NULL; + + rb = al_malloc(16, sizeof(*rb) + power_of_two*elem_sz); + if(!rb) return NULL; + + ATOMIC_INIT(&rb->write_ptr, 0); + ATOMIC_INIT(&rb->read_ptr, 0); + rb->size = power_of_two; + rb->size_mask = rb->size - 1; + rb->elem_size = elem_sz; + return rb; +} + +/* Free all data associated with the ringbuffer `rb'. */ +void ll_ringbuffer_free(ll_ringbuffer_t *rb) +{ + al_free(rb); +} + +/* Reset the read and write pointers to zero. This is not thread safe. */ +void ll_ringbuffer_reset(ll_ringbuffer_t *rb) +{ + ATOMIC_STORE(&rb->write_ptr, 0, almemory_order_release); + ATOMIC_STORE(&rb->read_ptr, 0, almemory_order_release); + memset(rb->buf, 0, rb->size*rb->elem_size); +} + +/* Return the number of elements available for reading. This is the number of + * elements in front of the read pointer and behind the write pointer. */ +size_t ll_ringbuffer_read_space(const ll_ringbuffer_t *rb) +{ + size_t w = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->write_ptr, almemory_order_acquire); + size_t r = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->read_ptr, almemory_order_acquire); + return (w-r) & rb->size_mask; +} +/* Return the number of elements available for writing. This is the number of + * elements in front of the write pointer and behind the read pointer. */ +size_t ll_ringbuffer_write_space(const ll_ringbuffer_t *rb) +{ + size_t w = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->write_ptr, almemory_order_acquire); + size_t r = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->read_ptr, almemory_order_acquire); + return (r-w-1) & rb->size_mask; +} + +/* The copying data reader. Copy at most `cnt' elements from `rb' to `dest'. + * Returns the actual number of elements copied. */ +size_t ll_ringbuffer_read(ll_ringbuffer_t *rb, char *dest, size_t cnt) +{ + size_t read_ptr; + size_t free_cnt; + size_t cnt2; + size_t to_read; + size_t n1, n2; + + free_cnt = ll_ringbuffer_read_space(rb); + if(free_cnt == 0) return 0; + + to_read = (cnt > free_cnt) ? free_cnt : cnt; + read_ptr = ATOMIC_LOAD(&rb->read_ptr, almemory_order_relaxed) & rb->size_mask; + + cnt2 = read_ptr + to_read; + if(cnt2 > rb->size) + { + n1 = rb->size - read_ptr; + n2 = cnt2 & rb->size_mask; + } + else + { + n1 = to_read; + n2 = 0; + } + + memcpy(dest, &rb->buf[read_ptr*rb->elem_size], n1*rb->elem_size); + read_ptr += n1; + if(n2) + { + memcpy(dest + n1*rb->elem_size, &rb->buf[(read_ptr&rb->size_mask)*rb->elem_size], + n2*rb->elem_size); + read_ptr += n2; + } + ATOMIC_STORE(&rb->read_ptr, read_ptr, almemory_order_release); + return to_read; +} + +/* The copying data reader w/o read pointer advance. Copy at most `cnt' + * elements from `rb' to `dest'. Returns the actual number of elements copied. + */ +size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, char *dest, size_t cnt) +{ + size_t free_cnt; + size_t cnt2; + size_t to_read; + size_t n1, n2; + size_t read_ptr; + + free_cnt = ll_ringbuffer_read_space(rb); + if(free_cnt == 0) return 0; + + to_read = (cnt > free_cnt) ? free_cnt : cnt; + read_ptr = ATOMIC_LOAD(&rb->read_ptr, almemory_order_relaxed) & rb->size_mask; + + cnt2 = read_ptr + to_read; + if(cnt2 > rb->size) + { + n1 = rb->size - read_ptr; + n2 = cnt2 & rb->size_mask; + } + else + { + n1 = to_read; + n2 = 0; + } + + memcpy(dest, &rb->buf[read_ptr*rb->elem_size], n1*rb->elem_size); + if(n2) + { + read_ptr += n1; + memcpy(dest + n1*rb->elem_size, &rb->buf[(read_ptr&rb->size_mask)*rb->elem_size], + n2*rb->elem_size); + } + return to_read; +} + +/* The copying data writer. Copy at most `cnt' elements to `rb' from `src'. + * Returns the actual number of elements copied. */ +size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const char *src, size_t cnt) +{ + size_t write_ptr; + size_t free_cnt; + size_t cnt2; + size_t to_write; + size_t n1, n2; + + free_cnt = ll_ringbuffer_write_space(rb); + if(free_cnt == 0) return 0; + + to_write = (cnt > free_cnt) ? free_cnt : cnt; + write_ptr = ATOMIC_LOAD(&rb->write_ptr, almemory_order_relaxed) & rb->size_mask; + + cnt2 = write_ptr + to_write; + if(cnt2 > rb->size) + { + n1 = rb->size - write_ptr; + n2 = cnt2 & rb->size_mask; + } + else + { + n1 = to_write; + n2 = 0; + } + + memcpy(&rb->buf[write_ptr*rb->elem_size], src, n1*rb->elem_size); + write_ptr += n1; + if(n2) + { + memcpy(&rb->buf[(write_ptr&rb->size_mask)*rb->elem_size], src + n1*rb->elem_size, + n2*rb->elem_size); + write_ptr += n2; + } + ATOMIC_STORE(&rb->write_ptr, write_ptr, almemory_order_release); + return to_write; +} + +/* Advance the read pointer `cnt' places. */ +void ll_ringbuffer_read_advance(ll_ringbuffer_t *rb, size_t cnt) +{ + ATOMIC_ADD(&rb->read_ptr, cnt, almemory_order_acq_rel); +} + +/* Advance the write pointer `cnt' places. */ +void ll_ringbuffer_write_advance(ll_ringbuffer_t *rb, size_t cnt) +{ + ATOMIC_ADD(&rb->write_ptr, cnt, almemory_order_acq_rel); +} + +/* The non-copying data reader. `vec' is an array of two places. Set the values + * at `vec' to hold the current readable data at `rb'. If the readable data is + * in one segment the second segment has zero length. */ +void ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t * vec) +{ + size_t free_cnt; + size_t cnt2; + size_t w, r; + + w = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->write_ptr, almemory_order_acquire); + r = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->read_ptr, almemory_order_acquire); + w &= rb->size_mask; + r &= rb->size_mask; + free_cnt = (w-r) & rb->size_mask; + + cnt2 = r + free_cnt; + if(cnt2 > rb->size) + { + /* Two part vector: the rest of the buffer after the current write ptr, + * plus some from the start of the buffer. */ + vec[0].buf = (char*)&rb->buf[r*rb->elem_size]; + vec[0].len = rb->size - r; + vec[1].buf = (char*)rb->buf; + vec[1].len = cnt2 & rb->size_mask; + } + else + { + /* Single part vector: just the rest of the buffer */ + vec[0].buf = (char*)&rb->buf[r*rb->elem_size]; + vec[0].len = free_cnt; + vec[1].buf = NULL; + vec[1].len = 0; + } +} + +/* The non-copying data writer. `vec' is an array of two places. Set the values + * at `vec' to hold the current writeable data at `rb'. If the writeable data + * is in one segment the second segment has zero length. */ +void ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t *vec) +{ + size_t free_cnt; + size_t cnt2; + size_t w, r; + + w = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->write_ptr, almemory_order_acquire); + r = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->read_ptr, almemory_order_acquire); + w &= rb->size_mask; + r &= rb->size_mask; + free_cnt = (r-w-1) & rb->size_mask; + + cnt2 = w + free_cnt; + if(cnt2 > rb->size) + { + /* Two part vector: the rest of the buffer after the current write ptr, + * plus some from the start of the buffer. */ + vec[0].buf = (char*)&rb->buf[w*rb->elem_size]; + vec[0].len = rb->size - w; + vec[1].buf = (char*)rb->buf; + vec[1].len = cnt2 & rb->size_mask; + } + else + { + vec[0].buf = (char*)&rb->buf[w*rb->elem_size]; + vec[0].len = free_cnt; + vec[1].buf = NULL; + vec[1].len = 0; + } +} diff --git a/Alc/ringbuffer.h b/Alc/ringbuffer.h new file mode 100644 index 00000000..f764c20f --- /dev/null +++ b/Alc/ringbuffer.h @@ -0,0 +1,29 @@ +#ifndef RINGBUFFER_H +#define RINGBUFFER_H + +#include + + +typedef struct ll_ringbuffer ll_ringbuffer_t; +typedef struct ll_ringbuffer_data { + char *buf; + size_t len; +} ll_ringbuffer_data_t; + +ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz); +void ll_ringbuffer_free(ll_ringbuffer_t *rb); +void ll_ringbuffer_reset(ll_ringbuffer_t *rb); + +void ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t *vec); +void ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t *vec); + +size_t ll_ringbuffer_read(ll_ringbuffer_t *rb, char *dest, size_t cnt); +size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, char *dest, size_t cnt); +void ll_ringbuffer_read_advance(ll_ringbuffer_t *rb, size_t cnt); +size_t ll_ringbuffer_read_space(const ll_ringbuffer_t *rb); + +size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const char *src, size_t cnt); +void ll_ringbuffer_write_advance(ll_ringbuffer_t *rb, size_t cnt); +size_t ll_ringbuffer_write_space(const ll_ringbuffer_t *rb); + +#endif /* RINGBUFFER_H */ diff --git a/CMakeLists.txt b/CMakeLists.txt index 929b5517..0b07f4ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -714,10 +714,10 @@ SET(OPENAL_OBJS OpenAL32/alAuxEffectSlot.c SET(ALC_OBJS Alc/ALc.c Alc/ALu.c Alc/alconfig.c - Alc/alcRing.c Alc/bs2b.c Alc/converter.c Alc/mastering.c + Alc/ringbuffer.c Alc/effects/chorus.c Alc/effects/compressor.c Alc/effects/dedicated.c diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 5b4519eb..c11eb6d1 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -799,26 +799,6 @@ void ALCcontext_DeferUpdates(ALCcontext *context); void ALCcontext_ProcessUpdates(ALCcontext *context); -typedef struct ll_ringbuffer ll_ringbuffer_t; -typedef struct ll_ringbuffer_data { - char *buf; - size_t len; -} ll_ringbuffer_data_t; -ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz); -void ll_ringbuffer_free(ll_ringbuffer_t *rb); -void ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t *vec); -void ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t *vec); -size_t ll_ringbuffer_read(ll_ringbuffer_t *rb, char *dest, size_t cnt); -size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, char *dest, size_t cnt); -void ll_ringbuffer_read_advance(ll_ringbuffer_t *rb, size_t cnt); -size_t ll_ringbuffer_read_space(const ll_ringbuffer_t *rb); -int ll_ringbuffer_mlock(ll_ringbuffer_t *rb); -void ll_ringbuffer_reset(ll_ringbuffer_t *rb); -size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const char *src, size_t cnt); -void ll_ringbuffer_write_advance(ll_ringbuffer_t *rb, size_t cnt); -size_t ll_ringbuffer_write_space(const ll_ringbuffer_t *rb); - - void SetRTPriority(void); void SetDefaultChannelOrder(ALCdevice *device); -- cgit v1.2.3 From 2873abcbc056ca2123382b2b1e08b8bd94d608a4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 11 Jan 2018 10:55:35 -0800 Subject: Fix up some types for MSVC --- Alc/backends/dsound.c | 2 +- Alc/backends/winmm.c | 2 +- Alc/bformatdec.c | 8 ++++---- Alc/effects/chorus.c | 3 ++- Alc/hrtf.c | 3 ++- Alc/panning.c | 2 +- common/atomic.h | 3 ++- 7 files changed, 13 insertions(+), 10 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index f88a50c1..8a0a30cb 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -948,7 +948,7 @@ static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self) } done: - return ll_ringbuffer_read_space(self->Ring); + return (ALCuint)ll_ringbuffer_read_space(self->Ring); } diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index 4e4d0c06..0fcab458 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -708,7 +708,7 @@ static ALCenum ALCwinmmCapture_captureSamples(ALCwinmmCapture *self, ALCvoid *bu static ALCuint ALCwinmmCapture_availableSamples(ALCwinmmCapture *self) { - return ll_ringbuffer_read_space(self->Ring); + return (ALCuint)ll_ringbuffer_read_space(self->Ring); } diff --git a/Alc/bformatdec.c b/Alc/bformatdec.c index 3efdfba9..6503ac65 100644 --- a/Alc/bformatdec.c +++ b/Alc/bformatdec.c @@ -532,7 +532,7 @@ void ambiup_free(struct AmbiUpsampler *ambiup) void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device) { ALfloat ratio; - size_t i; + ALsizei i; ratio = 400.0f / (ALfloat)device->Frequency; for(i = 0;i < 4;i++) @@ -545,11 +545,11 @@ void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device) ALsizei j; size_t k; - for(i = 0;i < COUNTOF(Ambi3DPoints);i++) + for(k = 0;k < COUNTOF(Ambi3DPoints);k++) { ALfloat coeffs[MAX_AMBI_COEFFS] = { 0.0f }; - CalcDirectionCoeffs(Ambi3DPoints[i], 0.0f, coeffs); - ComputeDryPanGains(&device->Dry, coeffs, 1.0f, encgains[i]); + CalcDirectionCoeffs(Ambi3DPoints[k], 0.0f, coeffs); + ComputeDryPanGains(&device->Dry, coeffs, 1.0f, encgains[k]); } /* Combine the matrices that do the in->virt and virt->out conversions diff --git a/Alc/effects/chorus.c b/Alc/effects/chorus.c index 901c1157..2592c673 100644 --- a/Alc/effects/chorus.c +++ b/Alc/effects/chorus.c @@ -142,7 +142,8 @@ static ALvoid ALchorusState_update(ALchorusState *state, const ALCcontext *Conte */ state->delay = maxi(fastf2i(props->Chorus.Delay*frequency*FRACTIONONE + 0.5f), mindelay); - state->depth = minf(props->Chorus.Depth * state->delay, state->delay - mindelay); + state->depth = minf(props->Chorus.Depth * state->delay, + (ALfloat)(state->delay - mindelay)); state->feedback = props->Chorus.Feedback; diff --git a/Alc/hrtf.c b/Alc/hrtf.c index 9d5e2ca9..310dc68c 100644 --- a/Alc/hrtf.c +++ b/Alc/hrtf.c @@ -298,7 +298,8 @@ void BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsizei N } } /* Round up to the next IR size multiple. */ - max_length = RoundUp(max_length, MOD_IR_SIZE); + max_length += MOD_IR_SIZE-1; + max_length -= max_length%MOD_IR_SIZE; TRACE("Skipped min delay: %d, new combined length: %d\n", min_delay, max_length); state->IrSize = max_length; diff --git a/Alc/panning.c b/Alc/panning.c index dfb71918..1691aacd 100644 --- a/Alc/panning.c +++ b/Alc/panning.c @@ -512,7 +512,7 @@ static void InitDistanceComp(ALCdevice *device, const AmbDecConf *conf, const AL { const char *devname = alstr_get_cstr(device->DeviceName); ALfloat maxdist = 0.0f; - ALsizei total = 0; + size_t total = 0; ALsizei i; for(i = 0;i < conf->NumSpeakers;i++) diff --git a/common/atomic.h b/common/atomic.h index 2033476b..64b06cce 100644 --- a/common/atomic.h +++ b/common/atomic.h @@ -306,6 +306,7 @@ enum almemory_order { } while(0) int _al_invalid_atomic_size(); /* not defined */ +void *_al_invalid_atomic_ptr_size(); /* not defined */ #define ATOMIC_ADD(_val, _incr, _MO) \ ((sizeof((_val)->value)==4) ? WRAP_ADDSUB(LONG, AtomicAdd32, &(_val)->value, (_incr)) : \ @@ -327,7 +328,7 @@ int _al_invalid_atomic_size(); /* not defined */ #define ATOMIC_EXCHANGE_PTR(_val, _newval, _MO) \ ((sizeof((_val)->value)==sizeof(void*)) ? AtomicSwapPtr((void*volatile*)&(_val)->value, (_newval)) : \ - (void*)_al_invalid_atomic_size()) + _al_invalid_atomic_ptr_size()) #define ATOMIC_COMPARE_EXCHANGE_PTR_STRONG(_val, _oldval, _newval, _MO1, _MO2)\ ((sizeof((_val)->value)==sizeof(void*)) ? CompareAndSwapPtr((void*volatile*)&(_val)->value, (_newval), (void**)(_oldval)) : \ (bool)_al_invalid_atomic_size()) -- cgit v1.2.3 From 1f236d8f204c66a5c0a1885b6893d6cb8b0c289d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 11 Jan 2018 22:42:25 -0800 Subject: Define a function where it's used --- Alc/backends/mmdevapi.c | 7 +++++++ Alc/helpers.c | 3 --- OpenAL32/Include/alMain.h | 18 ------------------ 3 files changed, 7 insertions(+), 21 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index ecd7eb5d..9604d0f9 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -71,6 +71,13 @@ DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x #define DEVNAME_HEAD "OpenAL Soft on " +/* Scales the given value using 64-bit integer math, ceiling the result. */ +static inline ALuint64 ScaleCeil(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale) +{ + return (val*new_scale + old_scale-1) / old_scale; +} + + typedef struct { al_string name; al_string endpoint_guid; // obtained from PKEY_AudioEndpoint_GUID , set to "Unknown device GUID" if absent. diff --git a/Alc/helpers.c b/Alc/helpers.c index 238569d6..5d39f3d8 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -120,9 +120,6 @@ DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x extern inline ALuint NextPowerOf2(ALuint value); extern inline size_t RoundUp(size_t value, size_t r); -extern inline ALuint64 ScaleRound(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale); -extern inline ALuint64 ScaleFloor(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale); -extern inline ALuint64 ScaleCeil(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale); extern inline ALint fastf2i(ALfloat f); diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 7706d598..76624a66 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -306,24 +306,6 @@ inline size_t RoundUp(size_t value, size_t r) return value - (value%r); } -/* Scales the given value using 64-bit integer math, rounding the result. */ -inline ALuint64 ScaleRound(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale) -{ - return (val*new_scale + old_scale/2) / old_scale; -} - -/* Scales the given value using 64-bit integer math, flooring the result. */ -inline ALuint64 ScaleFloor(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale) -{ - return val * new_scale / old_scale; -} - -/* Scales the given value using 64-bit integer math, ceiling the result. */ -inline ALuint64 ScaleCeil(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale) -{ - return (val*new_scale + old_scale-1) / old_scale; -} - /* Fast float-to-int conversion. Assumes the FPU is already in round-to-zero * mode. */ inline ALint fastf2i(ALfloat f) -- cgit v1.2.3 From dae5faedb05c3a889a0bb1f957e610c8af85a155 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 11 Jan 2018 23:28:15 -0800 Subject: Use atomic variables in place of volatile --- Alc/backends/mmdevapi.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 9604d0f9..670d1561 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -533,9 +533,9 @@ typedef struct ALCmmdevPlayback { HANDLE MsgEvent; - volatile UINT32 Padding; + ATOMIC(UINT32) Padding; - volatile int killNow; + ATOMIC(int) killNow; althrd_t thread; } ALCmmdevPlayback; @@ -580,9 +580,9 @@ static void ALCmmdevPlayback_Construct(ALCmmdevPlayback *self, ALCdevice *device self->MsgEvent = NULL; - self->Padding = 0; + ATOMIC_INIT(&self->Padding, 0); - self->killNow = 0; + ATOMIC_INIT(&self->killNow, 0); } static void ALCmmdevPlayback_Destruct(ALCmmdevPlayback *self) @@ -626,7 +626,7 @@ FORCE_ALIGN static int ALCmmdevPlayback_mixerProc(void *arg) update_size = device->UpdateSize; buffer_len = update_size * device->NumUpdates; - while(!self->killNow) + while(!ATOMIC_LOAD(&self->killNow, almemory_order_relaxed)) { hr = IAudioClient_GetCurrentPadding(self->client, &written); if(FAILED(hr)) @@ -637,7 +637,7 @@ FORCE_ALIGN static int ALCmmdevPlayback_mixerProc(void *arg) V0(device->Backend,unlock)(); break; } - self->Padding = written; + ATOMIC_STORE(&self->Padding, written, almemory_order_relaxed); len = buffer_len - written; if(len < update_size) @@ -655,7 +655,7 @@ FORCE_ALIGN static int ALCmmdevPlayback_mixerProc(void *arg) { ALCmmdevPlayback_lock(self); aluMixData(device, buffer, len); - self->Padding = written + len; + ATOMIC_STORE(&self->Padding, written + len, almemory_order_relaxed); ALCmmdevPlayback_unlock(self); hr = IAudioRenderClient_ReleaseBuffer(self->render, len, 0); } @@ -668,7 +668,7 @@ FORCE_ALIGN static int ALCmmdevPlayback_mixerProc(void *arg) break; } } - self->Padding = 0; + ATOMIC_STORE(&self->Padding, 0, almemory_order_release); CoUninitialize(); return 0; @@ -1162,7 +1162,7 @@ static HRESULT ALCmmdevPlayback_startProxy(ALCmmdevPlayback *self) if(SUCCEEDED(hr)) { self->render = ptr; - self->killNow = 0; + ATOMIC_STORE(&self->killNow, 0, almemory_order_release); if(althrd_create(&self->thread, ALCmmdevPlayback_mixerProc, self) != althrd_success) { if(self->render) @@ -1192,7 +1192,7 @@ static void ALCmmdevPlayback_stopProxy(ALCmmdevPlayback *self) if(!self->render) return; - self->killNow = 1; + ATOMIC_STORE_SEQ(&self->killNow, 1); althrd_join(self->thread, &res); IAudioRenderClient_Release(self->render); @@ -1208,7 +1208,8 @@ static ClockLatency ALCmmdevPlayback_getClockLatency(ALCmmdevPlayback *self) ALCmmdevPlayback_lock(self); ret.ClockTime = GetDeviceClockTime(device); - ret.Latency = self->Padding * DEVICE_CLOCK_RES / device->Frequency; + ret.Latency = ATOMIC_LOAD(&self->Padding, almemory_order_relaxed) * DEVICE_CLOCK_RES / + device->Frequency; ALCmmdevPlayback_unlock(self); return ret; @@ -1232,7 +1233,7 @@ typedef struct ALCmmdevCapture { SampleConverter *SampleConv; ll_ringbuffer_t *Ring; - volatile int killNow; + ATOMIC(int) killNow; althrd_t thread; } ALCmmdevCapture; @@ -1281,7 +1282,7 @@ static void ALCmmdevCapture_Construct(ALCmmdevCapture *self, ALCdevice *device) self->SampleConv = NULL; self->Ring = NULL; - self->killNow = 0; + ATOMIC_INIT(&self->killNow, 0); } static void ALCmmdevCapture_Destruct(ALCmmdevCapture *self) @@ -1327,7 +1328,7 @@ FORCE_ALIGN int ALCmmdevCapture_recordProc(void *arg) althrd_setname(althrd_current(), RECORD_THREAD_NAME); - while(!self->killNow) + while(!ATOMIC_LOAD(&self->killNow, almemory_order_relaxed)) { UINT32 avail; DWORD res; @@ -1875,7 +1876,7 @@ static HRESULT ALCmmdevCapture_startProxy(ALCmmdevCapture *self) if(SUCCEEDED(hr)) { self->capture = ptr; - self->killNow = 0; + ATOMIC_STORE(&self->killNow, 0, almemory_order_release); if(althrd_create(&self->thread, ALCmmdevCapture_recordProc, self) != althrd_success) { ERR("Failed to start thread\n"); @@ -1909,7 +1910,7 @@ static void ALCmmdevCapture_stopProxy(ALCmmdevCapture *self) if(!self->capture) return; - self->killNow = 1; + ATOMIC_STORE_SEQ(&self->killNow, 1); althrd_join(self->thread, &res); IAudioCaptureClient_Release(self->capture); -- cgit v1.2.3 From e634564b26091fc315fdc592f4f87fdff86be729 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 12 Jan 2018 02:37:48 -0800 Subject: Make a couple functions inline --- Alc/ALc.c | 17 +++-------------- Alc/backends/base.c | 2 ++ Alc/backends/base.h | 7 +++++++ OpenAL32/Include/alMain.h | 10 +++------- 4 files changed, 15 insertions(+), 21 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index 00d75f8c..e70e83dd 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -1494,17 +1494,6 @@ static ALCboolean IsValidAmbiScaling(ALCenum scaling) * Miscellaneous ALC helpers ************************************************/ -void ALCdevice_Lock(ALCdevice *device) -{ - V0(device->Backend,lock)(); -} - -void ALCdevice_Unlock(ALCdevice *device) -{ - V0(device->Backend,unlock)(); -} - - /* SetDefaultWFXChannelOrder * * Sets the default channel order used by WaveFormatEx. @@ -2732,7 +2721,7 @@ static bool ReleaseContext(ALCcontext *context, ALCdevice *device) if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext, &origctx, NULL)) ALCcontext_DecRef(context); - ALCdevice_Lock(device); + V0(device->Backend,lock)(); origctx = context; newhead = context->next; if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device->ContextList, &origctx, newhead)) @@ -2750,13 +2739,13 @@ static bool ReleaseContext(ALCcontext *context, ALCdevice *device) } else ret = !!newhead; - ALCdevice_Unlock(device); + V0(device->Backend,unlock)(); ALCcontext_DecRef(context); return ret; } -void ALCcontext_IncRef(ALCcontext *context) +static void ALCcontext_IncRef(ALCcontext *context) { uint ref = IncrementRef(&context->ref); TRACEREF("%p increasing refcount to %u\n", context, ref); diff --git a/Alc/backends/base.c b/Alc/backends/base.c index 5f568d8e..a451fee9 100644 --- a/Alc/backends/base.c +++ b/Alc/backends/base.c @@ -10,6 +10,8 @@ extern inline ALuint64 GetDeviceClockTime(ALCdevice *device); +extern inline void ALCdevice_Lock(ALCdevice *device); +extern inline void ALCdevice_Unlock(ALCdevice *device); /* Base ALCbackend method implementations. */ void ALCbackend_Construct(ALCbackend *self, ALCdevice *device) diff --git a/Alc/backends/base.h b/Alc/backends/base.h index 8464fdee..318e86fc 100644 --- a/Alc/backends/base.h +++ b/Alc/backends/base.h @@ -152,4 +152,11 @@ ALCbackendFactory *ALCnullBackendFactory_getFactory(void); ALCbackendFactory *ALCwaveBackendFactory_getFactory(void); ALCbackendFactory *ALCloopbackFactory_getFactory(void); + +inline void ALCdevice_Lock(ALCdevice *device) +{ V0(device->Backend,lock)(); } + +inline void ALCdevice_Unlock(ALCdevice *device) +{ V0(device->Backend,unlock)(); } + #endif /* AL_BACKENDS_BASE_H */ diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 76624a66..2fe7f71f 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -738,20 +738,16 @@ struct ALCcontext_struct { ALCcontext *GetContextRef(void); -void ALCcontext_IncRef(ALCcontext *context); void ALCcontext_DecRef(ALCcontext *context); +void ALCcontext_DeferUpdates(ALCcontext *context); +void ALCcontext_ProcessUpdates(ALCcontext *context); + void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends); void AppendAllDevicesList(const ALCchar *name); void AppendCaptureDeviceList(const ALCchar *name); -void ALCdevice_Lock(ALCdevice *device); -void ALCdevice_Unlock(ALCdevice *device); - -void ALCcontext_DeferUpdates(ALCcontext *context); -void ALCcontext_ProcessUpdates(ALCcontext *context); - extern ALint RTPrioLevel; void SetRTPriority(void); -- cgit v1.2.3 From bbc4ebecabc9417f92fbc9a185edf7360f1a8b6e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 13 Jan 2018 03:41:56 -0800 Subject: Use GetProcBinary to get the executable name for PulseAudio --- Alc/backends/pulseaudio.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index 9f3c4762..3208bf26 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -334,18 +334,20 @@ static void wait_for_operation(pa_operation *op, pa_threaded_mainloop *loop) static pa_context *connect_context(pa_threaded_mainloop *loop, ALboolean silent) { const char *name = "OpenAL Soft"; - char path_name[PATH_MAX]; + al_string binname = AL_STRING_INIT_STATIC(); 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); + GetProcBinary(NULL, &binname); + if(!alstr_empty(binname)) + name = alstr_get_cstr(binname); context = pa_context_new(pa_threaded_mainloop_get_api(loop), name); if(!context) { ERR("pa_context_new() failed\n"); + alstr_reset(&binname); return NULL; } @@ -372,9 +374,10 @@ static pa_context *connect_context(pa_threaded_mainloop *loop, ALboolean silent) if(!silent) ERR("Context did not connect: %s\n", pa_strerror(err)); pa_context_unref(context); - return NULL; + context = NULL; } + alstr_reset(&binname); return context; } -- cgit v1.2.3 From 8c19497340951aceb88d4f91038cafece6f00d7c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 16 Jan 2018 09:40:34 -0800 Subject: Properly cast some parameters for MSVC --- Alc/backends/mmdevapi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 670d1561..55d8ec54 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -1374,7 +1374,7 @@ FORCE_ALIGN int ALCmmdevCapture_recordProc(void *arg) ALsizei srcframes = numsamples; dstframes = SampleConverterInput(self->SampleConv, - &srcdata, &srcframes, data[0].buf, data[0].len + &srcdata, &srcframes, data[0].buf, (ALsizei)minz(data[0].len, INT_MAX) ); if(srcframes > 0 && dstframes == data[0].len && data[1].len > 0) { @@ -1383,16 +1383,16 @@ FORCE_ALIGN int ALCmmdevCapture_recordProc(void *arg) * dest block, do another run for the second block. */ dstframes += SampleConverterInput(self->SampleConv, - &srcdata, &srcframes, data[1].buf, data[1].len + &srcdata, &srcframes, data[1].buf, (ALsizei)minz(data[1].len, INT_MAX) ); } } else { - size_t framesize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, + ALuint framesize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); - ALuint len1 = minu(data[0].len, numsamples); - ALuint len2 = minu(data[1].len, numsamples-len1); + size_t len1 = minz(data[0].len, numsamples); + size_t len2 = minz(data[1].len, numsamples-len1); memcpy(data[0].buf, rdata, len1*framesize); if(len2 > 0) -- cgit v1.2.3 From 273dca2fa0fc4b009735010fd42c2c53649f872c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 16 Jan 2018 12:54:20 -0800 Subject: Avoid using alloca in the CoreAudio backend --- Alc/backends/coreaudio.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index ba73ab82..2ee3fa54 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -23,7 +23,6 @@ #include #include #include -#include #include "alMain.h" #include "alu.h" @@ -725,27 +724,26 @@ static void ALCcoreAudioCapture_stop(ALCcoreAudioCapture *self) static ALCenum ALCcoreAudioCapture_captureSamples(ALCcoreAudioCapture *self, ALCvoid *buffer, ALCuint samples) { - AudioBufferList *list; + union { + ALbyte _[sizeof(AudioBufferList) + sizeof(AudioBuffer)]; + AudioBufferList list; + } audiobuf = { { 0 } }; UInt32 frameCount; OSStatus err; // If no samples are requested, just return - if(samples == 0) - return ALC_NO_ERROR; - - // Allocate a temporary AudioBufferList to use as the return resamples data - list = alloca(sizeof(AudioBufferList) + sizeof(AudioBuffer)); + if(samples == 0) return ALC_NO_ERROR; // Point the resampling buffer to the capture buffer - list->mNumberBuffers = 1; - list->mBuffers[0].mNumberChannels = self->format.mChannelsPerFrame; - list->mBuffers[0].mDataByteSize = samples * self->frameSize; - list->mBuffers[0].mData = buffer; + audiobuf.list.mNumberBuffers = 1; + audiobuf.list.mBuffers[0].mNumberChannels = self->format.mChannelsPerFrame; + audiobuf.list.mBuffers[0].mDataByteSize = samples * self->frameSize; + audiobuf.list.mBuffers[0].mData = buffer; // Resample into another AudioBufferList frameCount = samples; err = AudioConverterFillComplexBuffer(self->audioConverter, - ALCcoreAudioCapture_ConvertCallback, self, &frameCount, list, NULL + ALCcoreAudioCapture_ConvertCallback, self, &frameCount, &audiobuf.list, NULL ); if(err != noErr) { -- cgit v1.2.3 From a042dbf30524429b49adb63efda35f53054ae924 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 28 Jan 2018 23:32:28 -0800 Subject: Call the backend close method in the destructor --- Alc/backends/alsa.c | 20 ++++++++++++++++++-- Alc/backends/coreaudio.c | 1 + Alc/backends/dsound.c | 25 ++++++++++++++++++++----- Alc/backends/mmdevapi.c | 10 ++++++++++ Alc/backends/opensl.c | 35 ++++++----------------------------- Alc/backends/oss.c | 22 ++++++++++++++++++---- Alc/backends/portaudio.c | 18 ++++-------------- Alc/backends/pulseaudio.c | 28 ++++++++++++++++------------ Alc/backends/qsa.c | 22 ++++++++++++++++++---- Alc/backends/sndio.c | 7 +++---- Alc/backends/solaris.c | 7 +++---- Alc/backends/wave.c | 7 ++++++- Alc/backends/winmm.c | 2 ++ 13 files changed, 125 insertions(+), 79 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index fb5a4446..27d36560 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -446,7 +446,7 @@ static int ALCplaybackAlsa_mixerProc(void *ptr); static int ALCplaybackAlsa_mixerNoMMapProc(void *ptr); static void ALCplaybackAlsa_Construct(ALCplaybackAlsa *self, ALCdevice *device); -static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, void, Destruct) +static void ALCplaybackAlsa_Destruct(ALCplaybackAlsa *self); static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name); static void ALCplaybackAlsa_close(ALCplaybackAlsa *self); static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self); @@ -468,6 +468,12 @@ static void ALCplaybackAlsa_Construct(ALCplaybackAlsa *self, ALCdevice *device) SET_VTABLE2(ALCplaybackAlsa, ALCbackend, self); } +void ALCplaybackAlsa_Destruct(ALCplaybackAlsa *self) +{ + ALCplaybackAlsa_close(self); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + static int ALCplaybackAlsa_mixerProc(void *ptr) { @@ -705,6 +711,7 @@ static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name) static void ALCplaybackAlsa_close(ALCplaybackAlsa *self) { snd_pcm_close(self->pcmHandle); + self->pcmHandle = NULL; } static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self) @@ -973,7 +980,7 @@ typedef struct ALCcaptureAlsa { } ALCcaptureAlsa; static void ALCcaptureAlsa_Construct(ALCcaptureAlsa *self, ALCdevice *device); -static DECLARE_FORWARD(ALCcaptureAlsa, ALCbackend, void, Destruct) +static void ALCcaptureAlsa_Destruct(ALCcaptureAlsa *self); static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name); static void ALCcaptureAlsa_close(ALCcaptureAlsa *self); static DECLARE_FORWARD(ALCcaptureAlsa, ALCbackend, ALCboolean, reset) @@ -995,6 +1002,12 @@ static void ALCcaptureAlsa_Construct(ALCcaptureAlsa *self, ALCdevice *device) SET_VTABLE2(ALCcaptureAlsa, ALCbackend, self); } +void ALCcaptureAlsa_Destruct(ALCcaptureAlsa *self) +{ + ALCcaptureAlsa_close(self); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name) { @@ -1129,7 +1142,10 @@ error2: static void ALCcaptureAlsa_close(ALCcaptureAlsa *self) { snd_pcm_close(self->pcmHandle); + self->pcmHandle = NULL; + ll_ringbuffer_free(self->ring); + self->ring = NULL; al_free(self->buffer); self->buffer = NULL; diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index 2ee3fa54..bdd9b678 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -123,6 +123,7 @@ static void ALCcoreAudioPlayback_Construct(ALCcoreAudioPlayback *self, ALCdevice static void ALCcoreAudioPlayback_Destruct(ALCcoreAudioPlayback *self) { + ALCcoreAudioPlayback_close(self); ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index 8a0a30cb..7760e39d 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -192,7 +192,7 @@ typedef struct ALCdsoundPlayback { static int ALCdsoundPlayback_mixerProc(void *ptr); static void ALCdsoundPlayback_Construct(ALCdsoundPlayback *self, ALCdevice *device); -static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, void, Destruct) +static void ALCdsoundPlayback_Destruct(ALCdsoundPlayback *self); static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *name); static void ALCdsoundPlayback_close(ALCdsoundPlayback *self); static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self); @@ -214,6 +214,12 @@ static void ALCdsoundPlayback_Construct(ALCdsoundPlayback *self, ALCdevice *devi SET_VTABLE2(ALCdsoundPlayback, ALCbackend, self); } +static void ALCdsoundPlayback_Destruct(ALCdsoundPlayback *self) +{ + ALCdsoundPlayback_close(self); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr) { @@ -399,9 +405,11 @@ static void ALCdsoundPlayback_close(ALCdsoundPlayback *self) IDirectSoundBuffer_Release(self->PrimaryBuffer); self->PrimaryBuffer = NULL; - IDirectSound_Release(self->DS); + if(self->DS) + IDirectSound_Release(self->DS); self->DS = NULL; - CloseHandle(self->NotifyEvent); + if(self->NotifyEvent) + CloseHandle(self->NotifyEvent); self->NotifyEvent = NULL; } @@ -661,7 +669,7 @@ typedef struct ALCdsoundCapture { } ALCdsoundCapture; static void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device); -static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, void, Destruct) +static void ALCdsoundCapture_Destruct(ALCdsoundCapture *self); static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *name); static void ALCdsoundCapture_close(ALCdsoundCapture *self); static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, ALCboolean, reset) @@ -682,6 +690,12 @@ static void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device SET_VTABLE2(ALCdsoundCapture, ALCbackend, self); } +static void ALCdsoundCapture_Destruct(ALCdsoundCapture *self) +{ + ALCdsoundCapture_close(self); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *deviceName) { @@ -867,7 +881,8 @@ static void ALCdsoundCapture_close(ALCdsoundCapture *self) self->DSCbuffer = NULL; } - IDirectSoundCapture_Release(self->DSC); + if(self->DSC) + IDirectSoundCapture_Release(self->DSC); self->DSC = NULL; } diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 55d8ec54..899f73d4 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -587,6 +587,8 @@ static void ALCmmdevPlayback_Construct(ALCmmdevPlayback *self, ALCdevice *device static void ALCmmdevPlayback_Destruct(ALCmmdevPlayback *self) { + ALCmmdevPlayback_close(self); + if(self->NotifyEvent != NULL) CloseHandle(self->NotifyEvent); self->NotifyEvent = NULL; @@ -840,6 +842,9 @@ static void ALCmmdevPlayback_close(ALCmmdevPlayback *self) { ThreadRequest req = { self->MsgEvent, 0 }; + if(!req.FinishedEvt) + return; + if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) (void)WaitForResponse(&req); @@ -1287,6 +1292,8 @@ static void ALCmmdevCapture_Construct(ALCmmdevCapture *self, ALCdevice *device) static void ALCmmdevCapture_Destruct(ALCmmdevCapture *self) { + ALCmmdevCapture_close(self); + ll_ringbuffer_free(self->Ring); self->Ring = NULL; @@ -1573,6 +1580,9 @@ static void ALCmmdevCapture_close(ALCmmdevCapture *self) { ThreadRequest req = { self->MsgEvent, 0 }; + if(!req.FinishedEvt) + return; + if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) (void)WaitForResponse(&req); diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 4ec003d8..c1283111 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -194,21 +194,7 @@ static void ALCopenslPlayback_Construct(ALCopenslPlayback *self, ALCdevice *devi static void ALCopenslPlayback_Destruct(ALCopenslPlayback* self) { - if(self->mBufferQueueObj != NULL) - VCALL0(self->mBufferQueueObj,Destroy)(); - self->mBufferQueueObj = NULL; - - if(self->mOutputMix != NULL) - VCALL0(self->mOutputMix,Destroy)(); - self->mOutputMix = NULL; - - if(self->mEngineObj != NULL) - VCALL0(self->mEngineObj,Destroy)(); - self->mEngineObj = NULL; - self->mEngine = NULL; - - ll_ringbuffer_free(self->mRing); - self->mRing = NULL; + ALCopenslPlayback_close(self); alcnd_destroy(&self->mCond); @@ -409,10 +395,12 @@ static void ALCopenslPlayback_close(ALCopenslPlayback *self) VCALL0(self->mBufferQueueObj,Destroy)(); self->mBufferQueueObj = NULL; - VCALL0(self->mOutputMix,Destroy)(); + if(self->mOutputMix) + VCALL0(self->mOutputMix,Destroy)(); self->mOutputMix = NULL; - VCALL0(self->mEngineObj,Destroy)(); + if(self->mEngineObj) + VCALL0(self->mEngineObj,Destroy)(); self->mEngineObj = NULL; self->mEngine = NULL; } @@ -761,18 +749,7 @@ static void ALCopenslCapture_Construct(ALCopenslCapture *self, ALCdevice *device static void ALCopenslCapture_Destruct(ALCopenslCapture *self) { - ll_ringbuffer_free(self->mRing); - self->mRing = NULL; - - if(self->mRecordObj != NULL) - VCALL0(self->mRecordObj,Destroy)(); - self->mRecordObj = NULL; - - if(self->mEngineObj != NULL) - VCALL0(self->mEngineObj,Destroy)(); - self->mEngineObj = NULL; - self->mEngine = NULL; - + ALCopenslCapture_close(self); ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 2ff7c72b..e88e5ff3 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -252,7 +252,7 @@ typedef struct ALCplaybackOSS { static int ALCplaybackOSS_mixerProc(void *ptr); static void ALCplaybackOSS_Construct(ALCplaybackOSS *self, ALCdevice *device); -static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, void, Destruct) +static void ALCplaybackOSS_Destruct(ALCplaybackOSS *self); static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name); static void ALCplaybackOSS_close(ALCplaybackOSS *self); static ALCboolean ALCplaybackOSS_reset(ALCplaybackOSS *self); @@ -342,6 +342,12 @@ static void ALCplaybackOSS_Construct(ALCplaybackOSS *self, ALCdevice *device) ATOMIC_INIT(&self->killNow, AL_FALSE); } +static void ALCplaybackOSS_Destruct(ALCplaybackOSS *self) +{ + ALCplaybackOSS_close(self); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name) { struct oss_device *dev = &oss_playback; @@ -383,7 +389,8 @@ static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name) static void ALCplaybackOSS_close(ALCplaybackOSS *self) { - close(self->fd); + if(self->fd != -1) + close(self->fd); self->fd = -1; } @@ -519,7 +526,7 @@ typedef struct ALCcaptureOSS { static int ALCcaptureOSS_recordProc(void *ptr); static void ALCcaptureOSS_Construct(ALCcaptureOSS *self, ALCdevice *device); -static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, void, Destruct) +static void ALCcaptureOSS_Destruct(ALCcaptureOSS *self); static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name); static void ALCcaptureOSS_close(ALCcaptureOSS *self); static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, ALCboolean, reset) @@ -601,6 +608,12 @@ static void ALCcaptureOSS_Construct(ALCcaptureOSS *self, ALCdevice *device) ATOMIC_INIT(&self->killNow, AL_FALSE); } +static void ALCcaptureOSS_Destruct(ALCcaptureOSS *self) +{ + ALCcaptureOSS_close(self); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; @@ -728,7 +741,8 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) static void ALCcaptureOSS_close(ALCcaptureOSS *self) { - close(self->fd); + if(self->fd != -1) + close(self->fd); self->fd = -1; ll_ringbuffer_free(self->ring); diff --git a/Alc/backends/portaudio.c b/Alc/backends/portaudio.c index b793486f..58cf9762 100644 --- a/Alc/backends/portaudio.c +++ b/Alc/backends/portaudio.c @@ -165,10 +165,7 @@ static void ALCportPlayback_Construct(ALCportPlayback *self, ALCdevice *device) static void ALCportPlayback_Destruct(ALCportPlayback *self) { - if(self->stream) - Pa_CloseStream(self->stream); - self->stream = NULL; - + ALCportPlayback_close(self); ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -255,7 +252,7 @@ retry_open: static void ALCportPlayback_close(ALCportPlayback *self) { - PaError err = Pa_CloseStream(self->stream); + PaError err = self->stream ? Pa_CloseStream(self->stream) : paNoError; if(err != paNoError) ERR("Error closing stream: %s\n", Pa_GetErrorText(err)); self->stream = NULL; @@ -362,14 +359,7 @@ static void ALCportCapture_Construct(ALCportCapture *self, ALCdevice *device) static void ALCportCapture_Destruct(ALCportCapture *self) { - if(self->stream) - Pa_CloseStream(self->stream); - self->stream = NULL; - - if(self->ring) - ll_ringbuffer_free(self->ring); - self->ring = NULL; - + ALCportCapture_close(self); ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -454,7 +444,7 @@ static ALCenum ALCportCapture_open(ALCportCapture *self, const ALCchar *name) static void ALCportCapture_close(ALCportCapture *self) { - PaError err = Pa_CloseStream(self->stream); + PaError err = self->stream ? Pa_CloseStream(self->stream) : paNoError; if(err != paNoError) ERR("Error closing stream: %s\n", Pa_GetErrorText(err)); self->stream = NULL; diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index 3208bf26..581f4c38 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -519,6 +519,7 @@ static void ALCpulsePlayback_Construct(ALCpulsePlayback *self, ALCdevice *device static void ALCpulsePlayback_Destruct(ALCpulsePlayback *self) { + ALCpulsePlayback_close(self); AL_STRING_DEINIT(self->device_name); ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -958,12 +959,13 @@ static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name static void ALCpulsePlayback_close(ALCpulsePlayback *self) { - pulse_close(self->loop, self->context, self->stream); - self->loop = NULL; - self->context = NULL; - self->stream = NULL; - - alstr_clear(&self->device_name); + if(self->loop) + { + pulse_close(self->loop, self->context, self->stream); + self->loop = NULL; + self->context = NULL; + self->stream = NULL; + } } static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) @@ -1273,6 +1275,7 @@ static void ALCpulseCapture_Construct(ALCpulseCapture *self, ALCdevice *device) static void ALCpulseCapture_Destruct(ALCpulseCapture *self) { + ALCpulseCapture_close(self); AL_STRING_DEINIT(self->device_name); ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -1621,12 +1624,13 @@ fail: static void ALCpulseCapture_close(ALCpulseCapture *self) { - pulse_close(self->loop, self->context, self->stream); - self->loop = NULL; - self->context = NULL; - self->stream = NULL; - - alstr_clear(&self->device_name); + if(self->loop) + { + pulse_close(self->loop, self->context, self->stream); + self->loop = NULL; + self->context = NULL; + self->stream = NULL; + } } static ALCboolean ALCpulseCapture_start(ALCpulseCapture *self) diff --git a/Alc/backends/qsa.c b/Alc/backends/qsa.c index 58193c96..e1bbf2c2 100644 --- a/Alc/backends/qsa.c +++ b/Alc/backends/qsa.c @@ -166,7 +166,7 @@ typedef struct PlaybackWrapper { } PlaybackWrapper; static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device); -static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, Destruct) +static void PlaybackWrapper_Destruct(PlaybackWrapper *self); static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name); static void PlaybackWrapper_close(PlaybackWrapper *self); static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self); @@ -624,6 +624,12 @@ static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device) self->ExtraData = NULL; } +static void PlaybackWrapper_Destruct(PlaybackWrapper *self) +{ + PlaybackWrapper_close(self); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name) { return qsa_open_playback(self, name); @@ -631,7 +637,8 @@ static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name) static void PlaybackWrapper_close(PlaybackWrapper *self) { - qsa_close_playback(self); + if(self->ExtraData) + qsa_close_playback(self); } static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self) @@ -661,7 +668,7 @@ typedef struct CaptureWrapper { } CaptureWrapper; static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device); -static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, Destruct) +static void CaptureWrapper_Destruct(CaptureWrapper *self); static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name); static void CaptureWrapper_close(CaptureWrapper *self); static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ALCboolean, reset) @@ -945,6 +952,12 @@ static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device) self->ExtraData = NULL; } +static void CaptureWrapper_Destruct(CaptureWrapper *self) +{ + CaptureWrapper_close(self); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name) { return qsa_open_capture(self, name); @@ -952,7 +965,8 @@ static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name) static void CaptureWrapper_close(CaptureWrapper *self) { - qsa_close_capture(self); + if(self->ExtraData) + qsa_close_capture(self); } static ALCboolean CaptureWrapper_start(CaptureWrapper *self) diff --git a/Alc/backends/sndio.c b/Alc/backends/sndio.c index 47e05353..436baf26 100644 --- a/Alc/backends/sndio.c +++ b/Alc/backends/sndio.c @@ -77,9 +77,7 @@ static void ALCsndioBackend_Construct(ALCsndioBackend *self, ALCdevice *device) static void ALCsndioBackend_Destruct(ALCsndioBackend *self) { - if(self->sndHandle) - sio_close(self->sndHandle); - self->sndHandle = NULL; + ALCsndioBackend_close(self); al_free(self->mix_data); self->mix_data = NULL; @@ -152,7 +150,8 @@ static ALCenum ALCsndioBackend_open(ALCsndioBackend *self, const ALCchar *name) static void ALCsndioBackend_close(ALCsndioBackend *self) { - sio_close(self->sndHandle); + if(self->sndHandle) + sio_close(self->sndHandle); self->sndHandle = NULL; } diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c index 59cc5ddc..3230b401 100644 --- a/Alc/backends/solaris.c +++ b/Alc/backends/solaris.c @@ -90,9 +90,7 @@ static void ALCsolarisBackend_Construct(ALCsolarisBackend *self, ALCdevice *devi static void ALCsolarisBackend_Destruct(ALCsolarisBackend *self) { - if(self->fd != -1) - close(self->fd); - self->fd = -1; + ALCsolarisBackend_close(self); free(self->mix_data); self->mix_data = NULL; @@ -193,7 +191,8 @@ static ALCenum ALCsolarisBackend_open(ALCsolarisBackend *self, const ALCchar *na static void ALCsolarisBackend_close(ALCsolarisBackend *self) { - close(self->fd); + if(self->fd != -1) + close(self->fd); self->fd = -1; } diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index 1c502fd9..538ab5e6 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -84,7 +84,7 @@ typedef struct ALCwaveBackend { static int ALCwaveBackend_mixerProc(void *ptr); static void ALCwaveBackend_Construct(ALCwaveBackend *self, ALCdevice *device); -static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, void, Destruct) +static void ALCwaveBackend_Destruct(ALCwaveBackend *self); static ALCenum ALCwaveBackend_open(ALCwaveBackend *self, const ALCchar *name); static void ALCwaveBackend_close(ALCwaveBackend *self); static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self); @@ -114,6 +114,11 @@ static void ALCwaveBackend_Construct(ALCwaveBackend *self, ALCdevice *device) self->killNow = 1; } +static void ALCwaveBackend_Destruct(ALCwaveBackend *self) +{ + ALCwaveBackend_close(self); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} static int ALCwaveBackend_mixerProc(void *ptr) { diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index 0fcab458..885b624c 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -475,6 +475,7 @@ static void ALCwinmmCapture_Construct(ALCwinmmCapture *self, ALCdevice *device) static void ALCwinmmCapture_Destruct(ALCwinmmCapture *self) { + ALCwinmmCapture_close(self); if(self->InHdl) waveInClose(self->InHdl); self->InHdl = 0; @@ -664,6 +665,7 @@ static void ALCwinmmCapture_close(ALCwinmmCapture *self) int i; /* Tell the processing thread to quit and wait for it to do so. */ + if(self->killNow) return; self->killNow = AL_TRUE; PostThreadMessage(self->thread, WM_QUIT, 0, 0); -- cgit v1.2.3 From e7217760f39071c7aec542c8f3fbaad21c71924a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 29 Jan 2018 01:00:53 -0800 Subject: Don't bother with an explicit stop backend method --- Alc/ALc.c | 9 +---- Alc/backends/alsa.c | 42 +++++++++++------------- Alc/backends/base.h | 3 -- Alc/backends/coreaudio.c | 11 ++----- Alc/backends/dsound.c | 82 ++++++++++++++++++++++----------------------- Alc/backends/jack.c | 15 --------- Alc/backends/loopback.c | 5 --- Alc/backends/mmdevapi.c | 84 ++++++++++++++++------------------------------- Alc/backends/null.c | 5 --- Alc/backends/opensl.c | 59 ++++++++++++++------------------- Alc/backends/oss.c | 34 ++++++++----------- Alc/backends/portaudio.c | 37 ++++++++------------- Alc/backends/pulseaudio.c | 42 +++++++++--------------- Alc/backends/qsa.c | 22 ++++--------- Alc/backends/sndio.c | 15 ++++----- Alc/backends/solaris.c | 13 +++----- Alc/backends/wave.c | 13 +++----- Alc/backends/winmm.c | 66 ++++++++++++++++--------------------- 18 files changed, 209 insertions(+), 348 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index f9f4b29c..53979704 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -2434,11 +2434,8 @@ static ALCvoid FreeDevice(ALCdevice *device) TRACE("%p\n", device); if(device->Backend) - { - V0(device->Backend,close)(); DELETE_OBJ(device->Backend); - device->Backend = NULL; - } + device->Backend = NULL; almtx_destroy(&device->BackendLock); @@ -4146,8 +4143,6 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) // Find a playback device to open if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR) { - DELETE_OBJ(device->Backend); - device->Backend = NULL; FreeDevice(device); alcSetError(NULL, err); return NULL; @@ -4318,8 +4313,6 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ); if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR) { - DELETE_OBJ(device->Backend); - device->Backend = NULL; FreeDevice(device); alcSetError(NULL, err); return NULL; diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 27d36560..915d31d3 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -448,7 +448,6 @@ static int ALCplaybackAlsa_mixerNoMMapProc(void *ptr); static void ALCplaybackAlsa_Construct(ALCplaybackAlsa *self, ALCdevice *device); static void ALCplaybackAlsa_Destruct(ALCplaybackAlsa *self); static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name); -static void ALCplaybackAlsa_close(ALCplaybackAlsa *self); static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self); static ALCboolean ALCplaybackAlsa_start(ALCplaybackAlsa *self); static void ALCplaybackAlsa_stop(ALCplaybackAlsa *self); @@ -466,11 +465,16 @@ static void ALCplaybackAlsa_Construct(ALCplaybackAlsa *self, ALCdevice *device) { ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCplaybackAlsa, ALCbackend, self); + + self->pcmHandle = NULL; + self->buffer = NULL; } void ALCplaybackAlsa_Destruct(ALCplaybackAlsa *self) { - ALCplaybackAlsa_close(self); + if(self->pcmHandle) + snd_pcm_close(self->pcmHandle); + self->pcmHandle = NULL; ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -708,12 +712,6 @@ static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name) return ALC_NO_ERROR; } -static void ALCplaybackAlsa_close(ALCplaybackAlsa *self) -{ - snd_pcm_close(self->pcmHandle); - self->pcmHandle = NULL; -} - static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; @@ -982,7 +980,6 @@ typedef struct ALCcaptureAlsa { static void ALCcaptureAlsa_Construct(ALCcaptureAlsa *self, ALCdevice *device); static void ALCcaptureAlsa_Destruct(ALCcaptureAlsa *self); static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name); -static void ALCcaptureAlsa_close(ALCcaptureAlsa *self); static DECLARE_FORWARD(ALCcaptureAlsa, ALCbackend, ALCboolean, reset) static ALCboolean ALCcaptureAlsa_start(ALCcaptureAlsa *self); static void ALCcaptureAlsa_stop(ALCcaptureAlsa *self); @@ -1000,11 +997,24 @@ static void ALCcaptureAlsa_Construct(ALCcaptureAlsa *self, ALCdevice *device) { ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCcaptureAlsa, ALCbackend, self); + + self->pcmHandle = NULL; + self->buffer = NULL; + self->ring = NULL; } void ALCcaptureAlsa_Destruct(ALCcaptureAlsa *self) { - ALCcaptureAlsa_close(self); + if(self->pcmHandle) + snd_pcm_close(self->pcmHandle); + self->pcmHandle = NULL; + + al_free(self->buffer); + self->buffer = NULL; + + ll_ringbuffer_free(self->ring); + self->ring = NULL; + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -1139,18 +1149,6 @@ error2: return ALC_INVALID_VALUE; } -static void ALCcaptureAlsa_close(ALCcaptureAlsa *self) -{ - snd_pcm_close(self->pcmHandle); - self->pcmHandle = NULL; - - ll_ringbuffer_free(self->ring); - self->ring = NULL; - - al_free(self->buffer); - self->buffer = NULL; -} - static ALCboolean ALCcaptureAlsa_start(ALCcaptureAlsa *self) { int err = snd_pcm_start(self->pcmHandle); diff --git a/Alc/backends/base.h b/Alc/backends/base.h index 318e86fc..177f6869 100644 --- a/Alc/backends/base.h +++ b/Alc/backends/base.h @@ -43,7 +43,6 @@ struct ALCbackendVtable { void (*const Destruct)(ALCbackend*); ALCenum (*const open)(ALCbackend*, const ALCchar*); - void (*const close)(ALCbackend*); ALCboolean (*const reset)(ALCbackend*); ALCboolean (*const start)(ALCbackend*); @@ -63,7 +62,6 @@ struct ALCbackendVtable { #define DEFINE_ALCBACKEND_VTABLE(T) \ DECLARE_THUNK(T, ALCbackend, void, Destruct) \ DECLARE_THUNK1(T, ALCbackend, ALCenum, open, const ALCchar*) \ -DECLARE_THUNK(T, ALCbackend, void, close) \ DECLARE_THUNK(T, ALCbackend, ALCboolean, reset) \ DECLARE_THUNK(T, ALCbackend, ALCboolean, start) \ DECLARE_THUNK(T, ALCbackend, void, stop) \ @@ -79,7 +77,6 @@ static const struct ALCbackendVtable T##_ALCbackend_vtable = { \ T##_ALCbackend_Destruct, \ \ T##_ALCbackend_open, \ - T##_ALCbackend_close, \ T##_ALCbackend_reset, \ T##_ALCbackend_start, \ T##_ALCbackend_stop, \ diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index bdd9b678..3db0d702 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -98,7 +98,6 @@ typedef struct ALCcoreAudioPlayback { static void ALCcoreAudioPlayback_Construct(ALCcoreAudioPlayback *self, ALCdevice *device); static void ALCcoreAudioPlayback_Destruct(ALCcoreAudioPlayback *self); static ALCenum ALCcoreAudioPlayback_open(ALCcoreAudioPlayback *self, const ALCchar *name); -static void ALCcoreAudioPlayback_close(ALCcoreAudioPlayback *self); static ALCboolean ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback *self); static ALCboolean ALCcoreAudioPlayback_start(ALCcoreAudioPlayback *self); static void ALCcoreAudioPlayback_stop(ALCcoreAudioPlayback *self); @@ -123,7 +122,9 @@ static void ALCcoreAudioPlayback_Construct(ALCcoreAudioPlayback *self, ALCdevice static void ALCcoreAudioPlayback_Destruct(ALCcoreAudioPlayback *self) { - ALCcoreAudioPlayback_close(self); + AudioUnitUninitialize(self->audioUnit); + AudioComponentInstanceDispose(self->audioUnit); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -190,12 +191,6 @@ static ALCenum ALCcoreAudioPlayback_open(ALCcoreAudioPlayback *self, const ALCch return ALC_NO_ERROR; } -static void ALCcoreAudioPlayback_close(ALCcoreAudioPlayback *self) -{ - AudioUnitUninitialize(self->audioUnit); - AudioComponentInstanceDispose(self->audioUnit); -} - static ALCboolean ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback *self) { ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index 7760e39d..3d130615 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -194,7 +194,6 @@ static int ALCdsoundPlayback_mixerProc(void *ptr); static void ALCdsoundPlayback_Construct(ALCdsoundPlayback *self, ALCdevice *device); static void ALCdsoundPlayback_Destruct(ALCdsoundPlayback *self); static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *name); -static void ALCdsoundPlayback_close(ALCdsoundPlayback *self); static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self); static ALCboolean ALCdsoundPlayback_start(ALCdsoundPlayback *self); static void ALCdsoundPlayback_stop(ALCdsoundPlayback *self); @@ -212,11 +211,33 @@ static void ALCdsoundPlayback_Construct(ALCdsoundPlayback *self, ALCdevice *devi { ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCdsoundPlayback, ALCbackend, self); + + self->DS = NULL; + self->PrimaryBuffer = NULL; + self->Buffer = NULL; + self->Notifies = NULL; + self->NotifyEvent = NULL; } static void ALCdsoundPlayback_Destruct(ALCdsoundPlayback *self) { - ALCdsoundPlayback_close(self); + if(self->Notifies) + IDirectSoundNotify_Release(self->Notifies); + self->Notifies = NULL; + if(self->Buffer) + IDirectSoundBuffer_Release(self->Buffer); + self->Buffer = NULL; + if(self->PrimaryBuffer != NULL) + IDirectSoundBuffer_Release(self->PrimaryBuffer); + self->PrimaryBuffer = NULL; + + if(self->DS) + IDirectSound_Release(self->DS); + self->DS = NULL; + if(self->NotifyEvent) + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -393,26 +414,6 @@ static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *de return ALC_NO_ERROR; } -static void ALCdsoundPlayback_close(ALCdsoundPlayback *self) -{ - if(self->Notifies) - IDirectSoundNotify_Release(self->Notifies); - self->Notifies = NULL; - if(self->Buffer) - IDirectSoundBuffer_Release(self->Buffer); - self->Buffer = NULL; - if(self->PrimaryBuffer != NULL) - IDirectSoundBuffer_Release(self->PrimaryBuffer); - self->PrimaryBuffer = NULL; - - if(self->DS) - IDirectSound_Release(self->DS); - self->DS = NULL; - if(self->NotifyEvent) - CloseHandle(self->NotifyEvent); - self->NotifyEvent = NULL; -} - static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; @@ -671,7 +672,6 @@ typedef struct ALCdsoundCapture { static void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device); static void ALCdsoundCapture_Destruct(ALCdsoundCapture *self); static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *name); -static void ALCdsoundCapture_close(ALCdsoundCapture *self); static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, ALCboolean, reset) static ALCboolean ALCdsoundCapture_start(ALCdsoundCapture *self); static void ALCdsoundCapture_stop(ALCdsoundCapture *self); @@ -688,11 +688,28 @@ static void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device { ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCdsoundCapture, ALCbackend, self); + + self->DSC = NULL; + self->DSCbuffer = NULL; + self->Ring = NULL; } static void ALCdsoundCapture_Destruct(ALCdsoundCapture *self) { - ALCdsoundCapture_close(self); + ll_ringbuffer_free(self->Ring); + self->Ring = NULL; + + if(self->DSCbuffer != NULL) + { + IDirectSoundCaptureBuffer_Stop(self->DSCbuffer); + IDirectSoundCaptureBuffer_Release(self->DSCbuffer); + self->DSCbuffer = NULL; + } + + if(self->DSC) + IDirectSoundCapture_Release(self->DSC); + self->DSC = NULL; + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -869,23 +886,6 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi return ALC_NO_ERROR; } -static void ALCdsoundCapture_close(ALCdsoundCapture *self) -{ - ll_ringbuffer_free(self->Ring); - self->Ring = NULL; - - if(self->DSCbuffer != NULL) - { - IDirectSoundCaptureBuffer_Stop(self->DSCbuffer); - IDirectSoundCaptureBuffer_Release(self->DSCbuffer); - self->DSCbuffer = NULL; - } - - if(self->DSC) - IDirectSoundCapture_Release(self->DSC); - self->DSC = NULL; -} - static ALCboolean ALCdsoundCapture_start(ALCdsoundCapture *self) { HRESULT hr; diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index 0dc01ae7..f1141ce9 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -164,7 +164,6 @@ static int ALCjackPlayback_mixerProc(void *arg); static void ALCjackPlayback_Construct(ALCjackPlayback *self, ALCdevice *device); static void ALCjackPlayback_Destruct(ALCjackPlayback *self); static ALCenum ALCjackPlayback_open(ALCjackPlayback *self, const ALCchar *name); -static void ALCjackPlayback_close(ALCjackPlayback *self); static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self); static ALCboolean ALCjackPlayback_start(ALCjackPlayback *self); static void ALCjackPlayback_stop(ALCjackPlayback *self); @@ -388,20 +387,6 @@ static ALCenum ALCjackPlayback_open(ALCjackPlayback *self, const ALCchar *name) return ALC_NO_ERROR; } -static void ALCjackPlayback_close(ALCjackPlayback *self) -{ - ALuint i; - - for(i = 0;i < MAX_OUTPUT_CHANNELS;i++) - { - if(self->Port[i]) - jack_port_unregister(self->Client, self->Port[i]); - self->Port[i] = NULL; - } - jack_client_close(self->Client); - self->Client = NULL; -} - static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; diff --git a/Alc/backends/loopback.c b/Alc/backends/loopback.c index 8f23aad9..9186a92f 100644 --- a/Alc/backends/loopback.c +++ b/Alc/backends/loopback.c @@ -35,7 +35,6 @@ typedef struct ALCloopback { static void ALCloopback_Construct(ALCloopback *self, ALCdevice *device); static DECLARE_FORWARD(ALCloopback, ALCbackend, void, Destruct) static ALCenum ALCloopback_open(ALCloopback *self, const ALCchar *name); -static void ALCloopback_close(ALCloopback *self); static ALCboolean ALCloopback_reset(ALCloopback *self); static ALCboolean ALCloopback_start(ALCloopback *self); static void ALCloopback_stop(ALCloopback *self); @@ -63,10 +62,6 @@ static ALCenum ALCloopback_open(ALCloopback *self, const ALCchar *name) return ALC_NO_ERROR; } -static void ALCloopback_close(ALCloopback* UNUSED(self)) -{ -} - static ALCboolean ALCloopback_reset(ALCloopback *self) { SetDefaultWFXChannelOrder(STATIC_CAST(ALCbackend, self)->mDevice); diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 899f73d4..d63d22df 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -545,7 +545,6 @@ static void ALCmmdevPlayback_Construct(ALCmmdevPlayback *self, ALCdevice *device static void ALCmmdevPlayback_Destruct(ALCmmdevPlayback *self); static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *name); static HRESULT ALCmmdevPlayback_openProxy(ALCmmdevPlayback *self); -static void ALCmmdevPlayback_close(ALCmmdevPlayback *self); static void ALCmmdevPlayback_closeProxy(ALCmmdevPlayback *self); static ALCboolean ALCmmdevPlayback_reset(ALCmmdevPlayback *self); static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self); @@ -587,7 +586,22 @@ static void ALCmmdevPlayback_Construct(ALCmmdevPlayback *self, ALCdevice *device static void ALCmmdevPlayback_Destruct(ALCmmdevPlayback *self) { - ALCmmdevPlayback_close(self); + if(self->MsgEvent) + { + ThreadRequest req = { self->MsgEvent, 0 }; + if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) + (void)WaitForResponse(&req); + + CloseHandle(self->MsgEvent); + self->MsgEvent = NULL; + } + + if(self->NotifyEvent) + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; + + free(self->devid); + self->devid = NULL; if(self->NotifyEvent != NULL) CloseHandle(self->NotifyEvent); @@ -838,26 +852,6 @@ static HRESULT ALCmmdevPlayback_openProxy(ALCmmdevPlayback *self) } -static void ALCmmdevPlayback_close(ALCmmdevPlayback *self) -{ - ThreadRequest req = { self->MsgEvent, 0 }; - - if(!req.FinishedEvt) - return; - - if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) - (void)WaitForResponse(&req); - - CloseHandle(self->MsgEvent); - self->MsgEvent = NULL; - - CloseHandle(self->NotifyEvent); - self->NotifyEvent = NULL; - - free(self->devid); - self->devid = NULL; -} - static void ALCmmdevPlayback_closeProxy(ALCmmdevPlayback *self) { if(self->client) @@ -1248,7 +1242,6 @@ static void ALCmmdevCapture_Construct(ALCmmdevCapture *self, ALCdevice *device); static void ALCmmdevCapture_Destruct(ALCmmdevCapture *self); static ALCenum ALCmmdevCapture_open(ALCmmdevCapture *self, const ALCchar *name); static HRESULT ALCmmdevCapture_openProxy(ALCmmdevCapture *self); -static void ALCmmdevCapture_close(ALCmmdevCapture *self); static void ALCmmdevCapture_closeProxy(ALCmmdevCapture *self); static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, ALCboolean, reset) static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self); @@ -1292,7 +1285,19 @@ static void ALCmmdevCapture_Construct(ALCmmdevCapture *self, ALCdevice *device) static void ALCmmdevCapture_Destruct(ALCmmdevCapture *self) { - ALCmmdevCapture_close(self); + if(self->MsgEvent) + { + ThreadRequest req = { self->MsgEvent, 0 }; + if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) + (void)WaitForResponse(&req); + + CloseHandle(self->MsgEvent); + self->MsgEvent = NULL; + } + + if(self->NotifyEvent != NULL) + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; ll_ringbuffer_free(self->Ring); self->Ring = NULL; @@ -1300,13 +1305,6 @@ static void ALCmmdevCapture_Destruct(ALCmmdevCapture *self) DestroySampleConverter(&self->SampleConv); DestroyChannelConverter(&self->ChannelConv); - if(self->NotifyEvent != NULL) - CloseHandle(self->NotifyEvent); - self->NotifyEvent = NULL; - if(self->MsgEvent != NULL) - CloseHandle(self->MsgEvent); - self->MsgEvent = NULL; - free(self->devid); self->devid = NULL; @@ -1529,7 +1527,6 @@ static ALCenum ALCmmdevCapture_open(ALCmmdevCapture *self, const ALCchar *device if(FAILED(hr)) { - ALCmmdevCapture_close(self); if(hr == E_OUTOFMEMORY) return ALC_OUT_OF_MEMORY; return ALC_INVALID_VALUE; @@ -1576,29 +1573,6 @@ static HRESULT ALCmmdevCapture_openProxy(ALCmmdevCapture *self) } -static void ALCmmdevCapture_close(ALCmmdevCapture *self) -{ - ThreadRequest req = { self->MsgEvent, 0 }; - - if(!req.FinishedEvt) - return; - - if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) - (void)WaitForResponse(&req); - - ll_ringbuffer_free(self->Ring); - self->Ring = NULL; - - CloseHandle(self->MsgEvent); - self->MsgEvent = NULL; - - CloseHandle(self->NotifyEvent); - self->NotifyEvent = NULL; - - free(self->devid); - self->devid = NULL; -} - static void ALCmmdevCapture_closeProxy(ALCmmdevCapture *self) { if(self->client) diff --git a/Alc/backends/null.c b/Alc/backends/null.c index e8c43782..d17c8bda 100644 --- a/Alc/backends/null.c +++ b/Alc/backends/null.c @@ -45,7 +45,6 @@ static int ALCnullBackend_mixerProc(void *ptr); static void ALCnullBackend_Construct(ALCnullBackend *self, ALCdevice *device); static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, Destruct) static ALCenum ALCnullBackend_open(ALCnullBackend *self, const ALCchar *name); -static void ALCnullBackend_close(ALCnullBackend *self); static ALCboolean ALCnullBackend_reset(ALCnullBackend *self); static ALCboolean ALCnullBackend_start(ALCnullBackend *self); static void ALCnullBackend_stop(ALCnullBackend *self); @@ -135,10 +134,6 @@ static ALCenum ALCnullBackend_open(ALCnullBackend *self, const ALCchar *name) return ALC_NO_ERROR; } -static void ALCnullBackend_close(ALCnullBackend* UNUSED(self)) -{ -} - static ALCboolean ALCnullBackend_reset(ALCnullBackend *self) { SetDefaultWFXChannelOrder(STATIC_CAST(ALCbackend, self)->mDevice); diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index c1283111..7edc9ff8 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -160,7 +160,6 @@ static int ALCopenslPlayback_mixerProc(void *arg); static void ALCopenslPlayback_Construct(ALCopenslPlayback *self, ALCdevice *device); static void ALCopenslPlayback_Destruct(ALCopenslPlayback *self); static ALCenum ALCopenslPlayback_open(ALCopenslPlayback *self, const ALCchar *name); -static void ALCopenslPlayback_close(ALCopenslPlayback *self); static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self); static ALCboolean ALCopenslPlayback_start(ALCopenslPlayback *self); static void ALCopenslPlayback_stop(ALCopenslPlayback *self); @@ -194,7 +193,18 @@ static void ALCopenslPlayback_Construct(ALCopenslPlayback *self, ALCdevice *devi static void ALCopenslPlayback_Destruct(ALCopenslPlayback* self) { - ALCopenslPlayback_close(self); + if(self->mBufferQueueObj != NULL) + VCALL0(self->mBufferQueueObj,Destroy)(); + self->mBufferQueueObj = NULL; + + if(self->mOutputMix) + VCALL0(self->mOutputMix,Destroy)(); + self->mOutputMix = NULL; + + if(self->mEngineObj) + VCALL0(self->mEngineObj,Destroy)(); + self->mEngineObj = NULL; + self->mEngine = NULL; alcnd_destroy(&self->mCond); @@ -389,22 +399,6 @@ static ALCenum ALCopenslPlayback_open(ALCopenslPlayback *self, const ALCchar *na return ALC_NO_ERROR; } -static void ALCopenslPlayback_close(ALCopenslPlayback *self) -{ - if(self->mBufferQueueObj != NULL) - VCALL0(self->mBufferQueueObj,Destroy)(); - self->mBufferQueueObj = NULL; - - if(self->mOutputMix) - VCALL0(self->mOutputMix,Destroy)(); - self->mOutputMix = NULL; - - if(self->mEngineObj) - VCALL0(self->mEngineObj,Destroy)(); - self->mEngineObj = NULL; - self->mEngine = NULL; -} - static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self) { ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; @@ -710,7 +704,6 @@ static void ALCopenslCapture_process(SLAndroidSimpleBufferQueueItf bq, void *con static void ALCopenslCapture_Construct(ALCopenslCapture *self, ALCdevice *device); static void ALCopenslCapture_Destruct(ALCopenslCapture *self); static ALCenum ALCopenslCapture_open(ALCopenslCapture *self, const ALCchar *name); -static void ALCopenslCapture_close(ALCopenslCapture *self); static DECLARE_FORWARD(ALCopenslCapture, ALCbackend, ALCboolean, reset) static ALCboolean ALCopenslCapture_start(ALCopenslCapture *self); static void ALCopenslCapture_stop(ALCopenslCapture *self); @@ -749,7 +742,18 @@ static void ALCopenslCapture_Construct(ALCopenslCapture *self, ALCdevice *device static void ALCopenslCapture_Destruct(ALCopenslCapture *self) { - ALCopenslCapture_close(self); + ll_ringbuffer_free(self->mRing); + self->mRing = NULL; + + if(self->mRecordObj != NULL) + VCALL0(self->mRecordObj,Destroy)(); + self->mRecordObj = NULL; + + if(self->mEngineObj != NULL) + VCALL0(self->mEngineObj,Destroy)(); + self->mEngineObj = NULL; + self->mEngine = NULL; + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -918,21 +922,6 @@ static ALCenum ALCopenslCapture_open(ALCopenslCapture *self, const ALCchar *name return ALC_NO_ERROR; } -static void ALCopenslCapture_close(ALCopenslCapture *self) -{ - ll_ringbuffer_free(self->mRing); - self->mRing = NULL; - - if(self->mRecordObj != NULL) - VCALL0(self->mRecordObj,Destroy)(); - self->mRecordObj = NULL; - - if(self->mEngineObj != NULL) - VCALL0(self->mEngineObj,Destroy)(); - self->mEngineObj = NULL; - self->mEngine = NULL; -} - static ALCboolean ALCopenslCapture_start(ALCopenslCapture *self) { SLRecordItf record; diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index e88e5ff3..b2d9c555 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -254,7 +254,6 @@ static int ALCplaybackOSS_mixerProc(void *ptr); static void ALCplaybackOSS_Construct(ALCplaybackOSS *self, ALCdevice *device); static void ALCplaybackOSS_Destruct(ALCplaybackOSS *self); static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name); -static void ALCplaybackOSS_close(ALCplaybackOSS *self); static ALCboolean ALCplaybackOSS_reset(ALCplaybackOSS *self); static ALCboolean ALCplaybackOSS_start(ALCplaybackOSS *self); static void ALCplaybackOSS_stop(ALCplaybackOSS *self); @@ -339,12 +338,16 @@ static void ALCplaybackOSS_Construct(ALCplaybackOSS *self, ALCdevice *device) ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCplaybackOSS, ALCbackend, self); + self->fd = -1; ATOMIC_INIT(&self->killNow, AL_FALSE); } static void ALCplaybackOSS_Destruct(ALCplaybackOSS *self) { - ALCplaybackOSS_close(self); + if(self->fd != -1) + close(self->fd); + self->fd = -1; + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -387,13 +390,6 @@ static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name) return ALC_NO_ERROR; } -static void ALCplaybackOSS_close(ALCplaybackOSS *self) -{ - if(self->fd != -1) - close(self->fd); - self->fd = -1; -} - static ALCboolean ALCplaybackOSS_reset(ALCplaybackOSS *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; @@ -528,7 +524,6 @@ static int ALCcaptureOSS_recordProc(void *ptr); static void ALCcaptureOSS_Construct(ALCcaptureOSS *self, ALCdevice *device); static void ALCcaptureOSS_Destruct(ALCcaptureOSS *self); static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name); -static void ALCcaptureOSS_close(ALCcaptureOSS *self); static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, ALCboolean, reset) static ALCboolean ALCcaptureOSS_start(ALCcaptureOSS *self); static void ALCcaptureOSS_stop(ALCcaptureOSS *self); @@ -605,12 +600,19 @@ static void ALCcaptureOSS_Construct(ALCcaptureOSS *self, ALCdevice *device) ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCcaptureOSS, ALCbackend, self); + self->fd = -1; + self->ring = NULL; ATOMIC_INIT(&self->killNow, AL_FALSE); } static void ALCcaptureOSS_Destruct(ALCcaptureOSS *self) { - ALCcaptureOSS_close(self); + if(self->fd != -1) + close(self->fd); + self->fd = -1; + + ll_ringbuffer_free(self->ring); + self->ring = NULL; ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -739,16 +741,6 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) return ALC_NO_ERROR; } -static void ALCcaptureOSS_close(ALCcaptureOSS *self) -{ - if(self->fd != -1) - close(self->fd); - self->fd = -1; - - ll_ringbuffer_free(self->ring); - self->ring = NULL; -} - static ALCboolean ALCcaptureOSS_start(ALCcaptureOSS *self) { ATOMIC_STORE_SEQ(&self->killNow, AL_FALSE); diff --git a/Alc/backends/portaudio.c b/Alc/backends/portaudio.c index 58cf9762..fdc8a2a5 100644 --- a/Alc/backends/portaudio.c +++ b/Alc/backends/portaudio.c @@ -141,7 +141,6 @@ static int ALCportPlayback_WriteCallback(const void *inputBuffer, void *outputBu static void ALCportPlayback_Construct(ALCportPlayback *self, ALCdevice *device); static void ALCportPlayback_Destruct(ALCportPlayback *self); static ALCenum ALCportPlayback_open(ALCportPlayback *self, const ALCchar *name); -static void ALCportPlayback_close(ALCportPlayback *self); static ALCboolean ALCportPlayback_reset(ALCportPlayback *self); static ALCboolean ALCportPlayback_start(ALCportPlayback *self); static void ALCportPlayback_stop(ALCportPlayback *self); @@ -165,7 +164,11 @@ static void ALCportPlayback_Construct(ALCportPlayback *self, ALCdevice *device) static void ALCportPlayback_Destruct(ALCportPlayback *self) { - ALCportPlayback_close(self); + PaError err = self->stream ? Pa_CloseStream(self->stream) : paNoError; + if(err != paNoError) + ERR("Error closing stream: %s\n", Pa_GetErrorText(err)); + self->stream = NULL; + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -250,14 +253,6 @@ retry_open: } -static void ALCportPlayback_close(ALCportPlayback *self) -{ - PaError err = self->stream ? Pa_CloseStream(self->stream) : paNoError; - if(err != paNoError) - ERR("Error closing stream: %s\n", Pa_GetErrorText(err)); - self->stream = NULL; -} - static ALCboolean ALCportPlayback_reset(ALCportPlayback *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; @@ -335,7 +330,6 @@ static int ALCportCapture_ReadCallback(const void *inputBuffer, void *outputBuff static void ALCportCapture_Construct(ALCportCapture *self, ALCdevice *device); static void ALCportCapture_Destruct(ALCportCapture *self); static ALCenum ALCportCapture_open(ALCportCapture *self, const ALCchar *name); -static void ALCportCapture_close(ALCportCapture *self); static DECLARE_FORWARD(ALCportCapture, ALCbackend, ALCboolean, reset) static ALCboolean ALCportCapture_start(ALCportCapture *self); static void ALCportCapture_stop(ALCportCapture *self); @@ -355,11 +349,19 @@ static void ALCportCapture_Construct(ALCportCapture *self, ALCdevice *device) SET_VTABLE2(ALCportCapture, ALCbackend, self); self->stream = NULL; + self->ring = NULL; } static void ALCportCapture_Destruct(ALCportCapture *self) { - ALCportCapture_close(self); + PaError err = self->stream ? Pa_CloseStream(self->stream) : paNoError; + if(err != paNoError) + ERR("Error closing stream: %s\n", Pa_GetErrorText(err)); + self->stream = NULL; + + ll_ringbuffer_free(self->ring); + self->ring = NULL; + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -442,17 +444,6 @@ static ALCenum ALCportCapture_open(ALCportCapture *self, const ALCchar *name) return ALC_NO_ERROR; } -static void ALCportCapture_close(ALCportCapture *self) -{ - PaError err = self->stream ? Pa_CloseStream(self->stream) : paNoError; - if(err != paNoError) - ERR("Error closing stream: %s\n", Pa_GetErrorText(err)); - self->stream = NULL; - - ll_ringbuffer_free(self->ring); - self->ring = NULL; -} - static ALCboolean ALCportCapture_start(ALCportCapture *self) { diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index 581f4c38..bcfbb6c2 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -495,7 +495,6 @@ static int ALCpulsePlayback_mixerProc(void *ptr); static void ALCpulsePlayback_Construct(ALCpulsePlayback *self, ALCdevice *device); static void ALCpulsePlayback_Destruct(ALCpulsePlayback *self); static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name); -static void ALCpulsePlayback_close(ALCpulsePlayback *self); static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self); static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self); static void ALCpulsePlayback_stop(ALCpulsePlayback *self); @@ -514,12 +513,19 @@ static void ALCpulsePlayback_Construct(ALCpulsePlayback *self, ALCdevice *device ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCpulsePlayback, ALCbackend, self); + self->loop = NULL; AL_STRING_INIT(self->device_name); } static void ALCpulsePlayback_Destruct(ALCpulsePlayback *self) { - ALCpulsePlayback_close(self); + if(self->loop) + { + pulse_close(self->loop, self->context, self->stream); + self->loop = NULL; + self->context = NULL; + self->stream = NULL; + } AL_STRING_DEINIT(self->device_name); ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -957,17 +963,6 @@ static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name return ALC_NO_ERROR; } -static void ALCpulsePlayback_close(ALCpulsePlayback *self) -{ - if(self->loop) - { - pulse_close(self->loop, self->context, self->stream); - self->loop = NULL; - self->context = NULL; - self->stream = NULL; - } -} - static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) { ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; @@ -1251,7 +1246,6 @@ static pa_stream *ALCpulseCapture_connectStream(const char *device_name, static void ALCpulseCapture_Construct(ALCpulseCapture *self, ALCdevice *device); static void ALCpulseCapture_Destruct(ALCpulseCapture *self); static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name); -static void ALCpulseCapture_close(ALCpulseCapture *self); static DECLARE_FORWARD(ALCpulseCapture, ALCbackend, ALCboolean, reset) static ALCboolean ALCpulseCapture_start(ALCpulseCapture *self); static void ALCpulseCapture_stop(ALCpulseCapture *self); @@ -1270,12 +1264,19 @@ static void ALCpulseCapture_Construct(ALCpulseCapture *self, ALCdevice *device) ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCpulseCapture, ALCbackend, self); + self->loop = NULL; AL_STRING_INIT(self->device_name); } static void ALCpulseCapture_Destruct(ALCpulseCapture *self) { - ALCpulseCapture_close(self); + if(self->loop) + { + pulse_close(self->loop, self->context, self->stream); + self->loop = NULL; + self->context = NULL; + self->stream = NULL; + } AL_STRING_DEINIT(self->device_name); ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -1622,17 +1623,6 @@ fail: return ALC_INVALID_VALUE; } -static void ALCpulseCapture_close(ALCpulseCapture *self) -{ - if(self->loop) - { - pulse_close(self->loop, self->context, self->stream); - self->loop = NULL; - self->context = NULL; - self->stream = NULL; - } -} - static ALCboolean ALCpulseCapture_start(ALCpulseCapture *self) { pa_operation *o; diff --git a/Alc/backends/qsa.c b/Alc/backends/qsa.c index e1bbf2c2..614d738c 100644 --- a/Alc/backends/qsa.c +++ b/Alc/backends/qsa.c @@ -168,7 +168,6 @@ typedef struct PlaybackWrapper { static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device); static void PlaybackWrapper_Destruct(PlaybackWrapper *self); static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name); -static void PlaybackWrapper_close(PlaybackWrapper *self); static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self); static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self); static void PlaybackWrapper_stop(PlaybackWrapper *self); @@ -626,7 +625,9 @@ static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device) static void PlaybackWrapper_Destruct(PlaybackWrapper *self) { - PlaybackWrapper_close(self); + if(self->ExtraData) + qsa_close_playback(self); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -635,12 +636,6 @@ static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name) return qsa_open_playback(self, name); } -static void PlaybackWrapper_close(PlaybackWrapper *self) -{ - if(self->ExtraData) - qsa_close_playback(self); -} - static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self) { return qsa_reset_playback(self); @@ -670,7 +665,6 @@ typedef struct CaptureWrapper { static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device); static void CaptureWrapper_Destruct(CaptureWrapper *self); static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name); -static void CaptureWrapper_close(CaptureWrapper *self); static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ALCboolean, reset) static ALCboolean CaptureWrapper_start(CaptureWrapper *self); static void CaptureWrapper_stop(CaptureWrapper *self); @@ -954,7 +948,9 @@ static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device) static void CaptureWrapper_Destruct(CaptureWrapper *self) { - CaptureWrapper_close(self); + if(self->ExtraData) + qsa_close_capture(self); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -963,12 +959,6 @@ static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name) return qsa_open_capture(self, name); } -static void CaptureWrapper_close(CaptureWrapper *self) -{ - if(self->ExtraData) - qsa_close_capture(self); -} - static ALCboolean CaptureWrapper_start(CaptureWrapper *self) { qsa_start_capture(self); diff --git a/Alc/backends/sndio.c b/Alc/backends/sndio.c index 436baf26..f7b9af69 100644 --- a/Alc/backends/sndio.c +++ b/Alc/backends/sndio.c @@ -52,7 +52,6 @@ static int ALCsndioBackend_mixerProc(void *ptr); static void ALCsndioBackend_Construct(ALCsndioBackend *self, ALCdevice *device); static void ALCsndioBackend_Destruct(ALCsndioBackend *self); static ALCenum ALCsndioBackend_open(ALCsndioBackend *self, const ALCchar *name); -static void ALCsndioBackend_close(ALCsndioBackend *self); static ALCboolean ALCsndioBackend_reset(ALCsndioBackend *self); static ALCboolean ALCsndioBackend_start(ALCsndioBackend *self); static void ALCsndioBackend_stop(ALCsndioBackend *self); @@ -73,11 +72,16 @@ static void ALCsndioBackend_Construct(ALCsndioBackend *self, ALCdevice *device) { ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCsndioBackend, ALCbackend, self); + + self->sndHandle = NULL; + self->mix_data = NULL; } static void ALCsndioBackend_Destruct(ALCsndioBackend *self) { - ALCsndioBackend_close(self); + if(self->sndHandle) + sio_close(self->sndHandle); + self->sndHandle = NULL; al_free(self->mix_data); self->mix_data = NULL; @@ -148,13 +152,6 @@ static ALCenum ALCsndioBackend_open(ALCsndioBackend *self, const ALCchar *name) return ALC_NO_ERROR; } -static void ALCsndioBackend_close(ALCsndioBackend *self) -{ - if(self->sndHandle) - sio_close(self->sndHandle); - self->sndHandle = NULL; -} - static ALCboolean ALCsndioBackend_reset(ALCsndioBackend *self) { ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c index 3230b401..49bfad3c 100644 --- a/Alc/backends/solaris.c +++ b/Alc/backends/solaris.c @@ -60,7 +60,6 @@ static int ALCsolarisBackend_mixerProc(void *ptr); static void ALCsolarisBackend_Construct(ALCsolarisBackend *self, ALCdevice *device); static void ALCsolarisBackend_Destruct(ALCsolarisBackend *self); static ALCenum ALCsolarisBackend_open(ALCsolarisBackend *self, const ALCchar *name); -static void ALCsolarisBackend_close(ALCsolarisBackend *self); static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self); static ALCboolean ALCsolarisBackend_start(ALCsolarisBackend *self); static void ALCsolarisBackend_stop(ALCsolarisBackend *self); @@ -85,12 +84,15 @@ static void ALCsolarisBackend_Construct(ALCsolarisBackend *self, ALCdevice *devi SET_VTABLE2(ALCsolarisBackend, ALCbackend, self); self->fd = -1; + self->mix_data = NULL; ATOMIC_INIT(&self->killNow, AL_FALSE); } static void ALCsolarisBackend_Destruct(ALCsolarisBackend *self) { - ALCsolarisBackend_close(self); + if(self->fd != -1) + close(self->fd); + self->fd = -1; free(self->mix_data); self->mix_data = NULL; @@ -189,13 +191,6 @@ static ALCenum ALCsolarisBackend_open(ALCsolarisBackend *self, const ALCchar *na return ALC_NO_ERROR; } -static void ALCsolarisBackend_close(ALCsolarisBackend *self) -{ - if(self->fd != -1) - close(self->fd); - self->fd = -1; -} - static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self) { ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index 538ab5e6..ecb066f8 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -86,7 +86,6 @@ static int ALCwaveBackend_mixerProc(void *ptr); static void ALCwaveBackend_Construct(ALCwaveBackend *self, ALCdevice *device); static void ALCwaveBackend_Destruct(ALCwaveBackend *self); static ALCenum ALCwaveBackend_open(ALCwaveBackend *self, const ALCchar *name); -static void ALCwaveBackend_close(ALCwaveBackend *self); static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self); static ALCboolean ALCwaveBackend_start(ALCwaveBackend *self); static void ALCwaveBackend_stop(ALCwaveBackend *self); @@ -116,7 +115,10 @@ static void ALCwaveBackend_Construct(ALCwaveBackend *self, ALCdevice *device) static void ALCwaveBackend_Destruct(ALCwaveBackend *self) { - ALCwaveBackend_close(self); + if(self->mFile) + fclose(self->mFile); + self->mFile = NULL; + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -239,13 +241,6 @@ static ALCenum ALCwaveBackend_open(ALCwaveBackend *self, const ALCchar *name) return ALC_NO_ERROR; } -static void ALCwaveBackend_close(ALCwaveBackend *self) -{ - if(self->mFile) - fclose(self->mFile); - self->mFile = NULL; -} - static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index 885b624c..59164441 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -159,7 +159,6 @@ static void CALLBACK ALCwinmmPlayback_waveOutProc(HWAVEOUT device, UINT msg, DWO static int ALCwinmmPlayback_mixerProc(void *arg); static ALCenum ALCwinmmPlayback_open(ALCwinmmPlayback *self, const ALCchar *name); -static void ALCwinmmPlayback_close(ALCwinmmPlayback *self); static ALCboolean ALCwinmmPlayback_reset(ALCwinmmPlayback *self); static ALCboolean ALCwinmmPlayback_start(ALCwinmmPlayback *self); static void ALCwinmmPlayback_stop(ALCwinmmPlayback *self); @@ -312,9 +311,6 @@ failure: return ALC_INVALID_VALUE; } -static void ALCwinmmPlayback_close(ALCwinmmPlayback* UNUSED(self)) -{ } - static ALCboolean ALCwinmmPlayback_reset(ALCwinmmPlayback *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; @@ -448,7 +444,6 @@ static void CALLBACK ALCwinmmCapture_waveInProc(HWAVEIN device, UINT msg, DWORD_ static int ALCwinmmCapture_captureProc(void *arg); static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name); -static void ALCwinmmCapture_close(ALCwinmmCapture *self); static DECLARE_FORWARD(ALCwinmmCapture, ALCbackend, ALCboolean, reset) static ALCboolean ALCwinmmCapture_start(ALCwinmmCapture *self); static void ALCwinmmCapture_stop(ALCwinmmCapture *self); @@ -475,7 +470,34 @@ static void ALCwinmmCapture_Construct(ALCwinmmCapture *self, ALCdevice *device) static void ALCwinmmCapture_Destruct(ALCwinmmCapture *self) { - ALCwinmmCapture_close(self); + void *buffer = NULL; + int i; + + /* Tell the processing thread to quit and wait for it to do so. */ + if(!self->killNow) + { + self->killNow = AL_TRUE; + PostThreadMessage(self->thread, WM_QUIT, 0, 0); + + althrd_join(self->thread, &i); + + /* Make sure capture is stopped and all pending buffers are flushed. */ + waveInReset(self->InHdl); + + // Release the wave buffers + for(i = 0;i < 4;i++) + { + waveInUnprepareHeader(self->InHdl, &self->WaveBuffer[i], sizeof(WAVEHDR)); + if(i == 0) buffer = self->WaveBuffer[i].lpData; + self->WaveBuffer[i].lpData = NULL; + } + free(buffer); + } + + ll_ringbuffer_free(self->Ring); + self->Ring = NULL; + + // Close the Wave device if(self->InHdl) waveInClose(self->InHdl); self->InHdl = 0; @@ -659,38 +681,6 @@ failure: return ALC_INVALID_VALUE; } -static void ALCwinmmCapture_close(ALCwinmmCapture *self) -{ - void *buffer = NULL; - int i; - - /* Tell the processing thread to quit and wait for it to do so. */ - if(self->killNow) return; - self->killNow = AL_TRUE; - PostThreadMessage(self->thread, WM_QUIT, 0, 0); - - althrd_join(self->thread, &i); - - /* Make sure capture is stopped and all pending buffers are flushed. */ - waveInReset(self->InHdl); - - // Release the wave buffers - for(i = 0;i < 4;i++) - { - waveInUnprepareHeader(self->InHdl, &self->WaveBuffer[i], sizeof(WAVEHDR)); - if(i == 0) buffer = self->WaveBuffer[i].lpData; - self->WaveBuffer[i].lpData = NULL; - } - free(buffer); - - ll_ringbuffer_free(self->Ring); - self->Ring = NULL; - - // Close the Wave device - waveInClose(self->InHdl); - self->InHdl = NULL; -} - static ALCboolean ALCwinmmCapture_start(ALCwinmmCapture *self) { waveInStart(self->InHdl); -- cgit v1.2.3 From 975c682ec367f61e6e700b21da38e2c59cf69c3b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 1 Feb 2018 18:54:13 -0800 Subject: Use semaphores to signal for more samples with JACK and OpenSL --- Alc/backends/jack.c | 34 ++++++++-------------------------- Alc/backends/opensl.c | 36 ++++++++---------------------------- 2 files changed, 16 insertions(+), 54 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index f1141ce9..09f778c7 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -150,7 +150,7 @@ typedef struct ALCjackPlayback { jack_port_t *Port[MAX_OUTPUT_CHANNELS]; ll_ringbuffer_t *Ring; - alcnd_t Cond; + alsem_t Sem; volatile int killNow; althrd_t thread; @@ -184,7 +184,7 @@ static void ALCjackPlayback_Construct(ALCjackPlayback *self, ALCdevice *device) ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCjackPlayback, ALCbackend, self); - alcnd_init(&self->Cond); + alsem_init(&self->Sem, 0); self->Client = NULL; for(i = 0;i < MAX_OUTPUT_CHANNELS;i++) @@ -210,7 +210,7 @@ static void ALCjackPlayback_Destruct(ALCjackPlayback *self) self->Client = NULL; } - alcnd_destroy(&self->Cond); + alsem_destroy(&self->Sem); ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -287,7 +287,7 @@ static int ALCjackPlayback_process(jack_nframes_t numframes, void *arg) } ll_ringbuffer_read_advance(self->Ring, total); - alcnd_signal(&self->Cond); + alsem_post(&self->Sem); if(numframes > total) { @@ -316,23 +316,11 @@ static int ALCjackPlayback_mixerProc(void *arg) { ALuint todo, len1, len2; - /* NOTE: Unfortunately, there is an unavoidable race condition here. - * It's possible for the process() method to run, updating the read - * pointer and signaling the condition variable, in between the mixer - * loop checking the write size and waiting for the condition variable. - * This will cause the mixer loop to wait until the *next* process() - * invocation, most likely writing silence for it. - * - * However, this should only happen if the mixer is running behind - * anyway (as ideally we'll be asleep in alcnd_wait by the time the - * process() method is invoked), so this behavior is not unwarranted. - * It's unfortunate since it'll be wasting time sleeping that could be - * used to catch up, but there's no way around it without blocking in - * the process() method. - */ if(ll_ringbuffer_write_space(self->Ring) < device->UpdateSize) { - alcnd_wait(&self->Cond, &STATIC_CAST(ALCbackend,self)->mMutex); + ALCjackPlayback_unlock(self); + alsem_wait(&self->Sem); + ALCjackPlayback_lock(self); continue; } @@ -509,13 +497,7 @@ static void ALCjackPlayback_stop(ALCjackPlayback *self) return; self->killNow = 1; - /* Lock the backend to ensure we don't flag the mixer to die and signal the - * mixer to wake up in between it checking the flag and going to sleep and - * wait for a wakeup (potentially leading to it never waking back up to see - * the flag). */ - ALCjackPlayback_lock(self); - ALCjackPlayback_unlock(self); - alcnd_signal(&self->Cond); + alsem_post(&self->Sem); althrd_join(self->thread, &res); jack_deactivate(self->Client); diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 7edc9ff8..fb56b67c 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -146,7 +146,7 @@ typedef struct ALCopenslPlayback { SLObjectItf mBufferQueueObj; ll_ringbuffer_t *mRing; - alcnd_t mCond; + alsem_t mSem; ALsizei mFrameSize; @@ -184,7 +184,7 @@ static void ALCopenslPlayback_Construct(ALCopenslPlayback *self, ALCdevice *devi self->mBufferQueueObj = NULL; self->mRing = NULL; - alcnd_init(&self->mCond); + alsem_init(&self->mSem, 0); self->mFrameSize = 0; @@ -206,7 +206,7 @@ static void ALCopenslPlayback_Destruct(ALCopenslPlayback* self) self->mEngineObj = NULL; self->mEngine = NULL; - alcnd_destroy(&self->mCond); + alsem_destroy(&self->mSem); ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -227,7 +227,7 @@ static void ALCopenslPlayback_process(SLAndroidSimpleBufferQueueItf UNUSED(bq), */ ll_ringbuffer_read_advance(self->mRing, 1); - alcnd_signal(&self->mCond); + alsem_post(&self->mSem); } @@ -287,24 +287,11 @@ static int ALCopenslPlayback_mixerProc(void *arg) break; } - /* NOTE: Unfortunately, there is an unavoidable race condition - * here. It's possible for the process() method to run, updating - * the read pointer and signaling the condition variable, in - * between checking the write size and waiting for the condition - * variable here. This will cause alcnd_wait to wait until the - * *next* process() invocation signals the condition variable - * again. - * - * However, this should only happen if the mixer is running behind - * anyway (as ideally we'll be asleep in alcnd_wait by the time the - * process() method is invoked), so this behavior is not completely - * unwarranted. It's unfortunate since it'll be wasting time - * sleeping that could be used to catch up, but there's no way - * around it without blocking in the process() method. - */ if(ll_ringbuffer_write_space(self->mRing) <= padding) { - alcnd_wait(&self->mCond, &STATIC_CAST(ALCbackend,self)->mMutex); + ALCopenslPlayback_unlock(self); + alsem_wait(&self->mSem); + ALCopenslPlayback_lock(self); continue; } } @@ -623,14 +610,7 @@ static void ALCopenslPlayback_stop(ALCopenslPlayback *self) if(ATOMIC_EXCHANGE_SEQ(&self->mKillNow, AL_TRUE)) return; - /* Lock the backend to ensure we don't flag the mixer to die and signal the - * mixer to wake up in between it checking the flag and going to sleep and - * wait for a wakeup (potentially leading to it never waking back up to see - * the flag). - */ - ALCopenslPlayback_lock(self); - ALCopenslPlayback_unlock(self); - alcnd_signal(&self->mCond); + alsem_post(&self->mSem); althrd_join(self->mThread, &res); result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_PLAY, &player); -- cgit v1.2.3 From ec14c98f2d7c2a01f62a2fcebf1d9479cb540a0d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 1 Feb 2018 18:59:32 -0800 Subject: Use an atomic instead of volatile to tell a thread to quit --- Alc/backends/jack.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index 09f778c7..14032d45 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -152,7 +152,7 @@ typedef struct ALCjackPlayback { ll_ringbuffer_t *Ring; alsem_t Sem; - volatile int killNow; + ATOMIC(ALenum) killNow; althrd_t thread; } ALCjackPlayback; @@ -191,7 +191,7 @@ static void ALCjackPlayback_Construct(ALCjackPlayback *self, ALCdevice *device) self->Port[i] = NULL; self->Ring = NULL; - self->killNow = 1; + ATOMIC_INIT(&self->killNow, AL_TRUE); } static void ALCjackPlayback_Destruct(ALCjackPlayback *self) @@ -312,7 +312,7 @@ static int ALCjackPlayback_mixerProc(void *arg) althrd_setname(althrd_current(), MIXER_THREAD_NAME); ALCjackPlayback_lock(self); - while(!self->killNow && device->Connected) + while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) && device->Connected) { ALuint todo, len1, len2; @@ -479,7 +479,7 @@ static ALCboolean ALCjackPlayback_start(ALCjackPlayback *self) } jack_free(ports); - self->killNow = 0; + ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); if(althrd_create(&self->thread, ALCjackPlayback_mixerProc, self) != althrd_success) { jack_deactivate(self->Client); @@ -493,10 +493,9 @@ static void ALCjackPlayback_stop(ALCjackPlayback *self) { int res; - if(self->killNow) + if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel)) return; - self->killNow = 1; alsem_post(&self->Sem); althrd_join(self->thread, &res); -- cgit v1.2.3 From b99e64a0e3759d326b53578516a4ca5084046e7c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 3 Feb 2018 13:54:42 -0800 Subject: Provide more descriptive messages to disconnection events --- Alc/ALc.c | 10 +++++----- Alc/ALu.c | 43 ++++++++++++++++++++++++++++++------------- Alc/backends/alsa.c | 13 +++++++------ Alc/backends/dsound.c | 14 ++++++++------ Alc/backends/jack.c | 2 +- Alc/backends/mmdevapi.c | 10 +++++----- Alc/backends/opensl.c | 9 +++++---- Alc/backends/oss.c | 9 +++++---- Alc/backends/pulseaudio.c | 17 +++++++++-------- Alc/backends/qsa.c | 11 ++++++----- Alc/backends/sndio.c | 2 +- Alc/backends/solaris.c | 5 +++-- Alc/backends/wave.c | 2 +- OpenAL32/Include/alu.h | 2 +- 14 files changed, 87 insertions(+), 62 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index dfda8381..3c9598ca 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -3810,7 +3810,7 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin if(err == ALC_INVALID_DEVICE) { V0(device->Backend,lock)(); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Device update failure"); V0(device->Backend,unlock)(); } ALCdevice_DecRef(device); @@ -4397,7 +4397,7 @@ ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device) device->Flags |= DEVICE_RUNNING; else { - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Device start failure"); alcSetError(device, ALC_INVALID_DEVICE); } } @@ -4621,10 +4621,10 @@ ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device) device->Flags |= DEVICE_RUNNING; else { - alcSetError(device, ALC_INVALID_DEVICE); V0(device->Backend,lock)(); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Device start failure"); V0(device->Backend,unlock)(); + alcSetError(device, ALC_INVALID_DEVICE); } } } @@ -4694,7 +4694,7 @@ ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCi if(err == ALC_INVALID_DEVICE) { V0(device->Backend,lock)(); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Device start failure"); V0(device->Backend,unlock)(); } ALCdevice_DecRef(device); diff --git a/Alc/ALu.c b/Alc/ALu.c index 2a89f455..9f4f7a30 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -1850,30 +1850,47 @@ void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples) } -void aluHandleDisconnect(ALCdevice *device) +void aluHandleDisconnect(ALCdevice *device, const char *msg, ...) { ALCcontext *ctx; + AsyncEvent evt; + va_list args; + int msglen; device->Connected = ALC_FALSE; + evt.EnumType = EventType_Disconnected; + evt.Type = AL_EVENT_TYPE_DISCONNECTED_SOFT; + evt.ObjectId = 0; + evt.Param = 0; + + va_start(args, msg); + msglen = vsnprintf(evt.Message, sizeof(evt.Message), msg, args); + va_end(args); + + if(msglen < 0 || (size_t)msglen >= sizeof(evt.Message)) + { + evt.Message[sizeof(evt.Message)-1] = 0; + msglen = (int)strlen(evt.Message); + } + if(msglen > 0) + msg = evt.Message; + else + { + msg = ""; + msglen = (int)strlen(msg); + } + ctx = ATOMIC_LOAD_SEQ(&device->ContextList); while(ctx) { ALsizei i; - if((ATOMIC_LOAD(&ctx->EnabledEvts, almemory_order_acquire)&EventType_Disconnected)) + if((ATOMIC_LOAD(&ctx->EnabledEvts, almemory_order_acquire)&EventType_Disconnected) && + ll_ringbuffer_write_space(ctx->AsyncEvents) > 0) { - AsyncEvent evt; - evt.EnumType = EventType_Disconnected; - evt.Type = AL_EVENT_TYPE_DISCONNECTED_SOFT; - evt.ObjectId = 0; - evt.Param = 0; - strcpy(evt.Message, "Device disconnected"); - if(ll_ringbuffer_write_space(ctx->AsyncEvents) > 0) - { - ll_ringbuffer_write(ctx->AsyncEvents, (const char*)&evt, 1); - alsem_post(&ctx->EventSem); - } + ll_ringbuffer_write(ctx->AsyncEvents, (const char*)&evt, 1); + alsem_post(&ctx->EventSem); } for(i = 0;i < ctx->VoiceCount;i++) diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 915d31d3..72e2936f 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -502,7 +502,7 @@ static int ALCplaybackAlsa_mixerProc(void *ptr) { ERR("Invalid state detected: %s\n", snd_strerror(state)); ALCplaybackAlsa_lock(self); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Bad state: %s", snd_strerror(state)); ALCplaybackAlsa_unlock(self); break; } @@ -592,7 +592,7 @@ static int ALCplaybackAlsa_mixerNoMMapProc(void *ptr) { ERR("Invalid state detected: %s\n", snd_strerror(state)); ALCplaybackAlsa_lock(self); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Bad state: %s", snd_strerror(state)); ALCplaybackAlsa_unlock(self); break; } @@ -1155,7 +1155,8 @@ static ALCboolean ALCcaptureAlsa_start(ALCcaptureAlsa *self) if(err < 0) { ERR("start failed: %s\n", snd_strerror(err)); - aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice); + aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice, "Capture state failure: %s", + snd_strerror(err)); return ALC_FALSE; } @@ -1249,7 +1250,7 @@ static ALCenum ALCcaptureAlsa_captureSamples(ALCcaptureAlsa *self, ALCvoid *buff if(amt < 0) { ERR("restore error: %s\n", snd_strerror(amt)); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Capture recovery failure: %s", snd_strerror(amt)); break; } /* If the amount available is less than what's asked, we lost it @@ -1290,7 +1291,7 @@ static ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self) if(avail < 0) { ERR("restore error: %s\n", snd_strerror(avail)); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Capture recovery failure: %s", snd_strerror(avail)); } } @@ -1329,7 +1330,7 @@ static ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self) if(amt < 0) { ERR("restore error: %s\n", snd_strerror(amt)); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Capture recovery failure: %s", snd_strerror(amt)); break; } avail = amt; diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index 3d130615..bca8b7f0 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -267,7 +267,7 @@ FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr) { ERR("Failed to get buffer caps: 0x%lx\n", err); ALCdevice_Lock(device); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failure retrieving playback buffer info: 0x%lx", err); ALCdevice_Unlock(device); return 1; } @@ -291,7 +291,7 @@ FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr) { ERR("Failed to play buffer: 0x%lx\n", err); ALCdevice_Lock(device); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failure starting playback: 0x%lx", err); ALCdevice_Unlock(device); return 1; } @@ -339,7 +339,7 @@ FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr) { ERR("Buffer lock error: %#lx\n", err); ALCdevice_Lock(device); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed to lock output buffer: 0x%lx", err); ALCdevice_Unlock(device); return 1; } @@ -894,7 +894,8 @@ static ALCboolean ALCdsoundCapture_start(ALCdsoundCapture *self) if(FAILED(hr)) { ERR("start failed: 0x%08lx\n", hr); - aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice); + aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice, + "Failure starting capture: 0x%lx", hr); return ALC_FALSE; } @@ -909,7 +910,8 @@ static void ALCdsoundCapture_stop(ALCdsoundCapture *self) if(FAILED(hr)) { ERR("stop failed: 0x%08lx\n", hr); - aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice); + aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice, + "Failure stopping capture: 0x%lx", hr); } } @@ -959,7 +961,7 @@ static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self) if(FAILED(hr)) { ERR("update failed: 0x%08lx\n", hr); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failure retrieving capture data: 0x%lx", hr); } done: diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index 14032d45..2f17bbf6 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -241,7 +241,7 @@ static int ALCjackPlayback_bufferSizeNotify(jack_nframes_t numframes, void *arg) if(!self->Ring) { ERR("Failed to reallocate ringbuffer\n"); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed to reallocate %u-sample buffer", bufsize); } ALCjackPlayback_unlock(self); return 0; diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index d63d22df..5f1dbba8 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -632,7 +632,7 @@ FORCE_ALIGN static int ALCmmdevPlayback_mixerProc(void *arg) { ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr); V0(device->Backend,lock)(); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "COM init failed: 0x%08lx", hr); V0(device->Backend,unlock)(); return 1; } @@ -649,7 +649,7 @@ FORCE_ALIGN static int ALCmmdevPlayback_mixerProc(void *arg) { ERR("Failed to get padding: 0x%08lx\n", hr); V0(device->Backend,lock)(); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed to retrieve buffer padding: 0x%08lx", hr); V0(device->Backend,unlock)(); break; } @@ -679,7 +679,7 @@ FORCE_ALIGN static int ALCmmdevPlayback_mixerProc(void *arg) { ERR("Failed to buffer data: 0x%08lx\n", hr); V0(device->Backend,lock)(); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed to send playback samples: 0x%08lx", hr); V0(device->Backend,unlock)(); break; } @@ -1326,7 +1326,7 @@ FORCE_ALIGN int ALCmmdevCapture_recordProc(void *arg) { ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr); V0(device->Backend,lock)(); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "COM init failed: 0x%08lx", hr); V0(device->Backend,unlock)(); return 1; } @@ -1415,7 +1415,7 @@ FORCE_ALIGN int ALCmmdevCapture_recordProc(void *arg) if(FAILED(hr)) { V0(device->Backend,lock)(); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed to capture samples: 0x%08lx", hr); V0(device->Backend,unlock)(); break; } diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index fb56b67c..93d2e521 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -255,7 +255,7 @@ static int ALCopenslPlayback_mixerProc(void *arg) if(SL_RESULT_SUCCESS != result) { ALCopenslPlayback_lock(self); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed to get playback buffer: 0x%08x", result); ALCopenslPlayback_unlock(self); return 1; } @@ -283,7 +283,7 @@ static int ALCopenslPlayback_mixerProc(void *arg) } if(SL_RESULT_SUCCESS != result) { - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed to start platback: 0x%08x", result); break; } @@ -919,7 +919,8 @@ static ALCboolean ALCopenslCapture_start(ALCopenslCapture *self) if(SL_RESULT_SUCCESS != result) { ALCopenslCapture_lock(self); - aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice); + aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice, + "Failed to start capture: 0x%08x", result); ALCopenslCapture_unlock(self); return ALC_FALSE; } @@ -1002,7 +1003,7 @@ static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid * if(SL_RESULT_SUCCESS != result) { ALCopenslCapture_lock(self); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed to update capture buffer: 0x%08x", result); ALCopenslCapture_unlock(self); return ALC_INVALID_DEVICE; } diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index b2d9c555..9b0c2d42 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -299,7 +299,7 @@ static int ALCplaybackOSS_mixerProc(void *ptr) if(errno == EINTR) continue; ERR("select failed: %s\n", strerror(errno)); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed waiting for playback buffer: %s", strerror(errno)); break; } else if(sret == 0) @@ -319,7 +319,8 @@ static int ALCplaybackOSS_mixerProc(void *ptr) if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) continue; ERR("write failed: %s\n", strerror(errno)); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed writing playback samples: %s", + strerror(errno)); break; } @@ -566,7 +567,7 @@ static int ALCcaptureOSS_recordProc(void *ptr) if(errno == EINTR) continue; ERR("select failed: %s\n", strerror(errno)); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed to check capture samples: %s", strerror(errno)); break; } else if(sret == 0) @@ -583,7 +584,7 @@ static int ALCcaptureOSS_recordProc(void *ptr) { ERR("read failed: %s\n", strerror(errno)); ALCcaptureOSS_lock(self); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed reading capture samples: %s", strerror(errno)); ALCcaptureOSS_unlock(self); break; } diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index bcfbb6c2..28858a72 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -650,7 +650,7 @@ static void ALCpulsePlayback_contextStateCallback(pa_context *context, void *pda if(pa_context_get_state(context) == PA_CONTEXT_FAILED) { ERR("Received context failure!\n"); - aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice); + aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice, "Playback state failure"); } pa_threaded_mainloop_signal(self->loop, 0); } @@ -661,7 +661,7 @@ static void ALCpulsePlayback_streamStateCallback(pa_stream *stream, void *pdata) if(pa_stream_get_state(stream) == PA_STREAM_FAILED) { ERR("Received stream failure!\n"); - aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice); + aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice, "Playback stream failure"); } pa_threaded_mainloop_signal(self->loop, 0); } @@ -835,7 +835,7 @@ static int ALCpulsePlayback_mixerProc(void *ptr) if(len < 0) { ERR("Failed to get writable size: %ld", (long)len); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed to get writable size: %ld", (long)len); break; } @@ -1388,7 +1388,7 @@ static void ALCpulseCapture_contextStateCallback(pa_context *context, void *pdat if(pa_context_get_state(context) == PA_CONTEXT_FAILED) { ERR("Received context failure!\n"); - aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice); + aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice, "Capture state failure"); } pa_threaded_mainloop_signal(self->loop, 0); } @@ -1399,7 +1399,7 @@ static void ALCpulseCapture_streamStateCallback(pa_stream *stream, void *pdata) if(pa_stream_get_state(stream) == PA_STREAM_FAILED) { ERR("Received stream failure!\n"); - aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice); + aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice, "Capture stream failure"); } pa_threaded_mainloop_signal(self->loop, 0); } @@ -1662,14 +1662,15 @@ static ALCenum ALCpulseCapture_captureSamples(ALCpulseCapture *self, ALCvoid *bu state = pa_stream_get_state(self->stream); if(!PA_STREAM_IS_GOOD(state)) { - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Bad capture state: %u", state); break; } if(pa_stream_peek(self->stream, &self->cap_store, &self->cap_len) < 0) { ERR("pa_stream_peek() failed: %s\n", pa_strerror(pa_context_errno(self->context))); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed retrieving capture samples: %s", + pa_strerror(pa_context_errno(self->context))); break; } self->cap_remain = self->cap_len; @@ -1710,7 +1711,7 @@ static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self) if(got < 0) { ERR("pa_stream_readable_size() failed: %s\n", pa_strerror(got)); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed getting readable size: %s", pa_strerror(got)); } else if((size_t)got > self->cap_len) readable += got - self->cap_len; diff --git a/Alc/backends/qsa.c b/Alc/backends/qsa.c index 614d738c..484cadaa 100644 --- a/Alc/backends/qsa.c +++ b/Alc/backends/qsa.c @@ -220,7 +220,7 @@ FORCE_ALIGN static int qsa_proc_playback(void *ptr) if(sret == -1) { ERR("select error: %s\n", strerror(errno)); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed waiting for playback buffer: %s", strerror(errno)); break; } if(sret == 0) @@ -251,7 +251,7 @@ FORCE_ALIGN static int qsa_proc_playback(void *ptr) { if(snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK) < 0) { - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Playback recovery failed"); break; } } @@ -847,7 +847,7 @@ static ALCuint qsa_available_samples(CaptureWrapper *self) if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0) { ERR("capture prepare failed: %s\n", snd_strerror(rstatus)); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed capture recovery: %s", snd_strerror(rstatus)); return 0; } @@ -890,7 +890,7 @@ static ALCenum qsa_capture_samples(CaptureWrapper *self, ALCvoid *buffer, ALCuin switch (selectret) { case -1: - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed to check capture samples"); return ALC_INVALID_DEVICE; case 0: break; @@ -921,7 +921,8 @@ static ALCenum qsa_capture_samples(CaptureWrapper *self, ALCvoid *buffer, ALCuin if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0) { ERR("capture prepare failed: %s\n", snd_strerror(rstatus)); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed capture recovery: %s", + snd_strerror(rstatus)); return ALC_INVALID_DEVICE; } snd_pcm_capture_go(data->pcmHandle); diff --git a/Alc/backends/sndio.c b/Alc/backends/sndio.c index f7b9af69..06a434d9 100644 --- a/Alc/backends/sndio.c +++ b/Alc/backends/sndio.c @@ -117,7 +117,7 @@ static int ALCsndioBackend_mixerProc(void *ptr) { ERR("sio_write failed\n"); ALCdevice_Lock(device); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed to write playback samples"); ALCdevice_Unlock(device); break; } diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c index 49bfad3c..fdc62562 100644 --- a/Alc/backends/solaris.c +++ b/Alc/backends/solaris.c @@ -135,7 +135,7 @@ static int ALCsolarisBackend_mixerProc(void *ptr) if(errno == EINTR) continue; ERR("select failed: %s\n", strerror(errno)); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed to wait for playback buffer: %s", strerror(errno)); break; } else if(sret == 0) @@ -155,7 +155,8 @@ static int ALCsolarisBackend_mixerProc(void *ptr) if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) continue; ERR("write failed: %s\n", strerror(errno)); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed to write playback samples: %s", + strerror(errno)); break; } diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index ecb066f8..13ffaeec 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -204,7 +204,7 @@ static int ALCwaveBackend_mixerProc(void *ptr) { ERR("Error writing to file\n"); ALCdevice_Lock(device); - aluHandleDisconnect(device); + aluHandleDisconnect(device, "Failed to write playback samples"); ALCdevice_Unlock(device); break; } diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h index 0d39729d..920b7b44 100644 --- a/OpenAL32/Include/alu.h +++ b/OpenAL32/Include/alu.h @@ -520,7 +520,7 @@ ALboolean MixSource(struct ALvoice *voice, ALuint SourceID, ALCcontext *Context, void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples); /* Caller must lock the device, and the mixer must not be running. */ -void aluHandleDisconnect(ALCdevice *device); +void aluHandleDisconnect(ALCdevice *device, const char *msg, ...) DECL_FORMAT(printf, 2, 3); void UpdateContextProps(ALCcontext *context); -- cgit v1.2.3 From 1f61472e77faa0b57231b19236272d3e4d67fbc0 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 3 Feb 2018 13:57:04 -0800 Subject: Avoid potentially writing partial samples --- Alc/backends/pulseaudio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Alc/backends') diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index 28858a72..6ba82cd2 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -876,8 +876,10 @@ static int ALCpulsePlayback_mixerProc(void *ptr) free_func = pa_xfree; } - aluMixData(device, buf, newlen/frame_size); + newlen /= frame_size; + aluMixData(device, buf, newlen); + newlen *= frame_size; ret = pa_stream_write(self->stream, buf, newlen, free_func, 0, PA_SEEK_RELATIVE); if(ret != PA_OK) { -- cgit v1.2.3 From 9b878c64f9ec83adc4886db553ca184952ff50b4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 4 Feb 2018 00:01:12 -0800 Subject: Make the Connected state atomic Also don't send the Disconnected event more than once. --- Alc/ALc.c | 20 +++++++++++--------- Alc/ALu.c | 3 ++- Alc/backends/alsa.c | 18 +++++++++--------- Alc/backends/dsound.c | 14 +++++++------- Alc/backends/jack.c | 3 ++- Alc/backends/null.c | 13 +++++++------ Alc/backends/opensl.c | 3 ++- Alc/backends/oss.c | 3 ++- Alc/backends/pulseaudio.c | 13 +++++++------ Alc/backends/qsa.c | 13 ++++++------- Alc/backends/sndio.c | 14 +++++++------- Alc/backends/solaris.c | 3 ++- Alc/backends/wave.c | 13 ++++++------- Alc/backends/winmm.c | 24 ++++++++++-------------- OpenAL32/Include/alMain.h | 2 +- OpenAL32/alSource.c | 2 +- 16 files changed, 82 insertions(+), 79 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index 3c9598ca..915addac 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -3248,7 +3248,7 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC values[i++] = ALC_CAPTURE_SAMPLES; values[i++] = V0(device->Backend,availableSamples)(); values[i++] = ALC_CONNECTED; - values[i++] = device->Connected; + values[i++] = ATOMIC_LOAD(&device->Connected, almemory_order_relaxed); almtx_unlock(&device->BackendLock); values[i++] = 0; @@ -3268,7 +3268,7 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC return 1; case ALC_CONNECTED: - values[0] = device->Connected; + values[0] = ATOMIC_LOAD(&device->Connected, almemory_order_acquire); return 1; default: @@ -3457,7 +3457,7 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC return 1; case ALC_CONNECTED: - values[0] = device->Connected; + values[0] = ATOMIC_LOAD(&device->Connected, almemory_order_acquire); return 1; case ALC_HRTF_SOFT: @@ -3764,7 +3764,8 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin * properly cleaned up after being made. */ LockLists(); - if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected) + if(!VerifyDevice(&device) || device->Type == Capture || + !ATOMIC_LOAD(&device->Connected, almemory_order_relaxed)) { UnlockLists(); alcSetError(device, ALC_INVALID_DEVICE); @@ -4034,7 +4035,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) //Validate device InitRef(&device->ref, 1); - device->Connected = ALC_TRUE; + ATOMIC_INIT(&device->Connected, ALC_TRUE); device->Type = Playback; ATOMIC_INIT(&device->LastError, ALC_NO_ERROR); @@ -4290,7 +4291,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, //Validate device InitRef(&device->ref, 1); - device->Connected = ALC_TRUE; + ATOMIC_INIT(&device->Connected, ALC_TRUE); device->Type = Capture; InitDevice(device); @@ -4389,7 +4390,7 @@ ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device) else { almtx_lock(&device->BackendLock); - if(!device->Connected) + if(!ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) alcSetError(device, ALC_INVALID_DEVICE); else if(!(device->Flags&DEVICE_RUNNING)) { @@ -4474,7 +4475,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN //Validate device InitRef(&device->ref, 1); - device->Connected = ALC_TRUE; + ATOMIC_INIT(&device->Connected, ALC_TRUE); device->Type = Loopback; ATOMIC_INIT(&device->LastError, ALC_NO_ERROR); @@ -4675,7 +4676,8 @@ ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCi ALCenum err; LockLists(); - if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected) + if(!VerifyDevice(&device) || device->Type == Capture || + !ATOMIC_LOAD(&device->Connected, almemory_order_relaxed)) { UnlockLists(); alcSetError(device, ALC_INVALID_DEVICE); diff --git a/Alc/ALu.c b/Alc/ALu.c index 9f4f7a30..2435558d 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -1857,7 +1857,8 @@ void aluHandleDisconnect(ALCdevice *device, const char *msg, ...) va_list args; int msglen; - device->Connected = ALC_FALSE; + if(!ATOMIC_EXCHANGE(&device->Connected, AL_FALSE, almemory_order_acq_rel)) + return; evt.EnumType = EventType_Disconnected; evt.Type = AL_EVENT_TYPE_DISCONNECTED_SOFT; diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 72e2936f..c75749de 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -438,7 +438,7 @@ typedef struct ALCplaybackAlsa { ALvoid *buffer; ALsizei size; - volatile int killNow; + ATOMIC(ALenum) killNow; althrd_t thread; } ALCplaybackAlsa; @@ -468,6 +468,8 @@ static void ALCplaybackAlsa_Construct(ALCplaybackAlsa *self, ALCdevice *device) self->pcmHandle = NULL; self->buffer = NULL; + + ATOMIC_INIT(&self->killNow, AL_TRUE); } void ALCplaybackAlsa_Destruct(ALCplaybackAlsa *self) @@ -495,7 +497,7 @@ static int ALCplaybackAlsa_mixerProc(void *ptr) update_size = device->UpdateSize; num_updates = device->NumUpdates; - while(!self->killNow) + while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire)) { int state = verify_state(self->pcmHandle); if(state < 0) @@ -585,7 +587,7 @@ static int ALCplaybackAlsa_mixerNoMMapProc(void *ptr) update_size = device->UpdateSize; num_updates = device->NumUpdates; - while(!self->killNow) + while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire)) { int state = verify_state(self->pcmHandle); if(state < 0) @@ -910,7 +912,7 @@ static ALCboolean ALCplaybackAlsa_start(ALCplaybackAlsa *self) } thread_func = ALCplaybackAlsa_mixerProc; } - self->killNow = 0; + ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); if(althrd_create(&self->thread, thread_func, self) != althrd_success) { ERR("Could not create playback thread\n"); @@ -931,10 +933,8 @@ static void ALCplaybackAlsa_stop(ALCplaybackAlsa *self) { int res; - if(self->killNow) + if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel)) return; - - self->killNow = 1; althrd_join(self->thread, &res); al_free(self->buffer); @@ -1207,7 +1207,7 @@ static ALCenum ALCcaptureAlsa_captureSamples(ALCcaptureAlsa *self, ALCvoid *buff } self->last_avail -= samples; - while(device->Connected && samples > 0) + while(ATOMIC_LOAD(&device->Connected, almemory_order_acquire) && samples > 0) { snd_pcm_sframes_t amt = 0; @@ -1275,7 +1275,7 @@ static ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self) ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; snd_pcm_sframes_t avail = 0; - if(device->Connected && self->doCapture) + if(ATOMIC_LOAD(&device->Connected, almemory_order_acquire) && self->doCapture) avail = snd_pcm_avail_update(self->pcmHandle); if(avail < 0) { diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index bca8b7f0..0040a840 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -185,7 +185,7 @@ typedef struct ALCdsoundPlayback { IDirectSoundNotify *Notifies; HANDLE NotifyEvent; - volatile int killNow; + ATOMIC(ALenum) killNow; althrd_t thread; } ALCdsoundPlayback; @@ -217,6 +217,7 @@ static void ALCdsoundPlayback_Construct(ALCdsoundPlayback *self, ALCdevice *devi self->Buffer = NULL; self->Notifies = NULL; self->NotifyEvent = NULL; + ATOMIC_INIT(&self->killNow, AL_TRUE); } static void ALCdsoundPlayback_Destruct(ALCdsoundPlayback *self) @@ -276,7 +277,8 @@ FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr) FragSize = device->UpdateSize * FrameSize; IDirectSoundBuffer_GetCurrentPosition(self->Buffer, &LastCursor, NULL); - while(!self->killNow) + while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) && + ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) { // Get current play cursor IDirectSoundBuffer_GetCurrentPosition(self->Buffer, &PlayCursor, NULL); @@ -636,7 +638,7 @@ retry_open: static ALCboolean ALCdsoundPlayback_start(ALCdsoundPlayback *self) { - self->killNow = 0; + ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); if(althrd_create(&self->thread, ALCdsoundPlayback_mixerProc, self) != althrd_success) return ALC_FALSE; @@ -647,10 +649,8 @@ static void ALCdsoundPlayback_stop(ALCdsoundPlayback *self) { int res; - if(self->killNow) + if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel)) return; - - self->killNow = 1; althrd_join(self->thread, &res); IDirectSoundBuffer_Stop(self->Buffer); @@ -930,7 +930,7 @@ static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self) DWORD FrameSize; HRESULT hr; - if(!device->Connected) + if(!ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) goto done; FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index 2f17bbf6..e6f4b435 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -312,7 +312,8 @@ static int ALCjackPlayback_mixerProc(void *arg) althrd_setname(althrd_current(), MIXER_THREAD_NAME); ALCjackPlayback_lock(self); - while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) && device->Connected) + while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) && + ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) { ALuint todo, len1, len2; diff --git a/Alc/backends/null.c b/Alc/backends/null.c index d17c8bda..2c2db54e 100644 --- a/Alc/backends/null.c +++ b/Alc/backends/null.c @@ -36,7 +36,7 @@ typedef struct ALCnullBackend { DERIVE_FROM_TYPE(ALCbackend); - volatile int killNow; + ATOMIC(int) killNow; althrd_t thread; } ALCnullBackend; @@ -65,6 +65,8 @@ static void ALCnullBackend_Construct(ALCnullBackend *self, ALCdevice *device) { ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCnullBackend, ALCbackend, self); + + ATOMIC_INIT(&self->killNow, AL_TRUE); } @@ -86,7 +88,8 @@ static int ALCnullBackend_mixerProc(void *ptr) ERR("Failed to get starting time\n"); return 1; } - while(!self->killNow && device->Connected) + while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) && + ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) { if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC) { @@ -142,7 +145,7 @@ static ALCboolean ALCnullBackend_reset(ALCnullBackend *self) static ALCboolean ALCnullBackend_start(ALCnullBackend *self) { - self->killNow = 0; + ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); if(althrd_create(&self->thread, ALCnullBackend_mixerProc, self) != althrd_success) return ALC_FALSE; return ALC_TRUE; @@ -152,10 +155,8 @@ static void ALCnullBackend_stop(ALCnullBackend *self) { int res; - if(self->killNow) + if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel)) return; - - self->killNow = 1; althrd_join(self->thread, &res); } diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 93d2e521..b20d7841 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -266,7 +266,8 @@ static int ALCopenslPlayback_mixerProc(void *arg) padding = ll_ringbuffer_write_space(self->mRing) - device->NumUpdates; ALCopenslPlayback_lock(self); - while(ATOMIC_LOAD_SEQ(&self->mKillNow) == AL_FALSE && device->Connected) + while(!ATOMIC_LOAD(&self->mKillNow, almemory_order_acquire) && + ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) { size_t todo, len0, len1; diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 9b0c2d42..faf3ee99 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -284,7 +284,8 @@ static int ALCplaybackOSS_mixerProc(void *ptr) frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); ALCplaybackOSS_lock(self); - while(!ATOMIC_LOAD_SEQ(&self->killNow) && device->Connected) + while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) && + ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) { FD_ZERO(&wfds); FD_SET(self->fd, &wfds); diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index 6ba82cd2..96794e20 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -472,7 +472,7 @@ typedef struct ALCpulsePlayback { pa_stream *stream; pa_context *context; - volatile ALboolean killNow; + ATOMIC(ALenum) killNow; althrd_t thread; } ALCpulsePlayback; @@ -515,6 +515,7 @@ static void ALCpulsePlayback_Construct(ALCpulsePlayback *self, ALCdevice *device self->loop = NULL; AL_STRING_INIT(self->device_name); + ATOMIC_INIT(&self->killNow, AL_TRUE); } static void ALCpulsePlayback_Destruct(ALCpulsePlayback *self) @@ -829,7 +830,8 @@ static int ALCpulsePlayback_mixerProc(void *ptr) pa_threaded_mainloop_lock(self->loop); frame_size = pa_frame_size(&self->spec); - while(!self->killNow && device->Connected) + while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) && + ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) { len = pa_stream_writable_size(self->stream); if(len < 0) @@ -1141,7 +1143,7 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self) { - self->killNow = AL_FALSE; + ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); if(althrd_create(&self->thread, ALCpulsePlayback_mixerProc, self) != althrd_success) return ALC_FALSE; return ALC_TRUE; @@ -1152,10 +1154,9 @@ static void ALCpulsePlayback_stop(ALCpulsePlayback *self) pa_operation *o; int res; - if(!self->stream || self->killNow) + if(!self->stream || ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel)) return; - self->killNow = AL_TRUE; /* Signal the main loop in case PulseAudio isn't sending us audio requests * (e.g. if the device is suspended). We need to lock the mainloop in case * the mixer is between checking the killNow flag but before waiting for @@ -1705,7 +1706,7 @@ static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self) ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; size_t readable = self->cap_remain; - if(device->Connected) + if(ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) { ssize_t got; pa_threaded_mainloop_lock(self->loop); diff --git a/Alc/backends/qsa.c b/Alc/backends/qsa.c index 484cadaa..8f87779b 100644 --- a/Alc/backends/qsa.c +++ b/Alc/backends/qsa.c @@ -46,7 +46,7 @@ typedef struct { ALvoid* buffer; ALsizei size; - volatile int killNow; + ATOMIC(ALenum) killNow; althrd_t thread; } qsa_data; @@ -206,7 +206,7 @@ FORCE_ALIGN static int qsa_proc_playback(void *ptr) ); V0(device->Backend,lock)(); - while(!data->killNow) + while(!ATOMIC_LOAD(&data->killNow, almemory_order_acquire)) { FD_ZERO(&wfds); FD_SET(data->audio_fd, &wfds); @@ -232,7 +232,7 @@ FORCE_ALIGN static int qsa_proc_playback(void *ptr) len = data->size; write_ptr = data->buffer; aluMixData(device, write_ptr, len/frame_size); - while(len>0 && !data->killNow) + while(len>0 && !ATOMIC_LOAD(&data->killNow, almemory_order_acquire)) { int wrote = snd_pcm_plugin_write(data->pcmHandle, write_ptr, len); if(wrote <= 0) @@ -282,6 +282,7 @@ static ALCenum qsa_open_playback(PlaybackWrapper *self, const ALCchar* deviceNam data = (qsa_data*)calloc(1, sizeof(qsa_data)); if(data == NULL) return ALC_OUT_OF_MEMORY; + ATOMIC_INIT(&data->killNow, AL_TRUE); if(!deviceName) deviceName = qsaDevice; @@ -595,7 +596,7 @@ static ALCboolean qsa_start_playback(PlaybackWrapper *self) { qsa_data *data = self->ExtraData; - data->killNow = 0; + ATOMIC_STORE(&data->killNow, AL_FALSE, almemory_order_release); if(althrd_create(&data->thread, qsa_proc_playback, self) != althrd_success) return ALC_FALSE; @@ -607,10 +608,8 @@ static void qsa_stop_playback(PlaybackWrapper *self) qsa_data *data = self->ExtraData; int res; - if(data->killNow) + if(ATOMIC_EXCHANGE(&data->killNow, AL_TRUE, almemory_order_acq_rel)) return; - - data->killNow = 1; althrd_join(data->thread, &res); } diff --git a/Alc/backends/sndio.c b/Alc/backends/sndio.c index 06a434d9..5aea457b 100644 --- a/Alc/backends/sndio.c +++ b/Alc/backends/sndio.c @@ -43,7 +43,7 @@ typedef struct ALCsndioBackend { ALvoid *mix_data; ALsizei data_size; - volatile int killNow; + ATOMIC(int) killNow; althrd_t thread; } ALCsndioBackend; @@ -75,6 +75,7 @@ static void ALCsndioBackend_Construct(ALCsndioBackend *self, ALCdevice *device) self->sndHandle = NULL; self->mix_data = NULL; + ATOMIC_INIT(&self->killNow, AL_TRUE); } static void ALCsndioBackend_Destruct(ALCsndioBackend *self) @@ -102,7 +103,8 @@ static int ALCsndioBackend_mixerProc(void *ptr) frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); - while(!self->killNow && device->Connected) + while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) && + ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) { ALsizei len = self->data_size; ALubyte *WritePtr = self->mix_data; @@ -110,7 +112,7 @@ static int ALCsndioBackend_mixerProc(void *ptr) ALCsndioBackend_lock(self); aluMixData(device, WritePtr, len/frameSize); ALCsndioBackend_unlock(self); - while(len > 0 && !self->killNow) + while(len > 0 && !ATOMIC_LOAD(&self->killNow, almemory_order_acquire)) { wrote = sio_write(self->sndHandle, WritePtr, len); if(wrote == 0) @@ -253,7 +255,7 @@ static ALCboolean ALCsndioBackend_start(ALCsndioBackend *self) return ALC_FALSE; } - self->killNow = 0; + ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); if(althrd_create(&self->thread, ALCsndioBackend_mixerProc, self) != althrd_success) { sio_stop(self->sndHandle); @@ -267,10 +269,8 @@ static void ALCsndioBackend_stop(ALCsndioBackend *self) { int res; - if(self->killNow) + if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel)) return; - - self->killNow = 1; althrd_join(self->thread, &res); if(!sio_stop(self->sndHandle)) diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c index fdc62562..f1c4aeaa 100644 --- a/Alc/backends/solaris.c +++ b/Alc/backends/solaris.c @@ -120,7 +120,8 @@ static int ALCsolarisBackend_mixerProc(void *ptr) frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); ALCsolarisBackend_lock(self); - while(!ATOMIC_LOAD_SEQ(&self->killNow) && device->Connected) + while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) && + ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) { FD_ZERO(&wfds); FD_SET(self->fd, &wfds); diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index 13ffaeec..557c2bf2 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -77,7 +77,7 @@ typedef struct ALCwaveBackend { ALvoid *mBuffer; ALuint mSize; - volatile int killNow; + ATOMIC(ALenum) killNow; althrd_t thread; } ALCwaveBackend; @@ -110,7 +110,7 @@ static void ALCwaveBackend_Construct(ALCwaveBackend *self, ALCdevice *device) self->mBuffer = NULL; self->mSize = 0; - self->killNow = 1; + ATOMIC_INIT(&self->killNow, AL_TRUE); } static void ALCwaveBackend_Destruct(ALCwaveBackend *self) @@ -143,7 +143,8 @@ static int ALCwaveBackend_mixerProc(void *ptr) ERR("Failed to get starting time\n"); return 1; } - while(!self->killNow && device->Connected) + while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) && + ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) { if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC) { @@ -355,7 +356,7 @@ static ALCboolean ALCwaveBackend_start(ALCwaveBackend *self) return ALC_FALSE; } - self->killNow = 0; + ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); if(althrd_create(&self->thread, ALCwaveBackend_mixerProc, self) != althrd_success) { free(self->mBuffer); @@ -373,10 +374,8 @@ static void ALCwaveBackend_stop(ALCwaveBackend *self) long size; int res; - if(self->killNow) + if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel)) return; - - self->killNow = 1; althrd_join(self->thread, &res); free(self->mBuffer); diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index 59164441..d6ecd7a9 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -148,7 +148,7 @@ typedef struct ALCwinmmPlayback { WAVEFORMATEX Format; - volatile ALboolean killNow; + ATOMIC(ALenum) killNow; althrd_t thread; } ALCwinmmPlayback; @@ -180,7 +180,7 @@ static void ALCwinmmPlayback_Construct(ALCwinmmPlayback *self, ALCdevice *device InitRef(&self->WaveBuffersCommitted, 0); self->OutHdl = NULL; - self->killNow = AL_TRUE; + ATOMIC_INIT(&self->killNow, AL_TRUE); } static void ALCwinmmPlayback_Destruct(ALCwinmmPlayback *self) @@ -224,7 +224,7 @@ FORCE_ALIGN static int ALCwinmmPlayback_mixerProc(void *arg) if(msg.message != WOM_DONE) continue; - if(self->killNow) + if(ATOMIC_LOAD(&self->killNow, almemory_order_acquire)) { if(ReadRef(&self->WaveBuffersCommitted) == 0) break; @@ -371,7 +371,7 @@ static ALCboolean ALCwinmmPlayback_start(ALCwinmmPlayback *self) ALint BufferSize; ALuint i; - self->killNow = AL_FALSE; + ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); if(althrd_create(&self->thread, ALCwinmmPlayback_mixerProc, self) != althrd_success) return ALC_FALSE; @@ -402,11 +402,8 @@ static void ALCwinmmPlayback_stop(ALCwinmmPlayback *self) void *buffer = NULL; int i; - if(self->killNow) + if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel)) return; - - // Set flag to stop processing headers - self->killNow = AL_TRUE; althrd_join(self->thread, &i); // Release the wave buffers @@ -433,7 +430,7 @@ typedef struct ALCwinmmCapture { WAVEFORMATEX Format; - volatile ALboolean killNow; + ATOMIC(ALenum) killNow; althrd_t thread; } ALCwinmmCapture; @@ -465,7 +462,7 @@ static void ALCwinmmCapture_Construct(ALCwinmmCapture *self, ALCdevice *device) InitRef(&self->WaveBuffersCommitted, 0); self->InHdl = NULL; - self->killNow = AL_TRUE; + ATOMIC_INIT(&self->killNow, AL_TRUE); } static void ALCwinmmCapture_Destruct(ALCwinmmCapture *self) @@ -474,9 +471,8 @@ static void ALCwinmmCapture_Destruct(ALCwinmmCapture *self) int i; /* Tell the processing thread to quit and wait for it to do so. */ - if(!self->killNow) + if(!ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel)) { - self->killNow = AL_TRUE; PostThreadMessage(self->thread, WM_QUIT, 0, 0); althrd_join(self->thread, &i); @@ -536,7 +532,7 @@ static int ALCwinmmCapture_captureProc(void *arg) continue; /* Don't wait for other buffers to finish before quitting. We're * closing so we don't need them. */ - if(self->killNow) + if(ATOMIC_LOAD(&self->killNow, almemory_order_acquire)) break; WaveHdr = ((WAVEHDR*)msg.lParam); @@ -656,7 +652,7 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name) IncrementRef(&self->WaveBuffersCommitted); } - self->killNow = AL_FALSE; + ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); if(althrd_create(&self->thread, ALCwinmmCapture_captureProc, self) != althrd_success) goto failure; diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 5c2435a4..baf610b8 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -466,7 +466,7 @@ struct ALCdevice_struct { RefCount ref; - ALCboolean Connected; + ATOMIC(ALenum) Connected; enum DeviceType Type; ALuint Frequency; diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index c20226ca..8c8b2149 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -2518,7 +2518,7 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) device = context->Device; ALCdevice_Lock(device); /* If the device is disconnected, go right to stopped. */ - if(!device->Connected) + if(!ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) { for(i = 0;i < n;i++) { -- cgit v1.2.3 From 6f62fed65c4dcdf999a612e258cca59a22355f3c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 1 Mar 2018 21:23:13 -0800 Subject: Add an option to limit the write size of the ringbuffer --- Alc/backends/alsa.c | 3 ++- Alc/backends/coreaudio.c | 2 +- Alc/backends/dsound.c | 2 +- Alc/backends/jack.c | 6 ++++-- Alc/backends/mmdevapi.c | 3 ++- Alc/backends/opensl.c | 16 +++++----------- Alc/backends/oss.c | 2 +- Alc/backends/portaudio.c | 2 +- Alc/backends/winmm.c | 2 +- Alc/ringbuffer.c | 32 +++++++++++++++++--------------- Alc/ringbuffer.h | 2 +- OpenAL32/event.c | 2 +- 12 files changed, 37 insertions(+), 37 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index c75749de..d0f0e24e 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -1124,7 +1124,8 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name) { self->ring = ll_ringbuffer_create( device->UpdateSize*device->NumUpdates + 1, - FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder) + FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder), + false ); if(!self->ring) { diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index 3db0d702..caa01167 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -664,7 +664,7 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar self->ring = ll_ringbuffer_create( device->UpdateSize*self->sampleRateRatio*device->NumUpdates + 1, - self->frameSize + self->frameSize, false ); if(!self->ring) goto error; diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index 0040a840..4c52e0f8 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -857,7 +857,7 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi if(SUCCEEDED(hr)) { self->Ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates + 1, - InputType.Format.nBlockAlign); + InputType.Format.nBlockAlign, false); if(self->Ring == NULL) hr = DSERR_OUTOFMEMORY; } diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index e6f4b435..003877a4 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -236,7 +236,8 @@ static int ALCjackPlayback_bufferSizeNotify(jack_nframes_t numframes, void *arg) ll_ringbuffer_free(self->Ring); self->Ring = ll_ringbuffer_create(bufsize, - FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder) + FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder), + true ); if(!self->Ring) { @@ -437,7 +438,8 @@ static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self) ll_ringbuffer_free(self->Ring); self->Ring = ll_ringbuffer_create(bufsize, - FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder) + FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder), + true ); if(!self->Ring) { diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 5f1dbba8..34dcf468 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -1813,7 +1813,8 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) buffer_len = maxu(device->UpdateSize*device->NumUpdates + 1, buffer_len); ll_ringbuffer_free(self->Ring); self->Ring = ll_ringbuffer_create(buffer_len, - FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder) + FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder), + false ); if(!self->Ring) { diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index b20d7841..d930526d 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -239,7 +239,6 @@ static int ALCopenslPlayback_mixerProc(void *arg) ll_ringbuffer_data_t data[2]; SLPlayItf player; SLresult result; - size_t padding; SetRTPriority(); althrd_setname(althrd_current(), MIXER_THREAD_NAME); @@ -260,18 +259,13 @@ static int ALCopenslPlayback_mixerProc(void *arg) return 1; } - /* NOTE: The ringbuffer will be larger than the desired buffer metrics. - * Calculate the amount of extra space so we know how much to keep unused. - */ - padding = ll_ringbuffer_write_space(self->mRing) - device->NumUpdates; - ALCopenslPlayback_lock(self); while(!ATOMIC_LOAD(&self->mKillNow, almemory_order_acquire) && ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) { size_t todo, len0, len1; - if(ll_ringbuffer_write_space(self->mRing) <= padding) + if(ll_ringbuffer_write_space(self->mRing) == 0) { SLuint32 state = 0; @@ -288,7 +282,7 @@ static int ALCopenslPlayback_mixerProc(void *arg) break; } - if(ll_ringbuffer_write_space(self->mRing) <= padding) + if(ll_ringbuffer_write_space(self->mRing) == 0) { ALCopenslPlayback_unlock(self); alsem_wait(&self->mSem); @@ -298,7 +292,7 @@ static int ALCopenslPlayback_mixerProc(void *arg) } ll_ringbuffer_get_write_vector(self->mRing, data); - todo = data[0].len+data[1].len - padding; + todo = data[0].len+data[1].len; len0 = minu(todo, data[0].len); len1 = minu(todo-len0, data[1].len); @@ -577,7 +571,7 @@ static ALCboolean ALCopenslPlayback_start(ALCopenslPlayback *self) * buffer will not be writeable, and we only write in period-sized chunks. */ self->mRing = ll_ringbuffer_create(device->NumUpdates + 1, - self->mFrameSize*device->UpdateSize); + self->mFrameSize*device->UpdateSize, true); result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bufferQueue); @@ -854,7 +848,7 @@ static ALCenum ALCopenslCapture_open(ALCopenslCapture *self, const ALCchar *name if(SL_RESULT_SUCCESS == result) { self->mRing = ll_ringbuffer_create(device->NumUpdates + 1, - device->UpdateSize * self->mFrameSize); + device->UpdateSize * self->mFrameSize, false); result = VCALL(self->mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bufferQueue); diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index faf3ee99..61d25476 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -729,7 +729,7 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) return ALC_INVALID_VALUE; } - self->ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates + 1, frameSize); + self->ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates + 1, frameSize, false); if(!self->ring) { ERR("Ring buffer create failed\n"); diff --git a/Alc/backends/portaudio.c b/Alc/backends/portaudio.c index fdc8a2a5..9b0d3487 100644 --- a/Alc/backends/portaudio.c +++ b/Alc/backends/portaudio.c @@ -395,7 +395,7 @@ static ALCenum ALCportCapture_open(ALCportCapture *self, const ALCchar *name) samples = maxu(samples, 100 * device->Frequency / 1000); frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); - self->ring = ll_ringbuffer_create(samples, frame_size); + self->ring = ll_ringbuffer_create(samples, frame_size, false); if(self->ring == NULL) return ALC_INVALID_VALUE; self->params.device = -1; diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index d6ecd7a9..787ba8e4 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -626,7 +626,7 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name) if(CapturedDataSize < (self->Format.nSamplesPerSec / 10)) CapturedDataSize = self->Format.nSamplesPerSec / 10; - self->Ring = ll_ringbuffer_create(CapturedDataSize+1, self->Format.nBlockAlign); + self->Ring = ll_ringbuffer_create(CapturedDataSize+1, self->Format.nBlockAlign, false); if(!self->Ring) goto failure; InitRef(&self->WaveBuffersCommitted, 0); diff --git a/Alc/ringbuffer.c b/Alc/ringbuffer.c index c594331e..02fa857c 100644 --- a/Alc/ringbuffer.c +++ b/Alc/ringbuffer.c @@ -48,7 +48,7 @@ struct ll_ringbuffer { /* Create a new ringbuffer to hold at least `sz' elements of `elem_sz' bytes. * The number of elements is rounded up to the next power of two. */ -ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz) +ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz, int limit_writes) { ll_ringbuffer_t *rb; size_t power_of_two = 0; @@ -73,8 +73,8 @@ ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz) ATOMIC_INIT(&rb->write_ptr, 0); ATOMIC_INIT(&rb->read_ptr, 0); - rb->size = power_of_two; - rb->size_mask = rb->size - 1; + rb->size = limit_writes ? sz : power_of_two; + rb->size_mask = power_of_two - 1; rb->elem_size = elem_sz; return rb; } @@ -90,7 +90,7 @@ void ll_ringbuffer_reset(ll_ringbuffer_t *rb) { ATOMIC_STORE(&rb->write_ptr, 0, almemory_order_release); ATOMIC_STORE(&rb->read_ptr, 0, almemory_order_release); - memset(rb->buf, 0, rb->size*rb->elem_size); + memset(rb->buf, 0, (rb->size_mask+1)*rb->elem_size); } /* Return the number of elements available for reading. This is the number of @@ -107,7 +107,8 @@ size_t ll_ringbuffer_write_space(const ll_ringbuffer_t *rb) { size_t w = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->write_ptr, almemory_order_acquire); size_t r = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->read_ptr, almemory_order_acquire); - return (r-w-1) & rb->size_mask; + w = (r-w-1) & rb->size_mask; + return (w > rb->size) ? rb->size : w; } /* The copying data reader. Copy at most `cnt' elements from `rb' to `dest'. @@ -127,9 +128,9 @@ size_t ll_ringbuffer_read(ll_ringbuffer_t *rb, char *dest, size_t cnt) read_ptr = ATOMIC_LOAD(&rb->read_ptr, almemory_order_relaxed) & rb->size_mask; cnt2 = read_ptr + to_read; - if(cnt2 > rb->size) + if(cnt2 > rb->size_mask+1) { - n1 = rb->size - read_ptr; + n1 = rb->size_mask+1 - read_ptr; n2 = cnt2 & rb->size_mask; } else @@ -168,9 +169,9 @@ size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, char *dest, size_t cnt) read_ptr = ATOMIC_LOAD(&rb->read_ptr, almemory_order_relaxed) & rb->size_mask; cnt2 = read_ptr + to_read; - if(cnt2 > rb->size) + if(cnt2 > rb->size_mask+1) { - n1 = rb->size - read_ptr; + n1 = rb->size_mask+1 - read_ptr; n2 = cnt2 & rb->size_mask; } else @@ -206,9 +207,9 @@ size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const char *src, size_t cnt) write_ptr = ATOMIC_LOAD(&rb->write_ptr, almemory_order_relaxed) & rb->size_mask; cnt2 = write_ptr + to_write; - if(cnt2 > rb->size) + if(cnt2 > rb->size_mask+1) { - n1 = rb->size - write_ptr; + n1 = rb->size_mask+1 - write_ptr; n2 = cnt2 & rb->size_mask; } else @@ -257,12 +258,12 @@ void ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data free_cnt = (w-r) & rb->size_mask; cnt2 = r + free_cnt; - if(cnt2 > rb->size) + if(cnt2 > rb->size_mask+1) { /* Two part vector: the rest of the buffer after the current write ptr, * plus some from the start of the buffer. */ vec[0].buf = (char*)&rb->buf[r*rb->elem_size]; - vec[0].len = rb->size - r; + vec[0].len = rb->size_mask+1 - r; vec[1].buf = (char*)rb->buf; vec[1].len = cnt2 & rb->size_mask; } @@ -290,14 +291,15 @@ void ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_dat w &= rb->size_mask; r &= rb->size_mask; free_cnt = (r-w-1) & rb->size_mask; + if(free_cnt > rb->size) free_cnt = rb->size; cnt2 = w + free_cnt; - if(cnt2 > rb->size) + if(cnt2 > rb->size_mask+1) { /* Two part vector: the rest of the buffer after the current write ptr, * plus some from the start of the buffer. */ vec[0].buf = (char*)&rb->buf[w*rb->elem_size]; - vec[0].len = rb->size - w; + vec[0].len = rb->size_mask+1 - w; vec[1].buf = (char*)rb->buf; vec[1].len = cnt2 & rb->size_mask; } diff --git a/Alc/ringbuffer.h b/Alc/ringbuffer.h index f764c20f..c1a7a6fa 100644 --- a/Alc/ringbuffer.h +++ b/Alc/ringbuffer.h @@ -10,7 +10,7 @@ typedef struct ll_ringbuffer_data { size_t len; } ll_ringbuffer_data_t; -ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz); +ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz, int limit_writes); void ll_ringbuffer_free(ll_ringbuffer_t *rb); void ll_ringbuffer_reset(ll_ringbuffer_t *rb); diff --git a/OpenAL32/event.c b/OpenAL32/event.c index ef36f977..333b7613 100644 --- a/OpenAL32/event.c +++ b/OpenAL32/event.c @@ -78,7 +78,7 @@ AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, A bool isrunning; almtx_lock(&context->EventThrdLock); if(!context->AsyncEvents) - context->AsyncEvents = ll_ringbuffer_create(64, sizeof(AsyncEvent)); + context->AsyncEvents = ll_ringbuffer_create(63, sizeof(AsyncEvent), false); enabledevts = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed); isrunning = !!enabledevts; while(ATOMIC_COMPARE_EXCHANGE_WEAK(&context->EnabledEvts, &enabledevts, enabledevts|flags, -- cgit v1.2.3 From 03274a5b95146675c05b5b6a0340f45a7b122c50 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 2 Mar 2018 12:46:31 -0800 Subject: Ensure at least the specified ringbuffer size is writable Previously, all but one of the specified size could be written (so for a size of n, only n-1 was guaranteed writable). All users pretty much compensated for this, but it makes more sense to fix it at the source. --- Alc/backends/alsa.c | 2 +- Alc/backends/coreaudio.c | 2 +- Alc/backends/dsound.c | 2 +- Alc/backends/jack.c | 10 +++------- Alc/backends/mmdevapi.c | 2 +- Alc/backends/opensl.c | 12 ++++-------- Alc/backends/oss.c | 2 +- Alc/backends/winmm.c | 2 +- Alc/ringbuffer.c | 34 ++++++++-------------------------- Alc/ringbuffer.h | 48 ++++++++++++++++++++++++++++++++++++++++++++---- 10 files changed, 65 insertions(+), 51 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index d0f0e24e..9fc36582 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -1123,7 +1123,7 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name) if(needring) { self->ring = ll_ringbuffer_create( - device->UpdateSize*device->NumUpdates + 1, + device->UpdateSize*device->NumUpdates, FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder), false ); diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index caa01167..b2545c47 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -663,7 +663,7 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar goto error; self->ring = ll_ringbuffer_create( - device->UpdateSize*self->sampleRateRatio*device->NumUpdates + 1, + (size_t)ceil(device->UpdateSize*self->sampleRateRatio*device->NumUpdates), self->frameSize, false ); if(!self->ring) goto error; diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index 4c52e0f8..6bab641c 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -856,7 +856,7 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi hr = IDirectSoundCapture_CreateCaptureBuffer(self->DSC, &DSCBDescription, &self->DSCbuffer, NULL); if(SUCCEEDED(hr)) { - self->Ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates + 1, + self->Ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates, InputType.Format.nBlockAlign, false); if(self->Ring == NULL) hr = DSERR_OUTOFMEMORY; diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index 003877a4..67e3c106 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -229,8 +229,7 @@ static int ALCjackPlayback_bufferSizeNotify(jack_nframes_t numframes, void *arg) bufsize = device->UpdateSize; if(ConfigValueUInt(alstr_get_cstr(device->DeviceName), "jack", "buffer-size", &bufsize)) bufsize = maxu(NextPowerOf2(bufsize), device->UpdateSize); - bufsize += device->UpdateSize; - device->NumUpdates = bufsize / device->UpdateSize; + device->NumUpdates = (bufsize+device->UpdateSize) / device->UpdateSize; TRACE("%u update size x%u\n", device->UpdateSize, device->NumUpdates); @@ -391,9 +390,7 @@ static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self) } /* Ignore the requested buffer metrics and just keep one JACK-sized buffer - * ready for when requested. Note that one period's worth of audio in the - * ring buffer will always be left unfilled because one element of the ring - * buffer will not be writeable, and we only write in period-sized chunks. + * ready for when requested. */ device->Frequency = jack_get_sample_rate(self->Client); device->UpdateSize = jack_get_buffer_size(self->Client); @@ -402,8 +399,7 @@ static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self) bufsize = device->UpdateSize; if(ConfigValueUInt(alstr_get_cstr(device->DeviceName), "jack", "buffer-size", &bufsize)) bufsize = maxu(NextPowerOf2(bufsize), device->UpdateSize); - bufsize += device->UpdateSize; - device->NumUpdates = bufsize / device->UpdateSize; + device->NumUpdates = (bufsize+device->UpdateSize) / device->UpdateSize; /* Force 32-bit float output. */ device->FmtType = DevFmtFloat; diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 34dcf468..961cba52 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -1810,7 +1810,7 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) return hr; } - buffer_len = maxu(device->UpdateSize*device->NumUpdates + 1, buffer_len); + buffer_len = maxu(device->UpdateSize*device->NumUpdates, buffer_len); ll_ringbuffer_free(self->Ring); self->Ring = ll_ringbuffer_create(buffer_len, FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder), diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index d930526d..a5ad3b09 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -566,12 +566,8 @@ static ALCboolean ALCopenslPlayback_start(ALCopenslPlayback *self) SLresult result; ll_ringbuffer_free(self->mRing); - /* NOTE: Add an extra update since one period's worth of audio in the ring - * buffer will always be left unfilled because one element of the ring - * buffer will not be writeable, and we only write in period-sized chunks. - */ - self->mRing = ll_ringbuffer_create(device->NumUpdates + 1, - self->mFrameSize*device->UpdateSize, true); + self->mRing = ll_ringbuffer_create(device->NumUpdates, self->mFrameSize*device->UpdateSize, + true); result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bufferQueue); @@ -847,8 +843,8 @@ static ALCenum ALCopenslCapture_open(ALCopenslCapture *self, const ALCchar *name if(SL_RESULT_SUCCESS == result) { - self->mRing = ll_ringbuffer_create(device->NumUpdates + 1, - device->UpdateSize * self->mFrameSize, false); + self->mRing = ll_ringbuffer_create(device->NumUpdates, device->UpdateSize*self->mFrameSize, + false); result = VCALL(self->mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bufferQueue); diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 61d25476..c0c98c43 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -729,7 +729,7 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) return ALC_INVALID_VALUE; } - self->ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates + 1, frameSize, false); + self->ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates, frameSize, false); if(!self->ring) { ERR("Ring buffer create failed\n"); diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index 787ba8e4..2f4c65df 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -626,7 +626,7 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name) if(CapturedDataSize < (self->Format.nSamplesPerSec / 10)) CapturedDataSize = self->Format.nSamplesPerSec / 10; - self->Ring = ll_ringbuffer_create(CapturedDataSize+1, self->Format.nBlockAlign, false); + self->Ring = ll_ringbuffer_create(CapturedDataSize, self->Format.nBlockAlign, false); if(!self->Ring) goto failure; InitRef(&self->WaveBuffersCommitted, 0); diff --git a/Alc/ringbuffer.c b/Alc/ringbuffer.c index 02fa857c..6c419cf8 100644 --- a/Alc/ringbuffer.c +++ b/Alc/ringbuffer.c @@ -46,8 +46,6 @@ struct ll_ringbuffer { alignas(16) char buf[]; }; -/* Create a new ringbuffer to hold at least `sz' elements of `elem_sz' bytes. - * The number of elements is rounded up to the next power of two. */ ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz, int limit_writes) { ll_ringbuffer_t *rb; @@ -55,7 +53,7 @@ ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz, int limit_write if(sz > 0) { - power_of_two = sz - 1; + power_of_two = sz; power_of_two |= power_of_two>>1; power_of_two |= power_of_two>>2; power_of_two |= power_of_two>>4; @@ -79,13 +77,11 @@ ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz, int limit_write return rb; } -/* Free all data associated with the ringbuffer `rb'. */ void ll_ringbuffer_free(ll_ringbuffer_t *rb) { al_free(rb); } -/* Reset the read and write pointers to zero. This is not thread safe. */ void ll_ringbuffer_reset(ll_ringbuffer_t *rb) { ATOMIC_STORE(&rb->write_ptr, 0, almemory_order_release); @@ -93,16 +89,14 @@ void ll_ringbuffer_reset(ll_ringbuffer_t *rb) memset(rb->buf, 0, (rb->size_mask+1)*rb->elem_size); } -/* Return the number of elements available for reading. This is the number of - * elements in front of the read pointer and behind the write pointer. */ + size_t ll_ringbuffer_read_space(const ll_ringbuffer_t *rb) { size_t w = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->write_ptr, almemory_order_acquire); size_t r = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->read_ptr, almemory_order_acquire); return (w-r) & rb->size_mask; } -/* Return the number of elements available for writing. This is the number of - * elements in front of the write pointer and behind the read pointer. */ + size_t ll_ringbuffer_write_space(const ll_ringbuffer_t *rb) { size_t w = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->write_ptr, almemory_order_acquire); @@ -111,8 +105,7 @@ size_t ll_ringbuffer_write_space(const ll_ringbuffer_t *rb) return (w > rb->size) ? rb->size : w; } -/* The copying data reader. Copy at most `cnt' elements from `rb' to `dest'. - * Returns the actual number of elements copied. */ + size_t ll_ringbuffer_read(ll_ringbuffer_t *rb, char *dest, size_t cnt) { size_t read_ptr; @@ -151,9 +144,6 @@ size_t ll_ringbuffer_read(ll_ringbuffer_t *rb, char *dest, size_t cnt) return to_read; } -/* The copying data reader w/o read pointer advance. Copy at most `cnt' - * elements from `rb' to `dest'. Returns the actual number of elements copied. - */ size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, char *dest, size_t cnt) { size_t free_cnt; @@ -190,8 +180,6 @@ size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, char *dest, size_t cnt) return to_read; } -/* The copying data writer. Copy at most `cnt' elements to `rb' from `src'. - * Returns the actual number of elements copied. */ size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const char *src, size_t cnt) { size_t write_ptr; @@ -230,22 +218,19 @@ size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const char *src, size_t cnt) return to_write; } -/* Advance the read pointer `cnt' places. */ + void ll_ringbuffer_read_advance(ll_ringbuffer_t *rb, size_t cnt) { ATOMIC_ADD(&rb->read_ptr, cnt, almemory_order_acq_rel); } -/* Advance the write pointer `cnt' places. */ void ll_ringbuffer_write_advance(ll_ringbuffer_t *rb, size_t cnt) { ATOMIC_ADD(&rb->write_ptr, cnt, almemory_order_acq_rel); } -/* The non-copying data reader. `vec' is an array of two places. Set the values - * at `vec' to hold the current readable data at `rb'. If the readable data is - * in one segment the second segment has zero length. */ -void ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t * vec) + +void ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t vec[2]) { size_t free_cnt; size_t cnt2; @@ -277,10 +262,7 @@ void ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data } } -/* The non-copying data writer. `vec' is an array of two places. Set the values - * at `vec' to hold the current writeable data at `rb'. If the writeable data - * is in one segment the second segment has zero length. */ -void ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t *vec) +void ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t vec[2]) { size_t free_cnt; size_t cnt2; diff --git a/Alc/ringbuffer.h b/Alc/ringbuffer.h index c1a7a6fa..bcf67374 100644 --- a/Alc/ringbuffer.h +++ b/Alc/ringbuffer.h @@ -10,20 +10,60 @@ typedef struct ll_ringbuffer_data { size_t len; } ll_ringbuffer_data_t; + +/** + * Create a new ringbuffer to hold at least `sz' elements of `elem_sz' bytes. + * The number of elements is rounded up to the next power of two (even if it is + * already a power of two, to ensure the requested amount can be written). + */ ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz, int limit_writes); +/** Free all data associated with the ringbuffer `rb'. */ void ll_ringbuffer_free(ll_ringbuffer_t *rb); +/** Reset the read and write pointers to zero. This is not thread safe. */ void ll_ringbuffer_reset(ll_ringbuffer_t *rb); -void ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t *vec); -void ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t *vec); +/** + * The non-copying data reader. `vec' is an array of two places. Set the values + * at `vec' to hold the current readable data at `rb'. If the readable data is + * in one segment the second segment has zero length. + */ +void ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t vec[2]); +/** + * The non-copying data writer. `vec' is an array of two places. Set the values + * at `vec' to hold the current writeable data at `rb'. If the writeable data + * is in one segment the second segment has zero length. + */ +void ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t vec[2]); +/** + * Return the number of elements available for reading. This is the number of + * elements in front of the read pointer and behind the write pointer. + */ +size_t ll_ringbuffer_read_space(const ll_ringbuffer_t *rb); +/** + * The copying data reader. Copy at most `cnt' elements from `rb' to `dest'. + * Returns the actual number of elements copied. + */ size_t ll_ringbuffer_read(ll_ringbuffer_t *rb, char *dest, size_t cnt); +/** + * The copying data reader w/o read pointer advance. Copy at most `cnt' + * elements from `rb' to `dest'. Returns the actual number of elements copied. + */ size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, char *dest, size_t cnt); +/** Advance the read pointer `cnt' places. */ void ll_ringbuffer_read_advance(ll_ringbuffer_t *rb, size_t cnt); -size_t ll_ringbuffer_read_space(const ll_ringbuffer_t *rb); +/** + * Return the number of elements available for writing. This is the number of + * elements in front of the write pointer and behind the read pointer. + */ +size_t ll_ringbuffer_write_space(const ll_ringbuffer_t *rb); +/** + * The copying data writer. Copy at most `cnt' elements to `rb' from `src'. + * Returns the actual number of elements copied. + */ size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const char *src, size_t cnt); +/** Advance the write pointer `cnt' places. */ void ll_ringbuffer_write_advance(ll_ringbuffer_t *rb, size_t cnt); -size_t ll_ringbuffer_write_space(const ll_ringbuffer_t *rb); #endif /* RINGBUFFER_H */ -- cgit v1.2.3 From 86319127e3e377312f815d55693f7b46569cde62 Mon Sep 17 00:00:00 2001 From: Jan Niklas Hasse Date: Wed, 7 Mar 2018 20:53:56 +0100 Subject: Add SDL2 backend for playback, fix #173 --- Alc/ALc.c | 3 + Alc/backends/base.h | 1 + Alc/backends/sdl2.c | 265 ++++++++++++++++++++++++++++++++++++++++++++++++++++ CMakeLists.txt | 22 ++++- config.h.in | 3 + 5 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 Alc/backends/sdl2.c (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index 0cde449e..c72a1833 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -100,6 +100,9 @@ static struct BackendInfo BackendList[] = { #ifdef HAVE_OPENSL { "opensl", ALCopenslBackendFactory_getFactory }, #endif +#ifdef HAVE_SDL2 + { "sdl2", ALCsdl2BackendFactory_getFactory }, +#endif { "null", ALCnullBackendFactory_getFactory }, #ifdef HAVE_WAVE diff --git a/Alc/backends/base.h b/Alc/backends/base.h index 177f6869..b05523b2 100644 --- a/Alc/backends/base.h +++ b/Alc/backends/base.h @@ -147,6 +147,7 @@ ALCbackendFactory *ALCportBackendFactory_getFactory(void); ALCbackendFactory *ALCopenslBackendFactory_getFactory(void); ALCbackendFactory *ALCnullBackendFactory_getFactory(void); ALCbackendFactory *ALCwaveBackendFactory_getFactory(void); +ALCbackendFactory *ALCsdl2BackendFactory_getFactory(void); ALCbackendFactory *ALCloopbackFactory_getFactory(void); diff --git a/Alc/backends/sdl2.c b/Alc/backends/sdl2.c new file mode 100644 index 00000000..4b2d3acd --- /dev/null +++ b/Alc/backends/sdl2.c @@ -0,0 +1,265 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2018 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include +#include + +#include "alMain.h" +#include "alu.h" +#include "threads.h" +#include "compat.h" + +#include "backends/base.h" + + +typedef struct ALCsdl2Backend { + DERIVE_FROM_TYPE(ALCbackend); + + SDL_AudioDeviceID deviceID; + ALvoid *mBuffer; + ALuint mSize; + ALCboolean quit; + ATOMIC(int) killNow; + althrd_t thread; +} ALCsdl2Backend; + +static int ALCsdl2Backend_mixerProc(void *ptr); + +static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device); +static DECLARE_FORWARD(ALCsdl2Backend, ALCbackend, void, Destruct) +static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name); +static ALCboolean ALCsdl2Backend_reset(ALCsdl2Backend *self); +static ALCboolean ALCsdl2Backend_start(ALCsdl2Backend *self); +static void ALCsdl2Backend_stop(ALCsdl2Backend *self); +static DECLARE_FORWARD2(ALCsdl2Backend, ALCbackend, ALCenum, captureSamples, void*, ALCuint) +static DECLARE_FORWARD(ALCsdl2Backend, ALCbackend, ALCuint, availableSamples) +static DECLARE_FORWARD(ALCsdl2Backend, ALCbackend, ClockLatency, getClockLatency) +static DECLARE_FORWARD(ALCsdl2Backend, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCsdl2Backend, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCsdl2Backend) + +DEFINE_ALCBACKEND_VTABLE(ALCsdl2Backend); + +static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCsdl2Backend, ALCbackend, self); + + self->mBuffer = NULL; + self->mSize = 0; + self->quit = ALC_FALSE; + if(SDL_WasInit(0) == 0) // Is SDL2 initialized at all? + { + SDL_Init(SDL_INIT_AUDIO); + self->quit = ALC_TRUE; + } + else if(!SDL_WasInit(SDL_INIT_AUDIO)) + SDL_InitSubSystem(SDL_INIT_AUDIO); + + ATOMIC_INIT(&self->killNow, AL_TRUE); +} + + +static int ALCsdl2Backend_mixerProc(void *ptr) +{ + ALCsdl2Backend *self = (ALCsdl2Backend*)ptr; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + struct timespec now, start; + ALuint64 avail, done; + const long restTime = (long)((ALuint64)device->UpdateSize * 1000000000 / + device->Frequency / 2); + + SetRTPriority(); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); + + done = 0; + if(altimespec_get(&start, AL_TIME_UTC) != AL_TIME_UTC) + { + ERR("Failed to get starting time\n"); + return 1; + } + while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) && + ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) + { + if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC) + { + ERR("Failed to get current time\n"); + return 1; + } + + avail = (now.tv_sec - start.tv_sec) * device->Frequency; + avail += (ALint64)(now.tv_nsec - start.tv_nsec) * device->Frequency / 1000000000; + if(avail < done) + { + /* Oops, time skipped backwards. Reset the number of samples done + * with one update available since we (likely) just came back from + * sleeping. */ + done = avail - device->UpdateSize; + } + + if(avail-done < device->UpdateSize) + al_nssleep(restTime); + else while(avail-done >= device->UpdateSize) + { + ALCsdl2Backend_lock(self); + aluMixData(device, self->mBuffer, device->UpdateSize); + SDL_QueueAudio(self->deviceID, self->mBuffer, self->mSize); + ALCsdl2Backend_unlock(self); + done += device->UpdateSize; + } + } + + return 0; +} + +static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + SDL_AudioSpec want; + SDL_zero(want); + want.freq = device->Frequency; + want.format = AUDIO_F32; + want.channels = 2; + want.samples = device->UpdateSize; + + if(!name) + name = SDL_GetAudioDeviceName(0, 0); + self->deviceID = SDL_OpenAudioDevice(name, 0, &want, NULL, 0); + if(self->deviceID == 0) { + ERR("Could not open device\n"); + return ALC_INVALID_VALUE; + } + alstr_copy_cstr(&STATIC_CAST(ALCbackend, self)->mDevice->DeviceName, name); + + return ALC_NO_ERROR; +} + +static ALCboolean ALCsdl2Backend_reset(ALCsdl2Backend *self) +{ + SetDefaultWFXChannelOrder(STATIC_CAST(ALCbackend, self)->mDevice); + return ALC_TRUE; +} + +static ALCboolean ALCsdl2Backend_start(ALCsdl2Backend *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + self->mSize = device->UpdateSize * FrameSizeFromDevFmt( + device->FmtChans, device->FmtType, device->AmbiOrder + ); + self->mBuffer = malloc(self->mSize); + if(!self->mBuffer) + { + ERR("Buffer malloc failed\n"); + return ALC_FALSE; + } + + ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); + if(althrd_create(&self->thread, ALCsdl2Backend_mixerProc, self) != althrd_success) + { + free(self->mBuffer); + self->mBuffer = NULL; + self->mSize = 0; + return ALC_FALSE; + } + SDL_PauseAudioDevice(self->deviceID, 0); + return ALC_TRUE; +} + +static void ALCsdl2Backend_stop(ALCsdl2Backend *self) +{ + int res; + + if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel)) + return; + althrd_join(self->thread, &res); + + free(self->mBuffer); + self->mBuffer = NULL; + if(self->quit) + SDL_Quit(); +} + + +typedef struct ALCsdl2BackendFactory { + DERIVE_FROM_TYPE(ALCbackendFactory); +} ALCsdl2BackendFactory; +#define ALCsdl2BACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCsdl2BackendFactory, ALCbackendFactory) } } + +ALCbackendFactory *ALCsdl2BackendFactory_getFactory(void); + +static ALCboolean ALCsdl2BackendFactory_init(ALCsdl2BackendFactory *self); +static DECLARE_FORWARD(ALCsdl2BackendFactory, ALCbackendFactory, void, deinit) +static ALCboolean ALCsdl2BackendFactory_querySupport(ALCsdl2BackendFactory *self, ALCbackend_Type type); +static void ALCsdl2BackendFactory_probe(ALCsdl2BackendFactory *self, enum DevProbe type); +static ALCbackend* ALCsdl2BackendFactory_createBackend(ALCsdl2BackendFactory *self, ALCdevice *device, ALCbackend_Type type); +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCsdl2BackendFactory); + + +ALCbackendFactory *ALCsdl2BackendFactory_getFactory(void) +{ + static ALCsdl2BackendFactory factory = ALCsdl2BACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); +} + + +static ALCboolean ALCsdl2BackendFactory_init(ALCsdl2BackendFactory* UNUSED(self)) +{ + return ALC_TRUE; +} + +static ALCboolean ALCsdl2BackendFactory_querySupport(ALCsdl2BackendFactory* UNUSED(self), ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + return ALC_TRUE; + return ALC_FALSE; +} + +static void ALCsdl2BackendFactory_probe(ALCsdl2BackendFactory* UNUSED(self), enum DevProbe type) +{ + if(type != ALL_DEVICE_PROBE) + return; + ALCboolean quit = ALC_FALSE; + if(SDL_WasInit(0) == 0) // Is SDL2 initialized at all? + { + SDL_Init(SDL_INIT_AUDIO); + quit = ALC_TRUE; + } + else if(!SDL_WasInit(SDL_INIT_AUDIO)) + SDL_InitSubSystem(SDL_INIT_AUDIO); + for(int i = 0; i < SDL_GetNumAudioDevices(0); ++i) + AppendAllDevicesList(SDL_GetAudioDeviceName(i, 0)); + if(quit) + SDL_Quit(); +} + +static ALCbackend* ALCsdl2BackendFactory_createBackend(ALCsdl2BackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + { + ALCsdl2Backend *backend; + NEW_OBJ(backend, ALCsdl2Backend)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + + return NULL; +} diff --git a/CMakeLists.txt b/CMakeLists.txt index bd531128..0c6196f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -759,6 +759,7 @@ SET(HAVE_PULSEAUDIO 0) SET(HAVE_COREAUDIO 0) SET(HAVE_OPENSL 0) SET(HAVE_WAVE 0) +SET(HAVE_SDL2 0) # Check for SSE support OPTION(ALSOFT_REQUIRE_SSE "Require SSE support" OFF) @@ -1123,6 +1124,23 @@ IF(ALSOFT_REQUIRE_OPENSL AND NOT HAVE_OPENSL) MESSAGE(FATAL_ERROR "Failed to enabled required OpenSL backend") ENDIF() +# Check for SDL2 backend +OPTION(ALSOFT_REQUIRE_SDL2 "Require SDL2 backend" OFF) +FIND_PACKAGE(SDL2) +IF(SDL2_FOUND) + # Off by default, since it adds a runtime dependency + OPTION(ALSOFT_BACKEND_SDL2 "Enable SDL2 backend" OFF) + IF(ALSOFT_BACKEND_SDL2) + SET(HAVE_SDL2 1) + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/sdl2.c) + SET(BACKENDS "${BACKENDS} SDL2,") + SET(EXTRA_LIBS ${SDL2_LIBRARY} ${EXTRA_LIBS}) + ENDIF() +ENDIF() +IF(ALSOFT_REQUIRE_SDL2 AND NOT SDL2_FOUND) + MESSAGE(FATAL_ERROR "Failed to enabled required SDL2 backend") +ENDIF() + # Optionally enable the Wave Writer backend OPTION(ALSOFT_BACKEND_WAVE "Enable Wave Writer backend" ON) IF(ALSOFT_BACKEND_WAVE) @@ -1206,7 +1224,9 @@ IF(ALSOFT_UTILS AND NOT ALSOFT_NO_CONFIG_UTIL) add_subdirectory(utils/alsoft-config) ENDIF() IF(ALSOFT_EXAMPLES) - FIND_PACKAGE(SDL2) + IF(NOT SDL2_FOUND) + FIND_PACKAGE(SDL2) + ENDIF() IF(SDL2_FOUND) FIND_PACKAGE(SDL_sound) FIND_PACKAGE(FFmpeg COMPONENTS AVFORMAT AVCODEC AVUTIL SWSCALE SWRESAMPLE) diff --git a/config.h.in b/config.h.in index 2abeedfd..345e8408 100644 --- a/config.h.in +++ b/config.h.in @@ -77,6 +77,9 @@ /* Define if we have the Wave Writer backend */ #cmakedefine HAVE_WAVE +/* Define if we have the SDL2 backend */ +#cmakedefine HAVE_SDL2 + /* Define if we have the stat function */ #cmakedefine HAVE_STAT -- cgit v1.2.3 From 767807cd2273eb9e760b25d792820b1c8f1946e1 Mon Sep 17 00:00:00 2001 From: Jan Niklas Hasse Date: Thu, 8 Mar 2018 09:50:16 +0100 Subject: SDL2 backend: Use callback instead of a timing loop The system clock and audio clock aren't necessarily synchronized. --- Alc/backends/sdl2.c | 94 +++++++---------------------------------------------- 1 file changed, 11 insertions(+), 83 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/sdl2.c b/Alc/backends/sdl2.c index 4b2d3acd..c191a528 100644 --- a/Alc/backends/sdl2.c +++ b/Alc/backends/sdl2.c @@ -35,15 +35,10 @@ typedef struct ALCsdl2Backend { DERIVE_FROM_TYPE(ALCbackend); SDL_AudioDeviceID deviceID; - ALvoid *mBuffer; - ALuint mSize; ALCboolean quit; - ATOMIC(int) killNow; althrd_t thread; } ALCsdl2Backend; -static int ALCsdl2Backend_mixerProc(void *ptr); - static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device); static DECLARE_FORWARD(ALCsdl2Backend, ALCbackend, void, Destruct) static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name); @@ -64,8 +59,6 @@ static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device) ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCsdl2Backend, ALCbackend, self); - self->mBuffer = NULL; - self->mSize = 0; self->quit = ALC_FALSE; if(SDL_WasInit(0) == 0) // Is SDL2 initialized at all? { @@ -74,61 +67,20 @@ static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device) } else if(!SDL_WasInit(SDL_INIT_AUDIO)) SDL_InitSubSystem(SDL_INIT_AUDIO); - - ATOMIC_INIT(&self->killNow, AL_TRUE); } -static int ALCsdl2Backend_mixerProc(void *ptr) +static void ALCsdl2Backend_audioCallback(void *ptr, Uint8* stream, int len) { ALCsdl2Backend *self = (ALCsdl2Backend*)ptr; ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - struct timespec now, start; - ALuint64 avail, done; - const long restTime = (long)((ALuint64)device->UpdateSize * 1000000000 / - device->Frequency / 2); - - SetRTPriority(); - althrd_setname(althrd_current(), MIXER_THREAD_NAME); - - done = 0; - if(altimespec_get(&start, AL_TIME_UTC) != AL_TIME_UTC) - { - ERR("Failed to get starting time\n"); - return 1; - } - while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) && - ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) - { - if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC) - { - ERR("Failed to get current time\n"); - return 1; - } - - avail = (now.tv_sec - start.tv_sec) * device->Frequency; - avail += (ALint64)(now.tv_nsec - start.tv_nsec) * device->Frequency / 1000000000; - if(avail < done) - { - /* Oops, time skipped backwards. Reset the number of samples done - * with one update available since we (likely) just came back from - * sleeping. */ - done = avail - device->UpdateSize; - } - - if(avail-done < device->UpdateSize) - al_nssleep(restTime); - else while(avail-done >= device->UpdateSize) - { - ALCsdl2Backend_lock(self); - aluMixData(device, self->mBuffer, device->UpdateSize); - SDL_QueueAudio(self->deviceID, self->mBuffer, self->mSize); - ALCsdl2Backend_unlock(self); - done += device->UpdateSize; - } - } - - return 0; + ALsizei frameSize = FrameSizeFromDevFmt( + device->FmtChans, device->FmtType, device->AmbiOrder + ); + assert(len % frameSize == 0); + ALCsdl2Backend_lock(self); + aluMixData(device, stream, len / frameSize); + ALCsdl2Backend_unlock(self); } static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) @@ -140,6 +92,8 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) want.format = AUDIO_F32; want.channels = 2; want.samples = device->UpdateSize; + want.callback = ALCsdl2Backend_audioCallback; + want.userdata = self; if(!name) name = SDL_GetAudioDeviceName(0, 0); @@ -161,39 +115,13 @@ static ALCboolean ALCsdl2Backend_reset(ALCsdl2Backend *self) static ALCboolean ALCsdl2Backend_start(ALCsdl2Backend *self) { - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - self->mSize = device->UpdateSize * FrameSizeFromDevFmt( - device->FmtChans, device->FmtType, device->AmbiOrder - ); - self->mBuffer = malloc(self->mSize); - if(!self->mBuffer) - { - ERR("Buffer malloc failed\n"); - return ALC_FALSE; - } - - ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); - if(althrd_create(&self->thread, ALCsdl2Backend_mixerProc, self) != althrd_success) - { - free(self->mBuffer); - self->mBuffer = NULL; - self->mSize = 0; - return ALC_FALSE; - } SDL_PauseAudioDevice(self->deviceID, 0); return ALC_TRUE; } static void ALCsdl2Backend_stop(ALCsdl2Backend *self) { - int res; - - if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel)) - return; - althrd_join(self->thread, &res); - - free(self->mBuffer); - self->mBuffer = NULL; + SDL_PauseAudioDevice(self->deviceID, 1); if(self->quit) SDL_Quit(); } -- cgit v1.2.3 From a6f93a501a08ddf35f98473822a70258e70f613a Mon Sep 17 00:00:00 2001 From: Jan Niklas Hasse Date: Thu, 8 Mar 2018 10:07:22 +0100 Subject: Handle passing NULL to SDL_OpenAudioDevice as a special device https://discourse.libsdl.org/t/changing-audio-output-when-the-default-audio-playback-device-changes/22399/2 --- Alc/backends/sdl2.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/sdl2.c b/Alc/backends/sdl2.c index c191a528..9881594d 100644 --- a/Alc/backends/sdl2.c +++ b/Alc/backends/sdl2.c @@ -54,6 +54,8 @@ DECLARE_DEFAULT_ALLOCATORS(ALCsdl2Backend) DEFINE_ALCBACKEND_VTABLE(ALCsdl2Backend); +static const ALCchar defaultDeviceName[] = "Default device"; + static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device) { ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); @@ -95,13 +97,16 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) want.callback = ALCsdl2Backend_audioCallback; want.userdata = self; - if(!name) - name = SDL_GetAudioDeviceName(0, 0); + if (name && strcmp(name, defaultDeviceName) == 0) + name = NULL; // Passing NULL to SDL_OpenAudioDevice is special and will NOT select the first + // device in the list. self->deviceID = SDL_OpenAudioDevice(name, 0, &want, NULL, 0); if(self->deviceID == 0) { ERR("Could not open device\n"); return ALC_INVALID_VALUE; } + if(!name) + name = defaultDeviceName; alstr_copy_cstr(&STATIC_CAST(ALCbackend, self)->mDevice->DeviceName, name); return ALC_NO_ERROR; @@ -173,6 +178,7 @@ static void ALCsdl2BackendFactory_probe(ALCsdl2BackendFactory* UNUSED(self), enu } else if(!SDL_WasInit(SDL_INIT_AUDIO)) SDL_InitSubSystem(SDL_INIT_AUDIO); + AppendAllDevicesList(defaultDeviceName); for(int i = 0; i < SDL_GetNumAudioDevices(0); ++i) AppendAllDevicesList(SDL_GetAudioDeviceName(i, 0)); if(quit) -- cgit v1.2.3 From ef2b813776a173425ff691749453f83265747768 Mon Sep 17 00:00:00 2001 From: Jan Niklas Hasse Date: Thu, 8 Mar 2018 10:17:02 +0100 Subject: SDL2 backend: Allow frequency changes --- Alc/backends/sdl2.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/sdl2.c b/Alc/backends/sdl2.c index 9881594d..a52b22c8 100644 --- a/Alc/backends/sdl2.c +++ b/Alc/backends/sdl2.c @@ -88,7 +88,7 @@ static void ALCsdl2Backend_audioCallback(void *ptr, Uint8* stream, int len) static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - SDL_AudioSpec want; + SDL_AudioSpec want, have; SDL_zero(want); want.freq = device->Frequency; want.format = AUDIO_F32; @@ -100,7 +100,12 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) if (name && strcmp(name, defaultDeviceName) == 0) name = NULL; // Passing NULL to SDL_OpenAudioDevice is special and will NOT select the first // device in the list. - self->deviceID = SDL_OpenAudioDevice(name, 0, &want, NULL, 0); + self->deviceID = SDL_OpenAudioDevice(name, 0, &want, &have, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); + if(want.freq != have.freq) + { + TRACE("Frequency changed by SDL2\n"); + device->Frequency = have.freq; + } if(self->deviceID == 0) { ERR("Could not open device\n"); return ALC_INVALID_VALUE; -- cgit v1.2.3 From 0af075b5ffb98e9093cd174862d4289ef4d98252 Mon Sep 17 00:00:00 2001 From: Jan Niklas Hasse Date: Thu, 8 Mar 2018 20:26:31 +0100 Subject: SDL2 backend: Allow changes to channels and format --- Alc/backends/sdl2.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'Alc/backends') diff --git a/Alc/backends/sdl2.c b/Alc/backends/sdl2.c index a52b22c8..414dbe19 100644 --- a/Alc/backends/sdl2.c +++ b/Alc/backends/sdl2.c @@ -100,12 +100,33 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) if (name && strcmp(name, defaultDeviceName) == 0) name = NULL; // Passing NULL to SDL_OpenAudioDevice is special and will NOT select the first // device in the list. - self->deviceID = SDL_OpenAudioDevice(name, 0, &want, &have, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); + self->deviceID = SDL_OpenAudioDevice(name, 0, &want, &have, SDL_AUDIO_ALLOW_ANY_CHANGE); if(want.freq != have.freq) { TRACE("Frequency changed by SDL2\n"); device->Frequency = have.freq; } + if(have.channels == 1) + device->FmtChans = DevFmtMono; + else if(have.channels == 2) + device->FmtChans = DevFmtStereo; + else + { + ERR("Invalid number of channels\n"); + return ALC_INVALID_VALUE; + } + switch(have.format) + { + case AUDIO_U8: device->FmtType = DevFmtUByte; break; + case AUDIO_S8: device->FmtType = DevFmtByte; break; + case AUDIO_U16SYS: device->FmtType = DevFmtUShort; break; + case AUDIO_S16SYS: device->FmtType = DevFmtShort; break; + case AUDIO_S32SYS: device->FmtType = DevFmtInt; break; + case AUDIO_F32SYS: device->FmtType = DevFmtFloat; break; + default: + ERR("Unsupported format\n"); + return ALC_INVALID_VALUE; + } if(self->deviceID == 0) { ERR("Could not open device\n"); return ALC_INVALID_VALUE; -- cgit v1.2.3 From 2eb29d538b0e90a48f45f55eaf110fa114b17f35 Mon Sep 17 00:00:00 2001 From: Jan Niklas Hasse Date: Thu, 8 Mar 2018 20:39:15 +0100 Subject: SDL2 backend: Reset device parameters --- Alc/backends/sdl2.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/sdl2.c b/Alc/backends/sdl2.c index 414dbe19..9bd42cdf 100644 --- a/Alc/backends/sdl2.c +++ b/Alc/backends/sdl2.c @@ -36,7 +36,9 @@ typedef struct ALCsdl2Backend { SDL_AudioDeviceID deviceID; ALCboolean quit; - althrd_t thread; + ALuint Frequency; + enum DevFmtChannels FmtChans; + enum DevFmtType FmtType; } ALCsdl2Backend; static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device); @@ -62,6 +64,9 @@ static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device) SET_VTABLE2(ALCsdl2Backend, ALCbackend, self); self->quit = ALC_FALSE; + self->Frequency = device->Frequency; + self->FmtChans = device->FmtChans; + self->FmtType = device->FmtType; if(SDL_WasInit(0) == 0) // Is SDL2 initialized at all? { SDL_Init(SDL_INIT_AUDIO); @@ -92,7 +97,7 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) SDL_zero(want); want.freq = device->Frequency; want.format = AUDIO_F32; - want.channels = 2; + want.channels = (device->FmtChans == DevFmtMono) ? 1 : 2; want.samples = device->UpdateSize; want.callback = ALCsdl2Backend_audioCallback; want.userdata = self; @@ -101,6 +106,11 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) name = NULL; // Passing NULL to SDL_OpenAudioDevice is special and will NOT select the first // device in the list. self->deviceID = SDL_OpenAudioDevice(name, 0, &want, &have, SDL_AUDIO_ALLOW_ANY_CHANGE); + if(self->deviceID == 0) + { + ERR("Could not open device\n"); + return ALC_INVALID_VALUE; + } if(want.freq != have.freq) { TRACE("Frequency changed by SDL2\n"); @@ -127,10 +137,9 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) ERR("Unsupported format\n"); return ALC_INVALID_VALUE; } - if(self->deviceID == 0) { - ERR("Could not open device\n"); - return ALC_INVALID_VALUE; - } + self->Frequency = device->Frequency; + self->FmtChans = device->FmtChans; + self->FmtType = device->FmtType; if(!name) name = defaultDeviceName; alstr_copy_cstr(&STATIC_CAST(ALCbackend, self)->mDevice->DeviceName, name); @@ -140,7 +149,11 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) static ALCboolean ALCsdl2Backend_reset(ALCsdl2Backend *self) { - SetDefaultWFXChannelOrder(STATIC_CAST(ALCbackend, self)->mDevice); + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + device->Frequency = self->Frequency; + device->FmtChans = self->FmtChans; + device->FmtType = self->FmtType; + SetDefaultWFXChannelOrder(device); return ALC_TRUE; } -- cgit v1.2.3 From d4fc87fc9c2cacb09d9538c410a701a8dd12aa6b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 8 Mar 2018 18:07:49 -0800 Subject: Avoid calling SDL_GetNumAudioDevices multiple times --- Alc/backends/sdl2.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/sdl2.c b/Alc/backends/sdl2.c index 9bd42cdf..416e745d 100644 --- a/Alc/backends/sdl2.c +++ b/Alc/backends/sdl2.c @@ -207,9 +207,12 @@ static ALCboolean ALCsdl2BackendFactory_querySupport(ALCsdl2BackendFactory* UNUS static void ALCsdl2BackendFactory_probe(ALCsdl2BackendFactory* UNUSED(self), enum DevProbe type) { + ALCboolean quit = ALC_FALSE; + int num_devices, i; + if(type != ALL_DEVICE_PROBE) return; - ALCboolean quit = ALC_FALSE; + if(SDL_WasInit(0) == 0) // Is SDL2 initialized at all? { SDL_Init(SDL_INIT_AUDIO); @@ -217,9 +220,13 @@ static void ALCsdl2BackendFactory_probe(ALCsdl2BackendFactory* UNUSED(self), enu } else if(!SDL_WasInit(SDL_INIT_AUDIO)) SDL_InitSubSystem(SDL_INIT_AUDIO); + + num_devices = SDL_GetNumAudioDevices(SDL_FALSE); + AppendAllDevicesList(defaultDeviceName); - for(int i = 0; i < SDL_GetNumAudioDevices(0); ++i) - AppendAllDevicesList(SDL_GetAudioDeviceName(i, 0)); + for(i = 0; i < num_devices; ++i) + AppendAllDevicesList(SDL_GetAudioDeviceName(i, SDL_FALSE)); + if(quit) SDL_Quit(); } -- cgit v1.2.3 From 52ca70d98e164cb925dcc28fa97ade6fea1bd6ae Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 8 Mar 2018 18:12:14 -0800 Subject: Properly close the SDL2 audio device --- Alc/backends/sdl2.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/sdl2.c b/Alc/backends/sdl2.c index 416e745d..df4324ad 100644 --- a/Alc/backends/sdl2.c +++ b/Alc/backends/sdl2.c @@ -42,7 +42,7 @@ typedef struct ALCsdl2Backend { } ALCsdl2Backend; static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device); -static DECLARE_FORWARD(ALCsdl2Backend, ALCbackend, void, Destruct) +static void ALCsdl2Backend_Destruct(ALCsdl2Backend *self); static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name); static ALCboolean ALCsdl2Backend_reset(ALCsdl2Backend *self); static ALCboolean ALCsdl2Backend_start(ALCsdl2Backend *self); @@ -63,6 +63,7 @@ static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device) ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCsdl2Backend, ALCbackend, self); + self->deviceID = 0; self->quit = ALC_FALSE; self->Frequency = device->Frequency; self->FmtChans = device->FmtChans; @@ -76,6 +77,18 @@ static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device) SDL_InitSubSystem(SDL_INIT_AUDIO); } +static void ALCsdl2Backend_Destruct(ALCsdl2Backend *self) +{ + if(self->deviceID) + SDL_CloseAudioDevice(self->deviceID); + self->deviceID = 0; + + if(self->quit) + SDL_Quit(); + + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + static void ALCsdl2Backend_audioCallback(void *ptr, Uint8* stream, int len) { @@ -166,8 +179,6 @@ static ALCboolean ALCsdl2Backend_start(ALCsdl2Backend *self) static void ALCsdl2Backend_stop(ALCsdl2Backend *self) { SDL_PauseAudioDevice(self->deviceID, 1); - if(self->quit) - SDL_Quit(); } @@ -224,7 +235,7 @@ static void ALCsdl2BackendFactory_probe(ALCsdl2BackendFactory* UNUSED(self), enu num_devices = SDL_GetNumAudioDevices(SDL_FALSE); AppendAllDevicesList(defaultDeviceName); - for(i = 0; i < num_devices; ++i) + for(i = 0;i < num_devices;++i) AppendAllDevicesList(SDL_GetAudioDeviceName(i, SDL_FALSE)); if(quit) -- cgit v1.2.3 From 58760e6184118e34fe2f8fde28fb7b51d449e8cc Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 8 Mar 2018 18:16:10 -0800 Subject: Use the audio device lock for the SDL2 backend --- Alc/backends/sdl2.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/sdl2.c b/Alc/backends/sdl2.c index df4324ad..b54fcc4b 100644 --- a/Alc/backends/sdl2.c +++ b/Alc/backends/sdl2.c @@ -50,8 +50,8 @@ static void ALCsdl2Backend_stop(ALCsdl2Backend *self); static DECLARE_FORWARD2(ALCsdl2Backend, ALCbackend, ALCenum, captureSamples, void*, ALCuint) static DECLARE_FORWARD(ALCsdl2Backend, ALCbackend, ALCuint, availableSamples) static DECLARE_FORWARD(ALCsdl2Backend, ALCbackend, ClockLatency, getClockLatency) -static DECLARE_FORWARD(ALCsdl2Backend, ALCbackend, void, lock) -static DECLARE_FORWARD(ALCsdl2Backend, ALCbackend, void, unlock) +static void ALCsdl2Backend_lock(ALCsdl2Backend *self); +static void ALCsdl2Backend_unlock(ALCsdl2Backend *self); DECLARE_DEFAULT_ALLOCATORS(ALCsdl2Backend) DEFINE_ALCBACKEND_VTABLE(ALCsdl2Backend); @@ -97,10 +97,9 @@ static void ALCsdl2Backend_audioCallback(void *ptr, Uint8* stream, int len) ALsizei frameSize = FrameSizeFromDevFmt( device->FmtChans, device->FmtType, device->AmbiOrder ); + assert(len % frameSize == 0); - ALCsdl2Backend_lock(self); aluMixData(device, stream, len / frameSize); - ALCsdl2Backend_unlock(self); } static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) @@ -181,6 +180,16 @@ static void ALCsdl2Backend_stop(ALCsdl2Backend *self) SDL_PauseAudioDevice(self->deviceID, 1); } +static void ALCsdl2Backend_lock(ALCsdl2Backend *self) +{ + SDL_LockAudioDevice(self->deviceID); +} + +static void ALCsdl2Backend_unlock(ALCsdl2Backend *self) +{ + SDL_UnlockAudioDevice(self->deviceID); +} + typedef struct ALCsdl2BackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); -- cgit v1.2.3 From aa7df8183f5acd81ca2d26b057eb89eccbf85492 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 8 Mar 2018 18:22:03 -0800 Subject: Also save the update size with SDL2 --- Alc/backends/sdl2.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/sdl2.c b/Alc/backends/sdl2.c index b54fcc4b..391b110d 100644 --- a/Alc/backends/sdl2.c +++ b/Alc/backends/sdl2.c @@ -36,9 +36,11 @@ typedef struct ALCsdl2Backend { SDL_AudioDeviceID deviceID; ALCboolean quit; + ALuint Frequency; enum DevFmtChannels FmtChans; enum DevFmtType FmtType; + ALuint UpdateSize; } ALCsdl2Backend; static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device); @@ -123,11 +125,8 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) ERR("Could not open device\n"); return ALC_INVALID_VALUE; } - if(want.freq != have.freq) - { - TRACE("Frequency changed by SDL2\n"); - device->Frequency = have.freq; - } + + device->Frequency = have.freq; if(have.channels == 1) device->FmtChans = DevFmtMono; else if(have.channels == 2) @@ -149,12 +148,15 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) ERR("Unsupported format\n"); return ALC_INVALID_VALUE; } + device->UpdateSize = have.samples; + device->NumUpdates = 2; /* SDL always (tries to) use two periods. */ + self->Frequency = device->Frequency; self->FmtChans = device->FmtChans; self->FmtType = device->FmtType; - if(!name) - name = defaultDeviceName; - alstr_copy_cstr(&STATIC_CAST(ALCbackend, self)->mDevice->DeviceName, name); + self->UpdateSize = device->UpdateSize; + + alstr_copy_cstr(&device->DeviceName, name ? name : defaultDeviceName); return ALC_NO_ERROR; } @@ -165,6 +167,8 @@ static ALCboolean ALCsdl2Backend_reset(ALCsdl2Backend *self) device->Frequency = self->Frequency; device->FmtChans = self->FmtChans; device->FmtType = self->FmtType; + device->UpdateSize = self->UpdateSize; + device->NumUpdates = 2; SetDefaultWFXChannelOrder(device); return ALC_TRUE; } -- cgit v1.2.3 From 2866c6cf280dec63336d2733bc300db9d7bbcce6 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 8 Mar 2018 18:59:22 -0800 Subject: Init and quit the SDL2 audio subsystem with the factory --- Alc/backends/sdl2.c | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/sdl2.c b/Alc/backends/sdl2.c index 391b110d..27f42129 100644 --- a/Alc/backends/sdl2.c +++ b/Alc/backends/sdl2.c @@ -35,7 +35,6 @@ typedef struct ALCsdl2Backend { DERIVE_FROM_TYPE(ALCbackend); SDL_AudioDeviceID deviceID; - ALCboolean quit; ALuint Frequency; enum DevFmtChannels FmtChans; @@ -66,17 +65,10 @@ static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device) SET_VTABLE2(ALCsdl2Backend, ALCbackend, self); self->deviceID = 0; - self->quit = ALC_FALSE; self->Frequency = device->Frequency; self->FmtChans = device->FmtChans; self->FmtType = device->FmtType; - if(SDL_WasInit(0) == 0) // Is SDL2 initialized at all? - { - SDL_Init(SDL_INIT_AUDIO); - self->quit = ALC_TRUE; - } - else if(!SDL_WasInit(SDL_INIT_AUDIO)) - SDL_InitSubSystem(SDL_INIT_AUDIO); + self->UpdateSize = device->UpdateSize; } static void ALCsdl2Backend_Destruct(ALCsdl2Backend *self) @@ -85,9 +77,6 @@ static void ALCsdl2Backend_Destruct(ALCsdl2Backend *self) SDL_CloseAudioDevice(self->deviceID); self->deviceID = 0; - if(self->quit) - SDL_Quit(); - ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -203,7 +192,7 @@ typedef struct ALCsdl2BackendFactory { ALCbackendFactory *ALCsdl2BackendFactory_getFactory(void); static ALCboolean ALCsdl2BackendFactory_init(ALCsdl2BackendFactory *self); -static DECLARE_FORWARD(ALCsdl2BackendFactory, ALCbackendFactory, void, deinit) +static void ALCsdl2BackendFactory_deinit(ALCsdl2BackendFactory *self); static ALCboolean ALCsdl2BackendFactory_querySupport(ALCsdl2BackendFactory *self, ALCbackend_Type type); static void ALCsdl2BackendFactory_probe(ALCsdl2BackendFactory *self, enum DevProbe type); static ALCbackend* ALCsdl2BackendFactory_createBackend(ALCsdl2BackendFactory *self, ALCdevice *device, ALCbackend_Type type); @@ -219,7 +208,14 @@ ALCbackendFactory *ALCsdl2BackendFactory_getFactory(void) static ALCboolean ALCsdl2BackendFactory_init(ALCsdl2BackendFactory* UNUSED(self)) { - return ALC_TRUE; + if(SDL_InitSubSystem(SDL_INIT_AUDIO) == 0) + return AL_TRUE; + return ALC_FALSE; +} + +static void ALCsdl2BackendFactory_deinit(ALCsdl2BackendFactory* UNUSED(self)) +{ + SDL_QuitSubSystem(SDL_INIT_AUDIO); } static ALCboolean ALCsdl2BackendFactory_querySupport(ALCsdl2BackendFactory* UNUSED(self), ALCbackend_Type type) @@ -231,28 +227,16 @@ static ALCboolean ALCsdl2BackendFactory_querySupport(ALCsdl2BackendFactory* UNUS static void ALCsdl2BackendFactory_probe(ALCsdl2BackendFactory* UNUSED(self), enum DevProbe type) { - ALCboolean quit = ALC_FALSE; int num_devices, i; if(type != ALL_DEVICE_PROBE) return; - if(SDL_WasInit(0) == 0) // Is SDL2 initialized at all? - { - SDL_Init(SDL_INIT_AUDIO); - quit = ALC_TRUE; - } - else if(!SDL_WasInit(SDL_INIT_AUDIO)) - SDL_InitSubSystem(SDL_INIT_AUDIO); - num_devices = SDL_GetNumAudioDevices(SDL_FALSE); AppendAllDevicesList(defaultDeviceName); for(i = 0;i < num_devices;++i) AppendAllDevicesList(SDL_GetAudioDeviceName(i, SDL_FALSE)); - - if(quit) - SDL_Quit(); } static ALCbackend* ALCsdl2BackendFactory_createBackend(ALCsdl2BackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) -- cgit v1.2.3 From 41cc82e84beff737afbdf2b56ba8f53d8fb04559 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 8 Mar 2018 22:09:30 -0800 Subject: Print the unsupported values from SDL2 --- Alc/backends/sdl2.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/sdl2.c b/Alc/backends/sdl2.c index 27f42129..61076789 100644 --- a/Alc/backends/sdl2.c +++ b/Alc/backends/sdl2.c @@ -110,10 +110,7 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) // device in the list. self->deviceID = SDL_OpenAudioDevice(name, 0, &want, &have, SDL_AUDIO_ALLOW_ANY_CHANGE); if(self->deviceID == 0) - { - ERR("Could not open device\n"); return ALC_INVALID_VALUE; - } device->Frequency = have.freq; if(have.channels == 1) @@ -122,7 +119,7 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) device->FmtChans = DevFmtStereo; else { - ERR("Invalid number of channels\n"); + ERR("Got unhandled SDL channel count: %d\n", (int)have.channels); return ALC_INVALID_VALUE; } switch(have.format) @@ -134,7 +131,7 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) case AUDIO_S32SYS: device->FmtType = DevFmtInt; break; case AUDIO_F32SYS: device->FmtType = DevFmtFloat; break; default: - ERR("Unsupported format\n"); + ERR("Got unsupported SDL format: 0x%04x\n", have.format); return ALC_INVALID_VALUE; } device->UpdateSize = have.samples; -- cgit v1.2.3 From 46e7e96eb3407405df9999cbb3134a5392c98a08 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 8 Mar 2018 22:23:36 -0800 Subject: Store the frame size for the SDL2 backend --- Alc/backends/sdl2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/sdl2.c b/Alc/backends/sdl2.c index 61076789..f301cf48 100644 --- a/Alc/backends/sdl2.c +++ b/Alc/backends/sdl2.c @@ -35,6 +35,7 @@ typedef struct ALCsdl2Backend { DERIVE_FROM_TYPE(ALCbackend); SDL_AudioDeviceID deviceID; + ALsizei frameSize; ALuint Frequency; enum DevFmtChannels FmtChans; @@ -65,6 +66,7 @@ static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device) SET_VTABLE2(ALCsdl2Backend, ALCbackend, self); self->deviceID = 0; + self->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); self->Frequency = device->Frequency; self->FmtChans = device->FmtChans; self->FmtType = device->FmtType; @@ -81,16 +83,13 @@ static void ALCsdl2Backend_Destruct(ALCsdl2Backend *self) } -static void ALCsdl2Backend_audioCallback(void *ptr, Uint8* stream, int len) +static void ALCsdl2Backend_audioCallback(void *ptr, Uint8 *stream, int len) { ALCsdl2Backend *self = (ALCsdl2Backend*)ptr; ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - ALsizei frameSize = FrameSizeFromDevFmt( - device->FmtChans, device->FmtType, device->AmbiOrder - ); - assert(len % frameSize == 0); - aluMixData(device, stream, len / frameSize); + assert((len % self->frameSize) == 0); + aluMixData(device, stream, len / self->frameSize); } static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) @@ -137,6 +136,7 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) device->UpdateSize = have.samples; device->NumUpdates = 2; /* SDL always (tries to) use two periods. */ + self->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); self->Frequency = device->Frequency; self->FmtChans = device->FmtChans; self->FmtType = device->FmtType; -- cgit v1.2.3 From 8b242555570b9afe260026721737ae4ba2eef563 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 9 Mar 2018 10:53:03 -0800 Subject: Request the device's sample type for SDL2 --- Alc/backends/sdl2.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'Alc/backends') diff --git a/Alc/backends/sdl2.c b/Alc/backends/sdl2.c index f301cf48..2955fb25 100644 --- a/Alc/backends/sdl2.c +++ b/Alc/backends/sdl2.c @@ -96,9 +96,21 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; SDL_AudioSpec want, have; + SDL_zero(want); + SDL_zero(have); + want.freq = device->Frequency; - want.format = AUDIO_F32; + switch(device->FmtType) + { + case DevFmtUByte: want.format = AUDIO_U8; break; + case DevFmtByte: want.format = AUDIO_S8; break; + case DevFmtUShort: want.format = AUDIO_U16SYS; break; + case DevFmtShort: want.format = AUDIO_S16SYS; break; + case DevFmtUInt: /* fall-through */ + case DevFmtInt: want.format = AUDIO_S32SYS; break; + case DevFmtFloat: want.format = AUDIO_F32; break; + } want.channels = (device->FmtChans == DevFmtMono) ? 1 : 2; want.samples = device->UpdateSize; want.callback = ALCsdl2Backend_audioCallback; -- cgit v1.2.3 From c0e7a5b8b07132f39e7bf60371586d5d56984e14 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 9 Mar 2018 11:41:28 -0800 Subject: Prefix SDL2 device names on Windows --- Alc/backends/sdl2.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/sdl2.c b/Alc/backends/sdl2.c index 2955fb25..cf005024 100644 --- a/Alc/backends/sdl2.c +++ b/Alc/backends/sdl2.c @@ -31,6 +31,12 @@ #include "backends/base.h" +#ifdef _WIN32 +#define DEVNAME_PREFIX "OpenAL Soft on " +#else +#define DEVNAME_PREFIX "" +#endif + typedef struct ALCsdl2Backend { DERIVE_FROM_TYPE(ALCbackend); @@ -58,7 +64,7 @@ DECLARE_DEFAULT_ALLOCATORS(ALCsdl2Backend) DEFINE_ALCBACKEND_VTABLE(ALCsdl2Backend); -static const ALCchar defaultDeviceName[] = "Default device"; +static const ALCchar defaultDeviceName[] = DEVNAME_PREFIX "Default Device"; static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device) { @@ -116,10 +122,22 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) want.callback = ALCsdl2Backend_audioCallback; want.userdata = self; - if (name && strcmp(name, defaultDeviceName) == 0) - name = NULL; // Passing NULL to SDL_OpenAudioDevice is special and will NOT select the first - // device in the list. - self->deviceID = SDL_OpenAudioDevice(name, 0, &want, &have, SDL_AUDIO_ALLOW_ANY_CHANGE); + /* Passing NULL to SDL_OpenAudioDevice opens a default, which isn't + * necessarily the first in the list. + */ + if(!name || strcmp(name, defaultDeviceName) == 0) + self->deviceID = SDL_OpenAudioDevice(NULL, SDL_FALSE, &want, &have, + SDL_AUDIO_ALLOW_ANY_CHANGE); + else + { + const size_t prefix_len = strlen(DEVNAME_PREFIX); + if(strncmp(name, DEVNAME_PREFIX, prefix_len) == 0) + self->deviceID = SDL_OpenAudioDevice(name+prefix_len, SDL_FALSE, &want, &have, + SDL_AUDIO_ALLOW_ANY_CHANGE); + else + self->deviceID = SDL_OpenAudioDevice(name, SDL_FALSE, &want, &have, + SDL_AUDIO_ALLOW_ANY_CHANGE); + } if(self->deviceID == 0) return ALC_INVALID_VALUE; @@ -237,15 +255,22 @@ static ALCboolean ALCsdl2BackendFactory_querySupport(ALCsdl2BackendFactory* UNUS static void ALCsdl2BackendFactory_probe(ALCsdl2BackendFactory* UNUSED(self), enum DevProbe type) { int num_devices, i; + al_string name; if(type != ALL_DEVICE_PROBE) return; + AL_STRING_INIT(name); num_devices = SDL_GetNumAudioDevices(SDL_FALSE); AppendAllDevicesList(defaultDeviceName); for(i = 0;i < num_devices;++i) - AppendAllDevicesList(SDL_GetAudioDeviceName(i, SDL_FALSE)); + { + alstr_copy_cstr(&name, DEVNAME_PREFIX); + alstr_append_cstr(&name, SDL_GetAudioDeviceName(i, SDL_FALSE)); + AppendAllDevicesList(alstr_get_cstr(name)); + } + alstr_reset(&name); } static ALCbackend* ALCsdl2BackendFactory_createBackend(ALCsdl2BackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) -- cgit v1.2.3 From 30821e978b69fa017cbcd76e5ff25c62f16b1d2a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 9 Mar 2018 17:24:03 -0800 Subject: Add extern "C" to some headers --- Alc/alstring.h | 8 ++++++++ Alc/backends/base.h | 8 ++++++++ Alc/compat.h | 8 ++++++++ Alc/logging.h | 8 ++++++++ Alc/ringbuffer.h | 8 ++++++++ OpenAL32/Include/alMain.h | 34 +++++++++++++++++----------------- 6 files changed, 57 insertions(+), 17 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/alstring.h b/Alc/alstring.h index e10811da..923a5ea2 100644 --- a/Alc/alstring.h +++ b/Alc/alstring.h @@ -6,6 +6,10 @@ #include "vector.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef char al_string_char_type; TYPEDEF_VECTOR(al_string_char_type, al_string) TYPEDEF_VECTOR(al_string, vector_al_string) @@ -47,4 +51,8 @@ void alstr_copy_wrange(al_string *str, const wchar_t *from, const wchar_t *to); void alstr_append_wrange(al_string *str, const wchar_t *from, const wchar_t *to); #endif +#ifdef __cplusplus +} /* extern "C" */ +#endif + #endif /* ALSTRING_H */ diff --git a/Alc/backends/base.h b/Alc/backends/base.h index b05523b2..6940a2a2 100644 --- a/Alc/backends/base.h +++ b/Alc/backends/base.h @@ -5,6 +5,10 @@ #include "threads.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct ClockLatency { ALint64 ClockTime; ALint64 Latency; @@ -157,4 +161,8 @@ inline void ALCdevice_Lock(ALCdevice *device) inline void ALCdevice_Unlock(ALCdevice *device) { V0(device->Backend,unlock)(); } +#ifdef __cplusplus +} /* extern "C" */ +#endif + #endif /* AL_BACKENDS_BASE_H */ diff --git a/Alc/compat.h b/Alc/compat.h index 6cf2d0d2..093184c8 100644 --- a/Alc/compat.h +++ b/Alc/compat.h @@ -3,6 +3,10 @@ #include "alstring.h" +#ifdef __cplusplus +extern "C" { +#endif + #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN @@ -54,4 +58,8 @@ void *GetSymbol(void *handle, const char *name); void *Android_GetJNIEnv(void); #endif +#ifdef __cplusplus +} /* extern "C" */ +#endif + #endif /* AL_COMPAT_H */ diff --git a/Alc/logging.h b/Alc/logging.h index 18093b75..785771c8 100644 --- a/Alc/logging.h +++ b/Alc/logging.h @@ -10,6 +10,10 @@ #define DECL_FORMAT(x, y, z) #endif +#ifdef __cplusplus +extern "C" { +#endif + extern FILE *LogFile; #if defined(__GNUC__) && !defined(_WIN32) @@ -58,4 +62,8 @@ extern enum LogLevel LogLevel; LOG_ANDROID(ANDROID_LOG_ERROR, __VA_ARGS__); \ } while(0) +#ifdef __cplusplus +} /* extern "C" */ +#endif + #endif /* LOGGING_H */ diff --git a/Alc/ringbuffer.h b/Alc/ringbuffer.h index bcf67374..0d05ec84 100644 --- a/Alc/ringbuffer.h +++ b/Alc/ringbuffer.h @@ -4,6 +4,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct ll_ringbuffer ll_ringbuffer_t; typedef struct ll_ringbuffer_data { char *buf; @@ -66,4 +70,8 @@ size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const char *src, size_t cnt); /** Advance the write pointer `cnt' places. */ void ll_ringbuffer_write_advance(ll_ringbuffer_t *rb, size_t cnt); +#ifdef __cplusplus +} /* extern "C" */ +#endif + #endif /* RINGBUFFER_H */ diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 6d6d661f..783a90de 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -49,19 +49,6 @@ #define UNLIKELY(x) (!!(x)) #endif -typedef ALint64SOFT ALint64; -typedef ALuint64SOFT ALuint64; - -#ifndef U64 -#if defined(_MSC_VER) -#define U64(x) ((ALuint64)(x##ui64)) -#elif SIZEOF_LONG == 8 -#define U64(x) ((ALuint64)(x##ul)) -#elif SIZEOF_LONG_LONG == 8 -#define U64(x) ((ALuint64)(x##ull)) -#endif -#endif - #ifndef UINT64_MAX #define UINT64_MAX U64(18446744073709551615) #endif @@ -85,6 +72,23 @@ typedef ALuint64SOFT ALuint64; #define FAM_SIZE(T, M, N) (offsetof(T, M) + sizeof(((T*)NULL)->M[0])*(N)) +#ifdef __cplusplus +extern "C" { +#endif + +typedef ALint64SOFT ALint64; +typedef ALuint64SOFT ALuint64; + +#ifndef U64 +#if defined(_MSC_VER) +#define U64(x) ((ALuint64)(x##ui64)) +#elif SIZEOF_LONG == 8 +#define U64(x) ((ALuint64)(x##ul)) +#elif SIZEOF_LONG_LONG == 8 +#define U64(x) ((ALuint64)(x##ull)) +#endif +#endif + /* Define a CTZ64 macro (count trailing zeros, for 64-bit integers). The result * is *UNDEFINED* if the value is 0. */ @@ -153,10 +157,6 @@ static const union { #define COUNTOF(x) (sizeof(x) / sizeof(0[x])) -#ifdef __cplusplus -extern "C" { -#endif - struct ll_ringbuffer; struct Hrtf; struct HrtfEntry; -- cgit v1.2.3 From a6ddeaf5f190a3640f816a4767ffa8b10fbd1b5d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 9 Mar 2018 18:56:24 -0800 Subject: Rename the mmdevapi backend to wasapi --- Alc/ALc.c | 14 +- Alc/backends/base.h | 2 +- Alc/backends/mmdevapi.c | 2054 ------------------------------------ Alc/backends/wasapi.c | 2049 +++++++++++++++++++++++++++++++++++ Alc/helpers.c | 2 +- CMakeLists.txt | 20 +- alsoftrc.sample | 4 +- appveyor.yml | 2 +- config.h.in | 4 +- utils/alsoft-config/mainwindow.cpp | 13 +- 10 files changed, 2089 insertions(+), 2075 deletions(-) delete mode 100644 Alc/backends/mmdevapi.c create mode 100644 Alc/backends/wasapi.c (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index 00c6b6fa..8a2f67aa 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -85,8 +85,8 @@ static struct BackendInfo BackendList[] = { #ifdef HAVE_QSA { "qsa", ALCqsaBackendFactory_getFactory }, #endif -#ifdef HAVE_MMDEVAPI - { "mmdevapi", ALCmmdevBackendFactory_getFactory }, +#ifdef HAVE_WASAPI + { "wasapi", ALCwasapiBackendFactory_getFactory }, #endif #ifdef HAVE_DSOUND { "dsound", ALCdsoundBackendFactory_getFactory }, @@ -1046,6 +1046,16 @@ static void alc_initconfig(void) len = (next ? ((size_t)(next-devs)) : strlen(devs)); while(len > 0 && isspace(devs[len-1])) len--; +#ifdef HAVE_WASAPI + /* HACK: For backwards compatibility, convert backend references of + * mmdevapi to wasapi. This should eventually be removed. + */ + if(len == 8 && strncmp(devs, "mmdevapi", len) == 0) + { + devs = "wasapi"; + len = 6; + } +#endif for(n = i;n < BackendListSize;n++) { if(len == strlen(BackendList[n].name) && diff --git a/Alc/backends/base.h b/Alc/backends/base.h index 6940a2a2..ba92b4ac 100644 --- a/Alc/backends/base.h +++ b/Alc/backends/base.h @@ -144,7 +144,7 @@ ALCbackendFactory *ALCjackBackendFactory_getFactory(void); ALCbackendFactory *ALCsolarisBackendFactory_getFactory(void); ALCbackendFactory *ALCsndioBackendFactory_getFactory(void); ALCbackendFactory *ALCqsaBackendFactory_getFactory(void); -ALCbackendFactory *ALCmmdevBackendFactory_getFactory(void); +ALCbackendFactory *ALCwasapiBackendFactory_getFactory(void); ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void); ALCbackendFactory *ALCwinmmBackendFactory_getFactory(void); ALCbackendFactory *ALCportBackendFactory_getFactory(void); diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c deleted file mode 100644 index 961cba52..00000000 --- a/Alc/backends/mmdevapi.c +++ /dev/null @@ -1,2054 +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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#include "config.h" - -#define COBJMACROS -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef _WAVEFORMATEXTENSIBLE_ -#include -#include -#endif - -#include "alMain.h" -#include "alu.h" -#include "ringbuffer.h" -#include "threads.h" -#include "compat.h" -#include "alstring.h" -#include "converter.h" - -#include "backends/base.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_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14); -DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_FormFactor, 0x1da5d803, 0xd492, 0x4edd, 0x8c,0x23, 0xe0,0xc0,0xff,0xee,0x7f,0x0e, 0); -DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23,0xe0, 0xc0,0xff,0xee,0x7f,0x0e, 4 ); - -#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_SIDE_LEFT|SPEAKER_SIDE_RIGHT) -#define X5DOT1REAR (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_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) -#define X7DOT1_WIDE (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_FRONT_LEFT_OF_CENTER|SPEAKER_FRONT_RIGHT_OF_CENTER) - -#define REFTIME_PER_SEC ((REFERENCE_TIME)10000000) - -#define DEVNAME_HEAD "OpenAL Soft on " - - -/* Scales the given value using 64-bit integer math, ceiling the result. */ -static inline ALuint64 ScaleCeil(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale) -{ - return (val*new_scale + old_scale-1) / old_scale; -} - - -typedef struct { - al_string name; - al_string endpoint_guid; // obtained from PKEY_AudioEndpoint_GUID , set to "Unknown device GUID" if absent. - WCHAR *devid; -} DevMap; -TYPEDEF_VECTOR(DevMap, vector_DevMap) - -static void clear_devlist(vector_DevMap *list) -{ -#define CLEAR_DEVMAP(i) do { \ - AL_STRING_DEINIT((i)->name); \ - AL_STRING_DEINIT((i)->endpoint_guid); \ - free((i)->devid); \ - (i)->devid = NULL; \ -} while(0) - VECTOR_FOR_EACH(DevMap, *list, CLEAR_DEVMAP); - VECTOR_RESIZE(*list, 0, 0); -#undef CLEAR_DEVMAP -} - -static vector_DevMap PlaybackDevices; -static vector_DevMap CaptureDevices; - - -static HANDLE ThreadHdl; -static DWORD ThreadID; - -typedef struct { - HANDLE FinishedEvt; - HRESULT result; -} ThreadRequest; - -#define WM_USER_First (WM_USER+0) -#define WM_USER_OpenDevice (WM_USER+0) -#define WM_USER_ResetDevice (WM_USER+1) -#define WM_USER_StartDevice (WM_USER+2) -#define WM_USER_StopDevice (WM_USER+3) -#define WM_USER_CloseDevice (WM_USER+4) -#define WM_USER_Enumerate (WM_USER+5) -#define WM_USER_Last (WM_USER+5) - -static const char MessageStr[WM_USER_Last+1-WM_USER][20] = { - "Open Device", - "Reset Device", - "Start Device", - "Stop Device", - "Close Device", - "Enumerate Devices", -}; - -static inline void ReturnMsgResponse(ThreadRequest *req, HRESULT res) -{ - req->result = res; - SetEvent(req->FinishedEvt); -} - -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 void get_device_name_and_guid(IMMDevice *device, al_string *name, al_string *guid) -{ - IPropertyStore *ps; - PROPVARIANT pvname; - PROPVARIANT pvguid; - HRESULT hr; - - alstr_copy_cstr(name, DEVNAME_HEAD); - - hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps); - if(FAILED(hr)) - { - WARN("OpenPropertyStore failed: 0x%08lx\n", hr); - alstr_append_cstr(name, "Unknown Device Name"); - if(guid!=NULL)alstr_copy_cstr(guid, "Unknown Device GUID"); - return; - } - - PropVariantInit(&pvname); - - hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pvname); - if(FAILED(hr)) - { - WARN("GetValue Device_FriendlyName failed: 0x%08lx\n", hr); - alstr_append_cstr(name, "Unknown Device Name"); - } - else if(pvname.vt == VT_LPWSTR) - alstr_append_wcstr(name, pvname.pwszVal); - else - { - WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvname.vt); - alstr_append_cstr(name, "Unknown Device Name"); - } - PropVariantClear(&pvname); - - if(guid!=NULL){ - PropVariantInit(&pvguid); - - hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&PKEY_AudioEndpoint_GUID, &pvguid); - if(FAILED(hr)) - { - WARN("GetValue AudioEndpoint_GUID failed: 0x%08lx\n", hr); - alstr_copy_cstr(guid, "Unknown Device GUID"); - } - else if(pvguid.vt == VT_LPWSTR) - alstr_copy_wcstr(guid, pvguid.pwszVal); - else - { - WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvguid.vt); - alstr_copy_cstr(guid, "Unknown Device GUID"); - } - - PropVariantClear(&pvguid); - } - - IPropertyStore_Release(ps); -} - -static void get_device_formfactor(IMMDevice *device, EndpointFormFactor *formfactor) -{ - IPropertyStore *ps; - PROPVARIANT pvform; - HRESULT hr; - - hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps); - if(FAILED(hr)) - { - WARN("OpenPropertyStore failed: 0x%08lx\n", hr); - return; - } - - PropVariantInit(&pvform); - - hr = IPropertyStore_GetValue(ps, &PKEY_AudioEndpoint_FormFactor, &pvform); - if(FAILED(hr)) - WARN("GetValue AudioEndpoint_FormFactor failed: 0x%08lx\n", hr); - else if(pvform.vt == VT_UI4) - *formfactor = pvform.ulVal; - else if(pvform.vt == VT_EMPTY) - *formfactor = UnknownFormFactor; - else - WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvform.vt); - - PropVariantClear(&pvform); - IPropertyStore_Release(ps); -} - - -static void add_device(IMMDevice *device, const WCHAR *devid, vector_DevMap *list) -{ - int count = 0; - al_string tmpname; - DevMap entry; - - AL_STRING_INIT(tmpname); - AL_STRING_INIT(entry.name); - AL_STRING_INIT(entry.endpoint_guid); - - entry.devid = strdupW(devid); - get_device_name_and_guid(device, &tmpname, &entry.endpoint_guid); - - while(1) - { - const DevMap *iter; - - alstr_copy(&entry.name, tmpname); - if(count != 0) - { - char str[64]; - snprintf(str, sizeof(str), " #%d", count+1); - alstr_append_cstr(&entry.name, str); - } - -#define MATCH_ENTRY(i) (alstr_cmp(entry.name, (i)->name) == 0) - VECTOR_FIND_IF(iter, const DevMap, *list, MATCH_ENTRY); - if(iter == VECTOR_END(*list)) break; -#undef MATCH_ENTRY - count++; - } - - TRACE("Got device \"%s\", \"%s\", \"%ls\"\n", alstr_get_cstr(entry.name), alstr_get_cstr(entry.endpoint_guid), entry.devid); - VECTOR_PUSH_BACK(*list, entry); - - AL_STRING_DEINIT(tmpname); -} - -static WCHAR *get_device_id(IMMDevice *device) -{ - WCHAR *devid; - HRESULT hr; - - hr = IMMDevice_GetId(device, &devid); - if(FAILED(hr)) - { - ERR("Failed to get device id: %lx\n", hr); - return NULL; - } - - return devid; -} - -static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, vector_DevMap *list) -{ - IMMDeviceCollection *coll; - IMMDevice *defdev = NULL; - WCHAR *defdevid = NULL; - HRESULT hr; - UINT count; - UINT i; - - hr = IMMDeviceEnumerator_EnumAudioEndpoints(devenum, flowdir, DEVICE_STATE_ACTIVE, &coll); - if(FAILED(hr)) - { - ERR("Failed to enumerate audio endpoints: 0x%08lx\n", hr); - return hr; - } - - count = 0; - hr = IMMDeviceCollection_GetCount(coll, &count); - if(SUCCEEDED(hr) && count > 0) - { - clear_devlist(list); - VECTOR_RESIZE(*list, 0, count); - - hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, flowdir, - eMultimedia, &defdev); - } - if(SUCCEEDED(hr) && defdev != NULL) - { - defdevid = get_device_id(defdev); - if(defdevid) - add_device(defdev, defdevid, list); - } - - for(i = 0;i < count;++i) - { - IMMDevice *device; - WCHAR *devid; - - hr = IMMDeviceCollection_Item(coll, i, &device); - if(FAILED(hr)) continue; - - devid = get_device_id(device); - if(devid) - { - if(wcscmp(devid, defdevid) != 0) - add_device(device, devid, list); - CoTaskMemFree(devid); - } - IMMDevice_Release(device); - } - - if(defdev) IMMDevice_Release(defdev); - if(defdevid) CoTaskMemFree(defdevid); - IMMDeviceCollection_Release(coll); - - return S_OK; -} - - -/* Proxy interface used by the message handler. */ -struct ALCmmdevProxyVtable; - -typedef struct ALCmmdevProxy { - const struct ALCmmdevProxyVtable *vtbl; -} ALCmmdevProxy; - -struct ALCmmdevProxyVtable { - HRESULT (*const openProxy)(ALCmmdevProxy*); - void (*const closeProxy)(ALCmmdevProxy*); - - HRESULT (*const resetProxy)(ALCmmdevProxy*); - HRESULT (*const startProxy)(ALCmmdevProxy*); - void (*const stopProxy)(ALCmmdevProxy*); -}; - -#define DEFINE_ALCMMDEVPROXY_VTABLE(T) \ -DECLARE_THUNK(T, ALCmmdevProxy, HRESULT, openProxy) \ -DECLARE_THUNK(T, ALCmmdevProxy, void, closeProxy) \ -DECLARE_THUNK(T, ALCmmdevProxy, HRESULT, resetProxy) \ -DECLARE_THUNK(T, ALCmmdevProxy, HRESULT, startProxy) \ -DECLARE_THUNK(T, ALCmmdevProxy, void, stopProxy) \ - \ -static const struct ALCmmdevProxyVtable T##_ALCmmdevProxy_vtable = { \ - T##_ALCmmdevProxy_openProxy, \ - T##_ALCmmdevProxy_closeProxy, \ - T##_ALCmmdevProxy_resetProxy, \ - T##_ALCmmdevProxy_startProxy, \ - T##_ALCmmdevProxy_stopProxy, \ -} - -static void ALCmmdevProxy_Construct(ALCmmdevProxy* UNUSED(self)) { } -static void ALCmmdevProxy_Destruct(ALCmmdevProxy* UNUSED(self)) { } - -static DWORD CALLBACK ALCmmdevProxy_messageHandler(void *ptr) -{ - ThreadRequest *req = ptr; - IMMDeviceEnumerator *Enumerator; - ALuint deviceCount = 0; - ALCmmdevProxy *proxy; - HRESULT hr, cohr; - MSG msg; - - TRACE("Starting message thread\n"); - - cohr = CoInitialize(NULL); - if(FAILED(cohr)) - { - WARN("Failed to initialize COM: 0x%08lx\n", cohr); - ReturnMsgResponse(req, cohr); - 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(); - ReturnMsgResponse(req, hr); - return 0; - } - Enumerator = ptr; - IMMDeviceEnumerator_Release(Enumerator); - Enumerator = NULL; - - CoUninitialize(); - - /* HACK: Force Windows to create a message queue for this thread before - * returning success, otherwise PostThreadMessage may fail if it gets - * called before GetMessage. - */ - PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); - - TRACE("Message thread initialization complete\n"); - ReturnMsgResponse(req, S_OK); - - TRACE("Starting message loop\n"); - while(GetMessage(&msg, NULL, WM_USER_First, WM_USER_Last)) - { - TRACE("Got message \"%s\" (0x%04x, lparam=%p, wparam=%p)\n", - (msg.message >= WM_USER && msg.message <= WM_USER_Last) ? - MessageStr[msg.message-WM_USER] : "Unknown", - msg.message, (void*)msg.lParam, (void*)msg.wParam - ); - switch(msg.message) - { - case WM_USER_OpenDevice: - req = (ThreadRequest*)msg.wParam; - proxy = (ALCmmdevProxy*)msg.lParam; - - hr = cohr = S_OK; - if(++deviceCount == 1) - hr = cohr = CoInitialize(NULL); - if(SUCCEEDED(hr)) - hr = V0(proxy,openProxy)(); - if(FAILED(hr)) - { - if(--deviceCount == 0 && SUCCEEDED(cohr)) - CoUninitialize(); - } - - ReturnMsgResponse(req, hr); - continue; - - case WM_USER_ResetDevice: - req = (ThreadRequest*)msg.wParam; - proxy = (ALCmmdevProxy*)msg.lParam; - - hr = V0(proxy,resetProxy)(); - ReturnMsgResponse(req, hr); - continue; - - case WM_USER_StartDevice: - req = (ThreadRequest*)msg.wParam; - proxy = (ALCmmdevProxy*)msg.lParam; - - hr = V0(proxy,startProxy)(); - ReturnMsgResponse(req, hr); - continue; - - case WM_USER_StopDevice: - req = (ThreadRequest*)msg.wParam; - proxy = (ALCmmdevProxy*)msg.lParam; - - V0(proxy,stopProxy)(); - ReturnMsgResponse(req, S_OK); - continue; - - case WM_USER_CloseDevice: - req = (ThreadRequest*)msg.wParam; - proxy = (ALCmmdevProxy*)msg.lParam; - - V0(proxy,closeProxy)(); - if(--deviceCount == 0) - CoUninitialize(); - - ReturnMsgResponse(req, S_OK); - continue; - - case WM_USER_Enumerate: - req = (ThreadRequest*)msg.wParam; - - hr = cohr = S_OK; - if(++deviceCount == 1) - hr = cohr = CoInitialize(NULL); - if(SUCCEEDED(hr)) - hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); - if(SUCCEEDED(hr)) - { - Enumerator = ptr; - - if(msg.lParam == ALL_DEVICE_PROBE) - hr = probe_devices(Enumerator, eRender, &PlaybackDevices); - else if(msg.lParam == CAPTURE_DEVICE_PROBE) - hr = probe_devices(Enumerator, eCapture, &CaptureDevices); - - IMMDeviceEnumerator_Release(Enumerator); - Enumerator = NULL; - } - - if(--deviceCount == 0 && SUCCEEDED(cohr)) - CoUninitialize(); - - ReturnMsgResponse(req, hr); - continue; - - default: - ERR("Unexpected message: %u\n", msg.message); - continue; - } - } - TRACE("Message loop finished\n"); - - return 0; -} - - -typedef struct ALCmmdevPlayback { - DERIVE_FROM_TYPE(ALCbackend); - DERIVE_FROM_TYPE(ALCmmdevProxy); - - WCHAR *devid; - - IMMDevice *mmdev; - IAudioClient *client; - IAudioRenderClient *render; - HANDLE NotifyEvent; - - HANDLE MsgEvent; - - ATOMIC(UINT32) Padding; - - ATOMIC(int) killNow; - althrd_t thread; -} ALCmmdevPlayback; - -static int ALCmmdevPlayback_mixerProc(void *arg); - -static void ALCmmdevPlayback_Construct(ALCmmdevPlayback *self, ALCdevice *device); -static void ALCmmdevPlayback_Destruct(ALCmmdevPlayback *self); -static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *name); -static HRESULT ALCmmdevPlayback_openProxy(ALCmmdevPlayback *self); -static void ALCmmdevPlayback_closeProxy(ALCmmdevPlayback *self); -static ALCboolean ALCmmdevPlayback_reset(ALCmmdevPlayback *self); -static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self); -static ALCboolean ALCmmdevPlayback_start(ALCmmdevPlayback *self); -static HRESULT ALCmmdevPlayback_startProxy(ALCmmdevPlayback *self); -static void ALCmmdevPlayback_stop(ALCmmdevPlayback *self); -static void ALCmmdevPlayback_stopProxy(ALCmmdevPlayback *self); -static DECLARE_FORWARD2(ALCmmdevPlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint) -static DECLARE_FORWARD(ALCmmdevPlayback, ALCbackend, ALCuint, availableSamples) -static ClockLatency ALCmmdevPlayback_getClockLatency(ALCmmdevPlayback *self); -static DECLARE_FORWARD(ALCmmdevPlayback, ALCbackend, void, lock) -static DECLARE_FORWARD(ALCmmdevPlayback, ALCbackend, void, unlock) -DECLARE_DEFAULT_ALLOCATORS(ALCmmdevPlayback) - -DEFINE_ALCMMDEVPROXY_VTABLE(ALCmmdevPlayback); -DEFINE_ALCBACKEND_VTABLE(ALCmmdevPlayback); - - -static void ALCmmdevPlayback_Construct(ALCmmdevPlayback *self, ALCdevice *device) -{ - SET_VTABLE2(ALCmmdevPlayback, ALCbackend, self); - SET_VTABLE2(ALCmmdevPlayback, ALCmmdevProxy, self); - ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); - ALCmmdevProxy_Construct(STATIC_CAST(ALCmmdevProxy, self)); - - self->devid = NULL; - - self->mmdev = NULL; - self->client = NULL; - self->render = NULL; - self->NotifyEvent = NULL; - - self->MsgEvent = NULL; - - ATOMIC_INIT(&self->Padding, 0); - - ATOMIC_INIT(&self->killNow, 0); -} - -static void ALCmmdevPlayback_Destruct(ALCmmdevPlayback *self) -{ - if(self->MsgEvent) - { - ThreadRequest req = { self->MsgEvent, 0 }; - if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) - (void)WaitForResponse(&req); - - CloseHandle(self->MsgEvent); - self->MsgEvent = NULL; - } - - if(self->NotifyEvent) - CloseHandle(self->NotifyEvent); - self->NotifyEvent = NULL; - - free(self->devid); - self->devid = NULL; - - if(self->NotifyEvent != NULL) - CloseHandle(self->NotifyEvent); - self->NotifyEvent = NULL; - if(self->MsgEvent != NULL) - CloseHandle(self->MsgEvent); - self->MsgEvent = NULL; - - free(self->devid); - self->devid = NULL; - - ALCmmdevProxy_Destruct(STATIC_CAST(ALCmmdevProxy, self)); - ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); -} - - -FORCE_ALIGN static int ALCmmdevPlayback_mixerProc(void *arg) -{ - ALCmmdevPlayback *self = arg; - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - UINT32 buffer_len, written; - ALuint update_size, len; - BYTE *buffer; - HRESULT hr; - - hr = CoInitialize(NULL); - if(FAILED(hr)) - { - ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr); - V0(device->Backend,lock)(); - aluHandleDisconnect(device, "COM init failed: 0x%08lx", hr); - V0(device->Backend,unlock)(); - return 1; - } - - SetRTPriority(); - althrd_setname(althrd_current(), MIXER_THREAD_NAME); - - update_size = device->UpdateSize; - buffer_len = update_size * device->NumUpdates; - while(!ATOMIC_LOAD(&self->killNow, almemory_order_relaxed)) - { - hr = IAudioClient_GetCurrentPadding(self->client, &written); - if(FAILED(hr)) - { - ERR("Failed to get padding: 0x%08lx\n", hr); - V0(device->Backend,lock)(); - aluHandleDisconnect(device, "Failed to retrieve buffer padding: 0x%08lx", hr); - V0(device->Backend,unlock)(); - break; - } - ATOMIC_STORE(&self->Padding, written, almemory_order_relaxed); - - len = buffer_len - written; - if(len < update_size) - { - DWORD res; - res = WaitForSingleObjectEx(self->NotifyEvent, 2000, FALSE); - if(res != WAIT_OBJECT_0) - ERR("WaitForSingleObjectEx error: 0x%lx\n", res); - continue; - } - len -= len%update_size; - - hr = IAudioRenderClient_GetBuffer(self->render, len, &buffer); - if(SUCCEEDED(hr)) - { - ALCmmdevPlayback_lock(self); - aluMixData(device, buffer, len); - ATOMIC_STORE(&self->Padding, written + len, almemory_order_relaxed); - ALCmmdevPlayback_unlock(self); - hr = IAudioRenderClient_ReleaseBuffer(self->render, len, 0); - } - if(FAILED(hr)) - { - ERR("Failed to buffer data: 0x%08lx\n", hr); - V0(device->Backend,lock)(); - aluHandleDisconnect(device, "Failed to send playback samples: 0x%08lx", hr); - V0(device->Backend,unlock)(); - break; - } - } - ATOMIC_STORE(&self->Padding, 0, almemory_order_release); - - CoUninitialize(); - return 0; -} - - -static ALCboolean MakeExtensible(WAVEFORMATEXTENSIBLE *out, const WAVEFORMATEX *in) -{ - memset(out, 0, sizeof(*out)); - if(in->wFormatTag == WAVE_FORMAT_EXTENSIBLE) - *out = *(const 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 ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *deviceName) -{ - HRESULT hr = S_OK; - - self->NotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL); - self->MsgEvent = CreateEventW(NULL, FALSE, FALSE, NULL); - if(self->NotifyEvent == NULL || self->MsgEvent == NULL) - { - ERR("Failed to create message events: %lu\n", GetLastError()); - hr = E_FAIL; - } - - if(SUCCEEDED(hr)) - { - if(deviceName) - { - const DevMap *iter; - - if(VECTOR_SIZE(PlaybackDevices) == 0) - { - ThreadRequest req = { self->MsgEvent, 0 }; - if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, ALL_DEVICE_PROBE)) - (void)WaitForResponse(&req); - } - - hr = E_FAIL; -#define MATCH_NAME(i) (alstr_cmp_cstr((i)->name, deviceName) == 0 || \ - alstr_cmp_cstr((i)->endpoint_guid, deviceName) == 0) - VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); -#undef MATCH_NAME - if(iter == VECTOR_END(PlaybackDevices)) - { - int len; - if((len=MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, NULL, 0)) > 0) - { - WCHAR *wname = calloc(sizeof(WCHAR), len); - MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, wname, len); -#define MATCH_NAME(i) (wcscmp((i)->devid, wname) == 0) - VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); -#undef MATCH_NAME - free(wname); - } - } - if(iter == VECTOR_END(PlaybackDevices)) - WARN("Failed to find device name matching \"%s\"\n", deviceName); - else - { - ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; - self->devid = strdupW(iter->devid); - alstr_copy(&device->DeviceName, iter->name); - hr = S_OK; - } - } - } - - if(SUCCEEDED(hr)) - { - ThreadRequest req = { self->MsgEvent, 0 }; - - hr = E_FAIL; - if(PostThreadMessage(ThreadID, WM_USER_OpenDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) - hr = WaitForResponse(&req); - else - ERR("Failed to post thread message: %lu\n", GetLastError()); - } - - if(FAILED(hr)) - { - if(self->NotifyEvent != NULL) - CloseHandle(self->NotifyEvent); - self->NotifyEvent = NULL; - if(self->MsgEvent != NULL) - CloseHandle(self->MsgEvent); - self->MsgEvent = NULL; - - free(self->devid); - self->devid = NULL; - - ERR("Device init failed: 0x%08lx\n", hr); - return ALC_INVALID_VALUE; - } - - return ALC_NO_ERROR; -} - -static HRESULT ALCmmdevPlayback_openProxy(ALCmmdevPlayback *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - void *ptr; - HRESULT hr; - - hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); - if(SUCCEEDED(hr)) - { - IMMDeviceEnumerator *Enumerator = ptr; - if(!self->devid) - hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(Enumerator, eRender, eMultimedia, &self->mmdev); - else - hr = IMMDeviceEnumerator_GetDevice(Enumerator, self->devid, &self->mmdev); - IMMDeviceEnumerator_Release(Enumerator); - Enumerator = NULL; - } - if(SUCCEEDED(hr)) - hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); - if(SUCCEEDED(hr)) - { - self->client = ptr; - if(alstr_empty(device->DeviceName)) - get_device_name_and_guid(self->mmdev, &device->DeviceName, NULL); - } - - if(FAILED(hr)) - { - if(self->mmdev) - IMMDevice_Release(self->mmdev); - self->mmdev = NULL; - } - - return hr; -} - - -static void ALCmmdevPlayback_closeProxy(ALCmmdevPlayback *self) -{ - if(self->client) - IAudioClient_Release(self->client); - self->client = NULL; - - if(self->mmdev) - IMMDevice_Release(self->mmdev); - self->mmdev = NULL; -} - - -static ALCboolean ALCmmdevPlayback_reset(ALCmmdevPlayback *self) -{ - ThreadRequest req = { self->MsgEvent, 0 }; - HRESULT hr = E_FAIL; - - if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) - hr = WaitForResponse(&req); - - return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE; -} - -static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - EndpointFormFactor formfactor = UnknownFormFactor; - WAVEFORMATEXTENSIBLE OutputType; - WAVEFORMATEX *wfx = NULL; - REFERENCE_TIME min_per, buf_time; - UINT32 buffer_len, min_len; - void *ptr = NULL; - HRESULT hr; - - if(self->client) - IAudioClient_Release(self->client); - self->client = NULL; - - hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); - if(FAILED(hr)) - { - ERR("Failed to reactivate audio client: 0x%08lx\n", hr); - return hr; - } - self->client = ptr; - - hr = IAudioClient_GetMixFormat(self->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; - - buf_time = ScaleCeil(device->UpdateSize*device->NumUpdates, REFTIME_PER_SEC, - device->Frequency); - - 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 == X5DOT1REAR) - device->FmtChans = DevFmtX51Rear; - else if(OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1) - device->FmtChans = DevFmtX61; - else if(OutputType.Format.nChannels == 8 && (OutputType.dwChannelMask == X7DOT1 || OutputType.dwChannelMask == X7DOT1_WIDE)) - 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 DevFmtAmbi3D: - device->FmtChans = DevFmtStereo; - /*fall-through*/ - 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 DevFmtX51Rear: - OutputType.Format.nChannels = 6; - OutputType.dwChannelMask = X5DOT1REAR; - 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 DevFmtUInt: - device->FmtType = DevFmtInt; - /* fall-through */ - case DevFmtInt: - OutputType.Format.wBitsPerSample = 32; - OutputType.Samples.wValidBitsPerSample = 32; - 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(self->client, AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx); - if(FAILED(hr)) - { - ERR("Failed to check format support: 0x%08lx\n", hr); - hr = IAudioClient_GetMixFormat(self->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; - - device->Frequency = OutputType.Format.nSamplesPerSec; - 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 == X5DOT1REAR) - device->FmtChans = DevFmtX51Rear; - else if(OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1) - device->FmtChans = DevFmtX61; - else if(OutputType.Format.nChannels == 8 && (OutputType.dwChannelMask == X7DOT1 || OutputType.dwChannelMask == X7DOT1_WIDE)) - 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.Format.wBitsPerSample == 8) - device->FmtType = DevFmtUByte; - else if(OutputType.Format.wBitsPerSample == 16) - device->FmtType = DevFmtShort; - else if(OutputType.Format.wBitsPerSample == 32) - device->FmtType = DevFmtInt; - else - { - device->FmtType = DevFmtShort; - OutputType.Format.wBitsPerSample = 16; - } - } - else if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) - { - device->FmtType = DevFmtFloat; - OutputType.Format.wBitsPerSample = 32; - } - else - { - ERR("Unhandled format sub-type\n"); - device->FmtType = DevFmtShort; - OutputType.Format.wBitsPerSample = 16; - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - } - OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; - } - get_device_formfactor(self->mmdev, &formfactor); - device->IsHeadphones = (device->FmtChans == DevFmtStereo && - (formfactor == Headphones || formfactor == Headset) - ); - - SetDefaultWFXChannelOrder(device); - - hr = IAudioClient_Initialize(self->client, AUDCLNT_SHAREMODE_SHARED, - AUDCLNT_STREAMFLAGS_EVENTCALLBACK, - buf_time, 0, &OutputType.Format, NULL); - if(FAILED(hr)) - { - ERR("Failed to initialize audio client: 0x%08lx\n", hr); - return hr; - } - - hr = IAudioClient_GetDevicePeriod(self->client, &min_per, NULL); - if(SUCCEEDED(hr)) - { - min_len = (UINT32)ScaleCeil(min_per, device->Frequency, REFTIME_PER_SEC); - /* Find the nearest multiple of the period size to the update size */ - if(min_len < device->UpdateSize) - min_len *= (device->UpdateSize + min_len/2)/min_len; - hr = IAudioClient_GetBufferSize(self->client, &buffer_len); - } - if(FAILED(hr)) - { - ERR("Failed to get audio buffer info: 0x%08lx\n", hr); - return hr; - } - - device->UpdateSize = min_len; - device->NumUpdates = buffer_len / device->UpdateSize; - if(device->NumUpdates <= 1) - { - ERR("Audio client returned buffer_len < period*2; expect break up\n"); - device->NumUpdates = 2; - device->UpdateSize = buffer_len / device->NumUpdates; - } - - hr = IAudioClient_SetEventHandle(self->client, self->NotifyEvent); - if(FAILED(hr)) - { - ERR("Failed to set event handle: 0x%08lx\n", hr); - return hr; - } - - return hr; -} - - -static ALCboolean ALCmmdevPlayback_start(ALCmmdevPlayback *self) -{ - ThreadRequest req = { self->MsgEvent, 0 }; - HRESULT hr = E_FAIL; - - if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) - hr = WaitForResponse(&req); - - return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE; -} - -static HRESULT ALCmmdevPlayback_startProxy(ALCmmdevPlayback *self) -{ - HRESULT hr; - void *ptr; - - ResetEvent(self->NotifyEvent); - hr = IAudioClient_Start(self->client); - if(FAILED(hr)) - ERR("Failed to start audio client: 0x%08lx\n", hr); - - if(SUCCEEDED(hr)) - hr = IAudioClient_GetService(self->client, &IID_IAudioRenderClient, &ptr); - if(SUCCEEDED(hr)) - { - self->render = ptr; - ATOMIC_STORE(&self->killNow, 0, almemory_order_release); - if(althrd_create(&self->thread, ALCmmdevPlayback_mixerProc, self) != althrd_success) - { - if(self->render) - IAudioRenderClient_Release(self->render); - self->render = NULL; - IAudioClient_Stop(self->client); - ERR("Failed to start thread\n"); - hr = E_FAIL; - } - } - - return hr; -} - - -static void ALCmmdevPlayback_stop(ALCmmdevPlayback *self) -{ - ThreadRequest req = { self->MsgEvent, 0 }; - if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) - (void)WaitForResponse(&req); -} - -static void ALCmmdevPlayback_stopProxy(ALCmmdevPlayback *self) -{ - int res; - - if(!self->render) - return; - - ATOMIC_STORE_SEQ(&self->killNow, 1); - althrd_join(self->thread, &res); - - IAudioRenderClient_Release(self->render); - self->render = NULL; - IAudioClient_Stop(self->client); -} - - -static ClockLatency ALCmmdevPlayback_getClockLatency(ALCmmdevPlayback *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - ClockLatency ret; - - ALCmmdevPlayback_lock(self); - ret.ClockTime = GetDeviceClockTime(device); - ret.Latency = ATOMIC_LOAD(&self->Padding, almemory_order_relaxed) * DEVICE_CLOCK_RES / - device->Frequency; - ALCmmdevPlayback_unlock(self); - - return ret; -} - - -typedef struct ALCmmdevCapture { - DERIVE_FROM_TYPE(ALCbackend); - DERIVE_FROM_TYPE(ALCmmdevProxy); - - WCHAR *devid; - - IMMDevice *mmdev; - IAudioClient *client; - IAudioCaptureClient *capture; - HANDLE NotifyEvent; - - HANDLE MsgEvent; - - ChannelConverter *ChannelConv; - SampleConverter *SampleConv; - ll_ringbuffer_t *Ring; - - ATOMIC(int) killNow; - althrd_t thread; -} ALCmmdevCapture; - -static int ALCmmdevCapture_recordProc(void *arg); - -static void ALCmmdevCapture_Construct(ALCmmdevCapture *self, ALCdevice *device); -static void ALCmmdevCapture_Destruct(ALCmmdevCapture *self); -static ALCenum ALCmmdevCapture_open(ALCmmdevCapture *self, const ALCchar *name); -static HRESULT ALCmmdevCapture_openProxy(ALCmmdevCapture *self); -static void ALCmmdevCapture_closeProxy(ALCmmdevCapture *self); -static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, ALCboolean, reset) -static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self); -static ALCboolean ALCmmdevCapture_start(ALCmmdevCapture *self); -static HRESULT ALCmmdevCapture_startProxy(ALCmmdevCapture *self); -static void ALCmmdevCapture_stop(ALCmmdevCapture *self); -static void ALCmmdevCapture_stopProxy(ALCmmdevCapture *self); -static ALCenum ALCmmdevCapture_captureSamples(ALCmmdevCapture *self, ALCvoid *buffer, ALCuint samples); -static ALuint ALCmmdevCapture_availableSamples(ALCmmdevCapture *self); -static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, ClockLatency, getClockLatency) -static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, void, lock) -static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, void, unlock) -DECLARE_DEFAULT_ALLOCATORS(ALCmmdevCapture) - -DEFINE_ALCMMDEVPROXY_VTABLE(ALCmmdevCapture); -DEFINE_ALCBACKEND_VTABLE(ALCmmdevCapture); - - -static void ALCmmdevCapture_Construct(ALCmmdevCapture *self, ALCdevice *device) -{ - SET_VTABLE2(ALCmmdevCapture, ALCbackend, self); - SET_VTABLE2(ALCmmdevCapture, ALCmmdevProxy, self); - ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); - ALCmmdevProxy_Construct(STATIC_CAST(ALCmmdevProxy, self)); - - self->devid = NULL; - - self->mmdev = NULL; - self->client = NULL; - self->capture = NULL; - self->NotifyEvent = NULL; - - self->MsgEvent = NULL; - - self->ChannelConv = NULL; - self->SampleConv = NULL; - self->Ring = NULL; - - ATOMIC_INIT(&self->killNow, 0); -} - -static void ALCmmdevCapture_Destruct(ALCmmdevCapture *self) -{ - if(self->MsgEvent) - { - ThreadRequest req = { self->MsgEvent, 0 }; - if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) - (void)WaitForResponse(&req); - - CloseHandle(self->MsgEvent); - self->MsgEvent = NULL; - } - - if(self->NotifyEvent != NULL) - CloseHandle(self->NotifyEvent); - self->NotifyEvent = NULL; - - ll_ringbuffer_free(self->Ring); - self->Ring = NULL; - - DestroySampleConverter(&self->SampleConv); - DestroyChannelConverter(&self->ChannelConv); - - free(self->devid); - self->devid = NULL; - - ALCmmdevProxy_Destruct(STATIC_CAST(ALCmmdevProxy, self)); - ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); -} - - -FORCE_ALIGN int ALCmmdevCapture_recordProc(void *arg) -{ - ALCmmdevCapture *self = arg; - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - ALfloat *samples = NULL; - size_t samplesmax = 0; - HRESULT hr; - - hr = CoInitialize(NULL); - if(FAILED(hr)) - { - ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr); - V0(device->Backend,lock)(); - aluHandleDisconnect(device, "COM init failed: 0x%08lx", hr); - V0(device->Backend,unlock)(); - return 1; - } - - althrd_setname(althrd_current(), RECORD_THREAD_NAME); - - while(!ATOMIC_LOAD(&self->killNow, almemory_order_relaxed)) - { - UINT32 avail; - DWORD res; - - hr = IAudioCaptureClient_GetNextPacketSize(self->capture, &avail); - if(FAILED(hr)) - ERR("Failed to get next packet size: 0x%08lx\n", hr); - else if(avail > 0) - { - UINT32 numsamples; - DWORD flags; - BYTE *rdata; - - hr = IAudioCaptureClient_GetBuffer(self->capture, - &rdata, &numsamples, &flags, NULL, NULL - ); - if(FAILED(hr)) - ERR("Failed to get capture buffer: 0x%08lx\n", hr); - else - { - ll_ringbuffer_data_t data[2]; - size_t dstframes = 0; - - if(self->ChannelConv) - { - if(samplesmax < numsamples) - { - size_t newmax = RoundUp(numsamples, 4096); - ALfloat *tmp = al_calloc(DEF_ALIGN, newmax*2*sizeof(ALfloat)); - al_free(samples); - samples = tmp; - samplesmax = newmax; - } - ChannelConverterInput(self->ChannelConv, rdata, samples, numsamples); - rdata = (BYTE*)samples; - } - - ll_ringbuffer_get_write_vector(self->Ring, data); - - if(self->SampleConv) - { - const ALvoid *srcdata = rdata; - ALsizei srcframes = numsamples; - - dstframes = SampleConverterInput(self->SampleConv, - &srcdata, &srcframes, data[0].buf, (ALsizei)minz(data[0].len, INT_MAX) - ); - if(srcframes > 0 && dstframes == data[0].len && data[1].len > 0) - { - /* If some source samples remain, all of the first dest - * block was filled, and there's space in the second - * dest block, do another run for the second block. - */ - dstframes += SampleConverterInput(self->SampleConv, - &srcdata, &srcframes, data[1].buf, (ALsizei)minz(data[1].len, INT_MAX) - ); - } - } - else - { - ALuint framesize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, - device->AmbiOrder); - size_t len1 = minz(data[0].len, numsamples); - size_t len2 = minz(data[1].len, numsamples-len1); - - memcpy(data[0].buf, rdata, len1*framesize); - if(len2 > 0) - memcpy(data[1].buf, rdata+len1*framesize, len2*framesize); - dstframes = len1 + len2; - } - - ll_ringbuffer_write_advance(self->Ring, dstframes); - - hr = IAudioCaptureClient_ReleaseBuffer(self->capture, numsamples); - if(FAILED(hr)) ERR("Failed to release capture buffer: 0x%08lx\n", hr); - } - } - - if(FAILED(hr)) - { - V0(device->Backend,lock)(); - aluHandleDisconnect(device, "Failed to capture samples: 0x%08lx", hr); - V0(device->Backend,unlock)(); - break; - } - - res = WaitForSingleObjectEx(self->NotifyEvent, 2000, FALSE); - if(res != WAIT_OBJECT_0) - ERR("WaitForSingleObjectEx error: 0x%lx\n", res); - } - - al_free(samples); - samples = NULL; - samplesmax = 0; - - CoUninitialize(); - return 0; -} - - -static ALCenum ALCmmdevCapture_open(ALCmmdevCapture *self, const ALCchar *deviceName) -{ - HRESULT hr = S_OK; - - self->NotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL); - self->MsgEvent = CreateEventW(NULL, FALSE, FALSE, NULL); - if(self->NotifyEvent == NULL || self->MsgEvent == NULL) - { - ERR("Failed to create message events: %lu\n", GetLastError()); - hr = E_FAIL; - } - - if(SUCCEEDED(hr)) - { - if(deviceName) - { - const DevMap *iter; - - if(VECTOR_SIZE(CaptureDevices) == 0) - { - ThreadRequest req = { self->MsgEvent, 0 }; - if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, CAPTURE_DEVICE_PROBE)) - (void)WaitForResponse(&req); - } - - hr = E_FAIL; -#define MATCH_NAME(i) (alstr_cmp_cstr((i)->name, deviceName) == 0 || \ - alstr_cmp_cstr((i)->endpoint_guid, deviceName) == 0) - VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); -#undef MATCH_NAME - if(iter == VECTOR_END(CaptureDevices)) - { - int len; - if((len=MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, NULL, 0)) > 0) - { - WCHAR *wname = calloc(sizeof(WCHAR), len); - MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, wname, len); -#define MATCH_NAME(i) (wcscmp((i)->devid, wname) == 0) - VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); -#undef MATCH_NAME - free(wname); - } - } - if(iter == VECTOR_END(CaptureDevices)) - WARN("Failed to find device name matching \"%s\"\n", deviceName); - else - { - ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; - self->devid = strdupW(iter->devid); - alstr_copy(&device->DeviceName, iter->name); - hr = S_OK; - } - } - } - - if(SUCCEEDED(hr)) - { - ThreadRequest req = { self->MsgEvent, 0 }; - - hr = E_FAIL; - if(PostThreadMessage(ThreadID, WM_USER_OpenDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) - hr = WaitForResponse(&req); - else - ERR("Failed to post thread message: %lu\n", GetLastError()); - } - - if(FAILED(hr)) - { - if(self->NotifyEvent != NULL) - CloseHandle(self->NotifyEvent); - self->NotifyEvent = NULL; - if(self->MsgEvent != NULL) - CloseHandle(self->MsgEvent); - self->MsgEvent = NULL; - - free(self->devid); - self->devid = NULL; - - ERR("Device init failed: 0x%08lx\n", hr); - return ALC_INVALID_VALUE; - } - else - { - ThreadRequest req = { self->MsgEvent, 0 }; - - hr = E_FAIL; - if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) - hr = WaitForResponse(&req); - else - ERR("Failed to post thread message: %lu\n", GetLastError()); - - if(FAILED(hr)) - { - if(hr == E_OUTOFMEMORY) - return ALC_OUT_OF_MEMORY; - return ALC_INVALID_VALUE; - } - } - - return ALC_NO_ERROR; -} - -static HRESULT ALCmmdevCapture_openProxy(ALCmmdevCapture *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - void *ptr; - HRESULT hr; - - hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); - if(SUCCEEDED(hr)) - { - IMMDeviceEnumerator *Enumerator = ptr; - if(!self->devid) - hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(Enumerator, eCapture, eMultimedia, &self->mmdev); - else - hr = IMMDeviceEnumerator_GetDevice(Enumerator, self->devid, &self->mmdev); - IMMDeviceEnumerator_Release(Enumerator); - Enumerator = NULL; - } - if(SUCCEEDED(hr)) - hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); - if(SUCCEEDED(hr)) - { - self->client = ptr; - if(alstr_empty(device->DeviceName)) - get_device_name_and_guid(self->mmdev, &device->DeviceName, NULL); - } - - if(FAILED(hr)) - { - if(self->mmdev) - IMMDevice_Release(self->mmdev); - self->mmdev = NULL; - } - - return hr; -} - - -static void ALCmmdevCapture_closeProxy(ALCmmdevCapture *self) -{ - if(self->client) - IAudioClient_Release(self->client); - self->client = NULL; - - if(self->mmdev) - IMMDevice_Release(self->mmdev); - self->mmdev = NULL; -} - - -static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - WAVEFORMATEXTENSIBLE OutputType; - WAVEFORMATEX *wfx = NULL; - enum DevFmtType srcType; - REFERENCE_TIME buf_time; - UINT32 buffer_len; - void *ptr = NULL; - HRESULT hr; - - if(self->client) - IAudioClient_Release(self->client); - self->client = NULL; - - hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); - if(FAILED(hr)) - { - ERR("Failed to reactivate audio client: 0x%08lx\n", hr); - return hr; - } - self->client = ptr; - - buf_time = ScaleCeil(device->UpdateSize*device->NumUpdates, REFTIME_PER_SEC, - device->Frequency); - // Make sure buffer is at least 100ms in size - buf_time = maxu64(buf_time, REFTIME_PER_SEC/10); - device->UpdateSize = (ALuint)ScaleCeil(buf_time, device->Frequency, REFTIME_PER_SEC) / - device->NumUpdates; - - OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; - 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 DevFmtX51Rear: - OutputType.Format.nChannels = 6; - OutputType.dwChannelMask = X5DOT1REAR; - break; - case DevFmtX61: - OutputType.Format.nChannels = 7; - OutputType.dwChannelMask = X6DOT1; - break; - case DevFmtX71: - OutputType.Format.nChannels = 8; - OutputType.dwChannelMask = X7DOT1; - break; - - case DevFmtAmbi3D: - return E_FAIL; - } - switch(device->FmtType) - { - /* NOTE: Signedness doesn't matter, the converter will handle it. */ - case DevFmtByte: - case DevFmtUByte: - OutputType.Format.wBitsPerSample = 8; - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - break; - case DevFmtShort: - case DevFmtUShort: - OutputType.Format.wBitsPerSample = 16; - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - break; - case DevFmtInt: - case DevFmtUInt: - OutputType.Format.wBitsPerSample = 32; - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - break; - case DevFmtFloat: - OutputType.Format.wBitsPerSample = 32; - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; - break; - } - OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; - OutputType.Format.nSamplesPerSec = device->Frequency; - - OutputType.Format.nBlockAlign = OutputType.Format.nChannels * - OutputType.Format.wBitsPerSample / 8; - OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec * - OutputType.Format.nBlockAlign; - OutputType.Format.cbSize = sizeof(OutputType) - sizeof(OutputType.Format); - - hr = IAudioClient_IsFormatSupported(self->client, - AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx - ); - if(FAILED(hr)) - { - ERR("Failed to check format support: 0x%08lx\n", hr); - return hr; - } - - DestroySampleConverter(&self->SampleConv); - DestroyChannelConverter(&self->ChannelConv); - - if(wfx != NULL) - { - if(!(wfx->nChannels == OutputType.Format.nChannels || - (wfx->nChannels == 1 && OutputType.Format.nChannels == 2) || - (wfx->nChannels == 2 && OutputType.Format.nChannels == 1))) - { - ERR("Failed to get matching format, wanted: %s %s %uhz, got: %d channel%s %d-bit %luhz\n", - DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), - device->Frequency, wfx->nChannels, (wfx->nChannels==1)?"":"s", wfx->wBitsPerSample, - wfx->nSamplesPerSec); - CoTaskMemFree(wfx); - return E_FAIL; - } - - if(!MakeExtensible(&OutputType, wfx)) - { - CoTaskMemFree(wfx); - return E_FAIL; - } - CoTaskMemFree(wfx); - wfx = NULL; - } - - if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) - { - if(OutputType.Format.wBitsPerSample == 8) - srcType = DevFmtUByte; - else if(OutputType.Format.wBitsPerSample == 16) - srcType = DevFmtShort; - else if(OutputType.Format.wBitsPerSample == 32) - srcType = DevFmtInt; - else - { - ERR("Unhandled integer bit depth: %d\n", OutputType.Format.wBitsPerSample); - return E_FAIL; - } - } - else if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) - { - if(OutputType.Format.wBitsPerSample == 32) - srcType = DevFmtFloat; - else - { - ERR("Unhandled float bit depth: %d\n", OutputType.Format.wBitsPerSample); - return E_FAIL; - } - } - else - { - ERR("Unhandled format sub-type\n"); - return E_FAIL; - } - - if(device->FmtChans == DevFmtMono && OutputType.Format.nChannels == 2) - { - self->ChannelConv = CreateChannelConverter(srcType, DevFmtStereo, - device->FmtChans); - if(!self->ChannelConv) - { - ERR("Failed to create %s stereo-to-mono converter\n", DevFmtTypeString(srcType)); - return E_FAIL; - } - TRACE("Created %s stereo-to-mono converter\n", DevFmtTypeString(srcType)); - /* The channel converter always outputs float, so change the input type - * for the resampler/type-converter. - */ - srcType = DevFmtFloat; - } - else if(device->FmtChans == DevFmtStereo && OutputType.Format.nChannels == 1) - { - self->ChannelConv = CreateChannelConverter(srcType, DevFmtMono, - device->FmtChans); - if(!self->ChannelConv) - { - ERR("Failed to create %s mono-to-stereo converter\n", DevFmtTypeString(srcType)); - return E_FAIL; - } - TRACE("Created %s mono-to-stereo converter\n", DevFmtTypeString(srcType)); - srcType = DevFmtFloat; - } - - if(device->Frequency != OutputType.Format.nSamplesPerSec || device->FmtType != srcType) - { - self->SampleConv = CreateSampleConverter( - srcType, device->FmtType, ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder), - OutputType.Format.nSamplesPerSec, device->Frequency - ); - if(!self->SampleConv) - { - ERR("Failed to create converter for %s format, dst: %s %uhz, src: %s %luhz\n", - DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), - device->Frequency, DevFmtTypeString(srcType), OutputType.Format.nSamplesPerSec); - return E_FAIL; - } - TRACE("Created converter for %s format, dst: %s %uhz, src: %s %luhz\n", - DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), - device->Frequency, DevFmtTypeString(srcType), OutputType.Format.nSamplesPerSec); - } - - hr = IAudioClient_Initialize(self->client, - AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, - buf_time, 0, &OutputType.Format, NULL - ); - if(FAILED(hr)) - { - ERR("Failed to initialize audio client: 0x%08lx\n", hr); - return hr; - } - - hr = IAudioClient_GetBufferSize(self->client, &buffer_len); - if(FAILED(hr)) - { - ERR("Failed to get buffer size: 0x%08lx\n", hr); - return hr; - } - - buffer_len = maxu(device->UpdateSize*device->NumUpdates, buffer_len); - ll_ringbuffer_free(self->Ring); - self->Ring = ll_ringbuffer_create(buffer_len, - FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder), - false - ); - if(!self->Ring) - { - ERR("Failed to allocate capture ring buffer\n"); - return E_OUTOFMEMORY; - } - - hr = IAudioClient_SetEventHandle(self->client, self->NotifyEvent); - if(FAILED(hr)) - { - ERR("Failed to set event handle: 0x%08lx\n", hr); - return hr; - } - - return hr; -} - - -static ALCboolean ALCmmdevCapture_start(ALCmmdevCapture *self) -{ - ThreadRequest req = { self->MsgEvent, 0 }; - HRESULT hr = E_FAIL; - - if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) - hr = WaitForResponse(&req); - - return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE; -} - -static HRESULT ALCmmdevCapture_startProxy(ALCmmdevCapture *self) -{ - HRESULT hr; - void *ptr; - - ResetEvent(self->NotifyEvent); - hr = IAudioClient_Start(self->client); - if(FAILED(hr)) - { - ERR("Failed to start audio client: 0x%08lx\n", hr); - return hr; - } - - hr = IAudioClient_GetService(self->client, &IID_IAudioCaptureClient, &ptr); - if(SUCCEEDED(hr)) - { - self->capture = ptr; - ATOMIC_STORE(&self->killNow, 0, almemory_order_release); - if(althrd_create(&self->thread, ALCmmdevCapture_recordProc, self) != althrd_success) - { - ERR("Failed to start thread\n"); - IAudioCaptureClient_Release(self->capture); - self->capture = NULL; - hr = E_FAIL; - } - } - - if(FAILED(hr)) - { - IAudioClient_Stop(self->client); - IAudioClient_Reset(self->client); - } - - return hr; -} - - -static void ALCmmdevCapture_stop(ALCmmdevCapture *self) -{ - ThreadRequest req = { self->MsgEvent, 0 }; - if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) - (void)WaitForResponse(&req); -} - -static void ALCmmdevCapture_stopProxy(ALCmmdevCapture *self) -{ - int res; - - if(!self->capture) - return; - - ATOMIC_STORE_SEQ(&self->killNow, 1); - althrd_join(self->thread, &res); - - IAudioCaptureClient_Release(self->capture); - self->capture = NULL; - IAudioClient_Stop(self->client); - IAudioClient_Reset(self->client); -} - - -ALuint ALCmmdevCapture_availableSamples(ALCmmdevCapture *self) -{ - return (ALuint)ll_ringbuffer_read_space(self->Ring); -} - -ALCenum ALCmmdevCapture_captureSamples(ALCmmdevCapture *self, ALCvoid *buffer, ALCuint samples) -{ - if(ALCmmdevCapture_availableSamples(self) < samples) - return ALC_INVALID_VALUE; - ll_ringbuffer_read(self->Ring, buffer, samples); - return ALC_NO_ERROR; -} - - -static inline void AppendAllDevicesList2(const DevMap *entry) -{ AppendAllDevicesList(alstr_get_cstr(entry->name)); } -static inline void AppendCaptureDeviceList2(const DevMap *entry) -{ AppendCaptureDeviceList(alstr_get_cstr(entry->name)); } - -typedef struct ALCmmdevBackendFactory { - DERIVE_FROM_TYPE(ALCbackendFactory); -} ALCmmdevBackendFactory; -#define ALCMMDEVBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCmmdevBackendFactory, ALCbackendFactory) } } - -static ALCboolean ALCmmdevBackendFactory_init(ALCmmdevBackendFactory *self); -static void ALCmmdevBackendFactory_deinit(ALCmmdevBackendFactory *self); -static ALCboolean ALCmmdevBackendFactory_querySupport(ALCmmdevBackendFactory *self, ALCbackend_Type type); -static void ALCmmdevBackendFactory_probe(ALCmmdevBackendFactory *self, enum DevProbe type); -static ALCbackend* ALCmmdevBackendFactory_createBackend(ALCmmdevBackendFactory *self, ALCdevice *device, ALCbackend_Type type); - -DEFINE_ALCBACKENDFACTORY_VTABLE(ALCmmdevBackendFactory); - - -static BOOL MMDevApiLoad(void) -{ - static HRESULT InitResult; - if(!ThreadHdl) - { - ThreadRequest req; - InitResult = E_FAIL; - - req.FinishedEvt = CreateEventW(NULL, FALSE, FALSE, NULL); - if(req.FinishedEvt == NULL) - ERR("Failed to create event: %lu\n", GetLastError()); - else - { - ThreadHdl = CreateThread(NULL, 0, ALCmmdevProxy_messageHandler, &req, 0, &ThreadID); - if(ThreadHdl != NULL) - InitResult = WaitForResponse(&req); - CloseHandle(req.FinishedEvt); - } - } - return SUCCEEDED(InitResult); -} - -static ALCboolean ALCmmdevBackendFactory_init(ALCmmdevBackendFactory* UNUSED(self)) -{ - VECTOR_INIT(PlaybackDevices); - VECTOR_INIT(CaptureDevices); - - if(!MMDevApiLoad()) - return ALC_FALSE; - return ALC_TRUE; -} - -static void ALCmmdevBackendFactory_deinit(ALCmmdevBackendFactory* UNUSED(self)) -{ - clear_devlist(&PlaybackDevices); - VECTOR_DEINIT(PlaybackDevices); - - clear_devlist(&CaptureDevices); - VECTOR_DEINIT(CaptureDevices); - - if(ThreadHdl) - { - TRACE("Sending WM_QUIT to Thread %04lx\n", ThreadID); - PostThreadMessage(ThreadID, WM_QUIT, 0, 0); - CloseHandle(ThreadHdl); - ThreadHdl = NULL; - } -} - -static ALCboolean ALCmmdevBackendFactory_querySupport(ALCmmdevBackendFactory* UNUSED(self), ALCbackend_Type type) -{ - /* TODO: Disable capture with mmdevapi for now, since it doesn't do any - * rechanneling or resampling; if the device is configured for 48000hz - * stereo input, for example, and the app asks for 22050hz mono, - * initialization will fail. - */ - if(type == ALCbackend_Playback || type == ALCbackend_Capture) - return ALC_TRUE; - return ALC_FALSE; -} - -static void ALCmmdevBackendFactory_probe(ALCmmdevBackendFactory* UNUSED(self), enum DevProbe type) -{ - ThreadRequest req = { NULL, 0 }; - - req.FinishedEvt = CreateEventW(NULL, FALSE, FALSE, NULL); - if(req.FinishedEvt == NULL) - ERR("Failed to create event: %lu\n", GetLastError()); - else - { - HRESULT hr = E_FAIL; - if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, type)) - hr = WaitForResponse(&req); - if(SUCCEEDED(hr)) switch(type) - { - case ALL_DEVICE_PROBE: - VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2); - break; - - case CAPTURE_DEVICE_PROBE: - VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2); - break; - } - CloseHandle(req.FinishedEvt); - req.FinishedEvt = NULL; - } -} - -static ALCbackend* ALCmmdevBackendFactory_createBackend(ALCmmdevBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) -{ - if(type == ALCbackend_Playback) - { - ALCmmdevPlayback *backend; - NEW_OBJ(backend, ALCmmdevPlayback)(device); - if(!backend) return NULL; - return STATIC_CAST(ALCbackend, backend); - } - if(type == ALCbackend_Capture) - { - ALCmmdevCapture *backend; - NEW_OBJ(backend, ALCmmdevCapture)(device); - if(!backend) return NULL; - return STATIC_CAST(ALCbackend, backend); - } - - return NULL; -} - - -ALCbackendFactory *ALCmmdevBackendFactory_getFactory(void) -{ - static ALCmmdevBackendFactory factory = ALCMMDEVBACKENDFACTORY_INITIALIZER; - return STATIC_CAST(ALCbackendFactory, &factory); -} diff --git a/Alc/backends/wasapi.c b/Alc/backends/wasapi.c new file mode 100644 index 00000000..b64e260b --- /dev/null +++ b/Alc/backends/wasapi.c @@ -0,0 +1,2049 @@ +/** + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#define COBJMACROS +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef _WAVEFORMATEXTENSIBLE_ +#include +#include +#endif + +#include "alMain.h" +#include "alu.h" +#include "ringbuffer.h" +#include "threads.h" +#include "compat.h" +#include "alstring.h" +#include "converter.h" + +#include "backends/base.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_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14); +DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_FormFactor, 0x1da5d803, 0xd492, 0x4edd, 0x8c,0x23, 0xe0,0xc0,0xff,0xee,0x7f,0x0e, 0); +DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23,0xe0, 0xc0,0xff,0xee,0x7f,0x0e, 4 ); + +#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_SIDE_LEFT|SPEAKER_SIDE_RIGHT) +#define X5DOT1REAR (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_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) +#define X7DOT1_WIDE (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_FRONT_LEFT_OF_CENTER|SPEAKER_FRONT_RIGHT_OF_CENTER) + +#define REFTIME_PER_SEC ((REFERENCE_TIME)10000000) + +#define DEVNAME_HEAD "OpenAL Soft on " + + +/* Scales the given value using 64-bit integer math, ceiling the result. */ +static inline ALuint64 ScaleCeil(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale) +{ + return (val*new_scale + old_scale-1) / old_scale; +} + + +typedef struct { + al_string name; + al_string endpoint_guid; // obtained from PKEY_AudioEndpoint_GUID , set to "Unknown device GUID" if absent. + WCHAR *devid; +} DevMap; +TYPEDEF_VECTOR(DevMap, vector_DevMap) + +static void clear_devlist(vector_DevMap *list) +{ +#define CLEAR_DEVMAP(i) do { \ + AL_STRING_DEINIT((i)->name); \ + AL_STRING_DEINIT((i)->endpoint_guid); \ + free((i)->devid); \ + (i)->devid = NULL; \ +} while(0) + VECTOR_FOR_EACH(DevMap, *list, CLEAR_DEVMAP); + VECTOR_RESIZE(*list, 0, 0); +#undef CLEAR_DEVMAP +} + +static vector_DevMap PlaybackDevices; +static vector_DevMap CaptureDevices; + + +static HANDLE ThreadHdl; +static DWORD ThreadID; + +typedef struct { + HANDLE FinishedEvt; + HRESULT result; +} ThreadRequest; + +#define WM_USER_First (WM_USER+0) +#define WM_USER_OpenDevice (WM_USER+0) +#define WM_USER_ResetDevice (WM_USER+1) +#define WM_USER_StartDevice (WM_USER+2) +#define WM_USER_StopDevice (WM_USER+3) +#define WM_USER_CloseDevice (WM_USER+4) +#define WM_USER_Enumerate (WM_USER+5) +#define WM_USER_Last (WM_USER+5) + +static const char MessageStr[WM_USER_Last+1-WM_USER][20] = { + "Open Device", + "Reset Device", + "Start Device", + "Stop Device", + "Close Device", + "Enumerate Devices", +}; + +static inline void ReturnMsgResponse(ThreadRequest *req, HRESULT res) +{ + req->result = res; + SetEvent(req->FinishedEvt); +} + +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 void get_device_name_and_guid(IMMDevice *device, al_string *name, al_string *guid) +{ + IPropertyStore *ps; + PROPVARIANT pvname; + PROPVARIANT pvguid; + HRESULT hr; + + alstr_copy_cstr(name, DEVNAME_HEAD); + + hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps); + if(FAILED(hr)) + { + WARN("OpenPropertyStore failed: 0x%08lx\n", hr); + alstr_append_cstr(name, "Unknown Device Name"); + if(guid!=NULL)alstr_copy_cstr(guid, "Unknown Device GUID"); + return; + } + + PropVariantInit(&pvname); + + hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pvname); + if(FAILED(hr)) + { + WARN("GetValue Device_FriendlyName failed: 0x%08lx\n", hr); + alstr_append_cstr(name, "Unknown Device Name"); + } + else if(pvname.vt == VT_LPWSTR) + alstr_append_wcstr(name, pvname.pwszVal); + else + { + WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvname.vt); + alstr_append_cstr(name, "Unknown Device Name"); + } + PropVariantClear(&pvname); + + if(guid!=NULL){ + PropVariantInit(&pvguid); + + hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&PKEY_AudioEndpoint_GUID, &pvguid); + if(FAILED(hr)) + { + WARN("GetValue AudioEndpoint_GUID failed: 0x%08lx\n", hr); + alstr_copy_cstr(guid, "Unknown Device GUID"); + } + else if(pvguid.vt == VT_LPWSTR) + alstr_copy_wcstr(guid, pvguid.pwszVal); + else + { + WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvguid.vt); + alstr_copy_cstr(guid, "Unknown Device GUID"); + } + + PropVariantClear(&pvguid); + } + + IPropertyStore_Release(ps); +} + +static void get_device_formfactor(IMMDevice *device, EndpointFormFactor *formfactor) +{ + IPropertyStore *ps; + PROPVARIANT pvform; + HRESULT hr; + + hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps); + if(FAILED(hr)) + { + WARN("OpenPropertyStore failed: 0x%08lx\n", hr); + return; + } + + PropVariantInit(&pvform); + + hr = IPropertyStore_GetValue(ps, &PKEY_AudioEndpoint_FormFactor, &pvform); + if(FAILED(hr)) + WARN("GetValue AudioEndpoint_FormFactor failed: 0x%08lx\n", hr); + else if(pvform.vt == VT_UI4) + *formfactor = pvform.ulVal; + else if(pvform.vt == VT_EMPTY) + *formfactor = UnknownFormFactor; + else + WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvform.vt); + + PropVariantClear(&pvform); + IPropertyStore_Release(ps); +} + + +static void add_device(IMMDevice *device, const WCHAR *devid, vector_DevMap *list) +{ + int count = 0; + al_string tmpname; + DevMap entry; + + AL_STRING_INIT(tmpname); + AL_STRING_INIT(entry.name); + AL_STRING_INIT(entry.endpoint_guid); + + entry.devid = strdupW(devid); + get_device_name_and_guid(device, &tmpname, &entry.endpoint_guid); + + while(1) + { + const DevMap *iter; + + alstr_copy(&entry.name, tmpname); + if(count != 0) + { + char str[64]; + snprintf(str, sizeof(str), " #%d", count+1); + alstr_append_cstr(&entry.name, str); + } + +#define MATCH_ENTRY(i) (alstr_cmp(entry.name, (i)->name) == 0) + VECTOR_FIND_IF(iter, const DevMap, *list, MATCH_ENTRY); + if(iter == VECTOR_END(*list)) break; +#undef MATCH_ENTRY + count++; + } + + TRACE("Got device \"%s\", \"%s\", \"%ls\"\n", alstr_get_cstr(entry.name), alstr_get_cstr(entry.endpoint_guid), entry.devid); + VECTOR_PUSH_BACK(*list, entry); + + AL_STRING_DEINIT(tmpname); +} + +static WCHAR *get_device_id(IMMDevice *device) +{ + WCHAR *devid; + HRESULT hr; + + hr = IMMDevice_GetId(device, &devid); + if(FAILED(hr)) + { + ERR("Failed to get device id: %lx\n", hr); + return NULL; + } + + return devid; +} + +static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, vector_DevMap *list) +{ + IMMDeviceCollection *coll; + IMMDevice *defdev = NULL; + WCHAR *defdevid = NULL; + HRESULT hr; + UINT count; + UINT i; + + hr = IMMDeviceEnumerator_EnumAudioEndpoints(devenum, flowdir, DEVICE_STATE_ACTIVE, &coll); + if(FAILED(hr)) + { + ERR("Failed to enumerate audio endpoints: 0x%08lx\n", hr); + return hr; + } + + count = 0; + hr = IMMDeviceCollection_GetCount(coll, &count); + if(SUCCEEDED(hr) && count > 0) + { + clear_devlist(list); + VECTOR_RESIZE(*list, 0, count); + + hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, flowdir, + eMultimedia, &defdev); + } + if(SUCCEEDED(hr) && defdev != NULL) + { + defdevid = get_device_id(defdev); + if(defdevid) + add_device(defdev, defdevid, list); + } + + for(i = 0;i < count;++i) + { + IMMDevice *device; + WCHAR *devid; + + hr = IMMDeviceCollection_Item(coll, i, &device); + if(FAILED(hr)) continue; + + devid = get_device_id(device); + if(devid) + { + if(wcscmp(devid, defdevid) != 0) + add_device(device, devid, list); + CoTaskMemFree(devid); + } + IMMDevice_Release(device); + } + + if(defdev) IMMDevice_Release(defdev); + if(defdevid) CoTaskMemFree(defdevid); + IMMDeviceCollection_Release(coll); + + return S_OK; +} + + +/* Proxy interface used by the message handler. */ +struct ALCwasapiProxyVtable; + +typedef struct ALCwasapiProxy { + const struct ALCwasapiProxyVtable *vtbl; +} ALCwasapiProxy; + +struct ALCwasapiProxyVtable { + HRESULT (*const openProxy)(ALCwasapiProxy*); + void (*const closeProxy)(ALCwasapiProxy*); + + HRESULT (*const resetProxy)(ALCwasapiProxy*); + HRESULT (*const startProxy)(ALCwasapiProxy*); + void (*const stopProxy)(ALCwasapiProxy*); +}; + +#define DEFINE_ALCWASAPIPROXY_VTABLE(T) \ +DECLARE_THUNK(T, ALCwasapiProxy, HRESULT, openProxy) \ +DECLARE_THUNK(T, ALCwasapiProxy, void, closeProxy) \ +DECLARE_THUNK(T, ALCwasapiProxy, HRESULT, resetProxy) \ +DECLARE_THUNK(T, ALCwasapiProxy, HRESULT, startProxy) \ +DECLARE_THUNK(T, ALCwasapiProxy, void, stopProxy) \ + \ +static const struct ALCwasapiProxyVtable T##_ALCwasapiProxy_vtable = { \ + T##_ALCwasapiProxy_openProxy, \ + T##_ALCwasapiProxy_closeProxy, \ + T##_ALCwasapiProxy_resetProxy, \ + T##_ALCwasapiProxy_startProxy, \ + T##_ALCwasapiProxy_stopProxy, \ +} + +static void ALCwasapiProxy_Construct(ALCwasapiProxy* UNUSED(self)) { } +static void ALCwasapiProxy_Destruct(ALCwasapiProxy* UNUSED(self)) { } + +static DWORD CALLBACK ALCwasapiProxy_messageHandler(void *ptr) +{ + ThreadRequest *req = ptr; + IMMDeviceEnumerator *Enumerator; + ALuint deviceCount = 0; + ALCwasapiProxy *proxy; + HRESULT hr, cohr; + MSG msg; + + TRACE("Starting message thread\n"); + + cohr = CoInitialize(NULL); + if(FAILED(cohr)) + { + WARN("Failed to initialize COM: 0x%08lx\n", cohr); + ReturnMsgResponse(req, cohr); + 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(); + ReturnMsgResponse(req, hr); + return 0; + } + Enumerator = ptr; + IMMDeviceEnumerator_Release(Enumerator); + Enumerator = NULL; + + CoUninitialize(); + + /* HACK: Force Windows to create a message queue for this thread before + * returning success, otherwise PostThreadMessage may fail if it gets + * called before GetMessage. + */ + PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); + + TRACE("Message thread initialization complete\n"); + ReturnMsgResponse(req, S_OK); + + TRACE("Starting message loop\n"); + while(GetMessage(&msg, NULL, WM_USER_First, WM_USER_Last)) + { + TRACE("Got message \"%s\" (0x%04x, lparam=%p, wparam=%p)\n", + (msg.message >= WM_USER && msg.message <= WM_USER_Last) ? + MessageStr[msg.message-WM_USER] : "Unknown", + msg.message, (void*)msg.lParam, (void*)msg.wParam + ); + switch(msg.message) + { + case WM_USER_OpenDevice: + req = (ThreadRequest*)msg.wParam; + proxy = (ALCwasapiProxy*)msg.lParam; + + hr = cohr = S_OK; + if(++deviceCount == 1) + hr = cohr = CoInitialize(NULL); + if(SUCCEEDED(hr)) + hr = V0(proxy,openProxy)(); + if(FAILED(hr)) + { + if(--deviceCount == 0 && SUCCEEDED(cohr)) + CoUninitialize(); + } + + ReturnMsgResponse(req, hr); + continue; + + case WM_USER_ResetDevice: + req = (ThreadRequest*)msg.wParam; + proxy = (ALCwasapiProxy*)msg.lParam; + + hr = V0(proxy,resetProxy)(); + ReturnMsgResponse(req, hr); + continue; + + case WM_USER_StartDevice: + req = (ThreadRequest*)msg.wParam; + proxy = (ALCwasapiProxy*)msg.lParam; + + hr = V0(proxy,startProxy)(); + ReturnMsgResponse(req, hr); + continue; + + case WM_USER_StopDevice: + req = (ThreadRequest*)msg.wParam; + proxy = (ALCwasapiProxy*)msg.lParam; + + V0(proxy,stopProxy)(); + ReturnMsgResponse(req, S_OK); + continue; + + case WM_USER_CloseDevice: + req = (ThreadRequest*)msg.wParam; + proxy = (ALCwasapiProxy*)msg.lParam; + + V0(proxy,closeProxy)(); + if(--deviceCount == 0) + CoUninitialize(); + + ReturnMsgResponse(req, S_OK); + continue; + + case WM_USER_Enumerate: + req = (ThreadRequest*)msg.wParam; + + hr = cohr = S_OK; + if(++deviceCount == 1) + hr = cohr = CoInitialize(NULL); + if(SUCCEEDED(hr)) + hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); + if(SUCCEEDED(hr)) + { + Enumerator = ptr; + + if(msg.lParam == ALL_DEVICE_PROBE) + hr = probe_devices(Enumerator, eRender, &PlaybackDevices); + else if(msg.lParam == CAPTURE_DEVICE_PROBE) + hr = probe_devices(Enumerator, eCapture, &CaptureDevices); + + IMMDeviceEnumerator_Release(Enumerator); + Enumerator = NULL; + } + + if(--deviceCount == 0 && SUCCEEDED(cohr)) + CoUninitialize(); + + ReturnMsgResponse(req, hr); + continue; + + default: + ERR("Unexpected message: %u\n", msg.message); + continue; + } + } + TRACE("Message loop finished\n"); + + return 0; +} + + +typedef struct ALCwasapiPlayback { + DERIVE_FROM_TYPE(ALCbackend); + DERIVE_FROM_TYPE(ALCwasapiProxy); + + WCHAR *devid; + + IMMDevice *mmdev; + IAudioClient *client; + IAudioRenderClient *render; + HANDLE NotifyEvent; + + HANDLE MsgEvent; + + ATOMIC(UINT32) Padding; + + ATOMIC(int) killNow; + althrd_t thread; +} ALCwasapiPlayback; + +static int ALCwasapiPlayback_mixerProc(void *arg); + +static void ALCwasapiPlayback_Construct(ALCwasapiPlayback *self, ALCdevice *device); +static void ALCwasapiPlayback_Destruct(ALCwasapiPlayback *self); +static ALCenum ALCwasapiPlayback_open(ALCwasapiPlayback *self, const ALCchar *name); +static HRESULT ALCwasapiPlayback_openProxy(ALCwasapiPlayback *self); +static void ALCwasapiPlayback_closeProxy(ALCwasapiPlayback *self); +static ALCboolean ALCwasapiPlayback_reset(ALCwasapiPlayback *self); +static HRESULT ALCwasapiPlayback_resetProxy(ALCwasapiPlayback *self); +static ALCboolean ALCwasapiPlayback_start(ALCwasapiPlayback *self); +static HRESULT ALCwasapiPlayback_startProxy(ALCwasapiPlayback *self); +static void ALCwasapiPlayback_stop(ALCwasapiPlayback *self); +static void ALCwasapiPlayback_stopProxy(ALCwasapiPlayback *self); +static DECLARE_FORWARD2(ALCwasapiPlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint) +static DECLARE_FORWARD(ALCwasapiPlayback, ALCbackend, ALCuint, availableSamples) +static ClockLatency ALCwasapiPlayback_getClockLatency(ALCwasapiPlayback *self); +static DECLARE_FORWARD(ALCwasapiPlayback, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCwasapiPlayback, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCwasapiPlayback) + +DEFINE_ALCWASAPIPROXY_VTABLE(ALCwasapiPlayback); +DEFINE_ALCBACKEND_VTABLE(ALCwasapiPlayback); + + +static void ALCwasapiPlayback_Construct(ALCwasapiPlayback *self, ALCdevice *device) +{ + SET_VTABLE2(ALCwasapiPlayback, ALCbackend, self); + SET_VTABLE2(ALCwasapiPlayback, ALCwasapiProxy, self); + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + ALCwasapiProxy_Construct(STATIC_CAST(ALCwasapiProxy, self)); + + self->devid = NULL; + + self->mmdev = NULL; + self->client = NULL; + self->render = NULL; + self->NotifyEvent = NULL; + + self->MsgEvent = NULL; + + ATOMIC_INIT(&self->Padding, 0); + + ATOMIC_INIT(&self->killNow, 0); +} + +static void ALCwasapiPlayback_Destruct(ALCwasapiPlayback *self) +{ + if(self->MsgEvent) + { + ThreadRequest req = { self->MsgEvent, 0 }; + if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self))) + (void)WaitForResponse(&req); + + CloseHandle(self->MsgEvent); + self->MsgEvent = NULL; + } + + if(self->NotifyEvent) + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; + + free(self->devid); + self->devid = NULL; + + if(self->NotifyEvent != NULL) + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; + if(self->MsgEvent != NULL) + CloseHandle(self->MsgEvent); + self->MsgEvent = NULL; + + free(self->devid); + self->devid = NULL; + + ALCwasapiProxy_Destruct(STATIC_CAST(ALCwasapiProxy, self)); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + + +FORCE_ALIGN static int ALCwasapiPlayback_mixerProc(void *arg) +{ + ALCwasapiPlayback *self = arg; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + UINT32 buffer_len, written; + ALuint update_size, len; + BYTE *buffer; + HRESULT hr; + + hr = CoInitialize(NULL); + if(FAILED(hr)) + { + ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr); + V0(device->Backend,lock)(); + aluHandleDisconnect(device, "COM init failed: 0x%08lx", hr); + V0(device->Backend,unlock)(); + return 1; + } + + SetRTPriority(); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); + + update_size = device->UpdateSize; + buffer_len = update_size * device->NumUpdates; + while(!ATOMIC_LOAD(&self->killNow, almemory_order_relaxed)) + { + hr = IAudioClient_GetCurrentPadding(self->client, &written); + if(FAILED(hr)) + { + ERR("Failed to get padding: 0x%08lx\n", hr); + V0(device->Backend,lock)(); + aluHandleDisconnect(device, "Failed to retrieve buffer padding: 0x%08lx", hr); + V0(device->Backend,unlock)(); + break; + } + ATOMIC_STORE(&self->Padding, written, almemory_order_relaxed); + + len = buffer_len - written; + if(len < update_size) + { + DWORD res; + res = WaitForSingleObjectEx(self->NotifyEvent, 2000, FALSE); + if(res != WAIT_OBJECT_0) + ERR("WaitForSingleObjectEx error: 0x%lx\n", res); + continue; + } + len -= len%update_size; + + hr = IAudioRenderClient_GetBuffer(self->render, len, &buffer); + if(SUCCEEDED(hr)) + { + ALCwasapiPlayback_lock(self); + aluMixData(device, buffer, len); + ATOMIC_STORE(&self->Padding, written + len, almemory_order_relaxed); + ALCwasapiPlayback_unlock(self); + hr = IAudioRenderClient_ReleaseBuffer(self->render, len, 0); + } + if(FAILED(hr)) + { + ERR("Failed to buffer data: 0x%08lx\n", hr); + V0(device->Backend,lock)(); + aluHandleDisconnect(device, "Failed to send playback samples: 0x%08lx", hr); + V0(device->Backend,unlock)(); + break; + } + } + ATOMIC_STORE(&self->Padding, 0, almemory_order_release); + + CoUninitialize(); + return 0; +} + + +static ALCboolean MakeExtensible(WAVEFORMATEXTENSIBLE *out, const WAVEFORMATEX *in) +{ + memset(out, 0, sizeof(*out)); + if(in->wFormatTag == WAVE_FORMAT_EXTENSIBLE) + *out = *(const 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 ALCenum ALCwasapiPlayback_open(ALCwasapiPlayback *self, const ALCchar *deviceName) +{ + HRESULT hr = S_OK; + + self->NotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + self->MsgEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + if(self->NotifyEvent == NULL || self->MsgEvent == NULL) + { + ERR("Failed to create message events: %lu\n", GetLastError()); + hr = E_FAIL; + } + + if(SUCCEEDED(hr)) + { + if(deviceName) + { + const DevMap *iter; + + if(VECTOR_SIZE(PlaybackDevices) == 0) + { + ThreadRequest req = { self->MsgEvent, 0 }; + if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, ALL_DEVICE_PROBE)) + (void)WaitForResponse(&req); + } + + hr = E_FAIL; +#define MATCH_NAME(i) (alstr_cmp_cstr((i)->name, deviceName) == 0 || \ + alstr_cmp_cstr((i)->endpoint_guid, deviceName) == 0) + VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); +#undef MATCH_NAME + if(iter == VECTOR_END(PlaybackDevices)) + { + int len; + if((len=MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, NULL, 0)) > 0) + { + WCHAR *wname = calloc(sizeof(WCHAR), len); + MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, wname, len); +#define MATCH_NAME(i) (wcscmp((i)->devid, wname) == 0) + VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); +#undef MATCH_NAME + free(wname); + } + } + if(iter == VECTOR_END(PlaybackDevices)) + WARN("Failed to find device name matching \"%s\"\n", deviceName); + else + { + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + self->devid = strdupW(iter->devid); + alstr_copy(&device->DeviceName, iter->name); + hr = S_OK; + } + } + } + + if(SUCCEEDED(hr)) + { + ThreadRequest req = { self->MsgEvent, 0 }; + + hr = E_FAIL; + if(PostThreadMessage(ThreadID, WM_USER_OpenDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self))) + hr = WaitForResponse(&req); + else + ERR("Failed to post thread message: %lu\n", GetLastError()); + } + + if(FAILED(hr)) + { + if(self->NotifyEvent != NULL) + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; + if(self->MsgEvent != NULL) + CloseHandle(self->MsgEvent); + self->MsgEvent = NULL; + + free(self->devid); + self->devid = NULL; + + ERR("Device init failed: 0x%08lx\n", hr); + return ALC_INVALID_VALUE; + } + + return ALC_NO_ERROR; +} + +static HRESULT ALCwasapiPlayback_openProxy(ALCwasapiPlayback *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + void *ptr; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); + if(SUCCEEDED(hr)) + { + IMMDeviceEnumerator *Enumerator = ptr; + if(!self->devid) + hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(Enumerator, eRender, eMultimedia, &self->mmdev); + else + hr = IMMDeviceEnumerator_GetDevice(Enumerator, self->devid, &self->mmdev); + IMMDeviceEnumerator_Release(Enumerator); + Enumerator = NULL; + } + if(SUCCEEDED(hr)) + hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); + if(SUCCEEDED(hr)) + { + self->client = ptr; + if(alstr_empty(device->DeviceName)) + get_device_name_and_guid(self->mmdev, &device->DeviceName, NULL); + } + + if(FAILED(hr)) + { + if(self->mmdev) + IMMDevice_Release(self->mmdev); + self->mmdev = NULL; + } + + return hr; +} + + +static void ALCwasapiPlayback_closeProxy(ALCwasapiPlayback *self) +{ + if(self->client) + IAudioClient_Release(self->client); + self->client = NULL; + + if(self->mmdev) + IMMDevice_Release(self->mmdev); + self->mmdev = NULL; +} + + +static ALCboolean ALCwasapiPlayback_reset(ALCwasapiPlayback *self) +{ + ThreadRequest req = { self->MsgEvent, 0 }; + HRESULT hr = E_FAIL; + + if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self))) + hr = WaitForResponse(&req); + + return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE; +} + +static HRESULT ALCwasapiPlayback_resetProxy(ALCwasapiPlayback *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + EndpointFormFactor formfactor = UnknownFormFactor; + WAVEFORMATEXTENSIBLE OutputType; + WAVEFORMATEX *wfx = NULL; + REFERENCE_TIME min_per, buf_time; + UINT32 buffer_len, min_len; + void *ptr = NULL; + HRESULT hr; + + if(self->client) + IAudioClient_Release(self->client); + self->client = NULL; + + hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); + if(FAILED(hr)) + { + ERR("Failed to reactivate audio client: 0x%08lx\n", hr); + return hr; + } + self->client = ptr; + + hr = IAudioClient_GetMixFormat(self->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; + + buf_time = ScaleCeil(device->UpdateSize*device->NumUpdates, REFTIME_PER_SEC, + device->Frequency); + + 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 == X5DOT1REAR) + device->FmtChans = DevFmtX51Rear; + else if(OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1) + device->FmtChans = DevFmtX61; + else if(OutputType.Format.nChannels == 8 && (OutputType.dwChannelMask == X7DOT1 || OutputType.dwChannelMask == X7DOT1_WIDE)) + 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 DevFmtAmbi3D: + device->FmtChans = DevFmtStereo; + /*fall-through*/ + 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 DevFmtX51Rear: + OutputType.Format.nChannels = 6; + OutputType.dwChannelMask = X5DOT1REAR; + 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 DevFmtUInt: + device->FmtType = DevFmtInt; + /* fall-through */ + case DevFmtInt: + OutputType.Format.wBitsPerSample = 32; + OutputType.Samples.wValidBitsPerSample = 32; + 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(self->client, AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx); + if(FAILED(hr)) + { + ERR("Failed to check format support: 0x%08lx\n", hr); + hr = IAudioClient_GetMixFormat(self->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; + + device->Frequency = OutputType.Format.nSamplesPerSec; + 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 == X5DOT1REAR) + device->FmtChans = DevFmtX51Rear; + else if(OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1) + device->FmtChans = DevFmtX61; + else if(OutputType.Format.nChannels == 8 && (OutputType.dwChannelMask == X7DOT1 || OutputType.dwChannelMask == X7DOT1_WIDE)) + 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.Format.wBitsPerSample == 8) + device->FmtType = DevFmtUByte; + else if(OutputType.Format.wBitsPerSample == 16) + device->FmtType = DevFmtShort; + else if(OutputType.Format.wBitsPerSample == 32) + device->FmtType = DevFmtInt; + else + { + device->FmtType = DevFmtShort; + OutputType.Format.wBitsPerSample = 16; + } + } + else if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) + { + device->FmtType = DevFmtFloat; + OutputType.Format.wBitsPerSample = 32; + } + else + { + ERR("Unhandled format sub-type\n"); + device->FmtType = DevFmtShort; + OutputType.Format.wBitsPerSample = 16; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + } + OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; + } + get_device_formfactor(self->mmdev, &formfactor); + device->IsHeadphones = (device->FmtChans == DevFmtStereo && + (formfactor == Headphones || formfactor == Headset) + ); + + SetDefaultWFXChannelOrder(device); + + hr = IAudioClient_Initialize(self->client, AUDCLNT_SHAREMODE_SHARED, + AUDCLNT_STREAMFLAGS_EVENTCALLBACK, + buf_time, 0, &OutputType.Format, NULL); + if(FAILED(hr)) + { + ERR("Failed to initialize audio client: 0x%08lx\n", hr); + return hr; + } + + hr = IAudioClient_GetDevicePeriod(self->client, &min_per, NULL); + if(SUCCEEDED(hr)) + { + min_len = (UINT32)ScaleCeil(min_per, device->Frequency, REFTIME_PER_SEC); + /* Find the nearest multiple of the period size to the update size */ + if(min_len < device->UpdateSize) + min_len *= (device->UpdateSize + min_len/2)/min_len; + hr = IAudioClient_GetBufferSize(self->client, &buffer_len); + } + if(FAILED(hr)) + { + ERR("Failed to get audio buffer info: 0x%08lx\n", hr); + return hr; + } + + device->UpdateSize = min_len; + device->NumUpdates = buffer_len / device->UpdateSize; + if(device->NumUpdates <= 1) + { + ERR("Audio client returned buffer_len < period*2; expect break up\n"); + device->NumUpdates = 2; + device->UpdateSize = buffer_len / device->NumUpdates; + } + + hr = IAudioClient_SetEventHandle(self->client, self->NotifyEvent); + if(FAILED(hr)) + { + ERR("Failed to set event handle: 0x%08lx\n", hr); + return hr; + } + + return hr; +} + + +static ALCboolean ALCwasapiPlayback_start(ALCwasapiPlayback *self) +{ + ThreadRequest req = { self->MsgEvent, 0 }; + HRESULT hr = E_FAIL; + + if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self))) + hr = WaitForResponse(&req); + + return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE; +} + +static HRESULT ALCwasapiPlayback_startProxy(ALCwasapiPlayback *self) +{ + HRESULT hr; + void *ptr; + + ResetEvent(self->NotifyEvent); + hr = IAudioClient_Start(self->client); + if(FAILED(hr)) + ERR("Failed to start audio client: 0x%08lx\n", hr); + + if(SUCCEEDED(hr)) + hr = IAudioClient_GetService(self->client, &IID_IAudioRenderClient, &ptr); + if(SUCCEEDED(hr)) + { + self->render = ptr; + ATOMIC_STORE(&self->killNow, 0, almemory_order_release); + if(althrd_create(&self->thread, ALCwasapiPlayback_mixerProc, self) != althrd_success) + { + if(self->render) + IAudioRenderClient_Release(self->render); + self->render = NULL; + IAudioClient_Stop(self->client); + ERR("Failed to start thread\n"); + hr = E_FAIL; + } + } + + return hr; +} + + +static void ALCwasapiPlayback_stop(ALCwasapiPlayback *self) +{ + ThreadRequest req = { self->MsgEvent, 0 }; + if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self))) + (void)WaitForResponse(&req); +} + +static void ALCwasapiPlayback_stopProxy(ALCwasapiPlayback *self) +{ + int res; + + if(!self->render) + return; + + ATOMIC_STORE_SEQ(&self->killNow, 1); + althrd_join(self->thread, &res); + + IAudioRenderClient_Release(self->render); + self->render = NULL; + IAudioClient_Stop(self->client); +} + + +static ClockLatency ALCwasapiPlayback_getClockLatency(ALCwasapiPlayback *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + ClockLatency ret; + + ALCwasapiPlayback_lock(self); + ret.ClockTime = GetDeviceClockTime(device); + ret.Latency = ATOMIC_LOAD(&self->Padding, almemory_order_relaxed) * DEVICE_CLOCK_RES / + device->Frequency; + ALCwasapiPlayback_unlock(self); + + return ret; +} + + +typedef struct ALCwasapiCapture { + DERIVE_FROM_TYPE(ALCbackend); + DERIVE_FROM_TYPE(ALCwasapiProxy); + + WCHAR *devid; + + IMMDevice *mmdev; + IAudioClient *client; + IAudioCaptureClient *capture; + HANDLE NotifyEvent; + + HANDLE MsgEvent; + + ChannelConverter *ChannelConv; + SampleConverter *SampleConv; + ll_ringbuffer_t *Ring; + + ATOMIC(int) killNow; + althrd_t thread; +} ALCwasapiCapture; + +static int ALCwasapiCapture_recordProc(void *arg); + +static void ALCwasapiCapture_Construct(ALCwasapiCapture *self, ALCdevice *device); +static void ALCwasapiCapture_Destruct(ALCwasapiCapture *self); +static ALCenum ALCwasapiCapture_open(ALCwasapiCapture *self, const ALCchar *name); +static HRESULT ALCwasapiCapture_openProxy(ALCwasapiCapture *self); +static void ALCwasapiCapture_closeProxy(ALCwasapiCapture *self); +static DECLARE_FORWARD(ALCwasapiCapture, ALCbackend, ALCboolean, reset) +static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self); +static ALCboolean ALCwasapiCapture_start(ALCwasapiCapture *self); +static HRESULT ALCwasapiCapture_startProxy(ALCwasapiCapture *self); +static void ALCwasapiCapture_stop(ALCwasapiCapture *self); +static void ALCwasapiCapture_stopProxy(ALCwasapiCapture *self); +static ALCenum ALCwasapiCapture_captureSamples(ALCwasapiCapture *self, ALCvoid *buffer, ALCuint samples); +static ALuint ALCwasapiCapture_availableSamples(ALCwasapiCapture *self); +static DECLARE_FORWARD(ALCwasapiCapture, ALCbackend, ClockLatency, getClockLatency) +static DECLARE_FORWARD(ALCwasapiCapture, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCwasapiCapture, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCwasapiCapture) + +DEFINE_ALCWASAPIPROXY_VTABLE(ALCwasapiCapture); +DEFINE_ALCBACKEND_VTABLE(ALCwasapiCapture); + + +static void ALCwasapiCapture_Construct(ALCwasapiCapture *self, ALCdevice *device) +{ + SET_VTABLE2(ALCwasapiCapture, ALCbackend, self); + SET_VTABLE2(ALCwasapiCapture, ALCwasapiProxy, self); + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + ALCwasapiProxy_Construct(STATIC_CAST(ALCwasapiProxy, self)); + + self->devid = NULL; + + self->mmdev = NULL; + self->client = NULL; + self->capture = NULL; + self->NotifyEvent = NULL; + + self->MsgEvent = NULL; + + self->ChannelConv = NULL; + self->SampleConv = NULL; + self->Ring = NULL; + + ATOMIC_INIT(&self->killNow, 0); +} + +static void ALCwasapiCapture_Destruct(ALCwasapiCapture *self) +{ + if(self->MsgEvent) + { + ThreadRequest req = { self->MsgEvent, 0 }; + if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self))) + (void)WaitForResponse(&req); + + CloseHandle(self->MsgEvent); + self->MsgEvent = NULL; + } + + if(self->NotifyEvent != NULL) + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; + + ll_ringbuffer_free(self->Ring); + self->Ring = NULL; + + DestroySampleConverter(&self->SampleConv); + DestroyChannelConverter(&self->ChannelConv); + + free(self->devid); + self->devid = NULL; + + ALCwasapiProxy_Destruct(STATIC_CAST(ALCwasapiProxy, self)); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + + +FORCE_ALIGN int ALCwasapiCapture_recordProc(void *arg) +{ + ALCwasapiCapture *self = arg; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + ALfloat *samples = NULL; + size_t samplesmax = 0; + HRESULT hr; + + hr = CoInitialize(NULL); + if(FAILED(hr)) + { + ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr); + V0(device->Backend,lock)(); + aluHandleDisconnect(device, "COM init failed: 0x%08lx", hr); + V0(device->Backend,unlock)(); + return 1; + } + + althrd_setname(althrd_current(), RECORD_THREAD_NAME); + + while(!ATOMIC_LOAD(&self->killNow, almemory_order_relaxed)) + { + UINT32 avail; + DWORD res; + + hr = IAudioCaptureClient_GetNextPacketSize(self->capture, &avail); + if(FAILED(hr)) + ERR("Failed to get next packet size: 0x%08lx\n", hr); + else if(avail > 0) + { + UINT32 numsamples; + DWORD flags; + BYTE *rdata; + + hr = IAudioCaptureClient_GetBuffer(self->capture, + &rdata, &numsamples, &flags, NULL, NULL + ); + if(FAILED(hr)) + ERR("Failed to get capture buffer: 0x%08lx\n", hr); + else + { + ll_ringbuffer_data_t data[2]; + size_t dstframes = 0; + + if(self->ChannelConv) + { + if(samplesmax < numsamples) + { + size_t newmax = RoundUp(numsamples, 4096); + ALfloat *tmp = al_calloc(DEF_ALIGN, newmax*2*sizeof(ALfloat)); + al_free(samples); + samples = tmp; + samplesmax = newmax; + } + ChannelConverterInput(self->ChannelConv, rdata, samples, numsamples); + rdata = (BYTE*)samples; + } + + ll_ringbuffer_get_write_vector(self->Ring, data); + + if(self->SampleConv) + { + const ALvoid *srcdata = rdata; + ALsizei srcframes = numsamples; + + dstframes = SampleConverterInput(self->SampleConv, + &srcdata, &srcframes, data[0].buf, (ALsizei)minz(data[0].len, INT_MAX) + ); + if(srcframes > 0 && dstframes == data[0].len && data[1].len > 0) + { + /* If some source samples remain, all of the first dest + * block was filled, and there's space in the second + * dest block, do another run for the second block. + */ + dstframes += SampleConverterInput(self->SampleConv, + &srcdata, &srcframes, data[1].buf, (ALsizei)minz(data[1].len, INT_MAX) + ); + } + } + else + { + ALuint framesize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, + device->AmbiOrder); + size_t len1 = minz(data[0].len, numsamples); + size_t len2 = minz(data[1].len, numsamples-len1); + + memcpy(data[0].buf, rdata, len1*framesize); + if(len2 > 0) + memcpy(data[1].buf, rdata+len1*framesize, len2*framesize); + dstframes = len1 + len2; + } + + ll_ringbuffer_write_advance(self->Ring, dstframes); + + hr = IAudioCaptureClient_ReleaseBuffer(self->capture, numsamples); + if(FAILED(hr)) ERR("Failed to release capture buffer: 0x%08lx\n", hr); + } + } + + if(FAILED(hr)) + { + V0(device->Backend,lock)(); + aluHandleDisconnect(device, "Failed to capture samples: 0x%08lx", hr); + V0(device->Backend,unlock)(); + break; + } + + res = WaitForSingleObjectEx(self->NotifyEvent, 2000, FALSE); + if(res != WAIT_OBJECT_0) + ERR("WaitForSingleObjectEx error: 0x%lx\n", res); + } + + al_free(samples); + samples = NULL; + samplesmax = 0; + + CoUninitialize(); + return 0; +} + + +static ALCenum ALCwasapiCapture_open(ALCwasapiCapture *self, const ALCchar *deviceName) +{ + HRESULT hr = S_OK; + + self->NotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + self->MsgEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + if(self->NotifyEvent == NULL || self->MsgEvent == NULL) + { + ERR("Failed to create message events: %lu\n", GetLastError()); + hr = E_FAIL; + } + + if(SUCCEEDED(hr)) + { + if(deviceName) + { + const DevMap *iter; + + if(VECTOR_SIZE(CaptureDevices) == 0) + { + ThreadRequest req = { self->MsgEvent, 0 }; + if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, CAPTURE_DEVICE_PROBE)) + (void)WaitForResponse(&req); + } + + hr = E_FAIL; +#define MATCH_NAME(i) (alstr_cmp_cstr((i)->name, deviceName) == 0 || \ + alstr_cmp_cstr((i)->endpoint_guid, deviceName) == 0) + VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); +#undef MATCH_NAME + if(iter == VECTOR_END(CaptureDevices)) + { + int len; + if((len=MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, NULL, 0)) > 0) + { + WCHAR *wname = calloc(sizeof(WCHAR), len); + MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, wname, len); +#define MATCH_NAME(i) (wcscmp((i)->devid, wname) == 0) + VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); +#undef MATCH_NAME + free(wname); + } + } + if(iter == VECTOR_END(CaptureDevices)) + WARN("Failed to find device name matching \"%s\"\n", deviceName); + else + { + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + self->devid = strdupW(iter->devid); + alstr_copy(&device->DeviceName, iter->name); + hr = S_OK; + } + } + } + + if(SUCCEEDED(hr)) + { + ThreadRequest req = { self->MsgEvent, 0 }; + + hr = E_FAIL; + if(PostThreadMessage(ThreadID, WM_USER_OpenDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self))) + hr = WaitForResponse(&req); + else + ERR("Failed to post thread message: %lu\n", GetLastError()); + } + + if(FAILED(hr)) + { + if(self->NotifyEvent != NULL) + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; + if(self->MsgEvent != NULL) + CloseHandle(self->MsgEvent); + self->MsgEvent = NULL; + + free(self->devid); + self->devid = NULL; + + ERR("Device init failed: 0x%08lx\n", hr); + return ALC_INVALID_VALUE; + } + else + { + ThreadRequest req = { self->MsgEvent, 0 }; + + hr = E_FAIL; + if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self))) + hr = WaitForResponse(&req); + else + ERR("Failed to post thread message: %lu\n", GetLastError()); + + if(FAILED(hr)) + { + if(hr == E_OUTOFMEMORY) + return ALC_OUT_OF_MEMORY; + return ALC_INVALID_VALUE; + } + } + + return ALC_NO_ERROR; +} + +static HRESULT ALCwasapiCapture_openProxy(ALCwasapiCapture *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + void *ptr; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); + if(SUCCEEDED(hr)) + { + IMMDeviceEnumerator *Enumerator = ptr; + if(!self->devid) + hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(Enumerator, eCapture, eMultimedia, &self->mmdev); + else + hr = IMMDeviceEnumerator_GetDevice(Enumerator, self->devid, &self->mmdev); + IMMDeviceEnumerator_Release(Enumerator); + Enumerator = NULL; + } + if(SUCCEEDED(hr)) + hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); + if(SUCCEEDED(hr)) + { + self->client = ptr; + if(alstr_empty(device->DeviceName)) + get_device_name_and_guid(self->mmdev, &device->DeviceName, NULL); + } + + if(FAILED(hr)) + { + if(self->mmdev) + IMMDevice_Release(self->mmdev); + self->mmdev = NULL; + } + + return hr; +} + + +static void ALCwasapiCapture_closeProxy(ALCwasapiCapture *self) +{ + if(self->client) + IAudioClient_Release(self->client); + self->client = NULL; + + if(self->mmdev) + IMMDevice_Release(self->mmdev); + self->mmdev = NULL; +} + + +static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + WAVEFORMATEXTENSIBLE OutputType; + WAVEFORMATEX *wfx = NULL; + enum DevFmtType srcType; + REFERENCE_TIME buf_time; + UINT32 buffer_len; + void *ptr = NULL; + HRESULT hr; + + if(self->client) + IAudioClient_Release(self->client); + self->client = NULL; + + hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); + if(FAILED(hr)) + { + ERR("Failed to reactivate audio client: 0x%08lx\n", hr); + return hr; + } + self->client = ptr; + + buf_time = ScaleCeil(device->UpdateSize*device->NumUpdates, REFTIME_PER_SEC, + device->Frequency); + // Make sure buffer is at least 100ms in size + buf_time = maxu64(buf_time, REFTIME_PER_SEC/10); + device->UpdateSize = (ALuint)ScaleCeil(buf_time, device->Frequency, REFTIME_PER_SEC) / + device->NumUpdates; + + OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + 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 DevFmtX51Rear: + OutputType.Format.nChannels = 6; + OutputType.dwChannelMask = X5DOT1REAR; + break; + case DevFmtX61: + OutputType.Format.nChannels = 7; + OutputType.dwChannelMask = X6DOT1; + break; + case DevFmtX71: + OutputType.Format.nChannels = 8; + OutputType.dwChannelMask = X7DOT1; + break; + + case DevFmtAmbi3D: + return E_FAIL; + } + switch(device->FmtType) + { + /* NOTE: Signedness doesn't matter, the converter will handle it. */ + case DevFmtByte: + case DevFmtUByte: + OutputType.Format.wBitsPerSample = 8; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + break; + case DevFmtShort: + case DevFmtUShort: + OutputType.Format.wBitsPerSample = 16; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + break; + case DevFmtInt: + case DevFmtUInt: + OutputType.Format.wBitsPerSample = 32; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + break; + case DevFmtFloat: + OutputType.Format.wBitsPerSample = 32; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; + break; + } + OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; + OutputType.Format.nSamplesPerSec = device->Frequency; + + OutputType.Format.nBlockAlign = OutputType.Format.nChannels * + OutputType.Format.wBitsPerSample / 8; + OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec * + OutputType.Format.nBlockAlign; + OutputType.Format.cbSize = sizeof(OutputType) - sizeof(OutputType.Format); + + hr = IAudioClient_IsFormatSupported(self->client, + AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx + ); + if(FAILED(hr)) + { + ERR("Failed to check format support: 0x%08lx\n", hr); + return hr; + } + + DestroySampleConverter(&self->SampleConv); + DestroyChannelConverter(&self->ChannelConv); + + if(wfx != NULL) + { + if(!(wfx->nChannels == OutputType.Format.nChannels || + (wfx->nChannels == 1 && OutputType.Format.nChannels == 2) || + (wfx->nChannels == 2 && OutputType.Format.nChannels == 1))) + { + ERR("Failed to get matching format, wanted: %s %s %uhz, got: %d channel%s %d-bit %luhz\n", + DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), + device->Frequency, wfx->nChannels, (wfx->nChannels==1)?"":"s", wfx->wBitsPerSample, + wfx->nSamplesPerSec); + CoTaskMemFree(wfx); + return E_FAIL; + } + + if(!MakeExtensible(&OutputType, wfx)) + { + CoTaskMemFree(wfx); + return E_FAIL; + } + CoTaskMemFree(wfx); + wfx = NULL; + } + + if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) + { + if(OutputType.Format.wBitsPerSample == 8) + srcType = DevFmtUByte; + else if(OutputType.Format.wBitsPerSample == 16) + srcType = DevFmtShort; + else if(OutputType.Format.wBitsPerSample == 32) + srcType = DevFmtInt; + else + { + ERR("Unhandled integer bit depth: %d\n", OutputType.Format.wBitsPerSample); + return E_FAIL; + } + } + else if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) + { + if(OutputType.Format.wBitsPerSample == 32) + srcType = DevFmtFloat; + else + { + ERR("Unhandled float bit depth: %d\n", OutputType.Format.wBitsPerSample); + return E_FAIL; + } + } + else + { + ERR("Unhandled format sub-type\n"); + return E_FAIL; + } + + if(device->FmtChans == DevFmtMono && OutputType.Format.nChannels == 2) + { + self->ChannelConv = CreateChannelConverter(srcType, DevFmtStereo, + device->FmtChans); + if(!self->ChannelConv) + { + ERR("Failed to create %s stereo-to-mono converter\n", DevFmtTypeString(srcType)); + return E_FAIL; + } + TRACE("Created %s stereo-to-mono converter\n", DevFmtTypeString(srcType)); + /* The channel converter always outputs float, so change the input type + * for the resampler/type-converter. + */ + srcType = DevFmtFloat; + } + else if(device->FmtChans == DevFmtStereo && OutputType.Format.nChannels == 1) + { + self->ChannelConv = CreateChannelConverter(srcType, DevFmtMono, + device->FmtChans); + if(!self->ChannelConv) + { + ERR("Failed to create %s mono-to-stereo converter\n", DevFmtTypeString(srcType)); + return E_FAIL; + } + TRACE("Created %s mono-to-stereo converter\n", DevFmtTypeString(srcType)); + srcType = DevFmtFloat; + } + + if(device->Frequency != OutputType.Format.nSamplesPerSec || device->FmtType != srcType) + { + self->SampleConv = CreateSampleConverter( + srcType, device->FmtType, ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder), + OutputType.Format.nSamplesPerSec, device->Frequency + ); + if(!self->SampleConv) + { + ERR("Failed to create converter for %s format, dst: %s %uhz, src: %s %luhz\n", + DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), + device->Frequency, DevFmtTypeString(srcType), OutputType.Format.nSamplesPerSec); + return E_FAIL; + } + TRACE("Created converter for %s format, dst: %s %uhz, src: %s %luhz\n", + DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), + device->Frequency, DevFmtTypeString(srcType), OutputType.Format.nSamplesPerSec); + } + + hr = IAudioClient_Initialize(self->client, + AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, + buf_time, 0, &OutputType.Format, NULL + ); + if(FAILED(hr)) + { + ERR("Failed to initialize audio client: 0x%08lx\n", hr); + return hr; + } + + hr = IAudioClient_GetBufferSize(self->client, &buffer_len); + if(FAILED(hr)) + { + ERR("Failed to get buffer size: 0x%08lx\n", hr); + return hr; + } + + buffer_len = maxu(device->UpdateSize*device->NumUpdates, buffer_len); + ll_ringbuffer_free(self->Ring); + self->Ring = ll_ringbuffer_create(buffer_len, + FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder), + false + ); + if(!self->Ring) + { + ERR("Failed to allocate capture ring buffer\n"); + return E_OUTOFMEMORY; + } + + hr = IAudioClient_SetEventHandle(self->client, self->NotifyEvent); + if(FAILED(hr)) + { + ERR("Failed to set event handle: 0x%08lx\n", hr); + return hr; + } + + return hr; +} + + +static ALCboolean ALCwasapiCapture_start(ALCwasapiCapture *self) +{ + ThreadRequest req = { self->MsgEvent, 0 }; + HRESULT hr = E_FAIL; + + if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self))) + hr = WaitForResponse(&req); + + return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE; +} + +static HRESULT ALCwasapiCapture_startProxy(ALCwasapiCapture *self) +{ + HRESULT hr; + void *ptr; + + ResetEvent(self->NotifyEvent); + hr = IAudioClient_Start(self->client); + if(FAILED(hr)) + { + ERR("Failed to start audio client: 0x%08lx\n", hr); + return hr; + } + + hr = IAudioClient_GetService(self->client, &IID_IAudioCaptureClient, &ptr); + if(SUCCEEDED(hr)) + { + self->capture = ptr; + ATOMIC_STORE(&self->killNow, 0, almemory_order_release); + if(althrd_create(&self->thread, ALCwasapiCapture_recordProc, self) != althrd_success) + { + ERR("Failed to start thread\n"); + IAudioCaptureClient_Release(self->capture); + self->capture = NULL; + hr = E_FAIL; + } + } + + if(FAILED(hr)) + { + IAudioClient_Stop(self->client); + IAudioClient_Reset(self->client); + } + + return hr; +} + + +static void ALCwasapiCapture_stop(ALCwasapiCapture *self) +{ + ThreadRequest req = { self->MsgEvent, 0 }; + if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self))) + (void)WaitForResponse(&req); +} + +static void ALCwasapiCapture_stopProxy(ALCwasapiCapture *self) +{ + int res; + + if(!self->capture) + return; + + ATOMIC_STORE_SEQ(&self->killNow, 1); + althrd_join(self->thread, &res); + + IAudioCaptureClient_Release(self->capture); + self->capture = NULL; + IAudioClient_Stop(self->client); + IAudioClient_Reset(self->client); +} + + +ALuint ALCwasapiCapture_availableSamples(ALCwasapiCapture *self) +{ + return (ALuint)ll_ringbuffer_read_space(self->Ring); +} + +ALCenum ALCwasapiCapture_captureSamples(ALCwasapiCapture *self, ALCvoid *buffer, ALCuint samples) +{ + if(ALCwasapiCapture_availableSamples(self) < samples) + return ALC_INVALID_VALUE; + ll_ringbuffer_read(self->Ring, buffer, samples); + return ALC_NO_ERROR; +} + + +static inline void AppendAllDevicesList2(const DevMap *entry) +{ AppendAllDevicesList(alstr_get_cstr(entry->name)); } +static inline void AppendCaptureDeviceList2(const DevMap *entry) +{ AppendCaptureDeviceList(alstr_get_cstr(entry->name)); } + +typedef struct ALCwasapiBackendFactory { + DERIVE_FROM_TYPE(ALCbackendFactory); +} ALCwasapiBackendFactory; +#define ALCWASAPIBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCwasapiBackendFactory, ALCbackendFactory) } } + +static ALCboolean ALCwasapiBackendFactory_init(ALCwasapiBackendFactory *self); +static void ALCwasapiBackendFactory_deinit(ALCwasapiBackendFactory *self); +static ALCboolean ALCwasapiBackendFactory_querySupport(ALCwasapiBackendFactory *self, ALCbackend_Type type); +static void ALCwasapiBackendFactory_probe(ALCwasapiBackendFactory *self, enum DevProbe type); +static ALCbackend* ALCwasapiBackendFactory_createBackend(ALCwasapiBackendFactory *self, ALCdevice *device, ALCbackend_Type type); + +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCwasapiBackendFactory); + + +static ALCboolean ALCwasapiBackendFactory_init(ALCwasapiBackendFactory* UNUSED(self)) +{ + static HRESULT InitResult; + + VECTOR_INIT(PlaybackDevices); + VECTOR_INIT(CaptureDevices); + + if(!ThreadHdl) + { + ThreadRequest req; + InitResult = E_FAIL; + + req.FinishedEvt = CreateEventW(NULL, FALSE, FALSE, NULL); + if(req.FinishedEvt == NULL) + ERR("Failed to create event: %lu\n", GetLastError()); + else + { + ThreadHdl = CreateThread(NULL, 0, ALCwasapiProxy_messageHandler, &req, 0, &ThreadID); + if(ThreadHdl != NULL) + InitResult = WaitForResponse(&req); + CloseHandle(req.FinishedEvt); + } + } + + return SUCCEEDED(InitResult) ? ALC_TRUE : ALC_FALSE; +} + +static void ALCwasapiBackendFactory_deinit(ALCwasapiBackendFactory* UNUSED(self)) +{ + clear_devlist(&PlaybackDevices); + VECTOR_DEINIT(PlaybackDevices); + + clear_devlist(&CaptureDevices); + VECTOR_DEINIT(CaptureDevices); + + if(ThreadHdl) + { + TRACE("Sending WM_QUIT to Thread %04lx\n", ThreadID); + PostThreadMessage(ThreadID, WM_QUIT, 0, 0); + CloseHandle(ThreadHdl); + ThreadHdl = NULL; + } +} + +static ALCboolean ALCwasapiBackendFactory_querySupport(ALCwasapiBackendFactory* UNUSED(self), ALCbackend_Type type) +{ + /* TODO: Disable capture with mmdevapi for now, since it doesn't do any + * rechanneling or resampling; if the device is configured for 48000hz + * stereo input, for example, and the app asks for 22050hz mono, + * initialization will fail. + */ + if(type == ALCbackend_Playback || type == ALCbackend_Capture) + return ALC_TRUE; + return ALC_FALSE; +} + +static void ALCwasapiBackendFactory_probe(ALCwasapiBackendFactory* UNUSED(self), enum DevProbe type) +{ + ThreadRequest req = { NULL, 0 }; + + req.FinishedEvt = CreateEventW(NULL, FALSE, FALSE, NULL); + if(req.FinishedEvt == NULL) + ERR("Failed to create event: %lu\n", GetLastError()); + else + { + HRESULT hr = E_FAIL; + if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, type)) + hr = WaitForResponse(&req); + if(SUCCEEDED(hr)) switch(type) + { + case ALL_DEVICE_PROBE: + VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2); + break; + + case CAPTURE_DEVICE_PROBE: + VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2); + break; + } + CloseHandle(req.FinishedEvt); + req.FinishedEvt = NULL; + } +} + +static ALCbackend* ALCwasapiBackendFactory_createBackend(ALCwasapiBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + { + ALCwasapiPlayback *backend; + NEW_OBJ(backend, ALCwasapiPlayback)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + if(type == ALCbackend_Capture) + { + ALCwasapiCapture *backend; + NEW_OBJ(backend, ALCwasapiCapture)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + + return NULL; +} + + +ALCbackendFactory *ALCwasapiBackendFactory_getFactory(void) +{ + static ALCwasapiBackendFactory factory = ALCWASAPIBACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); +} diff --git a/Alc/helpers.c b/Alc/helpers.c index 6de1fdc3..e5545492 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -66,7 +66,7 @@ DEFINE_GUID(IID_IAudioClient, 0x1cb9ad4c, 0xdbfa, 0x4c32, 0xb1,0x78, 0xc DEFINE_GUID(IID_IAudioRenderClient, 0xf294acfc, 0x3146, 0x4483, 0xa7,0xbf, 0xad,0xdc,0xa7,0xc2,0x60,0xe2); DEFINE_GUID(IID_IAudioCaptureClient, 0xc8adbd64, 0xe71e, 0x48a0, 0xa4,0xde, 0x18,0x5c,0x39,0x5c,0xd3,0x17); -#ifdef HAVE_MMDEVAPI +#ifdef HAVE_WASAPI #include #include #include diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c6196f1..4a6d8ae0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -752,7 +752,7 @@ SET(HAVE_SOLARIS 0) SET(HAVE_SNDIO 0) SET(HAVE_QSA 0) SET(HAVE_DSOUND 0) -SET(HAVE_MMDEVAPI 0) +SET(HAVE_WASAPI 0) SET(HAVE_WINMM 0) SET(HAVE_PORTAUDIO 0) SET(HAVE_PULSEAUDIO 0) @@ -970,7 +970,7 @@ ENDIF() # Check Windows-only backends OPTION(ALSOFT_REQUIRE_WINMM "Require Windows Multimedia backend" OFF) OPTION(ALSOFT_REQUIRE_DSOUND "Require DirectSound backend" OFF) -OPTION(ALSOFT_REQUIRE_MMDEVAPI "Require MMDevApi backend" OFF) +OPTION(ALSOFT_REQUIRE_WASAPI "Require WASAPI backend" OFF) IF(HAVE_WINDOWS_H) # Check MMSystem backend CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H -D_WIN32_WINNT=0x0502) @@ -1000,14 +1000,14 @@ IF(HAVE_WINDOWS_H) ENDIF() ENDIF() - # Check for MMDevApi backend + # Check for WASAPI backend CHECK_INCLUDE_FILE(mmdeviceapi.h HAVE_MMDEVICEAPI_H) IF(HAVE_MMDEVICEAPI_H) - OPTION(ALSOFT_BACKEND_MMDEVAPI "Enable MMDevApi backend" ON) - IF(ALSOFT_BACKEND_MMDEVAPI) - SET(HAVE_MMDEVAPI 1) - SET(BACKENDS "${BACKENDS} MMDevApi,") - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/mmdevapi.c) + OPTION(ALSOFT_BACKEND_WASAPI "Enable WASAPI backend" ON) + IF(ALSOFT_BACKEND_WASAPI) + SET(HAVE_WASAPI 1) + SET(BACKENDS "${BACKENDS} WASAPI,") + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/wasapi.c) ENDIF() ENDIF() ENDIF() @@ -1017,8 +1017,8 @@ ENDIF() IF(ALSOFT_REQUIRE_DSOUND AND NOT HAVE_DSOUND) MESSAGE(FATAL_ERROR "Failed to enabled required DSound backend") ENDIF() -IF(ALSOFT_REQUIRE_MMDEVAPI AND NOT HAVE_MMDEVAPI) - MESSAGE(FATAL_ERROR "Failed to enabled required MMDevApi backend") +IF(ALSOFT_REQUIRE_WASAPI AND NOT HAVE_WASAPI) + MESSAGE(FATAL_ERROR "Failed to enabled required WASAPI backend") ENDIF() # Check PortAudio backend diff --git a/alsoftrc.sample b/alsoftrc.sample index 06ef57d5..b457a2db 100644 --- a/alsoftrc.sample +++ b/alsoftrc.sample @@ -444,9 +444,9 @@ surround71 = #buffer-size = 0 ## -## MMDevApi backend stuff +## WASAPI backend stuff ## -[mmdevapi] +[wasapi] ## ## DirectSound backend stuff diff --git a/appveyor.yml b/appveyor.yml index eab4f397..0e5b7ce4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,6 +14,6 @@ install: build_script: - cd build - - cmake -G"%GEN%" -DALSOFT_REQUIRE_WINMM=ON -DALSOFT_REQUIRE_DSOUND=ON -DALSOFT_REQUIRE_MMDEVAPI=ON -DALSOFT_EMBED_HRTF_DATA=YES .. + - cmake -G"%GEN%" -DALSOFT_REQUIRE_WINMM=ON -DALSOFT_REQUIRE_DSOUND=ON -DALSOFT_REQUIRE_WASAPI=ON -DALSOFT_EMBED_HRTF_DATA=YES .. - cmake --build . --config %CFG% --clean-first diff --git a/config.h.in b/config.h.in index 345e8408..5768e345 100644 --- a/config.h.in +++ b/config.h.in @@ -50,8 +50,8 @@ /* Define if we have the QSA backend */ #cmakedefine HAVE_QSA -/* Define if we have the MMDevApi backend */ -#cmakedefine HAVE_MMDEVAPI +/* Define if we have the WASAPI backend */ +#cmakedefine HAVE_WASAPI /* Define if we have the DSound backend */ #cmakedefine HAVE_DSOUND diff --git a/utils/alsoft-config/mainwindow.cpp b/utils/alsoft-config/mainwindow.cpp index c5efbe38..a3b0c559 100644 --- a/utils/alsoft-config/mainwindow.cpp +++ b/utils/alsoft-config/mainwindow.cpp @@ -44,8 +44,8 @@ static const struct { #ifdef HAVE_QSA { "qsa", "QSA" }, #endif -#ifdef HAVE_MMDEVAPI - { "mmdevapi", "MMDevAPI" }, +#ifdef HAVE_WASAPI + { "wasapi", "WASAPI" }, #endif #ifdef HAVE_DSOUND { "dsound", "DirectSound" }, @@ -774,7 +774,16 @@ void MainWindow::loadConfig(const QString &fname) if(drivers.size() == 1) drivers = drivers[0].split(QChar(',')); for(QStringList::iterator iter = drivers.begin();iter != drivers.end();iter++) + { *iter = iter->trimmed(); + /* Convert "mmdevapi" references to "wasapi" for backwards + * compatibility. + */ + if(*iter == "-mmdevapi") + *iter = "-wasapi"; + else if(*iter == "mmdevapi") + *iter = "wasapi"; + } bool lastWasEmpty = false; foreach(const QString &backend, drivers) -- cgit v1.2.3 From f65e83c3499ed26ee3dea4b0a1ca0282d47ae7cc Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 14 Mar 2018 03:21:26 -0700 Subject: Avoid using pa_stream_begin_write with PulseAudio It seems to actually have a negative performance impact when the system is under load. Without having actual measurements for any potential benefits, simply go with the recommended (and previous fallback) method of allocating space for the write and passing the free method. Ideally some kind of ring buffer could be used, so rather than constantly allocating and freeing blocks of memory, it uses the same memory over again with the callback marking each one as reusable. Unfortunately the callback isn't given much information to work with, and the update size (minreq) can potentially change during playback, which complicates things. --- Alc/backends/pulseaudio.c | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index 96794e20..be785707 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -833,6 +833,9 @@ static int ALCpulsePlayback_mixerProc(void *ptr) while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) && ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) { + void *buf; + int ret; + len = pa_stream_writable_size(self->stream); if(len < 0) { @@ -863,33 +866,16 @@ static int ALCpulsePlayback_mixerProc(void *ptr) pa_threaded_mainloop_wait(self->loop); continue; } - len -= len%self->attr.minreq; - while(len > 0) - { - size_t newlen = len; - int ret; - void *buf; - pa_free_cb_t free_func = NULL; + len -= len%self->attr.minreq; + len -= len%frame_size; - if(pa_stream_begin_write(self->stream, &buf, &newlen) < 0) - { - buf = pa_xmalloc(newlen); - free_func = pa_xfree; - } + buf = pa_xmalloc(len); - newlen /= frame_size; - aluMixData(device, buf, newlen); + aluMixData(device, buf, len/frame_size); - newlen *= frame_size; - ret = pa_stream_write(self->stream, buf, newlen, free_func, 0, PA_SEEK_RELATIVE); - if(ret != PA_OK) - { - ERR("Failed to write to stream: %d, %s\n", ret, pa_strerror(ret)); - break; - } - len -= newlen; - } + ret = pa_stream_write(self->stream, buf, len, pa_xfree, 0, PA_SEEK_RELATIVE); + if(ret != PA_OK) ERR("Failed to write to stream: %d, %s\n", ret, pa_strerror(ret)); } pa_threaded_mainloop_unlock(self->loop); -- cgit v1.2.3 From 2011421e18442d7dd31dbb84135786dd8bf6a478 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 14 Mar 2018 23:48:46 -0700 Subject: Release the PulseAudio mainloop lock sooner --- Alc/backends/pulseaudio.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index be785707..74d1a149 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -1164,13 +1164,16 @@ static void ALCpulsePlayback_stop(ALCpulsePlayback *self) static ClockLatency ALCpulsePlayback_getClockLatency(ALCpulsePlayback *self) { - pa_usec_t latency = 0; ClockLatency ret; + pa_usec_t latency; int neg, err; pa_threaded_mainloop_lock(self->loop); ret.ClockTime = GetDeviceClockTime(STATIC_CAST(ALCbackend,self)->mDevice); - if((err=pa_stream_get_latency(self->stream, &latency, &neg)) != 0) + err = pa_stream_get_latency(self->stream, &latency, &neg); + pa_threaded_mainloop_unlock(self->loop); + + if(UNLIKELY(err != 0)) { /* FIXME: if err = -PA_ERR_NODATA, it means we were called too soon * after starting the stream and no timing info has been received from @@ -1181,9 +1184,9 @@ static ClockLatency ALCpulsePlayback_getClockLatency(ALCpulsePlayback *self) latency = 0; neg = 0; } - if(neg) latency = 0; - ret.Latency = minu64(latency, U64(0xffffffffffffffff)/1000) * 1000; - pa_threaded_mainloop_unlock(self->loop); + else if(UNLIKELY(neg)) + latency = 0; + ret.Latency = (ALint64)minu64(latency, U64(0x7fffffffffffffff)/1000) * 1000; return ret; } @@ -1715,21 +1718,24 @@ static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self) static ClockLatency ALCpulseCapture_getClockLatency(ALCpulseCapture *self) { - pa_usec_t latency = 0; ClockLatency ret; + pa_usec_t latency; int neg, err; pa_threaded_mainloop_lock(self->loop); ret.ClockTime = GetDeviceClockTime(STATIC_CAST(ALCbackend,self)->mDevice); - if((err=pa_stream_get_latency(self->stream, &latency, &neg)) != 0) + err = pa_stream_get_latency(self->stream, &latency, &neg); + pa_threaded_mainloop_unlock(self->loop); + + if(UNLIKELY(err != 0)) { ERR("Failed to get stream latency: 0x%x\n", err); latency = 0; neg = 0; } - if(neg) latency = 0; - ret.Latency = minu64(latency, U64(0xffffffffffffffff)/1000) * 1000; - pa_threaded_mainloop_unlock(self->loop); + else if(UNLIKELY(neg)) + latency = 0; + ret.Latency = (ALint64)minu64(latency, U64(0x7fffffffffffffff)/1000) * 1000; return ret; } -- cgit v1.2.3 From 603e3e23acf02d1bcb20f5ebb230bfb3c0fad9d8 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 14 Mar 2018 23:51:13 -0700 Subject: Remove an outdated comment --- Alc/backends/wasapi.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/wasapi.c b/Alc/backends/wasapi.c index b64e260b..8677afa9 100644 --- a/Alc/backends/wasapi.c +++ b/Alc/backends/wasapi.c @@ -1984,11 +1984,6 @@ static void ALCwasapiBackendFactory_deinit(ALCwasapiBackendFactory* UNUSED(self) static ALCboolean ALCwasapiBackendFactory_querySupport(ALCwasapiBackendFactory* UNUSED(self), ALCbackend_Type type) { - /* TODO: Disable capture with mmdevapi for now, since it doesn't do any - * rechanneling or resampling; if the device is configured for 48000hz - * stereo input, for example, and the app asks for 22050hz mono, - * initialization will fail. - */ if(type == ALCbackend_Playback || type == ALCbackend_Capture) return ALC_TRUE; return ALC_FALSE; -- cgit v1.2.3 From 63c9d95b845c0554b59eb7edf6bb05e5650633ba Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 23 Mar 2018 11:39:07 -0700 Subject: Combine multiple allocations into one --- Alc/backends/coreaudio.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index b2545c47..d6d32cc8 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -53,36 +53,25 @@ typedef struct { static const ALCchar ca_device[] = "CoreAudio Default"; -static AudioBufferList* allocate_buffer_list(UInt32 channelCount, UInt32 byteSize) +static AudioBufferList *allocate_buffer_list(UInt32 channelCount, UInt32 byteSize) { AudioBufferList *list; - list = calloc(1, sizeof(AudioBufferList) + sizeof(AudioBuffer)); + list = calloc(1, FAM_SIZE(AudioBufferList, mBuffers, 1) + byteSize); 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; - } + list->mBuffers[0].mData = &list->mBuffers[1]; } return list; } -static void destroy_buffer_list(AudioBufferList* list) +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); - } + free(list); } -- cgit v1.2.3 From e37634e908c7563e6281997d50800a2f9633d8d2 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 23 Mar 2018 11:58:11 -0700 Subject: Remove an unused struct and move some functions to where they're used --- Alc/backends/coreaudio.c | 62 +++++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 38 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index d6d32cc8..eeb19dab 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -36,45 +36,9 @@ #include "backends/base.h" -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 - - ll_ringbuffer_t *ring; -} ca_data; - static const ALCchar ca_device[] = "CoreAudio Default"; -static AudioBufferList *allocate_buffer_list(UInt32 channelCount, UInt32 byteSize) -{ - AudioBufferList *list; - - list = calloc(1, FAM_SIZE(AudioBufferList, mBuffers, 1) + byteSize); - if(list) - { - list->mNumberBuffers = 1; - - list->mBuffers[0].mNumberChannels = channelCount; - list->mBuffers[0].mDataByteSize = byteSize; - list->mBuffers[0].mData = &list->mBuffers[1]; - } - return list; -} - -static void destroy_buffer_list(AudioBufferList *list) -{ - free(list); -} - - typedef struct ALCcoreAudioPlayback { DERIVE_FROM_TYPE(ALCbackend); @@ -125,10 +89,10 @@ static OSStatus ALCcoreAudioPlayback_MixerProc(void *inRefCon, ALCcoreAudioPlayback *self = inRefCon; ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; - ALCdevice_Lock(device); + ALCcoreAudioPlayback_lock(self); aluMixData(device, ioData->mBuffers[0].mData, ioData->mBuffers[0].mDataByteSize / self->frameSize); - ALCdevice_Unlock(device); + ALCcoreAudioPlayback_unlock(self); return noErr; } @@ -381,6 +345,28 @@ DECLARE_DEFAULT_ALLOCATORS(ALCcoreAudioCapture) DEFINE_ALCBACKEND_VTABLE(ALCcoreAudioCapture); +static AudioBufferList *allocate_buffer_list(UInt32 channelCount, UInt32 byteSize) +{ + AudioBufferList *list; + + list = calloc(1, FAM_SIZE(AudioBufferList, mBuffers, 1) + byteSize); + if(list) + { + list->mNumberBuffers = 1; + + list->mBuffers[0].mNumberChannels = channelCount; + list->mBuffers[0].mDataByteSize = byteSize; + list->mBuffers[0].mData = &list->mBuffers[1]; + } + return list; +} + +static void destroy_buffer_list(AudioBufferList *list) +{ + free(list); +} + + static void ALCcoreAudioCapture_Construct(ALCcoreAudioCapture *self, ALCdevice *device) { ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); -- cgit v1.2.3 From e5e3b0501504036ecc9c5a8a6478d7ac55447955 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 24 Mar 2018 08:58:18 -0700 Subject: Fix capture device closing in the CoreAudio backend --- Alc/backends/coreaudio.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index eeb19dab..a8787f7b 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -331,7 +331,6 @@ typedef struct ALCcoreAudioCapture { static void ALCcoreAudioCapture_Construct(ALCcoreAudioCapture *self, ALCdevice *device); static void ALCcoreAudioCapture_Destruct(ALCcoreAudioCapture *self); static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar *name); -static void ALCcoreAudioCapture_close(ALCcoreAudioCapture *self); static DECLARE_FORWARD(ALCcoreAudioCapture, ALCbackend, ALCboolean, reset) static ALCboolean ALCcoreAudioCapture_start(ALCcoreAudioCapture *self); static void ALCcoreAudioCapture_stop(ALCcoreAudioCapture *self); @@ -372,10 +371,32 @@ static void ALCcoreAudioCapture_Construct(ALCcoreAudioCapture *self, ALCdevice * ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCcoreAudioCapture, ALCbackend, self); + self->audioUnit = 0; + self->audioConverter = NULL; + self->bufferList = NULL; + self->resampleBuffer = NULL; + self->ring = NULL; } static void ALCcoreAudioCapture_Destruct(ALCcoreAudioCapture *self) { + ll_ringbuffer_free(self->ring); + self->ring = NULL; + + free(self->resampleBuffer); + self->resampleBuffer = NULL; + + destroy_buffer_list(self->bufferList); + self->bufferList = NULL; + + if(self->audioConverter) + AudioConverterDispose(self->audioConverter); + self->audioConverter = NULL; + + if(self->audioUnit) + AudioComponentInstanceDispose(self->audioUnit); + self->audioUnit = 0; + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -651,30 +672,21 @@ error: ll_ringbuffer_free(self->ring); self->ring = NULL; free(self->resampleBuffer); + self->resampleBuffer = NULL; destroy_buffer_list(self->bufferList); + self->bufferList = NULL; if(self->audioConverter) AudioConverterDispose(self->audioConverter); + self->audioConverter = NULL; if(self->audioUnit) AudioComponentInstanceDispose(self->audioUnit); + self->audioUnit = 0; return ALC_INVALID_VALUE; } -static void ALCcoreAudioCapture_close(ALCcoreAudioCapture *self) -{ - ll_ringbuffer_free(self->ring); - self->ring = NULL; - - free(self->resampleBuffer); - - destroy_buffer_list(self->bufferList); - - AudioConverterDispose(self->audioConverter); - AudioComponentInstanceDispose(self->audioUnit); -} - static ALCboolean ALCcoreAudioCapture_start(ALCcoreAudioCapture *self) { OSStatus err = AudioOutputUnitStart(self->audioUnit); -- cgit v1.2.3 From 414b56edec5441211dc924fef365c54267c04f1c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 1 Apr 2018 16:39:20 -0700 Subject: Initialize COM using the multithreaded apartment I honestly have no idea which is the correct (or better) mode to use given the confusing mess COM is, but CoInitialize uses single-threaded apartments which seems to be a problem for with at least a couple games in the STALKER series (the call fails, which causes us to drop back to the DSound backend). --- Alc/backends/wasapi.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/wasapi.c b/Alc/backends/wasapi.c index 8677afa9..50471f6b 100644 --- a/Alc/backends/wasapi.c +++ b/Alc/backends/wasapi.c @@ -388,7 +388,7 @@ static DWORD CALLBACK ALCwasapiProxy_messageHandler(void *ptr) TRACE("Starting message thread\n"); - cohr = CoInitialize(NULL); + cohr = CoInitializeEx(NULL, COINIT_MULTITHREADED); if(FAILED(cohr)) { WARN("Failed to initialize COM: 0x%08lx\n", cohr); @@ -435,7 +435,7 @@ static DWORD CALLBACK ALCwasapiProxy_messageHandler(void *ptr) hr = cohr = S_OK; if(++deviceCount == 1) - hr = cohr = CoInitialize(NULL); + hr = cohr = CoInitializeEx(NULL, COINIT_MULTITHREADED); if(SUCCEEDED(hr)) hr = V0(proxy,openProxy)(); if(FAILED(hr)) @@ -487,7 +487,7 @@ static DWORD CALLBACK ALCwasapiProxy_messageHandler(void *ptr) hr = cohr = S_OK; if(++deviceCount == 1) - hr = cohr = CoInitialize(NULL); + hr = cohr = CoInitializeEx(NULL, COINIT_MULTITHREADED); if(SUCCEEDED(hr)) hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); if(SUCCEEDED(hr)) @@ -627,10 +627,10 @@ FORCE_ALIGN static int ALCwasapiPlayback_mixerProc(void *arg) BYTE *buffer; HRESULT hr; - hr = CoInitialize(NULL); + hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); if(FAILED(hr)) { - ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr); + ERR("CoInitializeEx(NULL, COINIT_MULTITHREADED) failed: 0x%08lx\n", hr); V0(device->Backend,lock)(); aluHandleDisconnect(device, "COM init failed: 0x%08lx", hr); V0(device->Backend,unlock)(); @@ -1321,10 +1321,10 @@ FORCE_ALIGN int ALCwasapiCapture_recordProc(void *arg) size_t samplesmax = 0; HRESULT hr; - hr = CoInitialize(NULL); + hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); if(FAILED(hr)) { - ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr); + ERR("CoInitializeEx(NULL, COINIT_MULTITHREADED) failed: 0x%08lx\n", hr); V0(device->Backend,lock)(); aluHandleDisconnect(device, "COM init failed: 0x%08lx", hr); V0(device->Backend,unlock)(); -- cgit v1.2.3 From 525b6fe1689de5aff6d4d4c0ac1c3e931d66c1b3 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 19 Apr 2018 12:22:39 -0700 Subject: Clear ALSA's PCM handle after closing it --- Alc/backends/alsa.c | 1 + 1 file changed, 1 insertion(+) (limited to 'Alc/backends') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 9fc36582..e0fdc070 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -1146,6 +1146,7 @@ error2: ll_ringbuffer_free(self->ring); self->ring = NULL; snd_pcm_close(self->pcmHandle); + self->pcmHandle = NULL; return ALC_INVALID_VALUE; } -- cgit v1.2.3 From fd1458ce1bfef0d8f8baba0aff5edb5cfa0940a4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 8 Jun 2018 05:02:47 -0700 Subject: Always prepare the ALSA PCM handle before starting capture Draining the ALSA device via stopping puts it into a setup state, which requires re-preparing before playback can start again. Preparing it prior to the first start seems to cause no harm, so just always do it before starting. --- Alc/backends/alsa.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index e0fdc070..409be7fa 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -1153,10 +1153,17 @@ error2: static ALCboolean ALCcaptureAlsa_start(ALCcaptureAlsa *self) { - int err = snd_pcm_start(self->pcmHandle); + int err = snd_pcm_prepare(self->pcmHandle); + if(err < 0) + ERR("prepare failed: %s\n", snd_strerror(err)); + else + { + err = snd_pcm_start(self->pcmHandle); + if(err < 0) + ERR("start failed: %s\n", snd_strerror(err)); + } if(err < 0) { - ERR("start failed: %s\n", snd_strerror(err)); aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice, "Capture state failure: %s", snd_strerror(err)); return ALC_FALSE; -- cgit v1.2.3 From 24b646dec0ea08434bc30b73389cbc01efb59596 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 23 Aug 2018 18:20:09 -0700 Subject: Append the OpenSL capture device to the appropriate list --- Alc/backends/opensl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Alc/backends') diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index a5ad3b09..262fdaef 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -1039,7 +1039,7 @@ static void ALCopenslBackendFactory_probe(ALCopenslBackendFactory* UNUSED(self), break; case CAPTURE_DEVICE_PROBE: - AppendAllDevicesList(opensl_device); + AppendCaptureDeviceList(opensl_device); break; } } -- cgit v1.2.3 From 7394dd512dd36e7bf105b065c9b773b0d9f5ace5 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 7 Sep 2018 18:45:24 -0700 Subject: Rename ALCsndioBackend --- Alc/ALc.c | 8 ++--- Alc/backends/base.h | 2 +- Alc/backends/sndio.c | 92 ++++++++++++++++++++++++++-------------------------- 3 files changed, 51 insertions(+), 51 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index 535f9475..1b47777e 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -79,7 +79,7 @@ static struct BackendInfo BackendList[] = { { "solaris", ALCsolarisBackendFactory_getFactory }, #endif #ifdef HAVE_SNDIO - { "sndio", ALCsndioBackendFactory_getFactory }, + { "sndio", SndioBackendFactory_getFactory }, #endif #ifdef HAVE_OSS { "oss", ALCossBackendFactory_getFactory }, @@ -656,9 +656,9 @@ static const struct { DECL(AL_DEDICATED_GAIN), - DECL(AL_AUTOWAH_ATTACK_TIME), - DECL(AL_AUTOWAH_RELEASE_TIME), - DECL(AL_AUTOWAH_RESONANCE), + DECL(AL_AUTOWAH_ATTACK_TIME), + DECL(AL_AUTOWAH_RELEASE_TIME), + DECL(AL_AUTOWAH_RESONANCE), DECL(AL_AUTOWAH_PEAK_GAIN), DECL(AL_NUM_RESAMPLERS_SOFT), diff --git a/Alc/backends/base.h b/Alc/backends/base.h index ba92b4ac..e6f624c2 100644 --- a/Alc/backends/base.h +++ b/Alc/backends/base.h @@ -142,7 +142,7 @@ ALCbackendFactory *ALCcoreAudioBackendFactory_getFactory(void); ALCbackendFactory *ALCossBackendFactory_getFactory(void); ALCbackendFactory *ALCjackBackendFactory_getFactory(void); ALCbackendFactory *ALCsolarisBackendFactory_getFactory(void); -ALCbackendFactory *ALCsndioBackendFactory_getFactory(void); +ALCbackendFactory *SndioBackendFactory_getFactory(void); ALCbackendFactory *ALCqsaBackendFactory_getFactory(void); ALCbackendFactory *ALCwasapiBackendFactory_getFactory(void); ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void); diff --git a/Alc/backends/sndio.c b/Alc/backends/sndio.c index 5aea457b..90d0866f 100644 --- a/Alc/backends/sndio.c +++ b/Alc/backends/sndio.c @@ -35,7 +35,7 @@ -typedef struct ALCsndioBackend { +typedef struct SndioPlayback { DERIVE_FROM_TYPE(ALCbackend); struct sio_hdl *sndHandle; @@ -45,40 +45,40 @@ typedef struct ALCsndioBackend { ATOMIC(int) killNow; althrd_t thread; -} ALCsndioBackend; +} SndioPlayback; -static int ALCsndioBackend_mixerProc(void *ptr); +static int SndioPlayback_mixerProc(void *ptr); -static void ALCsndioBackend_Construct(ALCsndioBackend *self, ALCdevice *device); -static void ALCsndioBackend_Destruct(ALCsndioBackend *self); -static ALCenum ALCsndioBackend_open(ALCsndioBackend *self, const ALCchar *name); -static ALCboolean ALCsndioBackend_reset(ALCsndioBackend *self); -static ALCboolean ALCsndioBackend_start(ALCsndioBackend *self); -static void ALCsndioBackend_stop(ALCsndioBackend *self); -static DECLARE_FORWARD2(ALCsndioBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint) -static DECLARE_FORWARD(ALCsndioBackend, ALCbackend, ALCuint, availableSamples) -static DECLARE_FORWARD(ALCsndioBackend, ALCbackend, ClockLatency, getClockLatency) -static DECLARE_FORWARD(ALCsndioBackend, ALCbackend, void, lock) -static DECLARE_FORWARD(ALCsndioBackend, ALCbackend, void, unlock) -DECLARE_DEFAULT_ALLOCATORS(ALCsndioBackend) +static void SndioPlayback_Construct(SndioPlayback *self, ALCdevice *device); +static void SndioPlayback_Destruct(SndioPlayback *self); +static ALCenum SndioPlayback_open(SndioPlayback *self, const ALCchar *name); +static ALCboolean SndioPlayback_reset(SndioPlayback *self); +static ALCboolean SndioPlayback_start(SndioPlayback *self); +static void SndioPlayback_stop(SndioPlayback *self); +static DECLARE_FORWARD2(SndioPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint) +static DECLARE_FORWARD(SndioPlayback, ALCbackend, ALCuint, availableSamples) +static DECLARE_FORWARD(SndioPlayback, ALCbackend, ClockLatency, getClockLatency) +static DECLARE_FORWARD(SndioPlayback, ALCbackend, void, lock) +static DECLARE_FORWARD(SndioPlayback, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(SndioPlayback) -DEFINE_ALCBACKEND_VTABLE(ALCsndioBackend); +DEFINE_ALCBACKEND_VTABLE(SndioPlayback); static const ALCchar sndio_device[] = "SndIO Default"; -static void ALCsndioBackend_Construct(ALCsndioBackend *self, ALCdevice *device) +static void SndioPlayback_Construct(SndioPlayback *self, ALCdevice *device) { ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); - SET_VTABLE2(ALCsndioBackend, ALCbackend, self); + SET_VTABLE2(SndioPlayback, ALCbackend, self); self->sndHandle = NULL; self->mix_data = NULL; ATOMIC_INIT(&self->killNow, AL_TRUE); } -static void ALCsndioBackend_Destruct(ALCsndioBackend *self) +static void SndioPlayback_Destruct(SndioPlayback *self) { if(self->sndHandle) sio_close(self->sndHandle); @@ -91,9 +91,9 @@ static void ALCsndioBackend_Destruct(ALCsndioBackend *self) } -static int ALCsndioBackend_mixerProc(void *ptr) +static int SndioPlayback_mixerProc(void *ptr) { - ALCsndioBackend *self = (ALCsndioBackend*)ptr; + SndioPlayback *self = (SndioPlayback*)ptr; ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; ALsizei frameSize; size_t wrote; @@ -109,9 +109,9 @@ static int ALCsndioBackend_mixerProc(void *ptr) ALsizei len = self->data_size; ALubyte *WritePtr = self->mix_data; - ALCsndioBackend_lock(self); + SndioPlayback_lock(self); aluMixData(device, WritePtr, len/frameSize); - ALCsndioBackend_unlock(self); + SndioPlayback_unlock(self); while(len > 0 && !ATOMIC_LOAD(&self->killNow, almemory_order_acquire)) { wrote = sio_write(self->sndHandle, WritePtr, len); @@ -133,7 +133,7 @@ static int ALCsndioBackend_mixerProc(void *ptr) } -static ALCenum ALCsndioBackend_open(ALCsndioBackend *self, const ALCchar *name) +static ALCenum SndioPlayback_open(SndioPlayback *self, const ALCchar *name) { ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; @@ -154,7 +154,7 @@ static ALCenum ALCsndioBackend_open(ALCsndioBackend *self, const ALCchar *name) return ALC_NO_ERROR; } -static ALCboolean ALCsndioBackend_reset(ALCsndioBackend *self) +static ALCboolean SndioPlayback_reset(SndioPlayback *self) { ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; struct sio_par par; @@ -239,7 +239,7 @@ static ALCboolean ALCsndioBackend_reset(ALCsndioBackend *self) return ALC_TRUE; } -static ALCboolean ALCsndioBackend_start(ALCsndioBackend *self) +static ALCboolean SndioPlayback_start(SndioPlayback *self) { ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; @@ -256,7 +256,7 @@ static ALCboolean ALCsndioBackend_start(ALCsndioBackend *self) } ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); - if(althrd_create(&self->thread, ALCsndioBackend_mixerProc, self) != althrd_success) + if(althrd_create(&self->thread, SndioPlayback_mixerProc, self) != althrd_success) { sio_stop(self->sndHandle); return ALC_FALSE; @@ -265,7 +265,7 @@ static ALCboolean ALCsndioBackend_start(ALCsndioBackend *self) return ALC_TRUE; } -static void ALCsndioBackend_stop(ALCsndioBackend *self) +static void SndioPlayback_stop(SndioPlayback *self) { int res; @@ -281,42 +281,42 @@ static void ALCsndioBackend_stop(ALCsndioBackend *self) } -typedef struct ALCsndioBackendFactory { +typedef struct SndioBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); -} ALCsndioBackendFactory; -#define ALCSNDIOBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCsndioBackendFactory, ALCbackendFactory) } } +} SndioBackendFactory; +#define SNDIOBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(SndioBackendFactory, ALCbackendFactory) } } -ALCbackendFactory *ALCsndioBackendFactory_getFactory(void); +ALCbackendFactory *SndioBackendFactory_getFactory(void); -static ALCboolean ALCsndioBackendFactory_init(ALCsndioBackendFactory *self); -static DECLARE_FORWARD(ALCsndioBackendFactory, ALCbackendFactory, void, deinit) -static ALCboolean ALCsndioBackendFactory_querySupport(ALCsndioBackendFactory *self, ALCbackend_Type type); -static void ALCsndioBackendFactory_probe(ALCsndioBackendFactory *self, enum DevProbe type); -static ALCbackend* ALCsndioBackendFactory_createBackend(ALCsndioBackendFactory *self, ALCdevice *device, ALCbackend_Type type); -DEFINE_ALCBACKENDFACTORY_VTABLE(ALCsndioBackendFactory); +static ALCboolean SndioBackendFactory_init(SndioBackendFactory *self); +static DECLARE_FORWARD(SndioBackendFactory, ALCbackendFactory, void, deinit) +static ALCboolean SndioBackendFactory_querySupport(SndioBackendFactory *self, ALCbackend_Type type); +static void SndioBackendFactory_probe(SndioBackendFactory *self, enum DevProbe type); +static ALCbackend* SndioBackendFactory_createBackend(SndioBackendFactory *self, ALCdevice *device, ALCbackend_Type type); +DEFINE_ALCBACKENDFACTORY_VTABLE(SndioBackendFactory); -ALCbackendFactory *ALCsndioBackendFactory_getFactory(void) +ALCbackendFactory *SndioBackendFactory_getFactory(void) { - static ALCsndioBackendFactory factory = ALCSNDIOBACKENDFACTORY_INITIALIZER; + static SndioBackendFactory factory = SNDIOBACKENDFACTORY_INITIALIZER; return STATIC_CAST(ALCbackendFactory, &factory); } -static ALCboolean ALCsndioBackendFactory_init(ALCsndioBackendFactory* UNUSED(self)) +static ALCboolean SndioBackendFactory_init(SndioBackendFactory* UNUSED(self)) { /* No dynamic loading */ return ALC_TRUE; } -static ALCboolean ALCsndioBackendFactory_querySupport(ALCsndioBackendFactory* UNUSED(self), ALCbackend_Type type) +static ALCboolean SndioBackendFactory_querySupport(SndioBackendFactory* UNUSED(self), ALCbackend_Type type) { if(type == ALCbackend_Playback) return ALC_TRUE; return ALC_FALSE; } -static void ALCsndioBackendFactory_probe(ALCsndioBackendFactory* UNUSED(self), enum DevProbe type) +static void SndioBackendFactory_probe(SndioBackendFactory* UNUSED(self), enum DevProbe type) { switch(type) { @@ -328,12 +328,12 @@ static void ALCsndioBackendFactory_probe(ALCsndioBackendFactory* UNUSED(self), e } } -static ALCbackend* ALCsndioBackendFactory_createBackend(ALCsndioBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +static ALCbackend* SndioBackendFactory_createBackend(SndioBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) { if(type == ALCbackend_Playback) { - ALCsndioBackend *backend; - NEW_OBJ(backend, ALCsndioBackend)(device); + SndioPlayback *backend; + NEW_OBJ(backend, SndioPlayback)(device); if(!backend) return NULL; return STATIC_CAST(ALCbackend, backend); } -- cgit v1.2.3 From 212cb8e298ccfd42e8d44cc2a20108513507e29e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 7 Sep 2018 20:08:24 -0700 Subject: Implement capture support for SoundIO --- Alc/backends/sndio.c | 272 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 266 insertions(+), 6 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/sndio.c b/Alc/backends/sndio.c index 90d0866f..062e6732 100644 --- a/Alc/backends/sndio.c +++ b/Alc/backends/sndio.c @@ -27,12 +27,14 @@ #include "alMain.h" #include "alu.h" #include "threads.h" +#include "ringbuffer.h" #include "backends/base.h" #include +static const ALCchar sndio_device[] = "SndIO Default"; typedef struct SndioPlayback { @@ -65,9 +67,6 @@ DECLARE_DEFAULT_ALLOCATORS(SndioPlayback) DEFINE_ALCBACKEND_VTABLE(SndioPlayback); -static const ALCchar sndio_device[] = "SndIO Default"; - - static void SndioPlayback_Construct(SndioPlayback *self, ALCdevice *device) { ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); @@ -281,6 +280,261 @@ static void SndioPlayback_stop(SndioPlayback *self) } +typedef struct SndioCapture { + DERIVE_FROM_TYPE(ALCbackend); + + struct sio_hdl *sndHandle; + + ll_ringbuffer_t *ring; + + ATOMIC(int) killNow; + althrd_t thread; +} SndioCapture; + +static int SndioCapture_recordProc(void *ptr); + +static void SndioCapture_Construct(SndioCapture *self, ALCdevice *device); +static void SndioCapture_Destruct(SndioCapture *self); +static ALCenum SndioCapture_open(SndioCapture *self, const ALCchar *name); +static DECLARE_FORWARD(SndioCapture, ALCbackend, ALCboolean, reset) +static ALCboolean SndioCapture_start(SndioCapture *self); +static void SndioCapture_stop(SndioCapture *self); +static ALCenum SndioCapture_captureSamples(SndioCapture *self, void *buffer, ALCuint samples); +static ALCuint SndioCapture_availableSamples(SndioCapture *self); +static DECLARE_FORWARD(SndioCapture, ALCbackend, ClockLatency, getClockLatency) +static DECLARE_FORWARD(SndioCapture, ALCbackend, void, lock) +static DECLARE_FORWARD(SndioCapture, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(SndioCapture) + +DEFINE_ALCBACKEND_VTABLE(SndioCapture); + + +static void SndioCapture_Construct(SndioCapture *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(SndioCapture, ALCbackend, self); + + self->sndHandle = NULL; + self->ring = NULL; + ATOMIC_INIT(&self->killNow, AL_TRUE); +} + +static void SndioCapture_Destruct(SndioCapture *self) +{ + if(self->sndHandle) + sio_close(self->sndHandle); + self->sndHandle = NULL; + + ll_ringbuffer_free(self->ring); + self->ring = NULL; + + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + + +static int SndioCapture_recordProc(void* ptr) +{ + SndioCapture *self = (SndioCapture*)ptr; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + ALsizei frameSize; + + SetRTPriority(); + althrd_setname(althrd_current(), RECORD_THREAD_NAME); + + frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); + + while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) && + ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) + { + ll_ringbuffer_data_t data[2]; + size_t total, todo; + + ll_ringbuffer_get_write_vector(self->ring, data); + todo = data[0].len + data[1].len; + if(todo == 0) + { + static char junk[4096]; + sio_read(self->sndHandle, junk, minz(sizeof(junk)/frameSize, device->UpdateSize)*frameSize); + continue; + } + + total = 0; + data[0].len *= frameSize; + data[1].len *= frameSize; + todo = minz(todo, device->UpdateSize) * frameSize; + while(total < todo) + { + size_t got; + + if(!data[0].len) + data[0] = data[1]; + + got = sio_read(self->sndHandle, data[0].buf, minz(todo-total, data[0].len)); + if(!got) + { + SndioCapture_lock(self); + aluHandleDisconnect(device, "Failed to read capture samples"); + SndioCapture_unlock(self); + break; + } + + data[0].buf += got; + data[0].len -= got; + total += got; + } + ll_ringbuffer_write_advance(self->ring, total / frameSize); + } + + return 0; +} + + +static ALCenum SndioCapture_open(SndioCapture *self, const ALCchar *name) +{ + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + struct sio_par par; + + if(!name) + name = sndio_device; + else if(strcmp(name, sndio_device) != 0) + return ALC_INVALID_VALUE; + + self->sndHandle = sio_open(NULL, SIO_REC, 0); + if(self->sndHandle == NULL) + { + ERR("Could not open device\n"); + return ALC_INVALID_VALUE; + } + + sio_initpar(&par); + + switch(device->FmtType) + { + case DevFmtByte: + par.bps = 1; + par.sig = 1; + break; + case DevFmtUByte: + par.bps = 1; + par.sig = 0; + break; + case DevFmtShort: + par.bps = 2; + par.sig = 1; + break; + case DevFmtUShort: + par.bps = 2; + par.sig = 0; + break; + case DevFmtInt: + par.bps = 4; + par.sig = 1; + break; + case DevFmtUInt: + par.bps = 4; + par.sig = 0; + break; + case DevFmtFloat: + ERR("%s capture samples not supported\n", DevFmtTypeString(device->FmtType)); + return ALC_INVALID_VALUE; + } + par.bits = par.bps * 8; + par.le = SIO_LE_NATIVE; + par.msb = SIO_LE_NATIVE ? 0 : 1; + par.rchan = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); + par.rate = device->Frequency; + + par.appbufsz = maxu(device->UpdateSize*device->NumUpdates, (device->Frequency+9)/10); + par.round = clampu(par.appbufsz/device->NumUpdates, (device->Frequency+99)/100, + (device->Frequency+19)/20); + + device->UpdateSize = par.round; + device->NumUpdates = maxu(par.appbufsz/par.round, 1); + + if(!sio_setpar(self->sndHandle, &par) || !sio_getpar(self->sndHandle, &par)) + { + ERR("Failed to set device parameters\n"); + return ALC_INVALID_VALUE; + } + + if(par.bits != par.bps*8) + { + ERR("Padded samples not supported (%u of %u bits)\n", par.bits, par.bps*8); + return ALC_INVALID_VALUE; + } + + if(!((device->FmtType == DevFmtByte && par.bits == 8 && par.sig != 0) || + (device->FmtType == DevFmtUByte && par.bits == 8 && par.sig == 0) || + (device->FmtType == DevFmtShort && par.bits == 16 && par.sig != 0) || + (device->FmtType == DevFmtUShort && par.bits == 16 && par.sig == 0) || + (device->FmtType == DevFmtInt && par.bits == 32 && par.sig != 0) || + (device->FmtType == DevFmtUInt && par.bits == 32 && par.sig == 0)) || + ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder) != (ALsizei)par.rchan || + device->Frequency != par.rate) + { + ERR("Failed to set format %s %s %uhz, got %c%u %u-channel %uhz instead\n", + DevFmtTypeString(device->FmtType), DevFmtChannelsString(device->FmtChans), + device->Frequency, par.sig?'s':'u', par.bits, par.rchan, par.rate); + return ALC_INVALID_VALUE; + } + + self->ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates, par.bps*par.rchan, 0); + if(!self->ring) + { + ERR("Failed to allocate %u-byte ringbuffer\n", + device->UpdateSize*device->NumUpdates*par.bps*par.rchan); + return ALC_OUT_OF_MEMORY; + } + + SetDefaultChannelOrder(device); + + alstr_copy_cstr(&device->DeviceName, name); + + return ALC_NO_ERROR; +} + +static ALCboolean SndioCapture_start(SndioCapture *self) +{ + if(!sio_start(self->sndHandle)) + { + ERR("Error starting playback\n"); + return ALC_FALSE; + } + + ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); + if(althrd_create(&self->thread, SndioCapture_recordProc, self) != althrd_success) + { + sio_stop(self->sndHandle); + return ALC_FALSE; + } + + return ALC_TRUE; +} + +static void SndioCapture_stop(SndioCapture *self) +{ + int res; + + if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel)) + return; + althrd_join(self->thread, &res); + + if(!sio_stop(self->sndHandle)) + ERR("Error stopping device\n"); +} + +static ALCenum SndioCapture_captureSamples(SndioCapture *self, void *buffer, ALCuint samples) +{ + ll_ringbuffer_read(self->ring, buffer, samples); + return ALC_NO_ERROR; +} + +static ALCuint SndioCapture_availableSamples(SndioCapture *self) +{ + return ll_ringbuffer_read_space(self->ring); +} + + typedef struct SndioBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); } SndioBackendFactory; @@ -295,14 +549,12 @@ static void SndioBackendFactory_probe(SndioBackendFactory *self, enum DevProbe t static ALCbackend* SndioBackendFactory_createBackend(SndioBackendFactory *self, ALCdevice *device, ALCbackend_Type type); DEFINE_ALCBACKENDFACTORY_VTABLE(SndioBackendFactory); - ALCbackendFactory *SndioBackendFactory_getFactory(void) { static SndioBackendFactory factory = SNDIOBACKENDFACTORY_INITIALIZER; return STATIC_CAST(ALCbackendFactory, &factory); } - static ALCboolean SndioBackendFactory_init(SndioBackendFactory* UNUSED(self)) { /* No dynamic loading */ @@ -311,7 +563,7 @@ static ALCboolean SndioBackendFactory_init(SndioBackendFactory* UNUSED(self)) static ALCboolean SndioBackendFactory_querySupport(SndioBackendFactory* UNUSED(self), ALCbackend_Type type) { - if(type == ALCbackend_Playback) + if(type == ALCbackend_Playback || type == ALCbackend_Capture) return ALC_TRUE; return ALC_FALSE; } @@ -324,6 +576,7 @@ static void SndioBackendFactory_probe(SndioBackendFactory* UNUSED(self), enum De AppendAllDevicesList(sndio_device); break; case CAPTURE_DEVICE_PROBE: + AppendCaptureDeviceList(sndio_device); break; } } @@ -337,6 +590,13 @@ static ALCbackend* SndioBackendFactory_createBackend(SndioBackendFactory* UNUSED if(!backend) return NULL; return STATIC_CAST(ALCbackend, backend); } + if(type == ALCbackend_Capture) + { + SndioCapture *backend; + NEW_OBJ(backend, SndioCapture)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } return NULL; } -- cgit v1.2.3 From 46cfedb1171ace7c21bd1d95c1c75a8274892d3d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 7 Sep 2018 22:02:37 -0700 Subject: Pass the device name list to the backend probe method --- Alc/ALc.c | 13 +------------ Alc/backends/alsa.c | 17 +++++++++-------- Alc/backends/base.h | 5 +++-- Alc/backends/coreaudio.c | 8 +++----- Alc/backends/dsound.c | 19 ++++++++++--------- Alc/backends/jack.c | 4 ++-- Alc/backends/loopback.c | 4 ++-- Alc/backends/null.c | 7 +++---- Alc/backends/opensl.c | 7 ++----- Alc/backends/oss.c | 31 +++++++++++-------------------- Alc/backends/portaudio.c | 9 +++------ Alc/backends/pulseaudio.c | 21 +++++++++++---------- Alc/backends/qsa.c | 31 +++++++++++++------------------ Alc/backends/sdl2.c | 9 +++++---- Alc/backends/sndio.c | 8 +++----- Alc/backends/solaris.c | 6 +++--- Alc/backends/wasapi.c | 19 ++++++++++--------- Alc/backends/wave.c | 6 +++--- Alc/backends/winmm.c | 24 +++++++++--------------- OpenAL32/Include/alMain.h | 3 --- 20 files changed, 106 insertions(+), 145 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index 1b47777e..27c36477 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -1314,7 +1314,7 @@ static void ProbeDevices(al_string *list, struct BackendInfo *backendinfo, enum if(backendinfo->getFactory) { ALCbackendFactory *factory = backendinfo->getFactory(); - V(factory,probe)(type); + V(factory,probe)(type, list); } UnlockLists(); @@ -1324,17 +1324,6 @@ static void ProbeAllDevicesList(void) static void ProbeCaptureDeviceList(void) { ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); } -static void AppendDevice(const ALCchar *name, al_string *devnames) -{ - size_t len = strlen(name); - if(len > 0) - alstr_append_range(devnames, name, name+len+1); -} -void AppendAllDevicesList(const ALCchar *name) -{ AppendDevice(name, &alcAllDevicesList); } -void AppendCaptureDeviceList(const ALCchar *name) -{ AppendDevice(name, &alcCaptureDeviceList); } - /************************************************ * Device format information diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 409be7fa..a967fff0 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -1375,11 +1375,6 @@ static ClockLatency ALCcaptureAlsa_getClockLatency(ALCcaptureAlsa *self) } -static inline void AppendAllDevicesList2(const DevMap *entry) -{ AppendAllDevicesList(alstr_get_cstr(entry->name)); } -static inline void AppendCaptureDeviceList2(const DevMap *entry) -{ AppendCaptureDeviceList(alstr_get_cstr(entry->name)); } - typedef struct ALCalsaBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); } ALCalsaBackendFactory; @@ -1417,19 +1412,25 @@ static ALCboolean ALCalsaBackendFactory_querySupport(ALCalsaBackendFactory* UNUS return ALC_FALSE; } -static void ALCalsaBackendFactory_probe(ALCalsaBackendFactory* UNUSED(self), enum DevProbe type) +static void ALCalsaBackendFactory_probe(ALCalsaBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) { switch(type) { +#define APPEND_OUTNAME(i) do { \ + if(!alstr_empty((i)->name)) \ + alstr_append_range(outnames, VECTOR_BEGIN((i)->name), \ + VECTOR_END((i)->name)+1); \ +} while(0) case ALL_DEVICE_PROBE: probe_devices(SND_PCM_STREAM_PLAYBACK, &PlaybackDevices); - VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2); + VECTOR_FOR_EACH(const DevMap, PlaybackDevices, APPEND_OUTNAME); break; case CAPTURE_DEVICE_PROBE: probe_devices(SND_PCM_STREAM_CAPTURE, &CaptureDevices); - VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2); + VECTOR_FOR_EACH(const DevMap, CaptureDevices, APPEND_OUTNAME); break; +#undef APPEND_OUTNAME } } diff --git a/Alc/backends/base.h b/Alc/backends/base.h index e6f624c2..0de4e590 100644 --- a/Alc/backends/base.h +++ b/Alc/backends/base.h @@ -3,6 +3,7 @@ #include "alMain.h" #include "threads.h" +#include "alstring.h" #ifdef __cplusplus @@ -115,7 +116,7 @@ struct ALCbackendFactoryVtable { ALCboolean (*const querySupport)(ALCbackendFactory *self, ALCbackend_Type type); - void (*const probe)(ALCbackendFactory *self, enum DevProbe type); + void (*const probe)(ALCbackendFactory *self, enum DevProbe type, al_string *outnames); ALCbackend* (*const createBackend)(ALCbackendFactory *self, ALCdevice *device, ALCbackend_Type type); }; @@ -124,7 +125,7 @@ struct ALCbackendFactoryVtable { DECLARE_THUNK(T, ALCbackendFactory, ALCboolean, init) \ DECLARE_THUNK(T, ALCbackendFactory, void, deinit) \ DECLARE_THUNK1(T, ALCbackendFactory, ALCboolean, querySupport, ALCbackend_Type) \ -DECLARE_THUNK1(T, ALCbackendFactory, void, probe, enum DevProbe) \ +DECLARE_THUNK2(T, ALCbackendFactory, void, probe, enum DevProbe, al_string*) \ DECLARE_THUNK2(T, ALCbackendFactory, ALCbackend*, createBackend, ALCdevice*, ALCbackend_Type) \ \ static const struct ALCbackendFactoryVtable T##_ALCbackendFactory_vtable = { \ diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index a8787f7b..5945834c 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -752,7 +752,7 @@ ALCbackendFactory *ALCcoreAudioBackendFactory_getFactory(void); static ALCboolean ALCcoreAudioBackendFactory_init(ALCcoreAudioBackendFactory *self); static DECLARE_FORWARD(ALCcoreAudioBackendFactory, ALCbackendFactory, void, deinit) static ALCboolean ALCcoreAudioBackendFactory_querySupport(ALCcoreAudioBackendFactory *self, ALCbackend_Type type); -static void ALCcoreAudioBackendFactory_probe(ALCcoreAudioBackendFactory *self, enum DevProbe type); +static void ALCcoreAudioBackendFactory_probe(ALCcoreAudioBackendFactory *self, enum DevProbe type, al_string *outnames); static ALCbackend* ALCcoreAudioBackendFactory_createBackend(ALCcoreAudioBackendFactory *self, ALCdevice *device, ALCbackend_Type type); DEFINE_ALCBACKENDFACTORY_VTABLE(ALCcoreAudioBackendFactory); @@ -776,15 +776,13 @@ static ALCboolean ALCcoreAudioBackendFactory_querySupport(ALCcoreAudioBackendFac return ALC_FALSE; } -static void ALCcoreAudioBackendFactory_probe(ALCcoreAudioBackendFactory* UNUSED(self), enum DevProbe type) +static void ALCcoreAudioBackendFactory_probe(ALCcoreAudioBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) { switch(type) { case ALL_DEVICE_PROBE: - AppendAllDevicesList(ca_device); - break; case CAPTURE_DEVICE_PROBE: - AppendCaptureDeviceList(ca_device); + alstr_append_range(outnames, ca_device, ca_device+sizeof(ca_device)); break; } } diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index 6bab641c..c368cffb 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -969,11 +969,6 @@ done: } -static inline void AppendAllDevicesList2(const DevMap *entry) -{ AppendAllDevicesList(alstr_get_cstr(entry->name)); } -static inline void AppendCaptureDeviceList2(const DevMap *entry) -{ AppendCaptureDeviceList(alstr_get_cstr(entry->name)); } - typedef struct ALCdsoundBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); } ALCdsoundBackendFactory; @@ -984,7 +979,7 @@ ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void); static ALCboolean ALCdsoundBackendFactory_init(ALCdsoundBackendFactory *self); static void ALCdsoundBackendFactory_deinit(ALCdsoundBackendFactory *self); static ALCboolean ALCdsoundBackendFactory_querySupport(ALCdsoundBackendFactory *self, ALCbackend_Type type); -static void ALCdsoundBackendFactory_probe(ALCdsoundBackendFactory *self, enum DevProbe type); +static void ALCdsoundBackendFactory_probe(ALCdsoundBackendFactory *self, enum DevProbe type, al_string *outnames); static ALCbackend* ALCdsoundBackendFactory_createBackend(ALCdsoundBackendFactory *self, ALCdevice *device, ALCbackend_Type type); DEFINE_ALCBACKENDFACTORY_VTABLE(ALCdsoundBackendFactory); @@ -1028,7 +1023,7 @@ static ALCboolean ALCdsoundBackendFactory_querySupport(ALCdsoundBackendFactory* return ALC_FALSE; } -static void ALCdsoundBackendFactory_probe(ALCdsoundBackendFactory* UNUSED(self), enum DevProbe type) +static void ALCdsoundBackendFactory_probe(ALCdsoundBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) { HRESULT hr, hrcom; @@ -1036,12 +1031,17 @@ static void ALCdsoundBackendFactory_probe(ALCdsoundBackendFactory* UNUSED(self), hrcom = CoInitialize(NULL); switch(type) { +#define APPEND_OUTNAME(e) do { \ + if(!alstr_empty((e)->name)) \ + alstr_append_range(outnames, VECTOR_BEGIN((e)->name), \ + VECTOR_END((e)->name)+1); \ +} while(0) case ALL_DEVICE_PROBE: clear_devlist(&PlaybackDevices); hr = DirectSoundEnumerateW(DSoundEnumDevices, &PlaybackDevices); if(FAILED(hr)) ERR("Error enumerating DirectSound playback devices (0x%lx)!\n", hr); - VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2); + VECTOR_FOR_EACH(const DevMap, PlaybackDevices, APPEND_OUTNAME); break; case CAPTURE_DEVICE_PROBE: @@ -1049,8 +1049,9 @@ static void ALCdsoundBackendFactory_probe(ALCdsoundBackendFactory* UNUSED(self), hr = DirectSoundCaptureEnumerateW(DSoundEnumDevices, &CaptureDevices); if(FAILED(hr)) ERR("Error enumerating DirectSound capture devices (0x%lx)!\n", hr); - VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2); + VECTOR_FOR_EACH(const DevMap, CaptureDevices, APPEND_OUTNAME); break; +#undef APPEND_OUTNAME } if(SUCCEEDED(hrcom)) CoUninitialize(); diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c index 67e3c106..fdbe93f2 100644 --- a/Alc/backends/jack.c +++ b/Alc/backends/jack.c @@ -571,12 +571,12 @@ static ALCboolean ALCjackBackendFactory_querySupport(ALCjackBackendFactory* UNUS return ALC_FALSE; } -static void ALCjackBackendFactory_probe(ALCjackBackendFactory* UNUSED(self), enum DevProbe type) +static void ALCjackBackendFactory_probe(ALCjackBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) { switch(type) { case ALL_DEVICE_PROBE: - AppendAllDevicesList(jackDevice); + alstr_append_range(outnames, jackDevice, jackDevice+sizeof(jackDevice)); break; case CAPTURE_DEVICE_PROBE: diff --git a/Alc/backends/loopback.c b/Alc/backends/loopback.c index 9186a92f..e9940086 100644 --- a/Alc/backends/loopback.c +++ b/Alc/backends/loopback.c @@ -87,7 +87,7 @@ ALCbackendFactory *ALCloopbackFactory_getFactory(void); static ALCboolean ALCloopbackFactory_init(ALCloopbackFactory *self); static DECLARE_FORWARD(ALCloopbackFactory, ALCbackendFactory, void, deinit) static ALCboolean ALCloopbackFactory_querySupport(ALCloopbackFactory *self, ALCbackend_Type type); -static void ALCloopbackFactory_probe(ALCloopbackFactory *self, enum DevProbe type); +static void ALCloopbackFactory_probe(ALCloopbackFactory *self, enum DevProbe type, al_string *outnames); static ALCbackend* ALCloopbackFactory_createBackend(ALCloopbackFactory *self, ALCdevice *device, ALCbackend_Type type); DEFINE_ALCBACKENDFACTORY_VTABLE(ALCloopbackFactory); @@ -110,7 +110,7 @@ static ALCboolean ALCloopbackFactory_querySupport(ALCloopbackFactory* UNUSED(sel return ALC_FALSE; } -static void ALCloopbackFactory_probe(ALCloopbackFactory* UNUSED(self), enum DevProbe UNUSED(type)) +static void ALCloopbackFactory_probe(ALCloopbackFactory* UNUSED(self), enum DevProbe UNUSED(type), al_string* UNUSED(outnames)) { } diff --git a/Alc/backends/null.c b/Alc/backends/null.c index 2c2db54e..d1c110e8 100644 --- a/Alc/backends/null.c +++ b/Alc/backends/null.c @@ -171,7 +171,7 @@ ALCbackendFactory *ALCnullBackendFactory_getFactory(void); static ALCboolean ALCnullBackendFactory_init(ALCnullBackendFactory *self); static DECLARE_FORWARD(ALCnullBackendFactory, ALCbackendFactory, void, deinit) static ALCboolean ALCnullBackendFactory_querySupport(ALCnullBackendFactory *self, ALCbackend_Type type); -static void ALCnullBackendFactory_probe(ALCnullBackendFactory *self, enum DevProbe type); +static void ALCnullBackendFactory_probe(ALCnullBackendFactory *self, enum DevProbe type, al_string *outnames); static ALCbackend* ALCnullBackendFactory_createBackend(ALCnullBackendFactory *self, ALCdevice *device, ALCbackend_Type type); DEFINE_ALCBACKENDFACTORY_VTABLE(ALCnullBackendFactory); @@ -195,14 +195,13 @@ static ALCboolean ALCnullBackendFactory_querySupport(ALCnullBackendFactory* UNUS return ALC_FALSE; } -static void ALCnullBackendFactory_probe(ALCnullBackendFactory* UNUSED(self), enum DevProbe type) +static void ALCnullBackendFactory_probe(ALCnullBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) { switch(type) { case ALL_DEVICE_PROBE: - AppendAllDevicesList(nullDevice); - break; case CAPTURE_DEVICE_PROBE: + alstr_append_range(outnames, nullDevice, nullDevice+sizeof(nullDevice)); break; } } diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 262fdaef..50fe77d8 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -1030,16 +1030,13 @@ static ALCboolean ALCopenslBackendFactory_querySupport(ALCopenslBackendFactory* return ALC_FALSE; } -static void ALCopenslBackendFactory_probe(ALCopenslBackendFactory* UNUSED(self), enum DevProbe type) +static void ALCopenslBackendFactory_probe(ALCopenslBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) { switch(type) { case ALL_DEVICE_PROBE: - AppendAllDevicesList(opensl_device); - break; - case CAPTURE_DEVICE_PROBE: - AppendCaptureDeviceList(opensl_device); + alstr_append_range(outnames, opensl_device, opensl_device+sizeof(opensl_device)); break; } } diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index c0c98c43..71faad25 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -786,7 +786,7 @@ ALCbackendFactory *ALCossBackendFactory_getFactory(void); static ALCboolean ALCossBackendFactory_init(ALCossBackendFactory *self); static void ALCossBackendFactory_deinit(ALCossBackendFactory *self); static ALCboolean ALCossBackendFactory_querySupport(ALCossBackendFactory *self, ALCbackend_Type type); -static void ALCossBackendFactory_probe(ALCossBackendFactory *self, enum DevProbe type); +static void ALCossBackendFactory_probe(ALCossBackendFactory *self, enum DevProbe type, al_string *outnames); static ALCbackend* ALCossBackendFactory_createBackend(ALCossBackendFactory *self, ALCdevice *device, ALCbackend_Type type); DEFINE_ALCBACKENDFACTORY_VTABLE(ALCossBackendFactory); @@ -820,40 +820,31 @@ ALCboolean ALCossBackendFactory_querySupport(ALCossBackendFactory* UNUSED(self), return ALC_FALSE; } -void ALCossBackendFactory_probe(ALCossBackendFactory* UNUSED(self), enum DevProbe type) +void ALCossBackendFactory_probe(ALCossBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) { - struct oss_device *cur; + struct oss_device *cur = NULL; switch(type) { case ALL_DEVICE_PROBE: ALCossListFree(&oss_playback); ALCossListPopulate(&oss_playback, DSP_CAP_OUTPUT); cur = &oss_playback; - while(cur != NULL) - { -#ifdef HAVE_STAT - struct stat buf; - if(stat(cur->path, &buf) == 0) -#endif - AppendAllDevicesList(cur->handle); - cur = cur->next; - } break; case CAPTURE_DEVICE_PROBE: ALCossListFree(&oss_capture); ALCossListPopulate(&oss_capture, DSP_CAP_INPUT); cur = &oss_capture; - while(cur != NULL) - { + break; + } + while(cur != NULL) + { #ifdef HAVE_STAT - struct stat buf; - if(stat(cur->path, &buf) == 0) + struct stat buf; + if(stat(cur->path, &buf) == 0) #endif - AppendCaptureDeviceList(cur->handle); - cur = cur->next; - } - break; + alstr_append_range(outnames, cur->handle, cur->handle+strlen(cur->handle)+1); + cur = cur->next; } } diff --git a/Alc/backends/portaudio.c b/Alc/backends/portaudio.c index 9b0d3487..6a6cfa31 100644 --- a/Alc/backends/portaudio.c +++ b/Alc/backends/portaudio.c @@ -484,9 +484,8 @@ typedef struct ALCportBackendFactory { static ALCboolean ALCportBackendFactory_init(ALCportBackendFactory *self); static void ALCportBackendFactory_deinit(ALCportBackendFactory *self); static ALCboolean ALCportBackendFactory_querySupport(ALCportBackendFactory *self, ALCbackend_Type type); -static void ALCportBackendFactory_probe(ALCportBackendFactory *self, enum DevProbe type); +static void ALCportBackendFactory_probe(ALCportBackendFactory *self, enum DevProbe type, al_string *outnames); static ALCbackend* ALCportBackendFactory_createBackend(ALCportBackendFactory *self, ALCdevice *device, ALCbackend_Type type); - DEFINE_ALCBACKENDFACTORY_VTABLE(ALCportBackendFactory); @@ -518,15 +517,13 @@ static ALCboolean ALCportBackendFactory_querySupport(ALCportBackendFactory* UNUS return ALC_FALSE; } -static void ALCportBackendFactory_probe(ALCportBackendFactory* UNUSED(self), enum DevProbe type) +static void ALCportBackendFactory_probe(ALCportBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) { switch(type) { case ALL_DEVICE_PROBE: - AppendAllDevicesList(pa_device); - break; case CAPTURE_DEVICE_PROBE: - AppendCaptureDeviceList(pa_device); + alstr_append_range(outnames, pa_device, pa_device+sizeof(pa_device)); break; } } diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index 74d1a149..b34d7abc 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -1760,9 +1760,8 @@ typedef struct ALCpulseBackendFactory { static ALCboolean ALCpulseBackendFactory_init(ALCpulseBackendFactory *self); static void ALCpulseBackendFactory_deinit(ALCpulseBackendFactory *self); static ALCboolean ALCpulseBackendFactory_querySupport(ALCpulseBackendFactory *self, ALCbackend_Type type); -static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory *self, enum DevProbe type); +static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory *self, enum DevProbe type, al_string *outnames); static ALCbackend* ALCpulseBackendFactory_createBackend(ALCpulseBackendFactory *self, ALCdevice *device, ALCbackend_Type type); - DEFINE_ALCBACKENDFACTORY_VTABLE(ALCpulseBackendFactory); @@ -1835,23 +1834,25 @@ static ALCboolean ALCpulseBackendFactory_querySupport(ALCpulseBackendFactory* UN return ALC_FALSE; } -static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory* UNUSED(self), enum DevProbe type) +static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) { switch(type) { +#define APPEND_OUTNAME(e) do { \ + if(!alstr_empty((e)->name)) \ + alstr_append_range(outnames, VECTOR_BEGIN((e)->name), \ + VECTOR_END((e)->name)+1); \ +} while(0) case ALL_DEVICE_PROBE: ALCpulsePlayback_probeDevices(); -#define APPEND_ALL_DEVICES_LIST(e) AppendAllDevicesList(alstr_get_cstr((e)->name)) - VECTOR_FOR_EACH(const DevMap, PlaybackDevices, APPEND_ALL_DEVICES_LIST); -#undef APPEND_ALL_DEVICES_LIST + VECTOR_FOR_EACH(const DevMap, PlaybackDevices, APPEND_OUTNAME); break; case CAPTURE_DEVICE_PROBE: ALCpulseCapture_probeDevices(); -#define APPEND_CAPTURE_DEVICE_LIST(e) AppendCaptureDeviceList(alstr_get_cstr((e)->name)) - VECTOR_FOR_EACH(const DevMap, CaptureDevices, APPEND_CAPTURE_DEVICE_LIST); -#undef APPEND_CAPTURE_DEVICE_LIST + VECTOR_FOR_EACH(const DevMap, CaptureDevices, APPEND_OUTNAME); break; +#undef APPEND_OUTNAME } } @@ -1899,7 +1900,7 @@ static ALCboolean ALCpulseBackendFactory_querySupport(ALCpulseBackendFactory* UN return ALC_FALSE; } -static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory* UNUSED(self), enum DevProbe UNUSED(type)) +static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory* UNUSED(self), enum DevProbe UNUSED(type), al_string* UNUSED(outnames)) { } diff --git a/Alc/backends/qsa.c b/Alc/backends/qsa.c index 8f87779b..81645096 100644 --- a/Alc/backends/qsa.c +++ b/Alc/backends/qsa.c @@ -119,6 +119,9 @@ static void deviceList(int type, vector_DevMap *devmap) if(max_cards < 0) return; +#define FREE_NAME(iter) free((iter)->name) + VECTOR_FOR_EACH(DevMap, *devmap, FREE_NAME); +#undef FREE_NAME VECTOR_RESIZE(*devmap, 0, max_cards+1); entry.name = strdup(qsaDevice); @@ -989,7 +992,7 @@ typedef struct ALCqsaBackendFactory { static ALCboolean ALCqsaBackendFactory_init(ALCqsaBackendFactory* UNUSED(self)); static void ALCqsaBackendFactory_deinit(ALCqsaBackendFactory* UNUSED(self)); static ALCboolean ALCqsaBackendFactory_querySupport(ALCqsaBackendFactory* UNUSED(self), ALCbackend_Type type); -static void ALCqsaBackendFactory_probe(ALCqsaBackendFactory* UNUSED(self), enum DevProbe type); +static void ALCqsaBackendFactory_probe(ALCqsaBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames); static ALCbackend* ALCqsaBackendFactory_createBackend(ALCqsaBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type); DEFINE_ALCBACKENDFACTORY_VTABLE(ALCqsaBackendFactory); @@ -1016,33 +1019,25 @@ static ALCboolean ALCqsaBackendFactory_querySupport(ALCqsaBackendFactory* UNUSED return ALC_FALSE; } -static void ALCqsaBackendFactory_probe(ALCqsaBackendFactory* UNUSED(self), enum DevProbe type) +static void ALCqsaBackendFactory_probe(ALCqsaBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) { switch (type) { +#define APPEND_OUTNAME(e) do { \ + const char *n_ = (e)->name; \ + if(n_ && n_[0]) \ + alstr_append_range(outnames, n_, n_+strlen(n_)+1); \ +} while(0) case ALL_DEVICE_PROBE: -#define FREE_NAME(iter) free((iter)->name) - VECTOR_FOR_EACH(DevMap, DeviceNameMap, FREE_NAME); - VECTOR_RESIZE(DeviceNameMap, 0, 0); -#undef FREE_NAME - deviceList(SND_PCM_CHANNEL_PLAYBACK, &DeviceNameMap); -#define APPEND_DEVICE(iter) AppendAllDevicesList((iter)->name) - VECTOR_FOR_EACH(const DevMap, DeviceNameMap, APPEND_DEVICE); -#undef APPEND_DEVICE + VECTOR_FOR_EACH(const DevMap, DeviceNameMap, APPEND_OUTNAME); break; case CAPTURE_DEVICE_PROBE: -#define FREE_NAME(iter) free((iter)->name) - VECTOR_FOR_EACH(DevMap, CaptureNameMap, FREE_NAME); - VECTOR_RESIZE(CaptureNameMap, 0, 0); -#undef FREE_NAME - deviceList(SND_PCM_CHANNEL_CAPTURE, &CaptureNameMap); -#define APPEND_DEVICE(iter) AppendCaptureDeviceList((iter)->name) - VECTOR_FOR_EACH(const DevMap, CaptureNameMap, APPEND_DEVICE); -#undef APPEND_DEVICE + VECTOR_FOR_EACH(const DevMap, CaptureNameMap, APPEND_OUTNAME); break; +#undef APPEND_OUTNAME } } diff --git a/Alc/backends/sdl2.c b/Alc/backends/sdl2.c index cf005024..3495e6bf 100644 --- a/Alc/backends/sdl2.c +++ b/Alc/backends/sdl2.c @@ -221,7 +221,7 @@ ALCbackendFactory *ALCsdl2BackendFactory_getFactory(void); static ALCboolean ALCsdl2BackendFactory_init(ALCsdl2BackendFactory *self); static void ALCsdl2BackendFactory_deinit(ALCsdl2BackendFactory *self); static ALCboolean ALCsdl2BackendFactory_querySupport(ALCsdl2BackendFactory *self, ALCbackend_Type type); -static void ALCsdl2BackendFactory_probe(ALCsdl2BackendFactory *self, enum DevProbe type); +static void ALCsdl2BackendFactory_probe(ALCsdl2BackendFactory *self, enum DevProbe type, al_string *outnames); static ALCbackend* ALCsdl2BackendFactory_createBackend(ALCsdl2BackendFactory *self, ALCdevice *device, ALCbackend_Type type); DEFINE_ALCBACKENDFACTORY_VTABLE(ALCsdl2BackendFactory); @@ -252,7 +252,7 @@ static ALCboolean ALCsdl2BackendFactory_querySupport(ALCsdl2BackendFactory* UNUS return ALC_FALSE; } -static void ALCsdl2BackendFactory_probe(ALCsdl2BackendFactory* UNUSED(self), enum DevProbe type) +static void ALCsdl2BackendFactory_probe(ALCsdl2BackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) { int num_devices, i; al_string name; @@ -263,12 +263,13 @@ static void ALCsdl2BackendFactory_probe(ALCsdl2BackendFactory* UNUSED(self), enu AL_STRING_INIT(name); num_devices = SDL_GetNumAudioDevices(SDL_FALSE); - AppendAllDevicesList(defaultDeviceName); + alstr_append_range(outnames, defaultDeviceName, defaultDeviceName+sizeof(defaultDeviceName)); for(i = 0;i < num_devices;++i) { alstr_copy_cstr(&name, DEVNAME_PREFIX); alstr_append_cstr(&name, SDL_GetAudioDeviceName(i, SDL_FALSE)); - AppendAllDevicesList(alstr_get_cstr(name)); + if(!alstr_empty(name)) + alstr_append_range(outnames, VECTOR_BEGIN(name), VECTOR_END(name)+1); } alstr_reset(&name); } diff --git a/Alc/backends/sndio.c b/Alc/backends/sndio.c index 062e6732..dd174cba 100644 --- a/Alc/backends/sndio.c +++ b/Alc/backends/sndio.c @@ -545,7 +545,7 @@ ALCbackendFactory *SndioBackendFactory_getFactory(void); static ALCboolean SndioBackendFactory_init(SndioBackendFactory *self); static DECLARE_FORWARD(SndioBackendFactory, ALCbackendFactory, void, deinit) static ALCboolean SndioBackendFactory_querySupport(SndioBackendFactory *self, ALCbackend_Type type); -static void SndioBackendFactory_probe(SndioBackendFactory *self, enum DevProbe type); +static void SndioBackendFactory_probe(SndioBackendFactory *self, enum DevProbe type, al_string *outnames); static ALCbackend* SndioBackendFactory_createBackend(SndioBackendFactory *self, ALCdevice *device, ALCbackend_Type type); DEFINE_ALCBACKENDFACTORY_VTABLE(SndioBackendFactory); @@ -568,15 +568,13 @@ static ALCboolean SndioBackendFactory_querySupport(SndioBackendFactory* UNUSED(s return ALC_FALSE; } -static void SndioBackendFactory_probe(SndioBackendFactory* UNUSED(self), enum DevProbe type) +static void SndioBackendFactory_probe(SndioBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) { switch(type) { case ALL_DEVICE_PROBE: - AppendAllDevicesList(sndio_device); - break; case CAPTURE_DEVICE_PROBE: - AppendCaptureDeviceList(sndio_device); + alstr_append_range(outnames, sndio_device, sndio_device+sizeof(sndio_device)); break; } } diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c index f1c4aeaa..71282204 100644 --- a/Alc/backends/solaris.c +++ b/Alc/backends/solaris.c @@ -302,7 +302,7 @@ ALCbackendFactory *ALCsolarisBackendFactory_getFactory(void); static ALCboolean ALCsolarisBackendFactory_init(ALCsolarisBackendFactory *self); static DECLARE_FORWARD(ALCsolarisBackendFactory, ALCbackendFactory, void, deinit) static ALCboolean ALCsolarisBackendFactory_querySupport(ALCsolarisBackendFactory *self, ALCbackend_Type type); -static void ALCsolarisBackendFactory_probe(ALCsolarisBackendFactory *self, enum DevProbe type); +static void ALCsolarisBackendFactory_probe(ALCsolarisBackendFactory *self, enum DevProbe type, al_string *outnames); static ALCbackend* ALCsolarisBackendFactory_createBackend(ALCsolarisBackendFactory *self, ALCdevice *device, ALCbackend_Type type); DEFINE_ALCBACKENDFACTORY_VTABLE(ALCsolarisBackendFactory); @@ -327,7 +327,7 @@ static ALCboolean ALCsolarisBackendFactory_querySupport(ALCsolarisBackendFactory return ALC_FALSE; } -static void ALCsolarisBackendFactory_probe(ALCsolarisBackendFactory* UNUSED(self), enum DevProbe type) +static void ALCsolarisBackendFactory_probe(ALCsolarisBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) { switch(type) { @@ -337,7 +337,7 @@ static void ALCsolarisBackendFactory_probe(ALCsolarisBackendFactory* UNUSED(self struct stat buf; if(stat(solaris_driver, &buf) == 0) #endif - AppendAllDevicesList(solaris_device); + alstr_append_range(outnames, solaris_device, solaris_device+sizeof(solaris_device)); } break; diff --git a/Alc/backends/wasapi.c b/Alc/backends/wasapi.c index 50471f6b..971a1f72 100644 --- a/Alc/backends/wasapi.c +++ b/Alc/backends/wasapi.c @@ -1919,11 +1919,6 @@ ALCenum ALCwasapiCapture_captureSamples(ALCwasapiCapture *self, ALCvoid *buffer, } -static inline void AppendAllDevicesList2(const DevMap *entry) -{ AppendAllDevicesList(alstr_get_cstr(entry->name)); } -static inline void AppendCaptureDeviceList2(const DevMap *entry) -{ AppendCaptureDeviceList(alstr_get_cstr(entry->name)); } - typedef struct ALCwasapiBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); } ALCwasapiBackendFactory; @@ -1932,7 +1927,7 @@ typedef struct ALCwasapiBackendFactory { static ALCboolean ALCwasapiBackendFactory_init(ALCwasapiBackendFactory *self); static void ALCwasapiBackendFactory_deinit(ALCwasapiBackendFactory *self); static ALCboolean ALCwasapiBackendFactory_querySupport(ALCwasapiBackendFactory *self, ALCbackend_Type type); -static void ALCwasapiBackendFactory_probe(ALCwasapiBackendFactory *self, enum DevProbe type); +static void ALCwasapiBackendFactory_probe(ALCwasapiBackendFactory *self, enum DevProbe type, al_string *outnames); static ALCbackend* ALCwasapiBackendFactory_createBackend(ALCwasapiBackendFactory *self, ALCdevice *device, ALCbackend_Type type); DEFINE_ALCBACKENDFACTORY_VTABLE(ALCwasapiBackendFactory); @@ -1989,7 +1984,7 @@ static ALCboolean ALCwasapiBackendFactory_querySupport(ALCwasapiBackendFactory* return ALC_FALSE; } -static void ALCwasapiBackendFactory_probe(ALCwasapiBackendFactory* UNUSED(self), enum DevProbe type) +static void ALCwasapiBackendFactory_probe(ALCwasapiBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) { ThreadRequest req = { NULL, 0 }; @@ -2003,13 +1998,19 @@ static void ALCwasapiBackendFactory_probe(ALCwasapiBackendFactory* UNUSED(self), hr = WaitForResponse(&req); if(SUCCEEDED(hr)) switch(type) { +#define APPEND_OUTNAME(e) do { \ + if(!alstr_empty((e)->name)) \ + alstr_append_range(outnames, VECTOR_BEGIN((e)->name), \ + VECTOR_END((e)->name)+1); \ +} while(0) case ALL_DEVICE_PROBE: - VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2); + VECTOR_FOR_EACH(const DevMap, PlaybackDevices, APPEND_OUTNAME); break; case CAPTURE_DEVICE_PROBE: - VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2); + VECTOR_FOR_EACH(const DevMap, CaptureDevices, APPEND_OUTNAME); break; +#undef APPEND_OUTNAME } CloseHandle(req.FinishedEvt); req.FinishedEvt = NULL; diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index 557c2bf2..390b2a5f 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -403,7 +403,7 @@ ALCbackendFactory *ALCwaveBackendFactory_getFactory(void); static ALCboolean ALCwaveBackendFactory_init(ALCwaveBackendFactory *self); static DECLARE_FORWARD(ALCwaveBackendFactory, ALCbackendFactory, void, deinit) static ALCboolean ALCwaveBackendFactory_querySupport(ALCwaveBackendFactory *self, ALCbackend_Type type); -static void ALCwaveBackendFactory_probe(ALCwaveBackendFactory *self, enum DevProbe type); +static void ALCwaveBackendFactory_probe(ALCwaveBackendFactory *self, enum DevProbe type, al_string *outnames); static ALCbackend* ALCwaveBackendFactory_createBackend(ALCwaveBackendFactory *self, ALCdevice *device, ALCbackend_Type type); DEFINE_ALCBACKENDFACTORY_VTABLE(ALCwaveBackendFactory); @@ -427,12 +427,12 @@ static ALCboolean ALCwaveBackendFactory_querySupport(ALCwaveBackendFactory* UNUS return ALC_FALSE; } -static void ALCwaveBackendFactory_probe(ALCwaveBackendFactory* UNUSED(self), enum DevProbe type) +static void ALCwaveBackendFactory_probe(ALCwaveBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) { switch(type) { case ALL_DEVICE_PROBE: - AppendAllDevicesList(waveDevice); + alstr_append_range(outnames, waveDevice, waveDevice+sizeof(waveDevice)); break; case CAPTURE_DEVICE_PROBE: break; diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index 2f4c65df..0d4a02b8 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -700,17 +700,6 @@ static ALCuint ALCwinmmCapture_availableSamples(ALCwinmmCapture *self) } -static inline void AppendAllDevicesList2(const al_string *name) -{ - if(!alstr_empty(*name)) - AppendAllDevicesList(alstr_get_cstr(*name)); -} -static inline void AppendCaptureDeviceList2(const al_string *name) -{ - if(!alstr_empty(*name)) - AppendCaptureDeviceList(alstr_get_cstr(*name)); -} - typedef struct ALCwinmmBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); } ALCwinmmBackendFactory; @@ -719,7 +708,7 @@ typedef struct ALCwinmmBackendFactory { static ALCboolean ALCwinmmBackendFactory_init(ALCwinmmBackendFactory *self); static void ALCwinmmBackendFactory_deinit(ALCwinmmBackendFactory *self); static ALCboolean ALCwinmmBackendFactory_querySupport(ALCwinmmBackendFactory *self, ALCbackend_Type type); -static void ALCwinmmBackendFactory_probe(ALCwinmmBackendFactory *self, enum DevProbe type); +static void ALCwinmmBackendFactory_probe(ALCwinmmBackendFactory *self, enum DevProbe type, al_string *outnames); static ALCbackend* ALCwinmmBackendFactory_createBackend(ALCwinmmBackendFactory *self, ALCdevice *device, ALCbackend_Type type); DEFINE_ALCBACKENDFACTORY_VTABLE(ALCwinmmBackendFactory); @@ -749,19 +738,24 @@ static ALCboolean ALCwinmmBackendFactory_querySupport(ALCwinmmBackendFactory* UN return ALC_FALSE; } -static void ALCwinmmBackendFactory_probe(ALCwinmmBackendFactory* UNUSED(self), enum DevProbe type) +static void ALCwinmmBackendFactory_probe(ALCwinmmBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) { switch(type) { +#define APPEND_OUTNAME(n) do { \ + if(!alstr_empty(*(n))) \ + alstr_append_range(outnames, VECTOR_BEGIN(*(n)), VECTOR_END(*(n))+1); \ +} while(0) case ALL_DEVICE_PROBE: ProbePlaybackDevices(); - VECTOR_FOR_EACH(const al_string, PlaybackDevices, AppendAllDevicesList2); + VECTOR_FOR_EACH(const al_string, PlaybackDevices, APPEND_OUTNAME); break; case CAPTURE_DEVICE_PROBE: ProbeCaptureDevices(); - VECTOR_FOR_EACH(const al_string, CaptureDevices, AppendCaptureDeviceList2); + VECTOR_FOR_EACH(const al_string, CaptureDevices, APPEND_OUTNAME); break; +#undef APPEND_OUTNAME } } diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 74dba1ad..d25f62b2 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -856,9 +856,6 @@ void ALCcontext_ProcessUpdates(ALCcontext *context); void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends); -void AppendAllDevicesList(const ALCchar *name); -void AppendCaptureDeviceList(const ALCchar *name); - extern ALint RTPrioLevel; void SetRTPriority(void); -- cgit v1.2.3 From 275658b6db9129f56ca49f1a9a21ea898e0835a5 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 7 Sep 2018 23:01:17 -0700 Subject: Some suggested changes for iOS --- Alc/backends/coreaudio.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index 5945834c..adb01fa6 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -28,7 +28,6 @@ #include "alu.h" #include "ringbuffer.h" -#include #include #include #include @@ -112,7 +111,11 @@ static ALCenum ALCcoreAudioPlayback_open(ALCcoreAudioPlayback *self, const ALCch /* open the default output unit */ desc.componentType = kAudioUnitType_Output; +#if TARGET_OS_IOS + desc.componentSubType = kAudioUnitSubType_RemoteIO; +#else desc.componentSubType = kAudioUnitSubType_DefaultOutput; +#endif desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; @@ -451,7 +454,6 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar AudioStreamBasicDescription outputFormat; // The AudioUnit output format AURenderCallbackStruct input; AudioComponentDescription desc; - AudioDeviceID inputDevice; UInt32 outputFrameCount; UInt32 propertySize; AudioObjectPropertyAddress propertyAddress; @@ -465,7 +467,11 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar return ALC_INVALID_VALUE; desc.componentType = kAudioUnitType_Output; +#if TARGET_OS_IOS + desc.componentSubType = kAudioUnitSubType_RemoteIO; +#else desc.componentSubType = kAudioUnitSubType_HALOutput; +#endif desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; @@ -504,7 +510,9 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar goto error; } +#if !TARGET_OS_IOS // Get the default input device + AudioDeviceID inputDevice = kAudioDeviceUnknown; propertySize = sizeof(AudioDeviceID); propertyAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice; @@ -517,7 +525,6 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar ERR("AudioObjectGetPropertyData failed\n"); goto error; } - if(inputDevice == kAudioDeviceUnknown) { ERR("No input device found\n"); @@ -531,6 +538,7 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar ERR("AudioUnitSetProperty failed\n"); goto error; } +#endif // set capture callback input.inputProc = ALCcoreAudioCapture_RecordProc; -- cgit v1.2.3 From b77e6096b8ed26b8fee24a18820c0592eeee87b4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 17 Sep 2018 22:49:52 -0700 Subject: Fix some potential race conditions with OpenSL For playback, increment the ring buffer's write pointer before queueing audio, to handle cases where the callback is invoked, advancing the read pointer, before the write pointer is advanced. For capture, limit the number of re-queued chunks to the number of fully read chunks. --- Alc/backends/opensl.c | 104 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 42 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 50fe77d8..9815b390 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -206,6 +206,9 @@ static void ALCopenslPlayback_Destruct(ALCopenslPlayback* self) self->mEngineObj = NULL; self->mEngine = NULL; + ll_ringbuffer_free(self->mRing); + self->mRing = NULL; + alsem_destroy(&self->mSem); ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); @@ -251,19 +254,16 @@ static int ALCopenslPlayback_mixerProc(void *arg) result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_PLAY, &player); PRINTERR(result, "bufferQueue->GetInterface SL_IID_PLAY"); } + + ALCopenslPlayback_lock(self); if(SL_RESULT_SUCCESS != result) - { - ALCopenslPlayback_lock(self); aluHandleDisconnect(device, "Failed to get playback buffer: 0x%08x", result); - ALCopenslPlayback_unlock(self); - return 1; - } - ALCopenslPlayback_lock(self); - while(!ATOMIC_LOAD(&self->mKillNow, almemory_order_acquire) && + while(SL_RESULT_SUCCESS == result && + !ATOMIC_LOAD(&self->mKillNow, almemory_order_acquire) && ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) { - size_t todo, len0, len1; + size_t todo; if(ll_ringbuffer_write_space(self->mRing) == 0) { @@ -292,34 +292,33 @@ static int ALCopenslPlayback_mixerProc(void *arg) } ll_ringbuffer_get_write_vector(self->mRing, data); - todo = data[0].len+data[1].len; - - len0 = minu(todo, data[0].len); - len1 = minu(todo-len0, data[1].len); - aluMixData(device, data[0].buf, len0*device->UpdateSize); - for(size_t i = 0;i < len0;i++) - { - result = VCALL(bufferQueue,Enqueue)(data[0].buf, device->UpdateSize*self->mFrameSize); - PRINTERR(result, "bufferQueue->Enqueue"); - if(SL_RESULT_SUCCESS == result) - ll_ringbuffer_write_advance(self->mRing, 1); + aluMixData(device, data[0].buf, data[0].len*device->UpdateSize); + if(data[1].len > 0) + aluMixData(device, data[1].buf, data[1].len*device->UpdateSize); - data[0].buf += device->UpdateSize*self->mFrameSize; - } + todo = data[0].len+data[1].len; + ll_ringbuffer_write_advance(self->mRing, todo); - if(len1 > 0) + for(size_t i = 0;i < todo;i++) { - aluMixData(device, data[1].buf, len1*device->UpdateSize); - for(size_t i = 0;i < len1;i++) + if(!data[0].len) { - result = VCALL(bufferQueue,Enqueue)(data[1].buf, device->UpdateSize*self->mFrameSize); - PRINTERR(result, "bufferQueue->Enqueue"); - if(SL_RESULT_SUCCESS == result) - ll_ringbuffer_write_advance(self->mRing, 1); + data[0] = data[1]; + data[1].buf = NULL; + data[1].len = 0; + } - data[1].buf += device->UpdateSize*self->mFrameSize; + result = VCALL(bufferQueue,Enqueue)(data[0].buf, device->UpdateSize*self->mFrameSize); + PRINTERR(result, "bufferQueue->Enqueue"); + if(SL_RESULT_SUCCESS != result) + { + aluHandleDisconnect(device, "Failed to queue audio: 0x%08x", result); + break; } + + data[0].len--; + data[0].buf += device->UpdateSize*self->mFrameSize; } } ALCopenslPlayback_unlock(self); @@ -398,6 +397,9 @@ static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self) VCALL0(self->mBufferQueueObj,Destroy)(); self->mBufferQueueObj = NULL; + ll_ringbuffer_free(self->mRing); + self->mRing = NULL; + sampleRate = device->Frequency; if(!(device->Flags&DEVICE_FREQUENCY_REQUEST) && (env=Android_GetJNIEnv()) != NULL) { @@ -546,6 +548,18 @@ static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self) result = VCALL(self->mBufferQueueObj,Realize)(SL_BOOLEAN_FALSE); PRINTERR(result, "bufferQueue->Realize"); } + if(SL_RESULT_SUCCESS == result) + { + self->mRing = ll_ringbuffer_create(device->NumUpdates, + self->mFrameSize*device->UpdateSize, true + ); + if(!self->mRing) + { + ERR("Out of memory allocating ring buffer %ux%u %u\n", device->UpdateSize, + device->NumUpdates, self->mFrameSize); + result = SL_RESULT_MEMORY_FAILURE; + } + } if(SL_RESULT_SUCCESS != result) { @@ -561,13 +575,10 @@ static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self) static ALCboolean ALCopenslPlayback_start(ALCopenslPlayback *self) { - ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; SLAndroidSimpleBufferQueueItf bufferQueue; SLresult result; - ll_ringbuffer_free(self->mRing); - self->mRing = ll_ringbuffer_create(device->NumUpdates, self->mFrameSize*device->UpdateSize, - true); + ll_ringbuffer_reset(self->mRing); result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bufferQueue); @@ -634,9 +645,6 @@ static void ALCopenslPlayback_stop(ALCopenslPlayback *self) } while(SL_RESULT_SUCCESS == result && state.count > 0); PRINTERR(result, "bufferQueue->GetState"); } - - ll_ringbuffer_free(self->mRing); - self->mRing = NULL; } static ClockLatency ALCopenslPlayback_getClockLatency(ALCopenslPlayback *self) @@ -713,9 +721,6 @@ static void ALCopenslCapture_Construct(ALCopenslCapture *self, ALCdevice *device static void ALCopenslCapture_Destruct(ALCopenslCapture *self) { - ll_ringbuffer_free(self->mRing); - self->mRing = NULL; - if(self->mRecordObj != NULL) VCALL0(self->mRecordObj,Destroy)(); self->mRecordObj = NULL; @@ -725,6 +730,9 @@ static void ALCopenslCapture_Destruct(ALCopenslCapture *self) self->mEngineObj = NULL; self->mEngine = NULL; + ll_ringbuffer_free(self->mRing); + self->mRing = NULL; + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } @@ -843,8 +851,9 @@ static ALCenum ALCopenslCapture_open(ALCopenslCapture *self, const ALCchar *name if(SL_RESULT_SUCCESS == result) { - self->mRing = ll_ringbuffer_create(device->NumUpdates, device->UpdateSize*self->mFrameSize, - false); + self->mRing = ll_ringbuffer_create(device->NumUpdates, + device->UpdateSize*self->mFrameSize, false + ); result = VCALL(self->mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bufferQueue); @@ -972,14 +981,25 @@ static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid * i += rem; } + if(!advance) + return ALC_NO_ERROR; ll_ringbuffer_read_advance(self->mRing, advance); result = VCALL(self->mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bufferQueue); PRINTERR(result, "recordObj->GetInterface"); - /* Enqueue any newly-writable chunks in the ring buffer. */ + /* Enqueue any newly-writable chunks in the ring buffer. Limit the number + * of enqueued chunks to the number of fully read chunks. + */ ll_ringbuffer_get_write_vector(self->mRing, data); + if(data[0].len > advance) + { + data[0].len = advance; + data[1].len = 0; + } + else if(data[1].len > advance-data[0].len) + data[1].len = advance-data[0].len; for(i = 0;i < data[0].len && SL_RESULT_SUCCESS == result;i++) { result = VCALL(bufferQueue,Enqueue)(data[0].buf + chunk_size*i, chunk_size); -- cgit v1.2.3 From 952ff84b994b72ec39e97e2441a422085884932a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 17 Sep 2018 23:43:23 -0700 Subject: Properly queue buffers for OpenSL capture --- Alc/backends/opensl.c | 41 +++++++++-------------------------------- 1 file changed, 9 insertions(+), 32 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index 9815b390..aa2a1a6e 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -950,14 +950,16 @@ static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid * SLAndroidSimpleBufferQueueItf bufferQueue; ll_ringbuffer_data_t data[2]; SLresult result; - size_t advance; ALCuint i; + result = VCALL(self->mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, + &bufferQueue); + PRINTERR(result, "recordObj->GetInterface"); + /* Read the desired samples from the ring buffer then advance its read * pointer. */ ll_ringbuffer_get_read_vector(self->mRing, data); - advance = 0; for(i = 0;i < samples;) { ALCuint rem = minu(samples - i, device->UpdateSize - self->mSplOffset); @@ -970,7 +972,11 @@ static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid * { /* Finished a chunk, reset the offset and advance the read pointer. */ self->mSplOffset = 0; - advance++; + + ll_ringbuffer_read_advance(self->mRing, 1); + result = VCALL(bufferQueue,Enqueue)(data[0].buf, chunk_size); + PRINTERR(result, "bufferQueue->Enqueue"); + if(SL_RESULT_SUCCESS != result) break; data[0].len--; if(!data[0].len) @@ -981,35 +987,6 @@ static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid * i += rem; } - if(!advance) - return ALC_NO_ERROR; - ll_ringbuffer_read_advance(self->mRing, advance); - - result = VCALL(self->mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, - &bufferQueue); - PRINTERR(result, "recordObj->GetInterface"); - - /* Enqueue any newly-writable chunks in the ring buffer. Limit the number - * of enqueued chunks to the number of fully read chunks. - */ - ll_ringbuffer_get_write_vector(self->mRing, data); - if(data[0].len > advance) - { - data[0].len = advance; - data[1].len = 0; - } - else if(data[1].len > advance-data[0].len) - data[1].len = advance-data[0].len; - for(i = 0;i < data[0].len && SL_RESULT_SUCCESS == result;i++) - { - result = VCALL(bufferQueue,Enqueue)(data[0].buf + chunk_size*i, chunk_size); - PRINTERR(result, "bufferQueue->Enqueue"); - } - for(i = 0;i < data[1].len && SL_RESULT_SUCCESS == result;i++) - { - result = VCALL(bufferQueue,Enqueue)(data[1].buf + chunk_size*i, chunk_size); - PRINTERR(result, "bufferQueue->Enqueue"); - } if(SL_RESULT_SUCCESS != result) { -- cgit v1.2.3 From 79314c4461333c7dfd7d425d69ffd121d6c163b6 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 25 Sep 2018 23:05:27 -0700 Subject: Include the limiter's lookAhead delay in the device latency --- Alc/ALc.c | 12 +++++++++--- Alc/backends/base.c | 1 + Alc/backends/base.h | 9 +++++++++ Alc/mastering.c | 6 +++--- OpenAL32/Include/alMain.h | 1 + OpenAL32/alSource.c | 4 ++-- 6 files changed, 25 insertions(+), 8 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index a65a56b6..70663780 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -2051,6 +2051,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) device->RealOut.NumChannels = 0; UpdateClockBase(device); + device->FixedLatency = 0; device->DitherSeed = DITHER_RNG_SEED; @@ -2253,6 +2254,8 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) al_free(device->Limiter); device->Limiter = CreateDeviceLimiter(device, log10f(thrshld) * 20.0f); + device->FixedLatency += (ALuint)(device->Limiter->LookAhead * DEVICE_CLOCK_RES / + device->Frequency); } else { @@ -2263,6 +2266,8 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) aluSelectPostProcess(device); + TRACE("Fixed device latency: %uns\n", device->FixedLatency); + /* Need to delay returning failure until replacement Send arrays have been * allocated with the appropriate size. */ @@ -2422,6 +2427,7 @@ static void InitDevice(ALCdevice *device, enum DeviceType type) device->ClockBase = 0; device->SamplesDone = 0; + device->FixedLatency = 0; device->SourcesMax = 0; device->AuxiliaryEffectSlotMax = 0; @@ -3637,7 +3643,7 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, values[i++] = ALC_OUTPUT_LIMITER_SOFT; values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE; - clock = V0(device->Backend,getClockLatency)(); + clock = GetClockLatency(device); values[i++] = ALC_DEVICE_CLOCK_SOFT; values[i++] = clock.ClockTime; @@ -3663,7 +3669,7 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, case ALC_DEVICE_LATENCY_SOFT: almtx_lock(&device->BackendLock); - clock = V0(device->Backend,getClockLatency)(); + clock = GetClockLatency(device); almtx_unlock(&device->BackendLock); *values = clock.Latency; break; @@ -3674,7 +3680,7 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, else { almtx_lock(&device->BackendLock); - clock = V0(device->Backend,getClockLatency)(); + clock = GetClockLatency(device); almtx_unlock(&device->BackendLock); values[0] = clock.ClockTime; values[1] = clock.Latency; diff --git a/Alc/backends/base.c b/Alc/backends/base.c index a451fee9..9d8614b1 100644 --- a/Alc/backends/base.c +++ b/Alc/backends/base.c @@ -12,6 +12,7 @@ extern inline ALuint64 GetDeviceClockTime(ALCdevice *device); extern inline void ALCdevice_Lock(ALCdevice *device); extern inline void ALCdevice_Unlock(ALCdevice *device); +extern inline ClockLatency GetClockLatency(ALCdevice *device); /* Base ALCbackend method implementations. */ void ALCbackend_Construct(ALCbackend *self, ALCdevice *device) diff --git a/Alc/backends/base.h b/Alc/backends/base.h index 0de4e590..03db56e9 100644 --- a/Alc/backends/base.h +++ b/Alc/backends/base.h @@ -162,6 +162,15 @@ inline void ALCdevice_Lock(ALCdevice *device) inline void ALCdevice_Unlock(ALCdevice *device) { V0(device->Backend,unlock)(); } + +inline ClockLatency GetClockLatency(ALCdevice *device) +{ + ClockLatency ret = V0(device->Backend,getClockLatency)(); + ret.Latency += device->FixedLatency; + return ret; +} + + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/Alc/mastering.c b/Alc/mastering.c index 78f6038d..a957066a 100644 --- a/Alc/mastering.c +++ b/Alc/mastering.c @@ -344,10 +344,10 @@ Compressor* CompressorInit(const ALuint NumChans, const ALuint SampleRate, ALsizei hold; size_t size; - lookAhead = (ALsizei)minf(BUFFERSIZE, roundf(maxf(0.0f, LookAheadTime) * SampleRate)); - hold = (ALsizei)minf(BUFFERSIZE, roundf(maxf(0.0f, HoldTime) * SampleRate)); - size = sizeof(*Comp); + lookAhead = (ALsizei)clampf(roundf(LookAheadTime*SampleRate), 0.0f, BUFFERSIZE); + hold = (ALsizei)clampf(roundf(HoldTime*SampleRate), 0.0f, BUFFERSIZE); + size = sizeof(*Comp); if(lookAhead > 0) { size += sizeof(*Comp->Delay) * NumChans; diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 3e328157..dce51301 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -676,6 +676,7 @@ struct ALCdevice_struct { ALuint64 ClockBase; ALuint SamplesDone; + ALuint FixedLatency; /* Temp storage used for mixer processing. */ alignas(16) ALfloat TempBuffer[4][BUFFERSIZE]; diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index 81d8c262..d7c68e4e 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -1295,7 +1295,7 @@ static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SourceProp p */ values[0] = GetSourceSecOffset(Source, Context, &srcclock); almtx_lock(&device->BackendLock); - clocktime = V0(device->Backend,getClockLatency)(); + clocktime = GetClockLatency(device); almtx_unlock(&device->BackendLock); if(srcclock == (ALuint64)clocktime.ClockTime) values[1] = (ALdouble)clocktime.Latency / 1000000000.0; @@ -1559,7 +1559,7 @@ static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp */ values[0] = GetSourceSampleOffset(Source, Context, &srcclock); almtx_lock(&device->BackendLock); - clocktime = V0(device->Backend,getClockLatency)(); + clocktime = GetClockLatency(device); almtx_unlock(&device->BackendLock); if(srcclock == (ALuint64)clocktime.ClockTime) values[1] = clocktime.Latency; -- cgit v1.2.3 From c39eeb963895a2eb05e17bc28c357f7d3f4ce815 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 2 Oct 2018 12:40:26 -0700 Subject: Don't try to get the JNIEnv on Android It's currently not used. More stuff is needed anyway which may need a different approach. --- Alc/ALc.c | 69 --------------------------------------------------- Alc/backends/opensl.c | 12 +++++---- Alc/compat.h | 8 ------ 3 files changed, 7 insertions(+), 82 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/ALc.c b/Alc/ALc.c index de6a2b75..47351b99 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -1165,75 +1165,6 @@ static void alc_initconfig(void) } #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig) -#ifdef __ANDROID__ -#include - -static JavaVM *gJavaVM; -static pthread_key_t gJVMThreadKey; - -static void CleanupJNIEnv(void* UNUSED(ptr)) -{ - JCALL0(gJavaVM,DetachCurrentThread)(); -} - -void *Android_GetJNIEnv(void) -{ - if(!gJavaVM) - { - WARN("gJavaVM is NULL!\n"); - return NULL; - } - - /* http://developer.android.com/guide/practices/jni.html - * - * All threads are Linux threads, scheduled by the kernel. They're usually - * started from managed code (using Thread.start), but they can also be - * created elsewhere and then attached to the JavaVM. For example, a thread - * started with pthread_create can be attached with the JNI - * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a - * thread is attached, it has no JNIEnv, and cannot make JNI calls. - * Attaching a natively-created thread causes a java.lang.Thread object to - * be constructed and added to the "main" ThreadGroup, making it visible to - * the debugger. Calling AttachCurrentThread on an already-attached thread - * is a no-op. - */ - JNIEnv *env = pthread_getspecific(gJVMThreadKey); - if(!env) - { - int status = JCALL(gJavaVM,AttachCurrentThread)(&env, NULL); - if(status < 0) - { - ERR("Failed to attach current thread\n"); - return NULL; - } - pthread_setspecific(gJVMThreadKey, env); - } - return env; -} - -/* Automatically called by JNI. */ -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void* UNUSED(reserved)) -{ - void *env; - int err; - - gJavaVM = jvm; - if(JCALL(gJavaVM,GetEnv)(&env, JNI_VERSION_1_4) != JNI_OK) - { - ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n"); - return JNI_ERR; - } - - /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each - * thread. The JNIEnv *must* be detached before the thread is destroyed. - */ - if((err=pthread_key_create(&gJVMThreadKey, CleanupJNIEnv)) != 0) - ERR("pthread_key_create failed: %d\n", err); - pthread_setspecific(gJVMThreadKey, env); - return JNI_VERSION_1_4; -} -#endif - /************************************************ * Library deinitialization diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index aa2a1a6e..d8ae001b 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -391,7 +391,6 @@ static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self) SLInterfaceID ids[2]; SLboolean reqs[2]; SLresult result; - JNIEnv *env; if(self->mBufferQueueObj != NULL) VCALL0(self->mBufferQueueObj,Destroy)(); @@ -401,12 +400,15 @@ static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self) self->mRing = NULL; sampleRate = device->Frequency; - if(!(device->Flags&DEVICE_FREQUENCY_REQUEST) && (env=Android_GetJNIEnv()) != NULL) +#if 0 + if(!(device->Flags&DEVICE_FREQUENCY_REQUEST)) { /* FIXME: Disabled until I figure out how to get the Context needed for * the getSystemService call. */ -#if 0 + JNIEnv *env = Android_GetJNIEnv(); + jobject jctx = Android_GetContext(); + /* Get necessary stuff for using java.lang.Integer, * android.content.Context, and android.media.AudioManager. */ @@ -442,7 +444,7 @@ static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self) /* Now make the calls. */ //AudioManager audMgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE); strobj = JCALL(env,GetStaticObjectField)(ctx_cls, ctx_audsvc); - jobject audMgr = JCALL(env,CallObjectMethod)(ctx_cls, ctx_getSysSvc, strobj); + jobject audMgr = JCALL(env,CallObjectMethod)(jctx, ctx_getSysSvc, strobj); strchars = JCALL(env,GetStringUTFChars)(strobj, NULL); TRACE("Context.getSystemService(%s) = %p\n", strchars, audMgr); JCALL(env,ReleaseStringUTFChars)(strobj, strchars); @@ -463,8 +465,8 @@ static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self) if(!sampleRate) sampleRate = device->Frequency; else sampleRate = maxu(sampleRate, MIN_OUTPUT_RATE); -#endif } +#endif if(sampleRate != device->Frequency) { diff --git a/Alc/compat.h b/Alc/compat.h index 093184c8..495bfdf2 100644 --- a/Alc/compat.h +++ b/Alc/compat.h @@ -50,14 +50,6 @@ void CloseLib(void *handle); void *GetSymbol(void *handle, const char *name); #endif -#ifdef __ANDROID__ -#define JCALL(obj, func) ((*(obj))->func((obj), EXTRACT_VCALL_ARGS -#define JCALL0(obj, func) ((*(obj))->func((obj) EXTRACT_VCALL_ARGS - -/** Returns a JNIEnv*. */ -void *Android_GetJNIEnv(void); -#endif - #ifdef __cplusplus } /* extern "C" */ #endif -- cgit v1.2.3 From 99a55c445211fea77af6ab61cbc6a6ec4fbdc9b9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 20 Feb 2019 00:22:19 -0800 Subject: Handle a missing default WASAPI device ID Backported fix from d1a86075 on master. --- Alc/backends/wasapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Alc/backends') diff --git a/Alc/backends/wasapi.c b/Alc/backends/wasapi.c index 971a1f72..b974321b 100644 --- a/Alc/backends/wasapi.c +++ b/Alc/backends/wasapi.c @@ -328,7 +328,7 @@ static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ve devid = get_device_id(device); if(devid) { - if(wcscmp(devid, defdevid) != 0) + if(!defdevid || wcscmp(devid, defdevid) != 0) add_device(device, devid, list); CoTaskMemFree(devid); } -- cgit v1.2.3