mirror of
https://github.com/love2d/megasource.git
synced 2026-08-18 19:54:37 +02:00
Updated SDL2 to the latest Mercurial revision.
This commit is contained in:
+305
-374
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -161,8 +161,16 @@ get_audio_device(SDL_AudioDeviceID id)
|
||||
|
||||
/* stubs for audio drivers that don't need a specific entry point... */
|
||||
static void
|
||||
SDL_AudioDetectDevices_Default(int iscapture, SDL_AddAudioDevice addfn)
|
||||
{ /* no-op. */
|
||||
SDL_AudioDetectDevices_Default(void)
|
||||
{
|
||||
/* you have to write your own implementation if these assertions fail. */
|
||||
SDL_assert(current_audio.impl.OnlyHasDefaultOutputDevice);
|
||||
SDL_assert(current_audio.impl.OnlyHasDefaultInputDevice || !current_audio.impl.HasCaptureSupport);
|
||||
|
||||
SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) ((size_t) 0x1));
|
||||
if (current_audio.impl.HasCaptureSupport) {
|
||||
SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, (void *) ((size_t) 0x2));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -207,10 +215,16 @@ SDL_AudioDeinitialize_Default(void)
|
||||
{ /* no-op. */
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_AudioFreeDeviceHandle_Default(void *handle)
|
||||
{ /* no-op. */
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture)
|
||||
SDL_AudioOpenDevice_Default(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
return -1;
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
static SDL_INLINE SDL_bool
|
||||
@@ -267,71 +281,139 @@ finalize_audio_entry_points(void)
|
||||
FILL_STUB(CloseDevice);
|
||||
FILL_STUB(LockDevice);
|
||||
FILL_STUB(UnlockDevice);
|
||||
FILL_STUB(FreeDeviceHandle);
|
||||
FILL_STUB(Deinitialize);
|
||||
#undef FILL_STUB
|
||||
}
|
||||
|
||||
#if 0 /* !!! FIXME: rewrite/remove this streamer code. */
|
||||
/* Streaming functions (for when the input and output buffer sizes are different) */
|
||||
/* Write [length] bytes from buf into the streamer */
|
||||
static void
|
||||
SDL_StreamWrite(SDL_AudioStreamer * stream, Uint8 * buf, int length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < length; ++i) {
|
||||
stream->buffer[stream->write_pos] = buf[i];
|
||||
++stream->write_pos;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read [length] bytes out of the streamer into buf */
|
||||
static void
|
||||
SDL_StreamRead(SDL_AudioStreamer * stream, Uint8 * buf, int length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < length; ++i) {
|
||||
buf[i] = stream->buffer[stream->read_pos];
|
||||
++stream->read_pos;
|
||||
}
|
||||
}
|
||||
/* device hotplug support... */
|
||||
|
||||
static int
|
||||
SDL_StreamLength(SDL_AudioStreamer * stream)
|
||||
add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
|
||||
{
|
||||
return (stream->write_pos - stream->read_pos) % stream->max_len;
|
||||
}
|
||||
|
||||
/* Initialize the stream by allocating the buffer and setting the read/write heads to the beginning */
|
||||
#if 0
|
||||
static int
|
||||
SDL_StreamInit(SDL_AudioStreamer * stream, int max_len, Uint8 silence)
|
||||
{
|
||||
/* First try to allocate the buffer */
|
||||
stream->buffer = (Uint8 *) SDL_malloc(max_len);
|
||||
if (stream->buffer == NULL) {
|
||||
int retval = -1;
|
||||
const size_t size = sizeof (SDL_AudioDeviceItem) + SDL_strlen(name) + 1;
|
||||
SDL_AudioDeviceItem *item = (SDL_AudioDeviceItem *) SDL_malloc(size);
|
||||
if (item == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
stream->max_len = max_len;
|
||||
stream->read_pos = 0;
|
||||
stream->write_pos = 0;
|
||||
SDL_assert(handle != NULL); /* we reserve NULL, audio backends can't use it. */
|
||||
|
||||
/* Zero out the buffer */
|
||||
SDL_memset(stream->buffer, silence, max_len);
|
||||
item->handle = handle;
|
||||
SDL_strlcpy(item->name, name, size - sizeof (SDL_AudioDeviceItem));
|
||||
|
||||
return 0;
|
||||
SDL_LockMutex(current_audio.detectionLock);
|
||||
item->next = *devices;
|
||||
*devices = item;
|
||||
retval = (*devCount)++;
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Deinitialize the stream simply by freeing the buffer */
|
||||
static void
|
||||
SDL_StreamDeinit(SDL_AudioStreamer * stream)
|
||||
static SDL_INLINE int
|
||||
add_capture_device(const char *name, void *handle)
|
||||
{
|
||||
SDL_free(stream->buffer);
|
||||
/* !!! FIXME: add this later. SDL_assert(current_audio.impl.HasCaptureSupport);*/
|
||||
return add_audio_device(name, handle, ¤t_audio.inputDevices, ¤t_audio.inputDeviceCount);
|
||||
}
|
||||
#endif
|
||||
|
||||
static SDL_INLINE int
|
||||
add_output_device(const char *name, void *handle)
|
||||
{
|
||||
return add_audio_device(name, handle, ¤t_audio.outputDevices, ¤t_audio.outputDeviceCount);
|
||||
}
|
||||
|
||||
static void
|
||||
free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
|
||||
{
|
||||
SDL_AudioDeviceItem *item, *next;
|
||||
for (item = *devices; item != NULL; item = next) {
|
||||
next = item->next;
|
||||
if (item->handle != NULL) {
|
||||
current_audio.impl.FreeDeviceHandle(item->handle);
|
||||
}
|
||||
SDL_free(item);
|
||||
}
|
||||
*devices = NULL;
|
||||
*devCount = 0;
|
||||
}
|
||||
|
||||
|
||||
/* The audio backends call this when a new device is plugged in. */
|
||||
void
|
||||
SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
|
||||
{
|
||||
const int device_index = iscapture ? add_capture_device(name, handle) : add_output_device(name, handle);
|
||||
if (device_index != -1) {
|
||||
/* Post the event, if desired */
|
||||
if (SDL_GetEventState(SDL_AUDIODEVICEADDED) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
event.adevice.type = SDL_AUDIODEVICEADDED;
|
||||
event.adevice.which = device_index;
|
||||
event.adevice.iscapture = iscapture;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The audio backends call this when a currently-opened device is lost. */
|
||||
void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
|
||||
{
|
||||
SDL_assert(get_audio_device(device->id) == device);
|
||||
|
||||
if (!device->enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ends the audio callback and mark the device as STOPPED, but the
|
||||
app still needs to close the device to free resources. */
|
||||
current_audio.impl.LockDevice(device);
|
||||
device->enabled = 0;
|
||||
current_audio.impl.UnlockDevice(device);
|
||||
|
||||
/* Post the event, if desired */
|
||||
if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
event.adevice.type = SDL_AUDIODEVICEREMOVED;
|
||||
event.adevice.which = device->id;
|
||||
event.adevice.iscapture = device->iscapture ? 1 : 0;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *removedFlag)
|
||||
{
|
||||
SDL_AudioDeviceItem *item;
|
||||
SDL_assert(handle != NULL);
|
||||
for (item = devices; item != NULL; item = item->next) {
|
||||
if (item->handle == handle) {
|
||||
item->handle = NULL;
|
||||
*removedFlag = SDL_TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The audio backends call this when a device is removed from the system. */
|
||||
void
|
||||
SDL_RemoveAudioDevice(const int iscapture, void *handle)
|
||||
{
|
||||
SDL_LockMutex(current_audio.detectionLock);
|
||||
if (iscapture) {
|
||||
mark_device_removed(handle, current_audio.inputDevices, ¤t_audio.captureDevicesRemoved);
|
||||
} else {
|
||||
mark_device_removed(handle, current_audio.outputDevices, ¤t_audio.outputDevicesRemoved);
|
||||
}
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
current_audio.impl.FreeDeviceHandle(handle);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* buffer queueing support... */
|
||||
@@ -508,26 +590,17 @@ SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
|
||||
}
|
||||
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
/* The general mixing thread function */
|
||||
int SDLCALL
|
||||
SDL_RunAudio(void *devicep)
|
||||
{
|
||||
SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
|
||||
const int silence = (int) device->spec.silence;
|
||||
const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
|
||||
const int stream_len = (device->convert.needed) ? device->convert.len : device->spec.size;
|
||||
Uint8 *stream;
|
||||
int stream_len;
|
||||
void *udata;
|
||||
void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
|
||||
Uint32 delay;
|
||||
|
||||
#if 0 /* !!! FIXME: rewrite/remove this streamer code. */
|
||||
/* For streaming when the buffer sizes don't match up */
|
||||
Uint8 *istream;
|
||||
int istream_len = 0;
|
||||
#endif
|
||||
void *udata = device->spec.userdata;
|
||||
void (SDLCALL *fill) (void *, Uint8 *, int) = device->spec.callback;
|
||||
|
||||
/* The audio mixing is always a high priority thread */
|
||||
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
|
||||
@@ -536,196 +609,59 @@ SDL_RunAudio(void *devicep)
|
||||
device->threadid = SDL_ThreadID();
|
||||
current_audio.impl.ThreadInit(device);
|
||||
|
||||
/* Set up the mixing function */
|
||||
fill = device->spec.callback;
|
||||
udata = device->spec.userdata;
|
||||
|
||||
/* By default do not stream */
|
||||
device->use_streamer = 0;
|
||||
|
||||
if (device->convert.needed) {
|
||||
#if 0 /* !!! FIXME: I took len_div out of the structure. Use rate_incr instead? */
|
||||
/* If the result of the conversion alters the length, i.e. resampling is being used, use the streamer */
|
||||
if (device->convert.len_mult != 1 || device->convert.len_div != 1) {
|
||||
/* The streamer's maximum length should be twice whichever is larger: spec.size or len_cvt */
|
||||
stream_max_len = 2 * device->spec.size;
|
||||
if (device->convert.len_mult > device->convert.len_div) {
|
||||
stream_max_len *= device->convert.len_mult;
|
||||
stream_max_len /= device->convert.len_div;
|
||||
}
|
||||
if (SDL_StreamInit(&device->streamer, stream_max_len, silence) <
|
||||
0)
|
||||
return -1;
|
||||
device->use_streamer = 1;
|
||||
|
||||
/* istream_len should be the length of what we grab from the callback and feed to conversion,
|
||||
so that we get close to spec_size. I.e. we want device.spec_size = istream_len * u / d
|
||||
*/
|
||||
istream_len =
|
||||
device->spec.size * device->convert.len_div /
|
||||
device->convert.len_mult;
|
||||
/* Loop, filling the audio buffers */
|
||||
while (!device->shutdown) {
|
||||
/* Fill the current buffer with sound */
|
||||
if (device->convert.needed) {
|
||||
stream = device->convert.buf;
|
||||
} else if (device->enabled) {
|
||||
stream = current_audio.impl.GetDeviceBuf(device);
|
||||
} else {
|
||||
/* if the device isn't enabled, we still write to the
|
||||
fake_stream, so the app's callback will fire with
|
||||
a regular frequency, in case they depend on that
|
||||
for timing or progress. They can use hotplug
|
||||
now to know if the device failed. */
|
||||
stream = NULL;
|
||||
}
|
||||
#endif
|
||||
stream_len = device->convert.len;
|
||||
} else {
|
||||
stream_len = device->spec.size;
|
||||
}
|
||||
|
||||
/* Calculate the delay while paused */
|
||||
delay = ((device->spec.samples * 1000) / device->spec.freq);
|
||||
|
||||
/* Determine if the streamer is necessary here */
|
||||
#if 0 /* !!! FIXME: rewrite/remove this streamer code. */
|
||||
if (device->use_streamer == 1) {
|
||||
/* This code is almost the same as the old code. The difference is, instead of reading
|
||||
directly from the callback into "stream", then converting and sending the audio off,
|
||||
we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device.
|
||||
However, reading and writing with streamer are done separately:
|
||||
- We only call the callback and write to the streamer when the streamer does not
|
||||
contain enough samples to output to the device.
|
||||
- We only read from the streamer and tell the device to play when the streamer
|
||||
does have enough samples to output.
|
||||
This allows us to perform resampling in the conversion step, where the output of the
|
||||
resampling process can be any number. We will have to see what a good size for the
|
||||
stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure.
|
||||
*/
|
||||
while (device->enabled) {
|
||||
|
||||
if (device->paused) {
|
||||
SDL_Delay(delay);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */
|
||||
if (SDL_StreamLength(&device->streamer) < stream_len) {
|
||||
/* Set up istream */
|
||||
if (device->convert.needed) {
|
||||
if (device->convert.buf) {
|
||||
istream = device->convert.buf;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
/* FIXME: Ryan, this is probably wrong. I imagine we don't want to get
|
||||
* a device buffer both here and below in the stream output.
|
||||
*/
|
||||
istream = current_audio.impl.GetDeviceBuf(device);
|
||||
if (istream == NULL) {
|
||||
istream = device->fake_stream;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read from the callback into the _input_ stream */
|
||||
SDL_LockMutex(device->mixer_lock);
|
||||
(*fill) (udata, istream, istream_len);
|
||||
SDL_UnlockMutex(device->mixer_lock);
|
||||
|
||||
/* Convert the audio if necessary and write to the streamer */
|
||||
if (device->convert.needed) {
|
||||
SDL_ConvertAudio(&device->convert);
|
||||
if (istream == NULL) {
|
||||
istream = device->fake_stream;
|
||||
}
|
||||
/* SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt); */
|
||||
SDL_StreamWrite(&device->streamer, device->convert.buf,
|
||||
device->convert.len_cvt);
|
||||
} else {
|
||||
SDL_StreamWrite(&device->streamer, istream, istream_len);
|
||||
}
|
||||
}
|
||||
|
||||
/* Only output audio if the streamer has enough to output */
|
||||
if (SDL_StreamLength(&device->streamer) >= stream_len) {
|
||||
/* Set up the output stream */
|
||||
if (device->convert.needed) {
|
||||
if (device->convert.buf) {
|
||||
stream = device->convert.buf;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
stream = current_audio.impl.GetDeviceBuf(device);
|
||||
if (stream == NULL) {
|
||||
stream = device->fake_stream;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now read from the streamer */
|
||||
SDL_StreamRead(&device->streamer, stream, stream_len);
|
||||
|
||||
/* Ready current buffer for play and change current buffer */
|
||||
if (stream != device->fake_stream) {
|
||||
current_audio.impl.PlayDevice(device);
|
||||
/* Wait for an audio buffer to become available */
|
||||
current_audio.impl.WaitDevice(device);
|
||||
} else {
|
||||
SDL_Delay(delay);
|
||||
}
|
||||
}
|
||||
|
||||
if (stream == NULL) {
|
||||
stream = device->fake_stream;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* Otherwise, do not use the streamer. This is the old code. */
|
||||
const int silence = (int) device->spec.silence;
|
||||
|
||||
/* Loop, filling the audio buffers */
|
||||
while (device->enabled) {
|
||||
/* !!! FIXME: this should be LockDevice. */
|
||||
SDL_LockMutex(device->mixer_lock);
|
||||
if (device->paused) {
|
||||
SDL_memset(stream, silence, stream_len);
|
||||
} else {
|
||||
(*fill) (udata, stream, stream_len);
|
||||
}
|
||||
SDL_UnlockMutex(device->mixer_lock);
|
||||
|
||||
/* Fill the current buffer with sound */
|
||||
if (device->convert.needed) {
|
||||
if (device->convert.buf) {
|
||||
stream = device->convert.buf;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
/* Convert the audio if necessary */
|
||||
if (device->enabled && device->convert.needed) {
|
||||
SDL_ConvertAudio(&device->convert);
|
||||
stream = current_audio.impl.GetDeviceBuf(device);
|
||||
if (stream == NULL) {
|
||||
stream = device->fake_stream;
|
||||
} else {
|
||||
stream = current_audio.impl.GetDeviceBuf(device);
|
||||
if (stream == NULL) {
|
||||
stream = device->fake_stream;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_LockMutex(device->mixer_lock);
|
||||
if (device->paused) {
|
||||
SDL_memset(stream, silence, stream_len);
|
||||
} else {
|
||||
(*fill) (udata, stream, stream_len);
|
||||
}
|
||||
SDL_UnlockMutex(device->mixer_lock);
|
||||
|
||||
/* Convert the audio if necessary */
|
||||
if (device->convert.needed) {
|
||||
SDL_ConvertAudio(&device->convert);
|
||||
stream = current_audio.impl.GetDeviceBuf(device);
|
||||
if (stream == NULL) {
|
||||
stream = device->fake_stream;
|
||||
}
|
||||
SDL_memcpy(stream, device->convert.buf,
|
||||
device->convert.len_cvt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Ready current buffer for play and change current buffer */
|
||||
if (stream != device->fake_stream) {
|
||||
current_audio.impl.PlayDevice(device);
|
||||
/* Wait for an audio buffer to become available */
|
||||
current_audio.impl.WaitDevice(device);
|
||||
} else {
|
||||
SDL_Delay(delay);
|
||||
}
|
||||
/* Ready current buffer for play and change current buffer */
|
||||
if (stream == device->fake_stream) {
|
||||
SDL_Delay(delay);
|
||||
} else {
|
||||
current_audio.impl.PlayDevice(device);
|
||||
current_audio.impl.WaitDevice(device);
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for the audio to drain.. */
|
||||
/* Wait for the audio to drain. */
|
||||
current_audio.impl.WaitDone(device);
|
||||
|
||||
/* If necessary, deinit the streamer */
|
||||
#if 0 /* !!! FIXME: rewrite/remove this streamer code. */
|
||||
if (device->use_streamer == 1)
|
||||
SDL_StreamDeinit(&device->streamer);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -782,8 +718,8 @@ SDL_AudioInit(const char *driver_name)
|
||||
SDL_AudioQuit(); /* shutdown driver if already running. */
|
||||
}
|
||||
|
||||
SDL_memset(¤t_audio, '\0', sizeof(current_audio));
|
||||
SDL_memset(open_devices, '\0', sizeof(open_devices));
|
||||
SDL_zero(current_audio);
|
||||
SDL_zero(open_devices);
|
||||
|
||||
/* Select the proper audio driver */
|
||||
if (driver_name == NULL) {
|
||||
@@ -799,7 +735,7 @@ SDL_AudioInit(const char *driver_name)
|
||||
}
|
||||
|
||||
tried_to_init = 1;
|
||||
SDL_memset(¤t_audio, 0, sizeof(current_audio));
|
||||
SDL_zero(current_audio);
|
||||
current_audio.name = backend->name;
|
||||
current_audio.desc = backend->desc;
|
||||
initialized = backend->init(¤t_audio.impl);
|
||||
@@ -815,12 +751,17 @@ SDL_AudioInit(const char *driver_name)
|
||||
}
|
||||
}
|
||||
|
||||
SDL_memset(¤t_audio, 0, sizeof(current_audio));
|
||||
SDL_zero(current_audio);
|
||||
return -1; /* No driver was available, so fail. */
|
||||
}
|
||||
|
||||
current_audio.detectionLock = SDL_CreateMutex();
|
||||
|
||||
finalize_audio_entry_points();
|
||||
|
||||
/* Make sure we have a list of devices available at startup. */
|
||||
current_audio.impl.DetectDevices();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -833,50 +774,32 @@ SDL_GetCurrentAudioDriver()
|
||||
return current_audio.name;
|
||||
}
|
||||
|
||||
/* Clean out devices that we've removed but had to keep around for stability. */
|
||||
static void
|
||||
free_device_list(char ***devices, int *devCount)
|
||||
clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *removedFlag)
|
||||
{
|
||||
int i = *devCount;
|
||||
if ((i > 0) && (*devices != NULL)) {
|
||||
while (i--) {
|
||||
SDL_free((*devices)[i]);
|
||||
SDL_AudioDeviceItem *item = *devices;
|
||||
SDL_AudioDeviceItem *prev = NULL;
|
||||
int total = 0;
|
||||
|
||||
while (item) {
|
||||
SDL_AudioDeviceItem *next = item->next;
|
||||
if (item->handle != NULL) {
|
||||
total++;
|
||||
prev = item;
|
||||
} else {
|
||||
if (prev) {
|
||||
prev->next = next;
|
||||
} else {
|
||||
*devices = next;
|
||||
}
|
||||
SDL_free(item);
|
||||
}
|
||||
item = next;
|
||||
}
|
||||
|
||||
SDL_free(*devices);
|
||||
|
||||
*devices = NULL;
|
||||
*devCount = 0;
|
||||
}
|
||||
|
||||
static
|
||||
void SDL_AddCaptureAudioDevice(const char *_name)
|
||||
{
|
||||
char *name = NULL;
|
||||
void *ptr = SDL_realloc(current_audio.inputDevices,
|
||||
(current_audio.inputDeviceCount+1) * sizeof(char*));
|
||||
if (ptr == NULL) {
|
||||
return; /* oh well. */
|
||||
}
|
||||
|
||||
current_audio.inputDevices = (char **) ptr;
|
||||
name = SDL_strdup(_name); /* if this returns NULL, that's okay. */
|
||||
current_audio.inputDevices[current_audio.inputDeviceCount++] = name;
|
||||
}
|
||||
|
||||
static
|
||||
void SDL_AddOutputAudioDevice(const char *_name)
|
||||
{
|
||||
char *name = NULL;
|
||||
void *ptr = SDL_realloc(current_audio.outputDevices,
|
||||
(current_audio.outputDeviceCount+1) * sizeof(char*));
|
||||
if (ptr == NULL) {
|
||||
return; /* oh well. */
|
||||
}
|
||||
|
||||
current_audio.outputDevices = (char **) ptr;
|
||||
name = SDL_strdup(_name); /* if this returns NULL, that's okay. */
|
||||
current_audio.outputDevices[current_audio.outputDeviceCount++] = name;
|
||||
*devCount = total;
|
||||
*removedFlag = SDL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
@@ -889,29 +812,18 @@ SDL_GetNumAudioDevices(int iscapture)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
|
||||
return 0;
|
||||
SDL_LockMutex(current_audio.detectionLock);
|
||||
if (iscapture && current_audio.captureDevicesRemoved) {
|
||||
clean_out_device_list(¤t_audio.inputDevices, ¤t_audio.inputDeviceCount, ¤t_audio.captureDevicesRemoved);
|
||||
}
|
||||
|
||||
if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
|
||||
return 1;
|
||||
if (!iscapture && current_audio.outputDevicesRemoved) {
|
||||
clean_out_device_list(¤t_audio.outputDevices, ¤t_audio.outputDeviceCount, ¤t_audio.outputDevicesRemoved);
|
||||
current_audio.outputDevicesRemoved = SDL_FALSE;
|
||||
}
|
||||
|
||||
if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (iscapture) {
|
||||
free_device_list(¤t_audio.inputDevices,
|
||||
¤t_audio.inputDeviceCount);
|
||||
current_audio.impl.DetectDevices(iscapture, SDL_AddCaptureAudioDevice);
|
||||
retval = current_audio.inputDeviceCount;
|
||||
} else {
|
||||
free_device_list(¤t_audio.outputDevices,
|
||||
¤t_audio.outputDeviceCount);
|
||||
current_audio.impl.DetectDevices(iscapture, SDL_AddOutputAudioDevice);
|
||||
retval = current_audio.outputDeviceCount;
|
||||
}
|
||||
retval = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
|
||||
return retval;
|
||||
}
|
||||
@@ -920,6 +832,8 @@ SDL_GetNumAudioDevices(int iscapture)
|
||||
const char *
|
||||
SDL_GetAudioDeviceName(int index, int iscapture)
|
||||
{
|
||||
const char *retval = NULL;
|
||||
|
||||
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
|
||||
SDL_SetError("Audio subsystem is not initialized");
|
||||
return NULL;
|
||||
@@ -930,39 +844,28 @@ SDL_GetAudioDeviceName(int index, int iscapture)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (index < 0) {
|
||||
goto no_such_device;
|
||||
if (index >= 0) {
|
||||
SDL_AudioDeviceItem *item;
|
||||
int i;
|
||||
|
||||
SDL_LockMutex(current_audio.detectionLock);
|
||||
item = iscapture ? current_audio.inputDevices : current_audio.outputDevices;
|
||||
i = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
|
||||
if (index < i) {
|
||||
for (i--; i > index; i--, item = item->next) {
|
||||
SDL_assert(item != NULL);
|
||||
}
|
||||
SDL_assert(item != NULL);
|
||||
retval = item->name;
|
||||
}
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
}
|
||||
|
||||
if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
|
||||
if (index > 0) {
|
||||
goto no_such_device;
|
||||
}
|
||||
return DEFAULT_INPUT_DEVNAME;
|
||||
if (retval == NULL) {
|
||||
SDL_SetError("No such device");
|
||||
}
|
||||
|
||||
if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
|
||||
if (index > 0) {
|
||||
goto no_such_device;
|
||||
}
|
||||
return DEFAULT_OUTPUT_DEVNAME;
|
||||
}
|
||||
|
||||
if (iscapture) {
|
||||
if (index >= current_audio.inputDeviceCount) {
|
||||
goto no_such_device;
|
||||
}
|
||||
return current_audio.inputDevices[index];
|
||||
} else {
|
||||
if (index >= current_audio.outputDeviceCount) {
|
||||
goto no_such_device;
|
||||
}
|
||||
return current_audio.outputDevices[index];
|
||||
}
|
||||
|
||||
no_such_device:
|
||||
SDL_SetError("No such device");
|
||||
return NULL;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
@@ -970,6 +873,7 @@ static void
|
||||
close_audio_device(SDL_AudioDevice * device)
|
||||
{
|
||||
device->enabled = 0;
|
||||
device->shutdown = 1;
|
||||
if (device->thread != NULL) {
|
||||
SDL_WaitThread(device->thread, NULL);
|
||||
}
|
||||
@@ -1063,6 +967,8 @@ open_audio_device(const char *devname, int iscapture,
|
||||
SDL_AudioSpec _obtained;
|
||||
SDL_AudioDevice *device;
|
||||
SDL_bool build_cvt;
|
||||
void *handle = NULL;
|
||||
Uint32 stream_len;
|
||||
int i = 0;
|
||||
|
||||
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
|
||||
@@ -1075,6 +981,18 @@ open_audio_device(const char *devname, int iscapture,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find an available device ID... */
|
||||
for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
|
||||
if (open_devices[id] == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (id == SDL_arraysize(open_devices)) {
|
||||
SDL_SetError("Too many open audio devices");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!obtained) {
|
||||
obtained = &_obtained;
|
||||
}
|
||||
@@ -1110,9 +1028,7 @@ open_audio_device(const char *devname, int iscapture,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
|
||||
} else if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
|
||||
if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
|
||||
SDL_SetError("No such device");
|
||||
return 0;
|
||||
@@ -1125,6 +1041,30 @@ open_audio_device(const char *devname, int iscapture,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else if (devname != NULL) {
|
||||
/* if the app specifies an exact string, we can pass the backend
|
||||
an actual device handle thingey, which saves them the effort of
|
||||
figuring out what device this was (such as, reenumerating
|
||||
everything again to find the matching human-readable name).
|
||||
It might still need to open a device based on the string for,
|
||||
say, a network audio server, but this optimizes some cases. */
|
||||
SDL_AudioDeviceItem *item;
|
||||
SDL_LockMutex(current_audio.detectionLock);
|
||||
for (item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; item; item = item->next) {
|
||||
if ((item->handle != NULL) && (SDL_strcmp(item->name, devname) == 0)) {
|
||||
handle = item->handle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
}
|
||||
|
||||
if (!current_audio.impl.AllowsArbitraryDeviceNames) {
|
||||
/* has to be in our device list, or the default device. */
|
||||
if ((handle == NULL) && (devname != NULL)) {
|
||||
SDL_SetError("No such device.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof(SDL_AudioDevice));
|
||||
@@ -1133,12 +1073,13 @@ open_audio_device(const char *devname, int iscapture,
|
||||
return 0;
|
||||
}
|
||||
SDL_zerop(device);
|
||||
device->id = id + 1;
|
||||
device->spec = *obtained;
|
||||
device->enabled = 1;
|
||||
device->paused = 1;
|
||||
device->iscapture = iscapture;
|
||||
|
||||
/* Create a semaphore for locking the sound buffers */
|
||||
/* Create a mutex for locking the sound buffers */
|
||||
if (!current_audio.impl.SkipMixerLock) {
|
||||
device->mixer_lock = SDL_CreateMutex();
|
||||
if (device->mixer_lock == NULL) {
|
||||
@@ -1148,26 +1089,12 @@ open_audio_device(const char *devname, int iscapture,
|
||||
}
|
||||
}
|
||||
|
||||
/* force a device detection if we haven't done one yet. */
|
||||
if ( ((iscapture) && (current_audio.inputDevices == NULL)) ||
|
||||
((!iscapture) && (current_audio.outputDevices == NULL)) ) {
|
||||
SDL_GetNumAudioDevices(iscapture);
|
||||
}
|
||||
|
||||
if (current_audio.impl.OpenDevice(device, devname, iscapture) < 0) {
|
||||
if (current_audio.impl.OpenDevice(device, handle, devname, iscapture) < 0) {
|
||||
close_audio_device(device);
|
||||
return 0;
|
||||
}
|
||||
device->opened = 1;
|
||||
|
||||
/* Allocate a fake audio memory buffer */
|
||||
device->fake_stream = (Uint8 *)SDL_AllocAudioMem(device->spec.size);
|
||||
if (device->fake_stream == NULL) {
|
||||
close_audio_device(device);
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See if we need to do any conversion */
|
||||
build_cvt = SDL_FALSE;
|
||||
if (obtained->freq != device->spec.freq) {
|
||||
@@ -1226,6 +1153,19 @@ open_audio_device(const char *devname, int iscapture,
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate a fake audio memory buffer */
|
||||
stream_len = (device->convert.needed) ? device->convert.len_cvt : 0;
|
||||
if (device->spec.size > stream_len) {
|
||||
stream_len = device->spec.size;
|
||||
}
|
||||
SDL_assert(stream_len > 0);
|
||||
device->fake_stream = (Uint8 *)SDL_AllocAudioMem(stream_len);
|
||||
if (device->fake_stream == NULL) {
|
||||
close_audio_device(device);
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (device->spec.callback == NULL) { /* use buffer queueing? */
|
||||
/* pool a few packets to start. Enough for two callbacks. */
|
||||
const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN;
|
||||
@@ -1245,25 +1185,14 @@ open_audio_device(const char *devname, int iscapture,
|
||||
device->spec.userdata = device;
|
||||
}
|
||||
|
||||
/* Find an available device ID and store the structure... */
|
||||
for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
|
||||
if (open_devices[id] == NULL) {
|
||||
open_devices[id] = device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (id == SDL_arraysize(open_devices)) {
|
||||
SDL_SetError("Too many open audio devices");
|
||||
close_audio_device(device);
|
||||
return 0;
|
||||
}
|
||||
/* add it to our list of open devices. */
|
||||
open_devices[id] = device;
|
||||
|
||||
/* Start the audio thread if necessary */
|
||||
if (!current_audio.impl.ProvidesOwnCallbackThread) {
|
||||
/* Start the audio thread */
|
||||
char name[64];
|
||||
SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) (id + 1));
|
||||
SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) device->id);
|
||||
/* !!! FIXME: this is nasty. */
|
||||
#if defined(__WIN32__) && !defined(HAVE_LIBC)
|
||||
#undef SDL_CreateThread
|
||||
@@ -1276,13 +1205,13 @@ open_audio_device(const char *devname, int iscapture,
|
||||
device->thread = SDL_CreateThread(SDL_RunAudio, name, device);
|
||||
#endif
|
||||
if (device->thread == NULL) {
|
||||
SDL_CloseAudioDevice(id + 1);
|
||||
SDL_CloseAudioDevice(device->id);
|
||||
SDL_SetError("Couldn't create audio thread");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return id + 1;
|
||||
return device->id;
|
||||
}
|
||||
|
||||
|
||||
@@ -1427,14 +1356,16 @@ SDL_AudioQuit(void)
|
||||
}
|
||||
}
|
||||
|
||||
free_device_list(¤t_audio.outputDevices, ¤t_audio.outputDeviceCount);
|
||||
free_device_list(¤t_audio.inputDevices, ¤t_audio.inputDeviceCount);
|
||||
|
||||
/* Free the driver data */
|
||||
current_audio.impl.Deinitialize();
|
||||
free_device_list(¤t_audio.outputDevices,
|
||||
¤t_audio.outputDeviceCount);
|
||||
free_device_list(¤t_audio.inputDevices,
|
||||
¤t_audio.inputDeviceCount);
|
||||
SDL_memset(¤t_audio, '\0', sizeof(current_audio));
|
||||
SDL_memset(open_devices, '\0', sizeof(open_devices));
|
||||
|
||||
SDL_DestroyMutex(current_audio.detectionLock);
|
||||
|
||||
SDL_zero(current_audio);
|
||||
SDL_zero(open_devices);
|
||||
}
|
||||
|
||||
#define NUM_FORMATS 10
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -46,18 +46,21 @@
|
||||
#define _PATH_DEV_AUDIO "/dev/audio"
|
||||
#endif
|
||||
|
||||
static SDL_INLINE void
|
||||
test_device(const char *fname, int flags, int (*test) (int fd),
|
||||
SDL_AddAudioDevice addfn)
|
||||
static void
|
||||
test_device(const int iscapture, const char *fname, int flags, int (*test) (int fd))
|
||||
{
|
||||
struct stat sb;
|
||||
if ((stat(fname, &sb) == 0) && (S_ISCHR(sb.st_mode))) {
|
||||
const int audio_fd = open(fname, flags, 0);
|
||||
if (audio_fd >= 0) {
|
||||
if (test(audio_fd)) {
|
||||
addfn(fname);
|
||||
}
|
||||
const int okay = test(audio_fd);
|
||||
close(audio_fd);
|
||||
if (okay) {
|
||||
static size_t dummyhandle = 0;
|
||||
dummyhandle++;
|
||||
SDL_assert(dummyhandle != 0);
|
||||
SDL_AddAudioDevice(iscapture, fname, (void *) dummyhandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,11 +71,10 @@ test_stub(int fd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_EnumUnixAudioDevices(int iscapture, int classic, int (*test)(int fd),
|
||||
SDL_AddAudioDevice addfn)
|
||||
static void
|
||||
SDL_EnumUnixAudioDevices_Internal(const int iscapture, const int classic, int (*test)(int))
|
||||
{
|
||||
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
|
||||
const int flags = iscapture ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT;
|
||||
const char *audiodev;
|
||||
char audiopath[1024];
|
||||
|
||||
@@ -97,17 +99,25 @@ SDL_EnumUnixAudioDevices(int iscapture, int classic, int (*test)(int fd),
|
||||
}
|
||||
}
|
||||
}
|
||||
test_device(audiodev, flags, test, addfn);
|
||||
test_device(iscapture, audiodev, flags, test);
|
||||
|
||||
if (SDL_strlen(audiodev) < (sizeof(audiopath) - 3)) {
|
||||
int instance = 0;
|
||||
while (instance++ <= 64) {
|
||||
SDL_snprintf(audiopath, SDL_arraysize(audiopath),
|
||||
"%s%d", audiodev, instance);
|
||||
test_device(audiopath, flags, test, addfn);
|
||||
test_device(iscapture, audiopath, flags, test);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_EnumUnixAudioDevices(const int classic, int (*test)(int))
|
||||
{
|
||||
SDL_EnumUnixAudioDevices_Internal(SDL_TRUE, classic, test);
|
||||
SDL_EnumUnixAudioDevices_Internal(SDL_FALSE, classic, test);
|
||||
}
|
||||
|
||||
#endif /* Audio driver selection */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -33,7 +33,6 @@
|
||||
#define OPEN_FLAGS_INPUT (O_RDONLY|O_NONBLOCK)
|
||||
#endif
|
||||
|
||||
void SDL_EnumUnixAudioDevices(int iscapture, int classic,
|
||||
int (*test) (int fd), SDL_AddAudioDevice addfn);
|
||||
extern void SDL_EnumUnixAudioDevices(const int classic, int (*test)(int));
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* DO NOT EDIT! This file is generated by sdlgenaudiocvt.pl */
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -30,8 +30,21 @@
|
||||
typedef struct SDL_AudioDevice SDL_AudioDevice;
|
||||
#define _THIS SDL_AudioDevice *_this
|
||||
|
||||
/* Used by audio targets during DetectDevices() */
|
||||
typedef void (*SDL_AddAudioDevice)(const char *name);
|
||||
/* Audio targets should call this as devices are added to the system (such as
|
||||
a USB headset being plugged in), and should also be called for
|
||||
for every device found during DetectDevices(). */
|
||||
extern void SDL_AddAudioDevice(const int iscapture, const char *name, void *handle);
|
||||
|
||||
/* Audio targets should call this as devices are removed, so SDL can update
|
||||
its list of available devices. */
|
||||
extern void SDL_RemoveAudioDevice(const int iscapture, void *handle);
|
||||
|
||||
/* Audio targets should call this if an opened audio device is lost while
|
||||
being used. This can happen due to i/o errors, or a device being unplugged,
|
||||
etc. If the device is totally gone, please also call SDL_RemoveAudioDevice()
|
||||
as appropriate so SDL's list of devices is accurate. */
|
||||
extern void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device);
|
||||
|
||||
|
||||
/* This is the size of a packet when using SDL_QueueAudio(). We allocate
|
||||
these as necessary and pool them, under the assumption that we'll
|
||||
@@ -55,8 +68,8 @@ typedef struct SDL_AudioBufferQueue
|
||||
|
||||
typedef struct SDL_AudioDriverImpl
|
||||
{
|
||||
void (*DetectDevices) (int iscapture, SDL_AddAudioDevice addfn);
|
||||
int (*OpenDevice) (_THIS, const char *devname, int iscapture);
|
||||
void (*DetectDevices) (void);
|
||||
int (*OpenDevice) (_THIS, void *handle, const char *devname, int iscapture);
|
||||
void (*ThreadInit) (_THIS); /* Called by audio thread at start */
|
||||
void (*WaitDevice) (_THIS);
|
||||
void (*PlayDevice) (_THIS);
|
||||
@@ -66,19 +79,34 @@ typedef struct SDL_AudioDriverImpl
|
||||
void (*CloseDevice) (_THIS);
|
||||
void (*LockDevice) (_THIS);
|
||||
void (*UnlockDevice) (_THIS);
|
||||
void (*FreeDeviceHandle) (void *handle); /**< SDL is done with handle from SDL_AddAudioDevice() */
|
||||
void (*Deinitialize) (void);
|
||||
|
||||
/* !!! FIXME: add pause(), so we can optimize instead of mixing silence. */
|
||||
|
||||
/* Some flags to push duplicate code into the core and reduce #ifdefs. */
|
||||
/* !!! FIXME: these should be SDL_bool */
|
||||
int ProvidesOwnCallbackThread;
|
||||
int SkipMixerLock; /* !!! FIXME: do we need this anymore? */
|
||||
int HasCaptureSupport;
|
||||
int OnlyHasDefaultOutputDevice;
|
||||
int OnlyHasDefaultInputDevice;
|
||||
int AllowsArbitraryDeviceNames;
|
||||
} SDL_AudioDriverImpl;
|
||||
|
||||
|
||||
typedef struct SDL_AudioDeviceItem
|
||||
{
|
||||
void *handle;
|
||||
struct SDL_AudioDeviceItem *next;
|
||||
#if (defined(__GNUC__) && (__GNUC__ <= 2))
|
||||
char name[1]; /* actually variable length. */
|
||||
#else
|
||||
char name[];
|
||||
#endif
|
||||
} SDL_AudioDeviceItem;
|
||||
|
||||
|
||||
typedef struct SDL_AudioDriver
|
||||
{
|
||||
/* * * */
|
||||
@@ -91,11 +119,14 @@ typedef struct SDL_AudioDriver
|
||||
|
||||
SDL_AudioDriverImpl impl;
|
||||
|
||||
char **outputDevices;
|
||||
/* A mutex for device detection */
|
||||
SDL_mutex *detectionLock;
|
||||
SDL_bool captureDevicesRemoved;
|
||||
SDL_bool outputDevicesRemoved;
|
||||
int outputDeviceCount;
|
||||
|
||||
char **inputDevices;
|
||||
int inputDeviceCount;
|
||||
SDL_AudioDeviceItem *outputDevices;
|
||||
SDL_AudioDeviceItem *inputDevices;
|
||||
} SDL_AudioDriver;
|
||||
|
||||
|
||||
@@ -113,6 +144,7 @@ struct SDL_AudioDevice
|
||||
{
|
||||
/* * * */
|
||||
/* Data common to all devices */
|
||||
SDL_AudioDeviceID id;
|
||||
|
||||
/* The current audio specification (shared with audio thread) */
|
||||
SDL_AudioSpec spec;
|
||||
@@ -125,15 +157,17 @@ struct SDL_AudioDevice
|
||||
SDL_AudioStreamer streamer;
|
||||
|
||||
/* Current state flags */
|
||||
/* !!! FIXME: should be SDL_bool */
|
||||
int iscapture;
|
||||
int enabled;
|
||||
int enabled; /* true if device is functioning and connected. */
|
||||
int shutdown; /* true if we are signaling the play thread to end. */
|
||||
int paused;
|
||||
int opened;
|
||||
|
||||
/* Fake audio buffer for when the audio hardware is busy */
|
||||
Uint8 *fake_stream;
|
||||
|
||||
/* A semaphore for locking the mixing buffers */
|
||||
/* A mutex for locking the mixing buffers */
|
||||
SDL_mutex *mixer_lock;
|
||||
|
||||
/* A thread to feed the audio device */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -320,7 +320,7 @@ ALSA_PlayDevice(_THIS)
|
||||
/* Hmm, not much we can do - abort */
|
||||
fprintf(stderr, "ALSA write failed (unrecoverable): %s\n",
|
||||
ALSA_snd_strerror(status));
|
||||
this->enabled = 0;
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
@@ -465,7 +465,7 @@ ALSA_set_buffer_size(_THIS, snd_pcm_hw_params_t *params, int override)
|
||||
}
|
||||
|
||||
static int
|
||||
ALSA_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
int status = 0;
|
||||
snd_pcm_t *pcm_handle = NULL;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -35,7 +35,7 @@
|
||||
static SDL_AudioDevice* audioDevice = NULL;
|
||||
|
||||
static int
|
||||
AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
AndroidAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
SDL_AudioFormat test_format;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -151,7 +151,7 @@ ARTS_WaitDevice(_THIS)
|
||||
/* Check every 10 loops */
|
||||
if (this->hidden->parent && (((++cnt) % 10) == 0)) {
|
||||
if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) {
|
||||
this->enabled = 0;
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,7 +179,7 @@ ARTS_PlayDevice(_THIS)
|
||||
|
||||
/* If we couldn't write, assume fatal error for now */
|
||||
if (written < 0) {
|
||||
this->enabled = 0;
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
|
||||
@@ -229,7 +229,7 @@ ARTS_Suspend(void)
|
||||
}
|
||||
|
||||
static int
|
||||
ARTS_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
ARTS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
int rc = 0;
|
||||
int bits = 0, frag_spec = 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -51,9 +51,9 @@
|
||||
|
||||
|
||||
static void
|
||||
BSDAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
|
||||
BSDAUDIO_DetectDevices(void)
|
||||
{
|
||||
SDL_EnumUnixAudioDevices(iscapture, 0, NULL, addfn);
|
||||
SDL_EnumUnixAudioDevices(0, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ BSDAUDIO_WaitDevice(_THIS)
|
||||
the user know what happened.
|
||||
*/
|
||||
fprintf(stderr, "SDL: %s\n", message);
|
||||
this->enabled = 0;
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
/* Don't try to close - may hang */
|
||||
this->hidden->audio_fd = -1;
|
||||
#ifdef DEBUG_AUDIO
|
||||
@@ -195,7 +195,7 @@ BSDAUDIO_PlayDevice(_THIS)
|
||||
|
||||
/* If we couldn't write, assume fatal error for now */
|
||||
if (written < 0) {
|
||||
this->enabled = 0;
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
|
||||
@@ -224,7 +224,7 @@ BSDAUDIO_CloseDevice(_THIS)
|
||||
}
|
||||
|
||||
static int
|
||||
BSDAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
|
||||
SDL_AudioFormat format = 0;
|
||||
@@ -348,6 +348,8 @@ BSDAUDIO_Init(SDL_AudioDriverImpl * impl)
|
||||
impl->GetDeviceBuf = BSDAUDIO_GetDeviceBuf;
|
||||
impl->CloseDevice = BSDAUDIO_CloseDevice;
|
||||
|
||||
impl->AllowsArbitraryDeviceNames = 1;
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -40,31 +40,48 @@ static void COREAUDIO_CloseDevice(_THIS);
|
||||
}
|
||||
|
||||
#if MACOSX_COREAUDIO
|
||||
typedef void (*addDevFn)(const char *name, AudioDeviceID devId, void *data);
|
||||
static const AudioObjectPropertyAddress devlist_address = {
|
||||
kAudioHardwarePropertyDevices,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
static void
|
||||
addToDevList(const char *name, AudioDeviceID devId, void *data)
|
||||
typedef void (*addDevFn)(const char *name, const int iscapture, AudioDeviceID devId, void *data);
|
||||
|
||||
typedef struct AudioDeviceList
|
||||
{
|
||||
SDL_AddAudioDevice addfn = (SDL_AddAudioDevice) data;
|
||||
addfn(name);
|
||||
AudioDeviceID devid;
|
||||
SDL_bool alive;
|
||||
struct AudioDeviceList *next;
|
||||
} AudioDeviceList;
|
||||
|
||||
static AudioDeviceList *output_devs = NULL;
|
||||
static AudioDeviceList *capture_devs = NULL;
|
||||
|
||||
static SDL_bool
|
||||
add_to_internal_dev_list(const int iscapture, AudioDeviceID devId)
|
||||
{
|
||||
AudioDeviceList *item = (AudioDeviceList *) SDL_malloc(sizeof (AudioDeviceList));
|
||||
if (item == NULL) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
item->devid = devId;
|
||||
item->alive = SDL_TRUE;
|
||||
item->next = iscapture ? capture_devs : output_devs;
|
||||
if (iscapture) {
|
||||
capture_devs = item;
|
||||
} else {
|
||||
output_devs = item;
|
||||
}
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *findname;
|
||||
AudioDeviceID devId;
|
||||
int found;
|
||||
} FindDevIdData;
|
||||
|
||||
static void
|
||||
findDevId(const char *name, AudioDeviceID devId, void *_data)
|
||||
addToDevList(const char *name, const int iscapture, AudioDeviceID devId, void *data)
|
||||
{
|
||||
FindDevIdData *data = (FindDevIdData *) _data;
|
||||
if (!data->found) {
|
||||
if (SDL_strcmp(name, data->findname) == 0) {
|
||||
data->found = 1;
|
||||
data->devId = devId;
|
||||
}
|
||||
if (add_to_internal_dev_list(iscapture, devId)) {
|
||||
SDL_AddAudioDevice(iscapture, name, (void *) ((size_t) devId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,14 +94,8 @@ build_device_list(int iscapture, addDevFn addfn, void *addfndata)
|
||||
UInt32 i = 0;
|
||||
UInt32 max = 0;
|
||||
|
||||
AudioObjectPropertyAddress addr = {
|
||||
kAudioHardwarePropertyDevices,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
result = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &addr,
|
||||
0, NULL, &size);
|
||||
result = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject,
|
||||
&devlist_address, 0, NULL, &size);
|
||||
if (result != kAudioHardwareNoError)
|
||||
return;
|
||||
|
||||
@@ -92,8 +103,8 @@ build_device_list(int iscapture, addDevFn addfn, void *addfndata)
|
||||
if (devs == NULL)
|
||||
return;
|
||||
|
||||
result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr,
|
||||
0, NULL, &size, devs);
|
||||
result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
||||
&devlist_address, 0, NULL, &size, devs);
|
||||
if (result != kAudioHardwareNoError)
|
||||
return;
|
||||
|
||||
@@ -105,10 +116,17 @@ build_device_list(int iscapture, addDevFn addfn, void *addfndata)
|
||||
AudioBufferList *buflist = NULL;
|
||||
int usable = 0;
|
||||
CFIndex len = 0;
|
||||
const AudioObjectPropertyAddress addr = {
|
||||
kAudioDevicePropertyStreamConfiguration,
|
||||
iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
addr.mScope = iscapture ? kAudioDevicePropertyScopeInput :
|
||||
kAudioDevicePropertyScopeOutput;
|
||||
addr.mSelector = kAudioDevicePropertyStreamConfiguration;
|
||||
const AudioObjectPropertyAddress nameaddr = {
|
||||
kAudioObjectPropertyName,
|
||||
iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
result = AudioObjectGetPropertyDataSize(dev, &addr, 0, NULL, &size);
|
||||
if (result != noErr)
|
||||
@@ -136,9 +154,9 @@ build_device_list(int iscapture, addDevFn addfn, void *addfndata)
|
||||
if (!usable)
|
||||
continue;
|
||||
|
||||
addr.mSelector = kAudioObjectPropertyName;
|
||||
|
||||
size = sizeof (CFStringRef);
|
||||
result = AudioObjectGetPropertyData(dev, &addr, 0, NULL, &size, &cfstr);
|
||||
result = AudioObjectGetPropertyData(dev, &nameaddr, 0, NULL, &size, &cfstr);
|
||||
if (result != kAudioHardwareNoError)
|
||||
continue;
|
||||
|
||||
@@ -169,79 +187,84 @@ build_device_list(int iscapture, addDevFn addfn, void *addfndata)
|
||||
((iscapture) ? "capture" : "output"),
|
||||
(int) *devCount, ptr, (int) dev);
|
||||
#endif
|
||||
addfn(ptr, dev, addfndata);
|
||||
addfn(ptr, iscapture, dev, addfndata);
|
||||
}
|
||||
SDL_free(ptr); /* addfn() would have copied the string. */
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
COREAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
|
||||
free_audio_device_list(AudioDeviceList **list)
|
||||
{
|
||||
build_device_list(iscapture, addToDevList, addfn);
|
||||
AudioDeviceList *item = *list;
|
||||
while (item) {
|
||||
AudioDeviceList *next = item->next;
|
||||
SDL_free(item);
|
||||
item = next;
|
||||
}
|
||||
*list = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
find_device_by_name(_THIS, const char *devname, int iscapture)
|
||||
static void
|
||||
COREAUDIO_DetectDevices(void)
|
||||
{
|
||||
AudioDeviceID devid = 0;
|
||||
OSStatus result = noErr;
|
||||
UInt32 size = 0;
|
||||
UInt32 alive = 0;
|
||||
pid_t pid = 0;
|
||||
build_device_list(SDL_TRUE, addToDevList, NULL);
|
||||
build_device_list(SDL_FALSE, addToDevList, NULL);
|
||||
}
|
||||
|
||||
AudioObjectPropertyAddress addr = {
|
||||
0,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
if (devname == NULL) {
|
||||
size = sizeof (AudioDeviceID);
|
||||
addr.mSelector =
|
||||
((iscapture) ? kAudioHardwarePropertyDefaultInputDevice :
|
||||
kAudioHardwarePropertyDefaultOutputDevice);
|
||||
result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr,
|
||||
0, NULL, &size, &devid);
|
||||
CHECK_RESULT("AudioHardwareGetProperty (default device)");
|
||||
} else {
|
||||
FindDevIdData data;
|
||||
SDL_zero(data);
|
||||
data.findname = devname;
|
||||
build_device_list(iscapture, findDevId, &data);
|
||||
if (!data.found) {
|
||||
SDL_SetError("CoreAudio: No such audio device.");
|
||||
return 0;
|
||||
static void
|
||||
build_device_change_list(const char *name, const int iscapture, AudioDeviceID devId, void *data)
|
||||
{
|
||||
AudioDeviceList **list = (AudioDeviceList **) data;
|
||||
AudioDeviceList *item;
|
||||
for (item = *list; item != NULL; item = item->next) {
|
||||
if (item->devid == devId) {
|
||||
item->alive = SDL_TRUE;
|
||||
return;
|
||||
}
|
||||
devid = data.devId;
|
||||
}
|
||||
|
||||
addr.mSelector = kAudioDevicePropertyDeviceIsAlive;
|
||||
addr.mScope = iscapture ? kAudioDevicePropertyScopeInput :
|
||||
kAudioDevicePropertyScopeOutput;
|
||||
add_to_internal_dev_list(iscapture, devId); /* new device, add it. */
|
||||
SDL_AddAudioDevice(iscapture, name, (void *) ((size_t) devId));
|
||||
}
|
||||
|
||||
size = sizeof (alive);
|
||||
result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &alive);
|
||||
CHECK_RESULT
|
||||
("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)");
|
||||
|
||||
if (!alive) {
|
||||
SDL_SetError("CoreAudio: requested device exists, but isn't alive.");
|
||||
return 0;
|
||||
static void
|
||||
reprocess_device_list(const int iscapture, AudioDeviceList **list)
|
||||
{
|
||||
AudioDeviceList *item;
|
||||
AudioDeviceList *prev = NULL;
|
||||
for (item = *list; item != NULL; item = item->next) {
|
||||
item->alive = SDL_FALSE;
|
||||
}
|
||||
|
||||
addr.mSelector = kAudioDevicePropertyHogMode;
|
||||
size = sizeof (pid);
|
||||
result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &pid);
|
||||
build_device_list(iscapture, build_device_change_list, list);
|
||||
|
||||
/* some devices don't support this property, so errors are fine here. */
|
||||
if ((result == noErr) && (pid != -1)) {
|
||||
SDL_SetError("CoreAudio: requested device is being hogged.");
|
||||
return 0;
|
||||
/* free items in the list that aren't still alive. */
|
||||
item = *list;
|
||||
while (item != NULL) {
|
||||
AudioDeviceList *next = item->next;
|
||||
if (item->alive) {
|
||||
prev = item;
|
||||
} else {
|
||||
SDL_RemoveAudioDevice(iscapture, (void *) ((size_t) item->devid));
|
||||
if (prev) {
|
||||
prev->next = item->next;
|
||||
} else {
|
||||
*list = item->next;
|
||||
}
|
||||
SDL_free(item);
|
||||
}
|
||||
item = next;
|
||||
}
|
||||
}
|
||||
|
||||
this->hidden->deviceID = devid;
|
||||
return 1;
|
||||
/* this is called when the system's list of available audio devices changes. */
|
||||
static OSStatus
|
||||
device_list_changed(AudioObjectID systemObj, UInt32 num_addr, const AudioObjectPropertyAddress *addrs, void *data)
|
||||
{
|
||||
reprocess_device_list(SDL_TRUE, &capture_devs);
|
||||
reprocess_device_list(SDL_FALSE, &output_devs);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -317,11 +340,54 @@ inputCallback(void *inRefCon,
|
||||
}
|
||||
|
||||
|
||||
#if MACOSX_COREAUDIO
|
||||
static const AudioObjectPropertyAddress alive_address =
|
||||
{
|
||||
kAudioDevicePropertyDeviceIsAlive,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
static OSStatus
|
||||
device_unplugged(AudioObjectID devid, UInt32 num_addr, const AudioObjectPropertyAddress *addrs, void *data)
|
||||
{
|
||||
SDL_AudioDevice *this = (SDL_AudioDevice *) data;
|
||||
SDL_bool dead = SDL_FALSE;
|
||||
UInt32 isAlive = 1;
|
||||
UInt32 size = sizeof (isAlive);
|
||||
OSStatus error;
|
||||
|
||||
if (!this->enabled) {
|
||||
return 0; /* already known to be dead. */
|
||||
}
|
||||
|
||||
error = AudioObjectGetPropertyData(this->hidden->deviceID, &alive_address,
|
||||
0, NULL, &size, &isAlive);
|
||||
|
||||
if (error == kAudioHardwareBadDeviceError) {
|
||||
dead = SDL_TRUE; /* device was unplugged. */
|
||||
} else if ((error == kAudioHardwareNoError) && (!isAlive)) {
|
||||
dead = SDL_TRUE; /* device died in some other way. */
|
||||
}
|
||||
|
||||
if (dead) {
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
COREAUDIO_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
if (this->hidden->audioUnitOpened) {
|
||||
#if MACOSX_COREAUDIO
|
||||
/* Unregister our disconnect callback. */
|
||||
AudioObjectRemovePropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this);
|
||||
#endif
|
||||
|
||||
AURenderCallbackStruct callback;
|
||||
const AudioUnitElement output_bus = 0;
|
||||
const AudioUnitElement input_bus = 1;
|
||||
@@ -355,9 +421,63 @@ COREAUDIO_CloseDevice(_THIS)
|
||||
}
|
||||
}
|
||||
|
||||
#if MACOSX_COREAUDIO
|
||||
static int
|
||||
prepare_device(_THIS, void *handle, int iscapture)
|
||||
{
|
||||
AudioDeviceID devid = (AudioDeviceID) ((size_t) handle);
|
||||
OSStatus result = noErr;
|
||||
UInt32 size = 0;
|
||||
UInt32 alive = 0;
|
||||
pid_t pid = 0;
|
||||
|
||||
AudioObjectPropertyAddress addr = {
|
||||
0,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
if (handle == NULL) {
|
||||
size = sizeof (AudioDeviceID);
|
||||
addr.mSelector =
|
||||
((iscapture) ? kAudioHardwarePropertyDefaultInputDevice :
|
||||
kAudioHardwarePropertyDefaultOutputDevice);
|
||||
result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr,
|
||||
0, NULL, &size, &devid);
|
||||
CHECK_RESULT("AudioHardwareGetProperty (default device)");
|
||||
}
|
||||
|
||||
addr.mSelector = kAudioDevicePropertyDeviceIsAlive;
|
||||
addr.mScope = iscapture ? kAudioDevicePropertyScopeInput :
|
||||
kAudioDevicePropertyScopeOutput;
|
||||
|
||||
size = sizeof (alive);
|
||||
result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &alive);
|
||||
CHECK_RESULT
|
||||
("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)");
|
||||
|
||||
if (!alive) {
|
||||
SDL_SetError("CoreAudio: requested device exists, but isn't alive.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
addr.mSelector = kAudioDevicePropertyHogMode;
|
||||
size = sizeof (pid);
|
||||
result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &pid);
|
||||
|
||||
/* some devices don't support this property, so errors are fine here. */
|
||||
if ((result == noErr) && (pid != -1)) {
|
||||
SDL_SetError("CoreAudio: requested device is being hogged.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
this->hidden->deviceID = devid;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
prepare_audiounit(_THIS, const char *devname, int iscapture,
|
||||
prepare_audiounit(_THIS, void *handle, int iscapture,
|
||||
const AudioStreamBasicDescription * strdesc)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
@@ -376,8 +496,7 @@ prepare_audiounit(_THIS, const char *devname, int iscapture,
|
||||
kAudioUnitScope_Input);
|
||||
|
||||
#if MACOSX_COREAUDIO
|
||||
if (!find_device_by_name(this, devname, iscapture)) {
|
||||
SDL_SetError("Couldn't find requested CoreAudio device");
|
||||
if (!prepare_device(this, handle, iscapture)) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -454,13 +573,18 @@ prepare_audiounit(_THIS, const char *devname, int iscapture,
|
||||
result = AudioOutputUnitStart(this->hidden->audioUnit);
|
||||
CHECK_RESULT("AudioOutputUnitStart");
|
||||
|
||||
#if MACOSX_COREAUDIO
|
||||
/* Fire a callback if the device stops being "alive" (disconnected, etc). */
|
||||
AudioObjectAddPropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this);
|
||||
#endif
|
||||
|
||||
/* We're running! */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
COREAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
AudioStreamBasicDescription strdesc;
|
||||
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
@@ -519,7 +643,7 @@ COREAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
strdesc.mBytesPerPacket =
|
||||
strdesc.mBytesPerFrame * strdesc.mFramesPerPacket;
|
||||
|
||||
if (!prepare_audiounit(this, devname, iscapture, &strdesc)) {
|
||||
if (!prepare_audiounit(this, handle, iscapture, &strdesc)) {
|
||||
COREAUDIO_CloseDevice(this);
|
||||
return -1; /* prepare_audiounit() will call SDL_SetError()... */
|
||||
}
|
||||
@@ -527,15 +651,27 @@ COREAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
return 0; /* good to go. */
|
||||
}
|
||||
|
||||
static void
|
||||
COREAUDIO_Deinitialize(void)
|
||||
{
|
||||
#if MACOSX_COREAUDIO
|
||||
AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &devlist_address, device_list_changed, NULL);
|
||||
free_audio_device_list(&capture_devs);
|
||||
free_audio_device_list(&output_devs);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
COREAUDIO_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = COREAUDIO_OpenDevice;
|
||||
impl->CloseDevice = COREAUDIO_CloseDevice;
|
||||
impl->Deinitialize = COREAUDIO_Deinitialize;
|
||||
|
||||
#if MACOSX_COREAUDIO
|
||||
impl->DetectDevices = COREAUDIO_DetectDevices;
|
||||
AudioObjectAddPropertyListener(kAudioObjectSystemObject, &devlist_address, device_list_changed, NULL);
|
||||
#else
|
||||
impl->OnlyHasDefaultOutputDevice = 1;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -144,15 +144,22 @@ SetDSerror(const char *function, int code)
|
||||
return SDL_SetError("%s", errbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
DSOUND_FreeDeviceHandle(void *handle)
|
||||
{
|
||||
SDL_free(handle);
|
||||
}
|
||||
|
||||
static BOOL CALLBACK
|
||||
FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID data)
|
||||
{
|
||||
SDL_AddAudioDevice addfn = (SDL_AddAudioDevice) data;
|
||||
const int iscapture = (int) ((size_t) data);
|
||||
if (guid != NULL) { /* skip default device */
|
||||
char *str = WIN_StringToUTF8(desc);
|
||||
if (str != NULL) {
|
||||
addfn(str);
|
||||
LPGUID cpyguid = (LPGUID) SDL_malloc(sizeof (GUID));
|
||||
SDL_memcpy(cpyguid, guid, sizeof (GUID));
|
||||
SDL_AddAudioDevice(iscapture, str, cpyguid);
|
||||
SDL_free(str); /* addfn() makes a copy of this string. */
|
||||
}
|
||||
}
|
||||
@@ -160,13 +167,10 @@ FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID data)
|
||||
}
|
||||
|
||||
static void
|
||||
DSOUND_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
|
||||
DSOUND_DetectDevices(void)
|
||||
{
|
||||
if (iscapture) {
|
||||
pDirectSoundCaptureEnumerateW(FindAllDevs, addfn);
|
||||
} else {
|
||||
pDirectSoundEnumerateW(FindAllDevs, addfn);
|
||||
}
|
||||
pDirectSoundCaptureEnumerateW(FindAllDevs, (void *) ((size_t) 1));
|
||||
pDirectSoundEnumerateW(FindAllDevs, (void *) ((size_t) 0));
|
||||
}
|
||||
|
||||
|
||||
@@ -419,53 +423,14 @@ CreateSecondary(_THIS, HWND focus)
|
||||
return (numchunks);
|
||||
}
|
||||
|
||||
typedef struct FindDevGUIDData
|
||||
{
|
||||
const char *devname;
|
||||
GUID guid;
|
||||
int found;
|
||||
} FindDevGUIDData;
|
||||
|
||||
static BOOL CALLBACK
|
||||
FindDevGUID(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID _data)
|
||||
{
|
||||
if (guid != NULL) { /* skip the default device. */
|
||||
FindDevGUIDData *data = (FindDevGUIDData *) _data;
|
||||
char *str = WIN_StringToUTF8(desc);
|
||||
const int match = (SDL_strcmp(str, data->devname) == 0);
|
||||
SDL_free(str);
|
||||
if (match) {
|
||||
data->found = 1;
|
||||
SDL_memcpy(&data->guid, guid, sizeof (data->guid));
|
||||
return FALSE; /* found it! stop enumerating. */
|
||||
}
|
||||
}
|
||||
return TRUE; /* keep enumerating. */
|
||||
}
|
||||
|
||||
static int
|
||||
DSOUND_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
HRESULT result;
|
||||
SDL_bool valid_format = SDL_FALSE;
|
||||
SDL_bool tried_format = SDL_FALSE;
|
||||
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
FindDevGUIDData devguid;
|
||||
LPGUID guid = NULL;
|
||||
|
||||
if (devname != NULL) {
|
||||
devguid.found = 0;
|
||||
devguid.devname = devname;
|
||||
if (iscapture)
|
||||
pDirectSoundCaptureEnumerateW(FindDevGUID, &devguid);
|
||||
else
|
||||
pDirectSoundEnumerateW(FindDevGUID, &devguid);
|
||||
|
||||
if (!devguid.found) {
|
||||
return SDL_SetError("DirectSound: Requested device not found");
|
||||
}
|
||||
guid = &devguid.guid;
|
||||
}
|
||||
LPGUID guid = (LPGUID) handle;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
@@ -536,6 +501,8 @@ DSOUND_Init(SDL_AudioDriverImpl * impl)
|
||||
impl->WaitDone = DSOUND_WaitDone;
|
||||
impl->GetDeviceBuf = DSOUND_GetDeviceBuf;
|
||||
impl->CloseDevice = DSOUND_CloseDevice;
|
||||
impl->FreeDeviceHandle = DSOUND_FreeDeviceHandle;
|
||||
|
||||
impl->Deinitialize = DSOUND_Deinitialize;
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -71,7 +71,7 @@ DISKAUD_PlayDevice(_THIS)
|
||||
|
||||
/* If we couldn't write, assume fatal error for now */
|
||||
if (written != this->hidden->mixlen) {
|
||||
this->enabled = 0;
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
|
||||
@@ -100,10 +100,11 @@ DISKAUD_CloseDevice(_THIS)
|
||||
}
|
||||
|
||||
static int
|
||||
DISKAUD_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
/* handle != NULL means "user specified the placeholder name on the fake detected device list" */
|
||||
const char *fname = DISKAUD_GetOutputFilename(handle ? NULL : devname);
|
||||
const char *envr = SDL_getenv(DISKENVR_WRITEDELAY);
|
||||
const char *fname = DISKAUD_GetOutputFilename(devname);
|
||||
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc(sizeof(*this->hidden));
|
||||
@@ -141,6 +142,13 @@ DISKAUD_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
DISKAUD_DetectDevices(void)
|
||||
{
|
||||
/* !!! FIXME: stole this literal string from DEFAULT_OUTPUT_DEVNAME in SDL_audio.c */
|
||||
SDL_AddAudioDevice(SDL_FALSE, "System audio output device", (void *) 0x1);
|
||||
}
|
||||
|
||||
static int
|
||||
DISKAUD_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
@@ -150,6 +158,9 @@ DISKAUD_Init(SDL_AudioDriverImpl * impl)
|
||||
impl->PlayDevice = DISKAUD_PlayDevice;
|
||||
impl->GetDeviceBuf = DISKAUD_GetDeviceBuf;
|
||||
impl->CloseDevice = DISKAUD_CloseDevice;
|
||||
impl->DetectDevices = DISKAUD_DetectDevices;
|
||||
|
||||
impl->AllowsArbitraryDeviceNames = 1;
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -51,9 +51,9 @@
|
||||
|
||||
|
||||
static void
|
||||
DSP_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
|
||||
DSP_DetectDevices(void)
|
||||
{
|
||||
SDL_EnumUnixAudioDevices(iscapture, 0, NULL, addfn);
|
||||
SDL_EnumUnixAudioDevices(0, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ DSP_CloseDevice(_THIS)
|
||||
|
||||
|
||||
static int
|
||||
DSP_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
|
||||
int format;
|
||||
@@ -270,7 +270,7 @@ DSP_PlayDevice(_THIS)
|
||||
const int mixlen = this->hidden->mixlen;
|
||||
if (write(this->hidden->audio_fd, mixbuf, mixlen) == -1) {
|
||||
perror("Audio write");
|
||||
this->enabled = 0;
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Wrote %d bytes of audio data\n", mixlen);
|
||||
@@ -293,6 +293,8 @@ DSP_Init(SDL_AudioDriverImpl * impl)
|
||||
impl->GetDeviceBuf = DSP_GetDeviceBuf;
|
||||
impl->CloseDevice = DSP_CloseDevice;
|
||||
|
||||
impl->AllowsArbitraryDeviceNames = 1;
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "SDL_dummyaudio.h"
|
||||
|
||||
static int
|
||||
DUMMYAUD_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
DUMMYAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
return 0; /* always succeeds. */
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -151,7 +151,7 @@ Emscripten_CloseDevice(_THIS)
|
||||
}
|
||||
|
||||
static int
|
||||
Emscripten_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
Emscripten_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
SDL_bool valid_format = SDL_FALSE;
|
||||
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
@@ -263,6 +263,10 @@ Emscripten_Init(SDL_AudioDriverImpl * impl)
|
||||
return 0;
|
||||
});
|
||||
|
||||
if (!available) {
|
||||
SDL_SetError("No audio context available");
|
||||
}
|
||||
|
||||
return available;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -129,7 +129,7 @@ ESD_WaitDevice(_THIS)
|
||||
/* Check every 10 loops */
|
||||
if (this->hidden->parent && (((++cnt) % 10) == 0)) {
|
||||
if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) {
|
||||
this->enabled = 0;
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -161,7 +161,7 @@ ESD_PlayDevice(_THIS)
|
||||
|
||||
/* If we couldn't write, assume fatal error for now */
|
||||
if (written < 0) {
|
||||
this->enabled = 0;
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,7 +215,7 @@ get_progname(void)
|
||||
|
||||
|
||||
static int
|
||||
ESD_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
ESD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
esd_format_t format = (ESD_STREAM | ESD_PLAY);
|
||||
SDL_AudioFormat test_format = 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -143,7 +143,7 @@ SDL_FS_PlayDevice(_THIS)
|
||||
this->hidden->mixsamples);
|
||||
/* If we couldn't write, assume fatal error for now */
|
||||
if (ret) {
|
||||
this->enabled = 0;
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
|
||||
@@ -186,7 +186,7 @@ SDL_FS_CloseDevice(_THIS)
|
||||
|
||||
|
||||
static int
|
||||
SDL_FS_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
int bytes;
|
||||
SDL_AudioFormat test_format = 0, format = 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -111,7 +111,7 @@ UnmaskSignals(sigset_t * omask)
|
||||
|
||||
|
||||
static int
|
||||
HAIKUAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
HAIKUAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
int valid_datatype = 0;
|
||||
media_raw_audio_format format;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -43,7 +43,7 @@
|
||||
#define SAMPLE_FRAME_COUNT 4096
|
||||
|
||||
/* Audio driver functions */
|
||||
static int NACLAUD_OpenDevice(_THIS, const char *devname, int iscapture);
|
||||
static int NACLAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture);
|
||||
static void NACLAUD_CloseDevice(_THIS);
|
||||
static void nacl_audio_callback(void* samples, uint32_t buffer_size, PP_TimeDelta latency, void* data);
|
||||
|
||||
@@ -85,7 +85,7 @@ static void NACLAUD_CloseDevice(SDL_AudioDevice *device) {
|
||||
}
|
||||
|
||||
static int
|
||||
NACLAUD_OpenDevice(_THIS, const char *devname, int iscapture) {
|
||||
NACLAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) {
|
||||
PP_Instance instance = PSGetInstanceId();
|
||||
const PPB_Audio *ppb_audio = PSInterfaceAudio();
|
||||
const PPB_AudioConfig *ppb_audiocfg = PSInterfaceAudioConfig();
|
||||
@@ -130,9 +130,7 @@ NACLAUD_Init(SDL_AudioDriverImpl * impl)
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = NACLAUD_OpenDevice;
|
||||
impl->CloseDevice = NACLAUD_CloseDevice;
|
||||
impl->HasCaptureSupport = 0;
|
||||
impl->OnlyHasDefaultOutputDevice = 1;
|
||||
impl->OnlyHasDefaultInputDevice = 1;
|
||||
impl->ProvidesOwnCallbackThread = 1;
|
||||
/*
|
||||
* impl->WaitDevice = NACLAUD_WaitDevice;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -276,7 +276,7 @@ find_device(_THIS, int nch)
|
||||
}
|
||||
|
||||
static int
|
||||
NAS_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
NAS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
AuElement elms[3];
|
||||
int buffer_size;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -111,7 +111,7 @@ OpenAudioPath(char *path, int maxlen, int flags, int classic)
|
||||
|
||||
if (stat(audiopath, &sb) == 0) {
|
||||
fd = open(audiopath, flags, 0);
|
||||
if (fd > 0) {
|
||||
if (fd >= 0) {
|
||||
if (path != NULL) {
|
||||
SDL_strlcpy(path, audiopath, maxlen);
|
||||
}
|
||||
@@ -176,7 +176,7 @@ PAUDIO_WaitDevice(_THIS)
|
||||
* the user know what happened.
|
||||
*/
|
||||
fprintf(stderr, "SDL: %s - %s\n", strerror(errno), message);
|
||||
this->enabled = 0;
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
/* Don't try to close - may hang */
|
||||
this->hidden->audio_fd = -1;
|
||||
#ifdef DEBUG_AUDIO
|
||||
@@ -212,7 +212,7 @@ PAUDIO_PlayDevice(_THIS)
|
||||
|
||||
/* If we couldn't write, assume fatal error for now */
|
||||
if (written < 0) {
|
||||
this->enabled = 0;
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
|
||||
@@ -241,7 +241,7 @@ PAUDIO_CloseDevice(_THIS)
|
||||
}
|
||||
|
||||
static int
|
||||
PAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
PAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
const char *workaround = SDL_getenv("SDL_DSP_NOSELECT");
|
||||
char audiodev[1024];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -43,7 +43,7 @@
|
||||
#define PSPAUD_DRIVER_NAME "psp"
|
||||
|
||||
static int
|
||||
PSPAUD_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
PSPAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
int format, mixlen, i;
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -26,6 +26,7 @@
|
||||
Stéphan Kochen: stephan .a.t. kochen.nl
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
#if SDL_AUDIO_DRIVER_PULSEAUDIO
|
||||
|
||||
@@ -38,7 +39,6 @@
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <pulse/pulseaudio.h>
|
||||
#include <pulse/simple.h>
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
@@ -66,16 +66,14 @@ static SDL_INLINE int PA_STREAM_IS_GOOD(pa_stream_state_t x) {
|
||||
|
||||
|
||||
static const char *(*PULSEAUDIO_pa_get_library_version) (void);
|
||||
static pa_simple *(*PULSEAUDIO_pa_simple_new) (const char *, const char *,
|
||||
pa_stream_direction_t, const char *, const char *, const pa_sample_spec *,
|
||||
const pa_channel_map *, const pa_buffer_attr *, int *);
|
||||
static void (*PULSEAUDIO_pa_simple_free) (pa_simple *);
|
||||
static pa_channel_map *(*PULSEAUDIO_pa_channel_map_init_auto) (
|
||||
pa_channel_map *, unsigned, pa_channel_map_def_t);
|
||||
static const char * (*PULSEAUDIO_pa_strerror) (int);
|
||||
static pa_mainloop * (*PULSEAUDIO_pa_mainloop_new) (void);
|
||||
static pa_mainloop_api * (*PULSEAUDIO_pa_mainloop_get_api) (pa_mainloop *);
|
||||
static int (*PULSEAUDIO_pa_mainloop_iterate) (pa_mainloop *, int, int *);
|
||||
static int (*PULSEAUDIO_pa_mainloop_run) (pa_mainloop *, int *);
|
||||
static void (*PULSEAUDIO_pa_mainloop_quit) (pa_mainloop *, int);
|
||||
static void (*PULSEAUDIO_pa_mainloop_free) (pa_mainloop *);
|
||||
|
||||
static pa_operation_state_t (*PULSEAUDIO_pa_operation_get_state) (
|
||||
@@ -87,7 +85,13 @@ static pa_context * (*PULSEAUDIO_pa_context_new) (pa_mainloop_api *,
|
||||
const char *);
|
||||
static int (*PULSEAUDIO_pa_context_connect) (pa_context *, const char *,
|
||||
pa_context_flags_t, const pa_spawn_api *);
|
||||
static pa_operation * (*PULSEAUDIO_pa_context_get_sink_info_list) (pa_context *, pa_sink_info_cb_t, void *);
|
||||
static pa_operation * (*PULSEAUDIO_pa_context_get_source_info_list) (pa_context *, pa_source_info_cb_t, void *);
|
||||
static pa_operation * (*PULSEAUDIO_pa_context_get_sink_info_by_index) (pa_context *, uint32_t, pa_sink_info_cb_t, void *);
|
||||
static pa_operation * (*PULSEAUDIO_pa_context_get_source_info_by_index) (pa_context *, uint32_t, pa_source_info_cb_t, void *);
|
||||
static pa_context_state_t (*PULSEAUDIO_pa_context_get_state) (pa_context *);
|
||||
static pa_operation * (*PULSEAUDIO_pa_context_subscribe) (pa_context *, pa_subscription_mask_t, pa_context_success_cb_t, void *);
|
||||
static void (*PULSEAUDIO_pa_context_set_subscribe_callback) (pa_context *, pa_context_subscribe_cb_t, void *);
|
||||
static void (*PULSEAUDIO_pa_context_disconnect) (pa_context *);
|
||||
static void (*PULSEAUDIO_pa_context_unref) (pa_context *);
|
||||
|
||||
@@ -179,18 +183,24 @@ static int
|
||||
load_pulseaudio_syms(void)
|
||||
{
|
||||
SDL_PULSEAUDIO_SYM(pa_get_library_version);
|
||||
SDL_PULSEAUDIO_SYM(pa_simple_new);
|
||||
SDL_PULSEAUDIO_SYM(pa_simple_free);
|
||||
SDL_PULSEAUDIO_SYM(pa_mainloop_new);
|
||||
SDL_PULSEAUDIO_SYM(pa_mainloop_get_api);
|
||||
SDL_PULSEAUDIO_SYM(pa_mainloop_iterate);
|
||||
SDL_PULSEAUDIO_SYM(pa_mainloop_run);
|
||||
SDL_PULSEAUDIO_SYM(pa_mainloop_quit);
|
||||
SDL_PULSEAUDIO_SYM(pa_mainloop_free);
|
||||
SDL_PULSEAUDIO_SYM(pa_operation_get_state);
|
||||
SDL_PULSEAUDIO_SYM(pa_operation_cancel);
|
||||
SDL_PULSEAUDIO_SYM(pa_operation_unref);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_new);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_connect);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_get_sink_info_list);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_get_source_info_list);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_get_sink_info_by_index);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_get_source_info_by_index);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_get_state);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_subscribe);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_set_subscribe_callback);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_disconnect);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_unref);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_new);
|
||||
@@ -206,122 +216,6 @@ load_pulseaudio_syms(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Check to see if we can connect to PulseAudio */
|
||||
static SDL_bool
|
||||
CheckPulseAudioAvailable()
|
||||
{
|
||||
pa_simple *s;
|
||||
pa_sample_spec ss;
|
||||
|
||||
ss.format = PA_SAMPLE_S16NE;
|
||||
ss.channels = 1;
|
||||
ss.rate = 22050;
|
||||
|
||||
s = PULSEAUDIO_pa_simple_new(NULL, "SDL", PA_STREAM_PLAYBACK, NULL,
|
||||
"Test", &ss, NULL, NULL, NULL);
|
||||
if (s) {
|
||||
PULSEAUDIO_pa_simple_free(s);
|
||||
return SDL_TRUE;
|
||||
} else {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function waits until it is possible to write a full sound buffer */
|
||||
static void
|
||||
PULSEAUDIO_WaitDevice(_THIS)
|
||||
{
|
||||
struct SDL_PrivateAudioData *h = this->hidden;
|
||||
|
||||
while(1) {
|
||||
if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
|
||||
PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
|
||||
PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
|
||||
this->enabled = 0;
|
||||
return;
|
||||
}
|
||||
if (PULSEAUDIO_pa_stream_writable_size(h->stream) >= h->mixlen) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
PULSEAUDIO_PlayDevice(_THIS)
|
||||
{
|
||||
/* Write the audio data */
|
||||
struct SDL_PrivateAudioData *h = this->hidden;
|
||||
if (PULSEAUDIO_pa_stream_write(h->stream, h->mixbuf, h->mixlen, NULL, 0LL,
|
||||
PA_SEEK_RELATIVE) < 0) {
|
||||
this->enabled = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stream_drain_complete(pa_stream *s, int success, void *userdata)
|
||||
{
|
||||
/* no-op for pa_stream_drain() to use for callback. */
|
||||
}
|
||||
|
||||
static void
|
||||
PULSEAUDIO_WaitDone(_THIS)
|
||||
{
|
||||
struct SDL_PrivateAudioData *h = this->hidden;
|
||||
pa_operation *o;
|
||||
|
||||
o = PULSEAUDIO_pa_stream_drain(h->stream, stream_drain_complete, NULL);
|
||||
if (!o) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (PULSEAUDIO_pa_operation_get_state(o) != PA_OPERATION_DONE) {
|
||||
if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
|
||||
PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
|
||||
PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
|
||||
PULSEAUDIO_pa_operation_cancel(o);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PULSEAUDIO_pa_operation_unref(o);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Uint8 *
|
||||
PULSEAUDIO_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return (this->hidden->mixbuf);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
PULSEAUDIO_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
SDL_FreeAudioMem(this->hidden->mixbuf);
|
||||
this->hidden->mixbuf = NULL;
|
||||
if (this->hidden->stream) {
|
||||
PULSEAUDIO_pa_stream_disconnect(this->hidden->stream);
|
||||
PULSEAUDIO_pa_stream_unref(this->hidden->stream);
|
||||
this->hidden->stream = NULL;
|
||||
}
|
||||
if (this->hidden->context != NULL) {
|
||||
PULSEAUDIO_pa_context_disconnect(this->hidden->context);
|
||||
PULSEAUDIO_pa_context_unref(this->hidden->context);
|
||||
this->hidden->context = NULL;
|
||||
}
|
||||
if (this->hidden->mainloop != NULL) {
|
||||
PULSEAUDIO_pa_mainloop_free(this->hidden->mainloop);
|
||||
this->hidden->mainloop = NULL;
|
||||
}
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static SDL_INLINE int
|
||||
squashVersion(const int major, const int minor, const int patch)
|
||||
{
|
||||
@@ -344,8 +238,193 @@ getAppName(void)
|
||||
return "SDL Application"; /* oh well. */
|
||||
}
|
||||
|
||||
static void
|
||||
WaitForPulseOperation(pa_mainloop *mainloop, pa_operation *o)
|
||||
{
|
||||
/* This checks for NO errors currently. Either fix that, check results elsewhere, or do things you don't care about. */
|
||||
if (mainloop && o) {
|
||||
SDL_bool okay = SDL_TRUE;
|
||||
while (okay && (PULSEAUDIO_pa_operation_get_state(o) == PA_OPERATION_RUNNING)) {
|
||||
okay = (PULSEAUDIO_pa_mainloop_iterate(mainloop, 1, NULL) >= 0);
|
||||
}
|
||||
PULSEAUDIO_pa_operation_unref(o);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DisconnectFromPulseServer(pa_mainloop *mainloop, pa_context *context)
|
||||
{
|
||||
if (context) {
|
||||
PULSEAUDIO_pa_context_disconnect(context);
|
||||
PULSEAUDIO_pa_context_unref(context);
|
||||
}
|
||||
if (mainloop != NULL) {
|
||||
PULSEAUDIO_pa_mainloop_free(mainloop);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
ConnectToPulseServer_Internal(pa_mainloop **_mainloop, pa_context **_context)
|
||||
{
|
||||
pa_mainloop *mainloop = NULL;
|
||||
pa_context *context = NULL;
|
||||
pa_mainloop_api *mainloop_api = NULL;
|
||||
int state = 0;
|
||||
|
||||
*_mainloop = NULL;
|
||||
*_context = NULL;
|
||||
|
||||
/* Set up a new main loop */
|
||||
if (!(mainloop = PULSEAUDIO_pa_mainloop_new())) {
|
||||
return SDL_SetError("pa_mainloop_new() failed");
|
||||
}
|
||||
|
||||
*_mainloop = mainloop;
|
||||
|
||||
mainloop_api = PULSEAUDIO_pa_mainloop_get_api(mainloop);
|
||||
SDL_assert(mainloop_api); /* this never fails, right? */
|
||||
|
||||
context = PULSEAUDIO_pa_context_new(mainloop_api, getAppName());
|
||||
if (!context) {
|
||||
return SDL_SetError("pa_context_new() failed");
|
||||
}
|
||||
*_context = context;
|
||||
|
||||
/* Connect to the PulseAudio server */
|
||||
if (PULSEAUDIO_pa_context_connect(context, NULL, 0, NULL) < 0) {
|
||||
return SDL_SetError("Could not setup connection to PulseAudio");
|
||||
}
|
||||
|
||||
do {
|
||||
if (PULSEAUDIO_pa_mainloop_iterate(mainloop, 1, NULL) < 0) {
|
||||
return SDL_SetError("pa_mainloop_iterate() failed");
|
||||
}
|
||||
state = PULSEAUDIO_pa_context_get_state(context);
|
||||
if (!PA_CONTEXT_IS_GOOD(state)) {
|
||||
return SDL_SetError("Could not connect to PulseAudio");
|
||||
}
|
||||
} while (state != PA_CONTEXT_READY);
|
||||
|
||||
return 0; /* connected and ready! */
|
||||
}
|
||||
|
||||
static int
|
||||
ConnectToPulseServer(pa_mainloop **_mainloop, pa_context **_context)
|
||||
{
|
||||
const int retval = ConnectToPulseServer_Internal(_mainloop, _context);
|
||||
if (retval < 0) {
|
||||
DisconnectFromPulseServer(*_mainloop, *_context);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/* This function waits until it is possible to write a full sound buffer */
|
||||
static void
|
||||
PULSEAUDIO_WaitDevice(_THIS)
|
||||
{
|
||||
struct SDL_PrivateAudioData *h = this->hidden;
|
||||
|
||||
while (this->enabled) {
|
||||
if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
|
||||
PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
|
||||
PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
return;
|
||||
}
|
||||
if (PULSEAUDIO_pa_stream_writable_size(h->stream) >= h->mixlen) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
PULSEAUDIO_PlayDevice(_THIS)
|
||||
{
|
||||
/* Write the audio data */
|
||||
struct SDL_PrivateAudioData *h = this->hidden;
|
||||
if (this->enabled) {
|
||||
if (PULSEAUDIO_pa_stream_write(h->stream, h->mixbuf, h->mixlen, NULL, 0LL, PA_SEEK_RELATIVE) < 0) {
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stream_drain_complete(pa_stream *s, int success, void *userdata)
|
||||
{
|
||||
/* no-op for pa_stream_drain() to use for callback. */
|
||||
}
|
||||
|
||||
static void
|
||||
PULSEAUDIO_WaitDone(_THIS)
|
||||
{
|
||||
if (this->enabled) {
|
||||
struct SDL_PrivateAudioData *h = this->hidden;
|
||||
pa_operation *o = PULSEAUDIO_pa_stream_drain(h->stream, stream_drain_complete, NULL);
|
||||
if (o) {
|
||||
while (PULSEAUDIO_pa_operation_get_state(o) != PA_OPERATION_DONE) {
|
||||
if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
|
||||
PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
|
||||
PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
|
||||
PULSEAUDIO_pa_operation_cancel(o);
|
||||
break;
|
||||
}
|
||||
}
|
||||
PULSEAUDIO_pa_operation_unref(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Uint8 *
|
||||
PULSEAUDIO_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return (this->hidden->mixbuf);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
PULSEAUDIO_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
SDL_FreeAudioMem(this->hidden->mixbuf);
|
||||
SDL_free(this->hidden->device_name);
|
||||
if (this->hidden->stream) {
|
||||
PULSEAUDIO_pa_stream_disconnect(this->hidden->stream);
|
||||
PULSEAUDIO_pa_stream_unref(this->hidden->stream);
|
||||
}
|
||||
DisconnectFromPulseServer(this->hidden->mainloop, this->hidden->context);
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceNameCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data)
|
||||
{
|
||||
if (i) {
|
||||
char **devname = (char **) data;
|
||||
*devname = SDL_strdup(i->name);
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
FindDeviceName(struct SDL_PrivateAudioData *h, void *handle)
|
||||
{
|
||||
const uint32_t idx = ((uint32_t) ((size_t) handle)) - 1;
|
||||
|
||||
if (handle == NULL) { /* NULL == default device. */
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
WaitForPulseOperation(h->mainloop, PULSEAUDIO_pa_context_get_sink_info_by_index(h->context, idx, DeviceNameCallback, &h->device_name));
|
||||
return (h->device_name != NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
struct SDL_PrivateAudioData *h = NULL;
|
||||
Uint16 test_format = 0;
|
||||
@@ -442,42 +521,21 @@ PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
paattr.minreq = h->mixlen;
|
||||
#endif
|
||||
|
||||
if (ConnectToPulseServer(&h->mainloop, &h->context) < 0) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
return SDL_SetError("Could not connect to PulseAudio server");
|
||||
}
|
||||
|
||||
if (!FindDeviceName(h, handle)) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
return SDL_SetError("Requested PulseAudio sink missing?");
|
||||
}
|
||||
|
||||
/* The SDL ALSA output hints us that we use Windows' channel mapping */
|
||||
/* http://bugzilla.libsdl.org/show_bug.cgi?id=110 */
|
||||
PULSEAUDIO_pa_channel_map_init_auto(&pacmap, this->spec.channels,
|
||||
PA_CHANNEL_MAP_WAVEEX);
|
||||
|
||||
/* Set up a new main loop */
|
||||
if (!(h->mainloop = PULSEAUDIO_pa_mainloop_new())) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
return SDL_SetError("pa_mainloop_new() failed");
|
||||
}
|
||||
|
||||
h->mainloop_api = PULSEAUDIO_pa_mainloop_get_api(h->mainloop);
|
||||
h->context = PULSEAUDIO_pa_context_new(h->mainloop_api, getAppName());
|
||||
if (!h->context) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
return SDL_SetError("pa_context_new() failed");
|
||||
}
|
||||
|
||||
/* Connect to the PulseAudio server */
|
||||
if (PULSEAUDIO_pa_context_connect(h->context, NULL, 0, NULL) < 0) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
return SDL_SetError("Could not setup connection to PulseAudio");
|
||||
}
|
||||
|
||||
do {
|
||||
if (PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
return SDL_SetError("pa_mainloop_iterate() failed");
|
||||
}
|
||||
state = PULSEAUDIO_pa_context_get_state(h->context);
|
||||
if (!PA_CONTEXT_IS_GOOD(state)) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
return SDL_SetError("Could not connect to PulseAudio");
|
||||
}
|
||||
} while (state != PA_CONTEXT_READY);
|
||||
|
||||
h->stream = PULSEAUDIO_pa_stream_new(
|
||||
h->context,
|
||||
"Simple DirectMedia Layer", /* stream description */
|
||||
@@ -490,7 +548,13 @@ PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
return SDL_SetError("Could not set up PulseAudio stream");
|
||||
}
|
||||
|
||||
if (PULSEAUDIO_pa_stream_connect_playback(h->stream, NULL, &paattr, flags,
|
||||
/* now that we have multi-device support, don't move a stream from
|
||||
a device that was unplugged to something else, unless we're default. */
|
||||
if (h->device_name != NULL) {
|
||||
flags |= PA_STREAM_DONT_MOVE;
|
||||
}
|
||||
|
||||
if (PULSEAUDIO_pa_stream_connect_playback(h->stream, h->device_name, &paattr, flags,
|
||||
NULL, NULL) < 0) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
return SDL_SetError("Could not connect PulseAudio stream");
|
||||
@@ -504,7 +568,7 @@ PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
state = PULSEAUDIO_pa_stream_get_state(h->stream);
|
||||
if (!PA_STREAM_IS_GOOD(state)) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
return SDL_SetError("Could not create to PulseAudio stream");
|
||||
return SDL_SetError("Could not connect PulseAudio stream");
|
||||
}
|
||||
} while (state != PA_STREAM_READY);
|
||||
|
||||
@@ -512,10 +576,92 @@ PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static pa_mainloop *hotplug_mainloop = NULL;
|
||||
static pa_context *hotplug_context = NULL;
|
||||
static SDL_Thread *hotplug_thread = NULL;
|
||||
|
||||
/* device handles are device index + 1, cast to void*, so we never pass a NULL. */
|
||||
|
||||
/* This is called when PulseAudio adds an output ("sink") device. */
|
||||
static void
|
||||
SinkInfoCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data)
|
||||
{
|
||||
if (i) {
|
||||
SDL_AddAudioDevice(SDL_FALSE, i->description, (void *) ((size_t) i->index+1));
|
||||
}
|
||||
}
|
||||
|
||||
/* This is called when PulseAudio adds a capture ("source") device. */
|
||||
static void
|
||||
SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_last, void *data)
|
||||
{
|
||||
if (i) {
|
||||
/* Skip "monitor" sources. These are just output from other sinks. */
|
||||
if (i->monitor_of_sink == PA_INVALID_INDEX) {
|
||||
SDL_AddAudioDevice(SDL_TRUE, i->description, (void *) ((size_t) i->index+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This is called when PulseAudio has a device connected/removed/changed. */
|
||||
static void
|
||||
HotplugCallback(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *data)
|
||||
{
|
||||
const SDL_bool added = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW);
|
||||
const SDL_bool removed = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE);
|
||||
|
||||
if (added || removed) { /* we only care about add/remove events. */
|
||||
const SDL_bool sink = ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK);
|
||||
const SDL_bool source = ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE);
|
||||
|
||||
/* adds need sink details from the PulseAudio server. Another callback... */
|
||||
if (added && sink) {
|
||||
PULSEAUDIO_pa_context_get_sink_info_by_index(hotplug_context, idx, SinkInfoCallback, NULL);
|
||||
} else if (added && source) {
|
||||
PULSEAUDIO_pa_context_get_source_info_by_index(hotplug_context, idx, SourceInfoCallback, NULL);
|
||||
} else if (removed && (sink || source)) {
|
||||
/* removes we can handle just with the device index. */
|
||||
SDL_RemoveAudioDevice(source != 0, (void *) ((size_t) idx+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* this runs as a thread while the Pulse target is initialized to catch hotplug events. */
|
||||
static int SDLCALL
|
||||
HotplugThread(void *data)
|
||||
{
|
||||
pa_operation *o;
|
||||
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_LOW);
|
||||
PULSEAUDIO_pa_context_set_subscribe_callback(hotplug_context, HotplugCallback, NULL);
|
||||
o = PULSEAUDIO_pa_context_subscribe(hotplug_context, PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE, NULL, NULL);
|
||||
PULSEAUDIO_pa_operation_unref(o); /* don't wait for it, just do our thing. */
|
||||
PULSEAUDIO_pa_mainloop_run(hotplug_mainloop, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
PULSEAUDIO_DetectDevices()
|
||||
{
|
||||
WaitForPulseOperation(hotplug_mainloop, PULSEAUDIO_pa_context_get_sink_info_list(hotplug_context, SinkInfoCallback, NULL));
|
||||
WaitForPulseOperation(hotplug_mainloop, PULSEAUDIO_pa_context_get_source_info_list(hotplug_context, SourceInfoCallback, NULL));
|
||||
|
||||
/* ok, we have a sane list, let's set up hotplug notifications now... */
|
||||
hotplug_thread = SDL_CreateThread(HotplugThread, "PulseHotplug", NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
PULSEAUDIO_Deinitialize(void)
|
||||
{
|
||||
if (hotplug_thread) {
|
||||
PULSEAUDIO_pa_mainloop_quit(hotplug_mainloop, 0);
|
||||
SDL_WaitThread(hotplug_thread, NULL);
|
||||
hotplug_thread = NULL;
|
||||
}
|
||||
|
||||
DisconnectFromPulseServer(hotplug_mainloop, hotplug_context);
|
||||
hotplug_mainloop = NULL;
|
||||
hotplug_context = NULL;
|
||||
|
||||
UnloadPulseAudioLibrary();
|
||||
}
|
||||
|
||||
@@ -526,12 +672,13 @@ PULSEAUDIO_Init(SDL_AudioDriverImpl * impl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!CheckPulseAudioAvailable()) {
|
||||
if (ConnectToPulseServer(&hotplug_mainloop, &hotplug_context) < 0) {
|
||||
UnloadPulseAudioLibrary();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the function pointers */
|
||||
impl->DetectDevices = PULSEAUDIO_DetectDevices;
|
||||
impl->OpenDevice = PULSEAUDIO_OpenDevice;
|
||||
impl->PlayDevice = PULSEAUDIO_PlayDevice;
|
||||
impl->WaitDevice = PULSEAUDIO_WaitDevice;
|
||||
@@ -539,12 +686,10 @@ PULSEAUDIO_Init(SDL_AudioDriverImpl * impl)
|
||||
impl->CloseDevice = PULSEAUDIO_CloseDevice;
|
||||
impl->WaitDone = PULSEAUDIO_WaitDone;
|
||||
impl->Deinitialize = PULSEAUDIO_Deinitialize;
|
||||
impl->OnlyHasDefaultOutputDevice = 1;
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
|
||||
AudioBootStrap PULSEAUDIO_bootstrap = {
|
||||
"pulseaudio", "PulseAudio", PULSEAUDIO_Init, 0
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -32,9 +32,10 @@
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
char *device_name;
|
||||
|
||||
/* pulseaudio structures */
|
||||
pa_mainloop *mainloop;
|
||||
pa_mainloop_api *mainloop_api;
|
||||
pa_context *context;
|
||||
pa_stream *stream;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -19,6 +19,15 @@
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* !!! FIXME: streamline this a little by removing all the
|
||||
* !!! FIXME: if (capture) {} else {} sections that are identical
|
||||
* !!! FIXME: except for one flag.
|
||||
*/
|
||||
|
||||
/* !!! FIXME: can this target support hotplugging? */
|
||||
/* !!! FIXME: ...does SDL2 even support QNX? */
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_AUDIO_DRIVER_QSA
|
||||
@@ -300,7 +309,7 @@ QSA_PlayDevice(_THIS)
|
||||
|
||||
/* If we couldn't write, assume fatal error for now */
|
||||
if (towrite != 0) {
|
||||
this->enabled = 0;
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,8 +346,9 @@ QSA_CloseDevice(_THIS)
|
||||
}
|
||||
|
||||
static int
|
||||
QSA_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
const QSA_Device *device = (const QSA_Device *) handle;
|
||||
int status = 0;
|
||||
int format = 0;
|
||||
SDL_AudioFormat test_format = 0;
|
||||
@@ -363,80 +373,19 @@ QSA_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
/* Initialize channel direction: capture or playback */
|
||||
this->hidden->iscapture = iscapture;
|
||||
|
||||
/* Find deviceid and cardid by device name for playback */
|
||||
if ((!this->hidden->iscapture) && (devname != NULL)) {
|
||||
uint32_t device;
|
||||
int32_t status;
|
||||
|
||||
/* Search in the playback devices */
|
||||
device = 0;
|
||||
do {
|
||||
status = SDL_strcmp(qsa_playback_device[device].name, devname);
|
||||
if (status == 0) {
|
||||
/* Found requested device */
|
||||
this->hidden->deviceno = qsa_playback_device[device].deviceno;
|
||||
this->hidden->cardno = qsa_playback_device[device].cardno;
|
||||
break;
|
||||
}
|
||||
device++;
|
||||
if (device >= qsa_playback_devices) {
|
||||
QSA_CloseDevice(this);
|
||||
return SDL_SetError("No such playback device");
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/* Find deviceid and cardid by device name for capture */
|
||||
if ((this->hidden->iscapture) && (devname != NULL)) {
|
||||
/* Search in the capture devices */
|
||||
uint32_t device;
|
||||
int32_t status;
|
||||
|
||||
/* Searching in the playback devices */
|
||||
device = 0;
|
||||
do {
|
||||
status = SDL_strcmp(qsa_capture_device[device].name, devname);
|
||||
if (status == 0) {
|
||||
/* Found requested device */
|
||||
this->hidden->deviceno = qsa_capture_device[device].deviceno;
|
||||
this->hidden->cardno = qsa_capture_device[device].cardno;
|
||||
break;
|
||||
}
|
||||
device++;
|
||||
if (device >= qsa_capture_devices) {
|
||||
QSA_CloseDevice(this);
|
||||
return SDL_SetError("No such capture device");
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/* Check if SDL requested default audio device */
|
||||
if (devname == NULL) {
|
||||
/* Open system default audio device */
|
||||
if (!this->hidden->iscapture) {
|
||||
status = snd_pcm_open_preferred(&this->hidden->audio_handle,
|
||||
&this->hidden->cardno,
|
||||
&this->hidden->deviceno,
|
||||
SND_PCM_OPEN_PLAYBACK);
|
||||
} else {
|
||||
status = snd_pcm_open_preferred(&this->hidden->audio_handle,
|
||||
&this->hidden->cardno,
|
||||
&this->hidden->deviceno,
|
||||
SND_PCM_OPEN_CAPTURE);
|
||||
}
|
||||
} else {
|
||||
if (device != NULL) {
|
||||
/* Open requested audio device */
|
||||
if (!this->hidden->iscapture) {
|
||||
status =
|
||||
snd_pcm_open(&this->hidden->audio_handle,
|
||||
this->hidden->cardno, this->hidden->deviceno,
|
||||
SND_PCM_OPEN_PLAYBACK);
|
||||
} else {
|
||||
status =
|
||||
snd_pcm_open(&this->hidden->audio_handle,
|
||||
this->hidden->cardno, this->hidden->deviceno,
|
||||
SND_PCM_OPEN_CAPTURE);
|
||||
}
|
||||
this->hidden->deviceno = device->deviceno;
|
||||
this->hidden->cardno = device->cardno;
|
||||
status = snd_pcm_open(&this->hidden->audio_handle,
|
||||
device->cardno, device->deviceno,
|
||||
iscapture ? SND_PCM_OPEN_PLAYBACK : SND_PCM_OPEN_CAPTURE);
|
||||
} else {
|
||||
/* Open system default audio device */
|
||||
status = snd_pcm_open_preferred(&this->hidden->audio_handle,
|
||||
&this->hidden->cardno,
|
||||
&this->hidden->deviceno,
|
||||
iscapture ? SND_PCM_OPEN_PLAYBACK : SND_PCM_OPEN_CAPTURE);
|
||||
}
|
||||
|
||||
/* Check if requested device is opened */
|
||||
@@ -638,7 +587,7 @@ QSA_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
}
|
||||
|
||||
static void
|
||||
QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
|
||||
QSA_DetectDevices(void)
|
||||
{
|
||||
uint32_t it;
|
||||
uint32_t cards;
|
||||
@@ -656,8 +605,9 @@ QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
|
||||
return;
|
||||
}
|
||||
|
||||
/* !!! FIXME: code duplication */
|
||||
/* Find requested devices by type */
|
||||
if (!iscapture) {
|
||||
{ /* output devices */
|
||||
/* Playback devices enumeration requested */
|
||||
for (it = 0; it < cards; it++) {
|
||||
devices = 0;
|
||||
@@ -688,7 +638,7 @@ QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
|
||||
devices;
|
||||
status = snd_pcm_close(handle);
|
||||
if (status == EOK) {
|
||||
addfn(qsa_playback_device[qsa_playback_devices].name);
|
||||
SDL_AddAudioDevice(SDL_FALSE, qsa_playback_device[qsa_playback_devices].name, &qsa_playback_device[qsa_playback_devices]);
|
||||
qsa_playback_devices++;
|
||||
}
|
||||
} else {
|
||||
@@ -713,7 +663,9 @@ QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
{ /* capture devices */
|
||||
/* Capture devices enumeration requested */
|
||||
for (it = 0; it < cards; it++) {
|
||||
devices = 0;
|
||||
@@ -744,7 +696,7 @@ QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
|
||||
devices;
|
||||
status = snd_pcm_close(handle);
|
||||
if (status == EOK) {
|
||||
addfn(qsa_capture_device[qsa_capture_devices].name);
|
||||
SDL_AddAudioDevice(SDL_TRUE, qsa_capture_device[qsa_capture_devices].name, &qsa_capture_device[qsa_capture_devices]);
|
||||
qsa_capture_devices++;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -38,7 +38,7 @@ sub outputHeader {
|
||||
/* DO NOT EDIT! This file is generated by sdlgenaudiocvt.pl */
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken\@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken\@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -158,7 +158,7 @@ SNDIO_PlayDevice(_THIS)
|
||||
|
||||
/* If we couldn't write, assume fatal error for now */
|
||||
if ( written == 0 ) {
|
||||
this->enabled = 0;
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
|
||||
@@ -193,7 +193,7 @@ SNDIO_CloseDevice(_THIS)
|
||||
}
|
||||
|
||||
static int
|
||||
SNDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
struct sio_par par;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -56,9 +56,9 @@ static Uint8 snd2au(int sample);
|
||||
|
||||
/* Audio driver bootstrap functions */
|
||||
static void
|
||||
SUNAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
|
||||
SUNAUDIO_DetectDevices(void)
|
||||
{
|
||||
SDL_EnumUnixAudioDevices(iscapture, 1, (int (*)(int fd)) NULL, addfn);
|
||||
SDL_EnumUnixAudioDevices(1, (int (*)(int)) NULL);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_AUDIO
|
||||
@@ -158,7 +158,7 @@ SUNAUDIO_PlayDevice(_THIS)
|
||||
if (write(this->hidden->audio_fd, this->hidden->ulaw_buf,
|
||||
this->hidden->fragsize) < 0) {
|
||||
/* Assume fatal error, for now */
|
||||
this->enabled = 0;
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
}
|
||||
this->hidden->written += this->hidden->fragsize;
|
||||
} else {
|
||||
@@ -168,7 +168,7 @@ SUNAUDIO_PlayDevice(_THIS)
|
||||
if (write(this->hidden->audio_fd, this->hidden->mixbuf,
|
||||
this->spec.size) < 0) {
|
||||
/* Assume fatal error, for now */
|
||||
this->enabled = 0;
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
}
|
||||
this->hidden->written += this->hidden->fragsize;
|
||||
}
|
||||
@@ -198,7 +198,7 @@ SUNAUDIO_CloseDevice(_THIS)
|
||||
}
|
||||
|
||||
static int
|
||||
SUNAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
SUNAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
|
||||
SDL_AudioFormat format = 0;
|
||||
@@ -414,6 +414,8 @@ SUNAUDIO_Init(SDL_AudioDriverImpl * impl)
|
||||
impl->GetDeviceBuf = SUNAUDIO_GetDeviceBuf;
|
||||
impl->CloseDevice = SUNAUDIO_CloseDevice;
|
||||
|
||||
impl->AllowsArbitraryDeviceNames = 1;
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -36,8 +36,9 @@
|
||||
#define WAVE_FORMAT_IEEE_FLOAT 0x0003
|
||||
#endif
|
||||
|
||||
#define DETECT_DEV_IMPL(typ, capstyp) \
|
||||
static void DetectWave##typ##Devs(SDL_AddAudioDevice addfn) { \
|
||||
#define DETECT_DEV_IMPL(iscap, typ, capstyp) \
|
||||
static void DetectWave##typ##Devs(void) { \
|
||||
const UINT iscapture = iscap ? 1 : 0; \
|
||||
const UINT devcount = wave##typ##GetNumDevs(); \
|
||||
capstyp caps; \
|
||||
UINT i; \
|
||||
@@ -45,24 +46,21 @@ static void DetectWave##typ##Devs(SDL_AddAudioDevice addfn) { \
|
||||
if (wave##typ##GetDevCaps(i,&caps,sizeof(caps))==MMSYSERR_NOERROR) { \
|
||||
char *name = WIN_StringToUTF8(caps.szPname); \
|
||||
if (name != NULL) { \
|
||||
addfn(name); \
|
||||
SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i+1)); \
|
||||
SDL_free(name); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
DETECT_DEV_IMPL(Out, WAVEOUTCAPS)
|
||||
DETECT_DEV_IMPL(In, WAVEINCAPS)
|
||||
DETECT_DEV_IMPL(SDL_FALSE, Out, WAVEOUTCAPS)
|
||||
DETECT_DEV_IMPL(SDL_TRUE, In, WAVEINCAPS)
|
||||
|
||||
static void
|
||||
WINMM_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
|
||||
WINMM_DetectDevices(void)
|
||||
{
|
||||
if (iscapture) {
|
||||
DetectWaveInDevs(addfn);
|
||||
} else {
|
||||
DetectWaveOutDevs(addfn);
|
||||
}
|
||||
DetectWaveInDevs();
|
||||
DetectWaveOutDevs();
|
||||
}
|
||||
|
||||
static void CALLBACK
|
||||
@@ -220,48 +218,19 @@ PrepWaveFormat(_THIS, UINT devId, WAVEFORMATEX *pfmt, const int iscapture)
|
||||
}
|
||||
|
||||
static int
|
||||
WINMM_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
int valid_datatype = 0;
|
||||
MMRESULT result;
|
||||
WAVEFORMATEX waveformat;
|
||||
UINT devId = WAVE_MAPPER; /* WAVE_MAPPER == choose system's default */
|
||||
char *utf8 = NULL;
|
||||
UINT i;
|
||||
|
||||
if (devname != NULL) { /* specific device requested? */
|
||||
if (iscapture) {
|
||||
const UINT devcount = waveInGetNumDevs();
|
||||
WAVEINCAPS caps;
|
||||
for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) {
|
||||
result = waveInGetDevCaps(i, &caps, sizeof (caps));
|
||||
if (result != MMSYSERR_NOERROR)
|
||||
continue;
|
||||
else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL)
|
||||
continue;
|
||||
else if (SDL_strcmp(devname, utf8) == 0)
|
||||
devId = i;
|
||||
SDL_free(utf8);
|
||||
}
|
||||
} else {
|
||||
const UINT devcount = waveOutGetNumDevs();
|
||||
WAVEOUTCAPS caps;
|
||||
for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) {
|
||||
result = waveOutGetDevCaps(i, &caps, sizeof (caps));
|
||||
if (result != MMSYSERR_NOERROR)
|
||||
continue;
|
||||
else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL)
|
||||
continue;
|
||||
else if (SDL_strcmp(devname, utf8) == 0)
|
||||
devId = i;
|
||||
SDL_free(utf8);
|
||||
}
|
||||
}
|
||||
|
||||
if (devId == WAVE_MAPPER) {
|
||||
return SDL_SetError("Requested device not found");
|
||||
}
|
||||
if (handle != NULL) { /* specific device requested? */
|
||||
/* -1 because we increment the original value to avoid NULL. */
|
||||
const size_t val = ((size_t) handle) - 1;
|
||||
devId = (UINT) val;
|
||||
}
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
@@ -279,10 +248,6 @@ WINMM_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
if (this->spec.channels > 2)
|
||||
this->spec.channels = 2; /* !!! FIXME: is this right? */
|
||||
|
||||
/* Check the buffer size -- minimum of 1/4 second (word aligned) */
|
||||
if (this->spec.samples < (this->spec.freq / 4))
|
||||
this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;
|
||||
|
||||
while ((!valid_datatype) && (test_format)) {
|
||||
switch (test_format) {
|
||||
case AUDIO_U8:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -65,6 +65,11 @@
|
||||
The XAudio2 implementation available in the Windows 8 SDK targets Windows 8 and newer.
|
||||
If you want to build SDL with XAudio2 support you should install the DirectX SDK.
|
||||
*/
|
||||
/* Disable compiling in the XAudio2 support pending fixes to dynamically load the XAudio2
|
||||
entry points so we can be robust to user configuration. Also needs to be fixed to build
|
||||
with the Windows 10 SDK.
|
||||
*/
|
||||
#if 0 /* See comment above */
|
||||
#include <dxsdkver.h>
|
||||
#if (!defined(_DXSDK_BUILD_MAJOR) || (_DXSDK_BUILD_MAJOR < 1284))
|
||||
# pragma message("Your DirectX SDK is too old. Disabling XAudio2 support.")
|
||||
@@ -72,6 +77,7 @@
|
||||
# define SDL_XAUDIO2_HAS_SDK 1
|
||||
#endif
|
||||
#endif
|
||||
#endif /* 0 */
|
||||
|
||||
#ifdef SDL_XAUDIO2_HAS_SDK
|
||||
|
||||
@@ -126,16 +132,13 @@ struct SDL_PrivateAudioData
|
||||
|
||||
|
||||
static void
|
||||
XAUDIO2_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
|
||||
XAUDIO2_DetectDevices(void)
|
||||
{
|
||||
IXAudio2 *ixa2 = NULL;
|
||||
UINT32 devcount = 0;
|
||||
UINT32 i = 0;
|
||||
|
||||
if (iscapture) {
|
||||
SDL_SetError("XAudio2: capture devices unsupported.");
|
||||
return;
|
||||
} else if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
|
||||
if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
|
||||
SDL_SetError("XAudio2: XAudio2Create() failed at detection.");
|
||||
return;
|
||||
} else if (IXAudio2_GetDeviceCount(ixa2, &devcount) != S_OK) {
|
||||
@@ -149,8 +152,8 @@ XAUDIO2_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
|
||||
if (IXAudio2_GetDeviceDetails(ixa2, i, &details) == S_OK) {
|
||||
char *str = WIN_StringToUTF8(details.DisplayName);
|
||||
if (str != NULL) {
|
||||
addfn(str);
|
||||
SDL_free(str); /* addfn() made a copy of the string. */
|
||||
SDL_AddAudioDevice(SDL_FALSE, str, (void *) ((size_t) i+1));
|
||||
SDL_free(str); /* SDL_AddAudioDevice made a copy of the string. */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,8 +172,8 @@ VoiceCBOnBufferEnd(THIS_ void *data)
|
||||
static void STDMETHODCALLTYPE
|
||||
VoiceCBOnVoiceError(THIS_ void *data, HRESULT Error)
|
||||
{
|
||||
/* !!! FIXME: attempt to recover, or mark device disconnected. */
|
||||
SDL_assert(0 && "write me!");
|
||||
SDL_AudioDevice *this = (SDL_AudioDevice *) data;
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
}
|
||||
|
||||
/* no-op callbacks... */
|
||||
@@ -221,7 +224,7 @@ XAUDIO2_PlayDevice(_THIS)
|
||||
|
||||
if (result != S_OK) { /* uhoh, panic! */
|
||||
IXAudio2SourceVoice_FlushSourceBuffers(source);
|
||||
this->enabled = 0;
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,7 +292,7 @@ XAUDIO2_CloseDevice(_THIS)
|
||||
}
|
||||
|
||||
static int
|
||||
XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
HRESULT result = S_OK;
|
||||
WAVEFORMATEX waveformat;
|
||||
@@ -315,9 +318,17 @@ XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
|
||||
static IXAudio2VoiceCallback callbacks = { &callbacks_vtable };
|
||||
|
||||
if (iscapture) {
|
||||
return SDL_SetError("XAudio2: capture devices unsupported.");
|
||||
} else if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
|
||||
#if defined(SDL_XAUDIO2_WIN8)
|
||||
/* !!! FIXME: hook up hotplugging. */
|
||||
#else
|
||||
if (handle != NULL) { /* specific device requested? */
|
||||
/* -1 because we increment the original value to avoid NULL. */
|
||||
const size_t val = ((size_t) handle) - 1;
|
||||
devId = (UINT32) val;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
|
||||
return SDL_SetError("XAudio2: XAudio2Create() failed at open.");
|
||||
}
|
||||
|
||||
@@ -332,37 +343,6 @@ XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
ixa2->SetDebugConfiguration(&debugConfig);
|
||||
*/
|
||||
|
||||
#if ! defined(__WINRT__)
|
||||
if (devname != NULL) {
|
||||
UINT32 devcount = 0;
|
||||
UINT32 i = 0;
|
||||
|
||||
if (IXAudio2_GetDeviceCount(ixa2, &devcount) != S_OK) {
|
||||
IXAudio2_Release(ixa2);
|
||||
return SDL_SetError("XAudio2: IXAudio2_GetDeviceCount() failed.");
|
||||
}
|
||||
for (i = 0; i < devcount; i++) {
|
||||
XAUDIO2_DEVICE_DETAILS details;
|
||||
if (IXAudio2_GetDeviceDetails(ixa2, i, &details) == S_OK) {
|
||||
char *str = WIN_StringToUTF8(details.DisplayName);
|
||||
if (str != NULL) {
|
||||
const int match = (SDL_strcmp(str, devname) == 0);
|
||||
SDL_free(str);
|
||||
if (match) {
|
||||
devId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i == devcount) {
|
||||
IXAudio2_Release(ixa2);
|
||||
return SDL_SetError("XAudio2: Requested device not found.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
@@ -529,6 +509,16 @@ XAUDIO2_Init(SDL_AudioDriverImpl * impl)
|
||||
impl->CloseDevice = XAUDIO2_CloseDevice;
|
||||
impl->Deinitialize = XAUDIO2_Deinitialize;
|
||||
|
||||
/* !!! FIXME: We can apparently use a C++ interface on Windows 8
|
||||
* !!! FIXME: (Windows::Devices::Enumeration::DeviceInformation) for device
|
||||
* !!! FIXME: detection, but it's not implemented here yet.
|
||||
* !!! FIXME: see http://blogs.msdn.com/b/chuckw/archive/2012/04/02/xaudio2-and-windows-8-consumer-preview.aspx
|
||||
* !!! FIXME: for now, force the default device.
|
||||
*/
|
||||
#if defined(SDL_XAUDIO2_WIN8) || defined(__WINRT__)
|
||||
impl->OnlyHasDefaultOutputDevice = 1;
|
||||
#endif
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
||||
Reference in New Issue
Block a user