audio: Refer to audio devices to "playback" and "recording".

Fixes #9619.
This commit is contained in:
Ryan C. Gordon 2024-06-14 17:57:14 -04:00
parent 031dc0743f
commit 38f0214e8a
66 changed files with 939 additions and 924 deletions

View File

@ -82,7 +82,7 @@ jobs:
- name: Build test apk's (CMake) - name: Build test apk's (CMake)
if: ${{ matrix.platform.cmake }} if: ${{ matrix.platform.cmake }}
run: | run: |
cmake --build build --config Release --parallel --verbose --target testautomation-apk testaudiocapture-apk testcontroller-apk testmultiaudio-apk testsprite-apk cmake --build build --config Release --parallel --verbose --target testautomation-apk testaudiorecording-apk testcontroller-apk testmultiaudio-apk testsprite-apk
- name: Install (CMake) - name: Install (CMake)
if: ${{ matrix.platform.cmake }} if: ${{ matrix.platform.cmake }}
run: | run: |

2
.gitignore vendored
View File

@ -94,7 +94,7 @@ test/gamepadmap
test/loopwave test/loopwave
test/loopwavequeue test/loopwavequeue
test/testatomic test/testatomic
test/testaudiocapture test/testaudiorecording
test/testaudiohotplug test/testaudiohotplug
test/testaudioinfo test/testaudioinfo
test/testautomation test/testautomation

View File

@ -221,7 +221,6 @@
<ClCompile Include="..\..\src\video\windows\SDL_windowswindow.c" /> <ClCompile Include="..\..\src\video\windows\SDL_windowswindow.c" />
<ClCompile Include="..\..\src\video\yuv2rgb\yuv_rgb.c" /> <ClCompile Include="..\..\src\video\yuv2rgb\yuv_rgb.c" />
<ClCompile Include="..\..\src\filesystem\windows\SDL_sysfilesystem.c" /> <ClCompile Include="..\..\src\filesystem\windows\SDL_sysfilesystem.c" />
<ClCompile Include="..\..\src\video\SDL_video_capture.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\include\SDL3\SDL_begin_code.h" /> <ClInclude Include="..\..\include\SDL3\SDL_begin_code.h" />

View File

@ -438,7 +438,7 @@ main(int argc, char *argv[])
SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver()); SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &wave.spec, NULL, NULL); stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &wave.spec, NULL, NULL);
if (!stream) { if (!stream) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create audio stream: %s\n", SDL_GetError()); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create audio stream: %s\n", SDL_GetError());
return -1; return -1;

View File

@ -18,7 +18,7 @@ There have been too many changes to list them all, but here are some of the high
* An example of hardware accelerated video playback using ffmpeg has been added in test/testffmpeg.c * An example of hardware accelerated video playback using ffmpeg has been added in test/testffmpeg.c
* The shaped window API has been replaced with transparent windows * The shaped window API has been replaced with transparent windows
* Time and date functions have been added in SDL_time.h * Time and date functions have been added in SDL_time.h
* Support for webcam video capture has been added in SDL_camera.h * Support for webcam video recording has been added in SDL_camera.h
* Support for handling pens and tablets has been added in SDL_pen.h * Support for handling pens and tablets has been added in SDL_pen.h
* Support for file open and save dialogs has been added in SDL_dialog.h * Support for file open and save dialogs has been added in SDL_dialog.h
* Cross-platform functions for working with files and directories are available in SDL_filesystem.h * Cross-platform functions for working with files and directories are available in SDL_filesystem.h

View File

@ -4677,7 +4677,7 @@
buildSettings = { buildSettings = {
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
INFOPLIST_KEY_NSCameraUsageDescription = "Testing camera capture"; INFOPLIST_KEY_NSCameraUsageDescription = "Testing camera recording";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@ -4689,7 +4689,7 @@
buildSettings = { buildSettings = {
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
INFOPLIST_KEY_NSCameraUsageDescription = "Testing camera capture"; INFOPLIST_KEY_NSCameraUsageDescription = "Testing camera recording";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";

View File

@ -68,12 +68,12 @@
void audioWriteFloatBuffer(float[]); void audioWriteFloatBuffer(float[]);
void audioWriteShortBuffer(short[]); void audioWriteShortBuffer(short[]);
void audioWriteByteBuffer(byte[]); void audioWriteByteBuffer(byte[]);
int[] captureOpen(int, int, int, int, int); int[] recordingOpen(int, int, int, int, int);
int captureReadFloatBuffer(float[], boolean); int recordingReadFloatBuffer(float[], boolean);
int captureReadShortBuffer(short[], boolean); int recordingReadShortBuffer(short[], boolean);
int captureReadByteBuffer(byte[], boolean); int recordingReadByteBuffer(byte[], boolean);
void audioClose(); void audioClose();
void captureClose(); void recordingClose();
void audioSetThreadPriority(boolean, int); void audioSetThreadPriority(boolean, int);
int nativeSetupJNI(); int nativeSetupJNI();
void removeAudioDevice(boolean, int); void removeAudioDevice(boolean, int);

View File

@ -32,7 +32,7 @@
android:required="false" /> android:required="false" />
<!-- Audio recording support --> <!-- Audio recording support -->
<!-- if you want to capture audio, uncomment this. --> <!-- if you want to record audio, uncomment this. -->
<!-- <uses-feature <!-- <uses-feature
android:name="android.hardware.microphone" android:name="android.hardware.microphone"
android:required="false" /> --> android:required="false" /> -->
@ -55,7 +55,7 @@
<!-- Allow access to the vibrator --> <!-- Allow access to the vibrator -->
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<!-- if you want to capture audio, uncomment this. --> <!-- if you want to record audio, uncomment this. -->
<!-- <uses-permission android:name="android.permission.RECORD_AUDIO" /> --> <!-- <uses-permission android:name="android.permission.RECORD_AUDIO" /> -->
<!-- Create a Java class extending SDLActivity and place it in a <!-- Create a Java class extending SDLActivity and place it in a

View File

@ -71,12 +71,12 @@ public class SDLAudioManager {
} }
} }
protected static int[] open(boolean isCapture, int sampleRate, int audioFormat, int desiredChannels, int desiredFrames, int deviceId) { protected static int[] open(boolean recording, int sampleRate, int audioFormat, int desiredChannels, int desiredFrames, int deviceId) {
int channelConfig; int channelConfig;
int sampleSize; int sampleSize;
int frameSize; int frameSize;
Log.v(TAG, "Opening " + (isCapture ? "capture" : "playback") + ", requested " + desiredFrames + " frames of " + desiredChannels + " channel " + getAudioFormatString(audioFormat) + " audio at " + sampleRate + " Hz"); Log.v(TAG, "Opening " + (recording ? "recording" : "playback") + ", requested " + desiredFrames + " frames of " + desiredChannels + " channel " + getAudioFormatString(audioFormat) + " audio at " + sampleRate + " Hz");
/* On older devices let's use known good settings */ /* On older devices let's use known good settings */
if (Build.VERSION.SDK_INT < 21 /* Android 5.0 (LOLLIPOP) */) { if (Build.VERSION.SDK_INT < 21 /* Android 5.0 (LOLLIPOP) */) {
@ -95,7 +95,7 @@ public class SDLAudioManager {
} }
if (audioFormat == AudioFormat.ENCODING_PCM_FLOAT) { if (audioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
int minSDKVersion = (isCapture ? 23 /* Android 6.0 (M) */ : 21 /* Android 5.0 (LOLLIPOP) */); int minSDKVersion = (recording ? 23 /* Android 6.0 (M) */ : 21 /* Android 5.0 (LOLLIPOP) */);
if (Build.VERSION.SDK_INT < minSDKVersion) { if (Build.VERSION.SDK_INT < minSDKVersion) {
audioFormat = AudioFormat.ENCODING_PCM_16BIT; audioFormat = AudioFormat.ENCODING_PCM_16BIT;
} }
@ -118,7 +118,7 @@ public class SDLAudioManager {
break; break;
} }
if (isCapture) { if (recording) {
switch (desiredChannels) { switch (desiredChannels) {
case 1: case 1:
channelConfig = AudioFormat.CHANNEL_IN_MONO; channelConfig = AudioFormat.CHANNEL_IN_MONO;
@ -215,7 +215,7 @@ public class SDLAudioManager {
// gods they probably shouldn't, the minimums are horrifyingly high // gods they probably shouldn't, the minimums are horrifyingly high
// latency already // latency already
int minBufferSize; int minBufferSize;
if (isCapture) { if (recording) {
minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat); minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
} else { } else {
minBufferSize = AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat); minBufferSize = AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat);
@ -224,7 +224,7 @@ public class SDLAudioManager {
int[] results = new int[4]; int[] results = new int[4];
if (isCapture) { if (recording) {
if (mAudioRecord == null) { if (mAudioRecord == null) {
mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, sampleRate, mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, sampleRate,
channelConfig, audioFormat, desiredFrames * frameSize); channelConfig, audioFormat, desiredFrames * frameSize);
@ -238,7 +238,7 @@ public class SDLAudioManager {
} }
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */ && deviceId != 0) { if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */ && deviceId != 0) {
mAudioRecord.setPreferredDevice(getOutputAudioDeviceInfo(deviceId)); mAudioRecord.setPreferredDevice(getPlaybackAudioDeviceInfo(deviceId));
} }
mAudioRecord.startRecording(); mAudioRecord.startRecording();
@ -277,7 +277,7 @@ public class SDLAudioManager {
} }
results[3] = desiredFrames; results[3] = desiredFrames;
Log.v(TAG, "Opening " + (isCapture ? "capture" : "playback") + ", got " + results[3] + " frames of " + results[2] + " channel " + getAudioFormatString(results[1]) + " audio at " + results[0] + " Hz"); Log.v(TAG, "Opening " + (recording ? "recording" : "playback") + ", got " + results[3] + " frames of " + results[2] + " channel " + getAudioFormatString(results[1]) + " audio at " + results[0] + " Hz");
return results; return results;
} }
@ -294,7 +294,7 @@ public class SDLAudioManager {
return null; return null;
} }
private static AudioDeviceInfo getOutputAudioDeviceInfo(int deviceId) { private static AudioDeviceInfo getPlaybackAudioDeviceInfo(int deviceId) {
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) { if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
for (AudioDeviceInfo deviceInfo : audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)) { for (AudioDeviceInfo deviceInfo : audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)) {
@ -423,12 +423,12 @@ public class SDLAudioManager {
/** /**
* This method is called by SDL using JNI. * This method is called by SDL using JNI.
*/ */
public static int[] captureOpen(int sampleRate, int audioFormat, int desiredChannels, int desiredFrames, int deviceId) { public static int[] recordingOpen(int sampleRate, int audioFormat, int desiredChannels, int desiredFrames, int deviceId) {
return open(true, sampleRate, audioFormat, desiredChannels, desiredFrames, deviceId); return open(true, sampleRate, audioFormat, desiredChannels, desiredFrames, deviceId);
} }
/** This method is called by SDL using JNI. */ /** This method is called by SDL using JNI. */
public static int captureReadFloatBuffer(float[] buffer, boolean blocking) { public static int recordingReadFloatBuffer(float[] buffer, boolean blocking) {
if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) { if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) {
return 0; return 0;
} else { } else {
@ -437,7 +437,7 @@ public class SDLAudioManager {
} }
/** This method is called by SDL using JNI. */ /** This method is called by SDL using JNI. */
public static int captureReadShortBuffer(short[] buffer, boolean blocking) { public static int recordingReadShortBuffer(short[] buffer, boolean blocking) {
if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) { if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) {
return mAudioRecord.read(buffer, 0, buffer.length); return mAudioRecord.read(buffer, 0, buffer.length);
} else { } else {
@ -446,7 +446,7 @@ public class SDLAudioManager {
} }
/** This method is called by SDL using JNI. */ /** This method is called by SDL using JNI. */
public static int captureReadByteBuffer(byte[] buffer, boolean blocking) { public static int recordingReadByteBuffer(byte[] buffer, boolean blocking) {
if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) { if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) {
return mAudioRecord.read(buffer, 0, buffer.length); return mAudioRecord.read(buffer, 0, buffer.length);
} else { } else {
@ -464,7 +464,7 @@ public class SDLAudioManager {
} }
/** This method is called by SDL using JNI. */ /** This method is called by SDL using JNI. */
public static void captureClose() { public static void recordingClose() {
if (mAudioRecord != null) { if (mAudioRecord != null) {
mAudioRecord.stop(); mAudioRecord.stop();
mAudioRecord.release(); mAudioRecord.release();
@ -473,11 +473,11 @@ public class SDLAudioManager {
} }
/** This method is called by SDL using JNI. */ /** This method is called by SDL using JNI. */
public static void audioSetThreadPriority(boolean iscapture, int device_id) { public static void audioSetThreadPriority(boolean recording, int device_id) {
try { try {
/* Set thread name */ /* Set thread name */
if (iscapture) { if (recording) {
Thread.currentThread().setName("SDLAudioC" + device_id); Thread.currentThread().setName("SDLAudioC" + device_id);
} else { } else {
Thread.currentThread().setName("SDLAudioP" + device_id); Thread.currentThread().setName("SDLAudioP" + device_id);
@ -493,8 +493,8 @@ public class SDLAudioManager {
public static native int nativeSetupJNI(); public static native int nativeSetupJNI();
public static native void removeAudioDevice(boolean isCapture, int deviceId); public static native void removeAudioDevice(boolean recording, int deviceId);
public static native void addAudioDevice(boolean isCapture, String name, int deviceId); public static native void addAudioDevice(boolean recording, String name, int deviceId);
} }

View File

@ -157,7 +157,7 @@ different depending on what sort of build you're compiling.
Audio works as expected at the API level, but not exactly like other Audio works as expected at the API level, but not exactly like other
platforms. platforms.
You'll only see a single default audio device. Audio capture also works; You'll only see a single default audio device. Audio recording also works;
if the browser pops up a prompt to ask for permission to access the if the browser pops up a prompt to ask for permission to access the
microphone, the SDL_OpenAudioDevice call will succeed and start producing microphone, the SDL_OpenAudioDevice call will succeed and start producing
silence at a regular interval. Once the user approves the request, real silence at a regular interval. Once the user approves the request, real

View File

@ -70,6 +70,8 @@ The SDL 1.2 audio compatibility API has also been removed, as it was a simplifie
SDL3 will not implicitly initialize the audio subsystem on your behalf if you open a device without doing so. Please explicitly call SDL_Init(SDL_INIT_AUDIO) at some point. SDL3 will not implicitly initialize the audio subsystem on your behalf if you open a device without doing so. Please explicitly call SDL_Init(SDL_INIT_AUDIO) at some point.
SDL2 refered to audio devices that record sound as "capture" devices, and ones that play sound to speakers as "output" devices. In SDL3, we've changed this terminology to be "recording" devices and "playback" devices, which we hope is more clear.
SDL3's audio subsystem offers an enormous amount of power over SDL2, but if you just want a simple migration of your existing code, you can ignore most of it. The simplest migration path from SDL2 looks something like this: SDL3's audio subsystem offers an enormous amount of power over SDL2, but if you just want a simple migration of your existing code, you can ignore most of it. The simplest migration path from SDL2 looks something like this:
In SDL2, you might have done something like this to play audio... In SDL2, you might have done something like this to play audio...
@ -114,7 +116,7 @@ In SDL2, you might have done something like this to play audio...
/* ...somewhere near startup... */ /* ...somewhere near startup... */
const SDL_AudioSpec spec = { SDL_AUDIO_S16, 2, 44100 }; const SDL_AudioSpec spec = { SDL_AUDIO_S16, 2, 44100 };
SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, MyNewAudioCallback, &my_audio_callback_user_data); SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, MyNewAudioCallback, &my_audio_callback_user_data);
SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream)); SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream));
``` ```
@ -123,7 +125,7 @@ If you used SDL_QueueAudio instead of a callback in SDL2, this is also straightf
```c ```c
/* ...somewhere near startup... */ /* ...somewhere near startup... */
const SDL_AudioSpec spec = { SDL_AUDIO_S16, 2, 44100 }; const SDL_AudioSpec spec = { SDL_AUDIO_S16, 2, 44100 };
SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, NULL, NULL); SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, NULL, NULL);
SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream)); SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream));
/* ...in your main loop... */ /* ...in your main loop... */
@ -132,7 +134,7 @@ If you used SDL_QueueAudio instead of a callback in SDL2, this is also straightf
``` ```
...these same migration examples apply to audio capture, just using SDL_GetAudioStreamData instead of SDL_PutAudioStreamData. ...these same migration examples apply to audio recording, just using SDL_GetAudioStreamData instead of SDL_PutAudioStreamData.
SDL_AudioInit() and SDL_AudioQuit() have been removed. Instead you can call SDL_InitSubSystem() and SDL_QuitSubSystem() with SDL_INIT_AUDIO, which will properly refcount the subsystems. You can choose a specific audio driver using SDL_AUDIO_DRIVER hint. SDL_AudioInit() and SDL_AudioQuit() have been removed. Instead you can call SDL_InitSubSystem() and SDL_QuitSubSystem() with SDL_INIT_AUDIO, which will properly refcount the subsystems. You can choose a specific audio driver using SDL_AUDIO_DRIVER hint.
@ -144,7 +146,7 @@ Devices are opened by physical device instance ID, and a new logical instance ID
Devices are not opened by an arbitrary string name anymore, but by device instance ID (or magic numbers to request a reasonable default, like a NULL string in SDL2). In SDL2, the string was used to open both a standard list of system devices, but also allowed for arbitrary devices, such as hostnames of network sound servers. In SDL3, many of the backends that supported arbitrary device names are obsolete and have been removed; of those that remain, arbitrary devices will be opened with a default device ID and an SDL_hint, so specific end-users can set an environment variable to fit their needs and apps don't have to concern themselves with it. Devices are not opened by an arbitrary string name anymore, but by device instance ID (or magic numbers to request a reasonable default, like a NULL string in SDL2). In SDL2, the string was used to open both a standard list of system devices, but also allowed for arbitrary devices, such as hostnames of network sound servers. In SDL3, many of the backends that supported arbitrary device names are obsolete and have been removed; of those that remain, arbitrary devices will be opened with a default device ID and an SDL_hint, so specific end-users can set an environment variable to fit their needs and apps don't have to concern themselves with it.
Many functions that would accept a device index and an `iscapture` parameter now just take an SDL_AudioDeviceID, as they are unique across all devices, instead of separate indices into output and capture device lists. Many functions that would accept a device index and an `iscapture` parameter now just take an SDL_AudioDeviceID, as they are unique across all devices, instead of separate indices into playback and recording device lists.
Rather than iterating over audio devices using a device index, there are new functions, SDL_GetAudioOutputDevices() and SDL_GetAudioCaptureDevices(), to get the current list of devices, and new functions to get information about devices from their instance ID: Rather than iterating over audio devices using a device index, there are new functions, SDL_GetAudioOutputDevices() and SDL_GetAudioCaptureDevices(), to get the current list of devices, and new functions to get information about devices from their instance ID:
@ -182,7 +184,7 @@ SDL_AudioSpec has been reduced; now it only holds format, channel, and sample ra
SDL_GetAudioDeviceSpec() is removed; use SDL_GetAudioDeviceFormat() instead. SDL_GetAudioDeviceSpec() is removed; use SDL_GetAudioDeviceFormat() instead.
SDL_GetDefaultAudioInfo() is removed; SDL_GetAudioDeviceFormat() with SDL_AUDIO_DEVICE_DEFAULT_OUTPUT or SDL_AUDIO_DEVICE_DEFAULT_CAPTURE. There is no replacement for querying the default device name; the string is no longer used to open devices, and SDL3 will migrate between physical devices on the fly if the system default changes, so if you must show this to the user, a generic name like "System default" is recommended. SDL_GetDefaultAudioInfo() is removed; SDL_GetAudioDeviceFormat() with SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK or SDL_AUDIO_DEVICE_DEFAULT_RECORDING. There is no replacement for querying the default device name; the string is no longer used to open devices, and SDL3 will migrate between physical devices on the fly if the system default changes, so if you must show this to the user, a generic name like "System default" is recommended.
SDL_MixAudioFormat() and SDL_MIX_MAXVOLUME have been removed in favour of SDL_MixAudio(), which now takes the audio format, and a float volume between 0.0 and 1.0. SDL_MixAudioFormat() and SDL_MIX_MAXVOLUME have been removed in favour of SDL_MixAudio(), which now takes the audio format, and a float volume between 0.0 and 1.0.
@ -353,6 +355,8 @@ The touchId and fingerId fields of SDL_TouchFingerEvent have been renamed touchI
The level field of SDL_JoyBatteryEvent has been split into state and percent. The level field of SDL_JoyBatteryEvent has been split into state and percent.
The iscapture field of SDL_AudioDeviceEvent has been renamed recording.
SDL_QUERY, SDL_IGNORE, SDL_ENABLE, and SDL_DISABLE have been removed. You can use the functions SDL_SetEventEnabled() and SDL_EventEnabled() to set and query event processing state. SDL_QUERY, SDL_IGNORE, SDL_ENABLE, and SDL_DISABLE have been removed. You can use the functions SDL_SetEventEnabled() and SDL_EventEnabled() to set and query event processing state.
SDL_AddEventWatch() now returns -1 if it fails because it ran out of memory and couldn't add the event watch callback. SDL_AddEventWatch() now returns -1 if it fails because it ran out of memory and couldn't add the event watch callback.

View File

@ -46,7 +46,7 @@ Here is a rough list of what works, and what doesn't:
* mouse input (unsupported on Windows Phone) * mouse input (unsupported on Windows Phone)
* audio, via SDL's WASAPI backend (if you want to record, your app must * audio, via SDL's WASAPI backend (if you want to record, your app must
have "Microphone" capabilities enabled in its manifest, and the user must have "Microphone" capabilities enabled in its manifest, and the user must
not have blocked access. Otherwise, capture devices will fail to work, not have blocked access. Otherwise, recording devices will fail to work,
presenting as a device disconnect shortly after opening it.) presenting as a device disconnect shortly after opening it.)
* .DLL file loading. Libraries *MUST* be packaged inside applications. Loading * .DLL file loading. Libraries *MUST* be packaged inside applications. Loading
anything outside of the app is not supported. anything outside of the app is not supported.

View File

@ -259,7 +259,7 @@ typedef Uint16 SDL_AudioFormat;
typedef Uint32 SDL_AudioDeviceID; typedef Uint32 SDL_AudioDeviceID;
/** /**
* A value used to request a default output audio device. * A value used to request a default playback audio device.
* *
* Several functions that require an SDL_AudioDeviceID will accept this value * Several functions that require an SDL_AudioDeviceID will accept this value
* to signify the app just wants the system to choose a default device instead * to signify the app just wants the system to choose a default device instead
@ -267,10 +267,10 @@ typedef Uint32 SDL_AudioDeviceID;
* *
* \since This macro is available since SDL 3.0.0. * \since This macro is available since SDL 3.0.0.
*/ */
#define SDL_AUDIO_DEVICE_DEFAULT_OUTPUT ((SDL_AudioDeviceID) 0xFFFFFFFF) #define SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK ((SDL_AudioDeviceID) 0xFFFFFFFF)
/** /**
* A value used to request a default capture audio device. * A value used to request a default recording audio device.
* *
* Several functions that require an SDL_AudioDeviceID will accept this value * Several functions that require an SDL_AudioDeviceID will accept this value
* to signify the app just wants the system to choose a default device instead * to signify the app just wants the system to choose a default device instead
@ -278,7 +278,7 @@ typedef Uint32 SDL_AudioDeviceID;
* *
* \since This macro is available since SDL 3.0.0. * \since This macro is available since SDL 3.0.0.
*/ */
#define SDL_AUDIO_DEVICE_DEFAULT_CAPTURE ((SDL_AudioDeviceID) 0xFFFFFFFE) #define SDL_AUDIO_DEVICE_DEFAULT_RECORDING ((SDL_AudioDeviceID) 0xFFFFFFFE)
/** /**
* Format specifier for audio data. * Format specifier for audio data.
@ -414,12 +414,12 @@ extern SDL_DECLSPEC const char *SDLCALL SDL_GetAudioDriver(int index);
extern SDL_DECLSPEC const char *SDLCALL SDL_GetCurrentAudioDriver(void); extern SDL_DECLSPEC const char *SDLCALL SDL_GetCurrentAudioDriver(void);
/** /**
* Get a list of currently-connected audio output devices. * Get a list of currently-connected audio playback devices.
* *
* This returns of list of available devices that play sound, perhaps to * This returns of list of available devices that play sound, perhaps to
* speakers or headphones ("output" devices). If you want devices that record * speakers or headphones ("playback" devices). If you want devices that record
* audio, like a microphone ("capture" devices), use * audio, like a microphone ("recording" devices), use
* SDL_GetAudioCaptureDevices() instead. * SDL_GetAudioRecordingDevices() instead.
* *
* This only returns a list of physical devices; it will not have any device * This only returns a list of physical devices; it will not have any device
* IDs returned by SDL_OpenAudioDevice(). * IDs returned by SDL_OpenAudioDevice().
@ -438,17 +438,17 @@ extern SDL_DECLSPEC const char *SDLCALL SDL_GetCurrentAudioDriver(void);
* \since This function is available since SDL 3.0.0. * \since This function is available since SDL 3.0.0.
* *
* \sa SDL_OpenAudioDevice * \sa SDL_OpenAudioDevice
* \sa SDL_GetAudioCaptureDevices * \sa SDL_GetAudioRecordingDevices
*/ */
extern SDL_DECLSPEC SDL_AudioDeviceID *SDLCALL SDL_GetAudioOutputDevices(int *count); extern SDL_DECLSPEC SDL_AudioDeviceID *SDLCALL SDL_GetAudioPlaybackDevices(int *count);
/** /**
* Get a list of currently-connected audio capture devices. * Get a list of currently-connected audio recording devices.
* *
* This returns of list of available devices that record audio, like a * This returns of list of available devices that record audio, like a
* microphone ("capture" devices). If you want devices that play sound, * microphone ("recording" devices). If you want devices that play sound,
* perhaps to speakers or headphones ("output" devices), use * perhaps to speakers or headphones ("playback" devices), use
* SDL_GetAudioOutputDevices() instead. * SDL_GetAudioPlaybackDevices() instead.
* *
* This only returns a list of physical devices; it will not have any device * This only returns a list of physical devices; it will not have any device
* IDs returned by SDL_OpenAudioDevice(). * IDs returned by SDL_OpenAudioDevice().
@ -467,9 +467,9 @@ extern SDL_DECLSPEC SDL_AudioDeviceID *SDLCALL SDL_GetAudioOutputDevices(int *co
* \since This function is available since SDL 3.0.0. * \since This function is available since SDL 3.0.0.
* *
* \sa SDL_OpenAudioDevice * \sa SDL_OpenAudioDevice
* \sa SDL_GetAudioOutputDevices * \sa SDL_GetAudioPlaybackDevices
*/ */
extern SDL_DECLSPEC SDL_AudioDeviceID *SDLCALL SDL_GetAudioCaptureDevices(int *count); extern SDL_DECLSPEC SDL_AudioDeviceID *SDLCALL SDL_GetAudioRecordingDevices(int *count);
/** /**
* Get the human-readable name of a specific audio device. * Get the human-readable name of a specific audio device.
@ -483,8 +483,8 @@ extern SDL_DECLSPEC SDL_AudioDeviceID *SDLCALL SDL_GetAudioCaptureDevices(int *c
* *
* \since This function is available since SDL 3.0.0. * \since This function is available since SDL 3.0.0.
* *
* \sa SDL_GetAudioOutputDevices * \sa SDL_GetAudioPlaybackDevices
* \sa SDL_GetAudioCaptureDevices * \sa SDL_GetAudioRecordingDevices
* \sa SDL_GetDefaultAudioInfo * \sa SDL_GetDefaultAudioInfo
*/ */
extern SDL_DECLSPEC const char *SDLCALL SDL_GetAudioDeviceName(SDL_AudioDeviceID devid); extern SDL_DECLSPEC const char *SDLCALL SDL_GetAudioDeviceName(SDL_AudioDeviceID devid);
@ -496,8 +496,8 @@ extern SDL_DECLSPEC const char *SDLCALL SDL_GetAudioDeviceName(SDL_AudioDeviceID
* using. If the device isn't yet opened, this will report the device's * using. If the device isn't yet opened, this will report the device's
* preferred format (or a reasonable default if this can't be determined). * preferred format (or a reasonable default if this can't be determined).
* *
* You may also specify SDL_AUDIO_DEVICE_DEFAULT_OUTPUT or * You may also specify SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK or
* SDL_AUDIO_DEVICE_DEFAULT_CAPTURE here, which is useful for getting a * SDL_AUDIO_DEVICE_DEFAULT_RECORDING here, which is useful for getting a
* reasonable recommendation before opening the system-recommended default * reasonable recommendation before opening the system-recommended default
* device. * device.
* *
@ -528,9 +528,9 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid
/** /**
* Open a specific audio device. * Open a specific audio device.
* *
* You can open both output and capture devices through this function. Output * You can open both playback and recording devices through this function. Playback
* devices will take data from bound audio streams, mix it, and send it to the * devices will take data from bound audio streams, mix it, and send it to the
* hardware. Capture devices will feed any bound audio streams with a copy of * hardware. Recording devices will feed any bound audio streams with a copy of
* any incoming data. * any incoming data.
* *
* An opened audio device starts out with no audio streams bound. To start * An opened audio device starts out with no audio streams bound. To start
@ -541,7 +541,7 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid
* function). * function).
* *
* If you don't care about opening a specific device, pass a `devid` of either * If you don't care about opening a specific device, pass a `devid` of either
* `SDL_AUDIO_DEVICE_DEFAULT_OUTPUT` or `SDL_AUDIO_DEVICE_DEFAULT_CAPTURE`. In * `SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK` or `SDL_AUDIO_DEVICE_DEFAULT_RECORDING`. In
* this case, SDL will try to pick the most reasonable default, and may also * this case, SDL will try to pick the most reasonable default, and may also
* switch between physical devices seamlessly later, if the most reasonable * switch between physical devices seamlessly later, if the most reasonable
* default changes during the lifetime of this opened device (user changed the * default changes during the lifetime of this opened device (user changed the
@ -583,8 +583,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid
* should call SDL_CloseAudioDevice() on the returned device id. * should call SDL_CloseAudioDevice() on the returned device id.
* *
* \param devid the device instance id to open, or * \param devid the device instance id to open, or
* SDL_AUDIO_DEVICE_DEFAULT_OUTPUT or * SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK or
* SDL_AUDIO_DEVICE_DEFAULT_CAPTURE for the most reasonable * SDL_AUDIO_DEVICE_DEFAULT_RECORDING for the most reasonable
* default device. * default device.
* \param spec the requested device configuration. Can be NULL to use * \param spec the requested device configuration. Can be NULL to use
* reasonable defaults. * reasonable defaults.
@ -705,9 +705,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_CloseAudioDevice(SDL_AudioDeviceID devid);
/** /**
* Bind a list of audio streams to an audio device. * Bind a list of audio streams to an audio device.
* *
* Audio data will flow through any bound streams. For an output device, data * Audio data will flow through any bound streams. For a playback device, data
* for all bound streams will be mixed together and fed to the device. For a * for all bound streams will be mixed together and fed to the device. For a
* capture device, a copy of recorded data will be provided to each bound * recording device, a copy of recorded data will be provided to each bound
* stream. * stream.
* *
* Audio streams can only be bound to an open device. This operation is * Audio streams can only be bound to an open device. This operation is
@ -718,8 +718,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_CloseAudioDevice(SDL_AudioDeviceID devid);
* It is an error to bind an already-bound stream; it must be explicitly * It is an error to bind an already-bound stream; it must be explicitly
* unbound first. * unbound first.
* *
* Binding a stream to a device will set its output format for output devices, * Binding a stream to a device will set its output format for playback devices,
* and its input format for capture devices, so they match the device's * and its input format for recording devices, so they match the device's
* settings. The caller is welcome to change the other end of the stream's * settings. The caller is welcome to change the other end of the stream's
* format at any time. * format at any time.
* *
@ -832,7 +832,7 @@ extern SDL_DECLSPEC SDL_AudioDeviceID SDLCALL SDL_GetAudioStreamDevice(SDL_Audio
* \sa SDL_GetAudioStreamAvailable * \sa SDL_GetAudioStreamAvailable
* \sa SDL_FlushAudioStream * \sa SDL_FlushAudioStream
* \sa SDL_ClearAudioStream * \sa SDL_ClearAudioStream
* \sa SDL_ChangeAudioStreamOutput * \sa SDL_SetAudioStreamFormat
* \sa SDL_DestroyAudioStream * \sa SDL_DestroyAudioStream
*/ */
extern SDL_DECLSPEC SDL_AudioStream *SDLCALL SDL_CreateAudioStream(const SDL_AudioSpec *src_spec, const SDL_AudioSpec *dst_spec); extern SDL_DECLSPEC SDL_AudioStream *SDLCALL SDL_CreateAudioStream(const SDL_AudioSpec *src_spec, const SDL_AudioSpec *dst_spec);
@ -863,6 +863,8 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetAudioStreamProperties(SDL_Au
* a stream-specific mutex while running. * a stream-specific mutex while running.
* *
* \since This function is available since SDL 3.0.0. * \since This function is available since SDL 3.0.0.
*
* \sa SDL_SetAudioStreamFormat
*/ */
extern SDL_DECLSPEC int SDLCALL SDL_GetAudioStreamFormat(SDL_AudioStream *stream, extern SDL_DECLSPEC int SDLCALL SDL_GetAudioStreamFormat(SDL_AudioStream *stream,
SDL_AudioSpec *src_spec, SDL_AudioSpec *src_spec,
@ -1367,7 +1369,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_DestroyAudioStream(SDL_AudioStream *stream)
* bind a stream to begin audio flowing. The audio device should be resumed * bind a stream to begin audio flowing. The audio device should be resumed
* with `SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream));` * with `SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream));`
* *
* This function works with both playback and capture devices. * This function works with both playback and recording devices.
* *
* The `spec` parameter represents the app's side of the audio stream. That * The `spec` parameter represents the app's side of the audio stream. That
* is, for recording audio, this will be the output format, and for playing * is, for recording audio, this will be the output format, and for playing
@ -1376,8 +1378,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_DestroyAudioStream(SDL_AudioStream *stream)
* this information later. * this information later.
* *
* If you don't care about opening a specific audio device, you can (and * If you don't care about opening a specific audio device, you can (and
* probably _should_), use SDL_AUDIO_DEVICE_DEFAULT_OUTPUT for playback and * probably _should_), use SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK for playback and
* SDL_AUDIO_DEVICE_DEFAULT_CAPTURE for recording. * SDL_AUDIO_DEVICE_DEFAULT_RECORDING for recording.
* *
* One can optionally provide a callback function; if NULL, the app is * One can optionally provide a callback function; if NULL, the app is
* expected to queue audio data for playback (or unqueue audio data if * expected to queue audio data for playback (or unqueue audio data if
@ -1387,11 +1389,11 @@ extern SDL_DECLSPEC void SDLCALL SDL_DestroyAudioStream(SDL_AudioStream *stream)
* Destroying the returned stream with SDL_DestroyAudioStream will also close * Destroying the returned stream with SDL_DestroyAudioStream will also close
* the audio device associated with this stream. * the audio device associated with this stream.
* *
* \param devid an audio device to open, or SDL_AUDIO_DEVICE_DEFAULT_OUTPUT or * \param devid an audio device to open, or SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK or
* SDL_AUDIO_DEVICE_DEFAULT_CAPTURE. * SDL_AUDIO_DEVICE_DEFAULT_RECORDING.
* \param spec the audio stream's data format. Can be NULL. * \param spec the audio stream's data format. Can be NULL.
* \param callback a callback where the app will provide new data for * \param callback a callback where the app will provide new data for
* playback, or receive new data for capture. Can be NULL, in * playback, or receive new data for recording. Can be NULL, in
* which case the app will need to call SDL_PutAudioStreamData * which case the app will need to call SDL_PutAudioStreamData
* or SDL_GetAudioStreamData as necessary. * or SDL_GetAudioStreamData as necessary.
* \param userdata app-controlled pointer passed to callback. Can be NULL. * \param userdata app-controlled pointer passed to callback. Can be NULL.

View File

@ -264,7 +264,7 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetCameraDeviceName(SDL_CameraDevic
extern SDL_DECLSPEC SDL_CameraPosition SDLCALL SDL_GetCameraDevicePosition(SDL_CameraDeviceID instance_id); extern SDL_DECLSPEC SDL_CameraPosition SDLCALL SDL_GetCameraDevicePosition(SDL_CameraDeviceID instance_id);
/** /**
* Open a video capture device (a "camera"). * Open a video recording device (a "camera").
* *
* You can open the device with any reasonable spec, and if the hardware can't * You can open the device with any reasonable spec, and if the hardware can't
* directly support it, it will convert data seamlessly to the requested * directly support it, it will convert data seamlessly to the requested

View File

@ -628,7 +628,7 @@ typedef struct SDL_AudioDeviceEvent
Uint32 reserved; Uint32 reserved;
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_AudioDeviceID which; /**< SDL_AudioDeviceID for the device being added or removed or changing */ SDL_AudioDeviceID which; /**< SDL_AudioDeviceID for the device being added or removed or changing */
Uint8 iscapture; /**< zero if an output device, non-zero if a capture device. */ Uint8 recording; /**< zero if a playback device, non-zero if a recording device. */
Uint8 padding1; Uint8 padding1;
Uint8 padding2; Uint8 padding2;
Uint8 padding3; Uint8 padding3;

View File

@ -370,7 +370,7 @@ extern "C" {
* Some audio backends (such as Pipewire) allow you to describe the role of * Some audio backends (such as Pipewire) allow you to describe the role of
* your audio stream. Among other things, this description might show up in a * your audio stream. Among other things, this description might show up in a
* system control panel or software for displaying and manipulating media * system control panel or software for displaying and manipulating media
* playback/capture graphs. * playback/recording graphs.
* *
* This hints lets you transmit that information to the OS. The contents of * This hints lets you transmit that information to the OS. The contents of
* this hint are used while opening an audio device. You should use a string * this hint are used while opening an audio device. You should use a string

View File

@ -226,7 +226,7 @@ static SDL_bool AudioDeviceCanUseSimpleCopy(SDL_AudioDevice *device)
// should hold device->lock before calling. // should hold device->lock before calling.
static void UpdateAudioStreamFormatsPhysical(SDL_AudioDevice *device) static void UpdateAudioStreamFormatsPhysical(SDL_AudioDevice *device)
{ {
if (!device->iscapture) { // for capture devices, we only want to move to float32 for postmix, which we'll handle elsewhere. if (!device->recording) { // for recording devices, we only want to move to float32 for postmix, which we'll handle elsewhere.
const SDL_bool simple_copy = AudioDeviceCanUseSimpleCopy(device); const SDL_bool simple_copy = AudioDeviceCanUseSimpleCopy(device);
SDL_AudioSpec spec; SDL_AudioSpec spec;
@ -273,14 +273,14 @@ static Uint8 *ZombieGetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
return device->work_buffer; return device->work_buffer;
} }
static int ZombieCaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int ZombieRecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
{ {
// return a full buffer of silence every time. // return a full buffer of silence every time.
SDL_memset(buffer, device->silence_value, buflen); SDL_memset(buffer, device->silence_value, buflen);
return buflen; return buflen;
} }
static void ZombieFlushCapture(SDL_AudioDevice *device) static void ZombieFlushRecording(SDL_AudioDevice *device)
{ {
// no-op, this is all imaginary. // no-op, this is all imaginary.
} }
@ -303,19 +303,19 @@ static void ZombieFlushCapture(SDL_AudioDevice *device)
static void ClosePhysicalAudioDevice(SDL_AudioDevice *device); static void ClosePhysicalAudioDevice(SDL_AudioDevice *device);
SDL_COMPILE_TIME_ASSERT(check_lowest_audio_default_value, SDL_AUDIO_DEVICE_DEFAULT_CAPTURE < SDL_AUDIO_DEVICE_DEFAULT_OUTPUT); SDL_COMPILE_TIME_ASSERT(check_lowest_audio_default_value, SDL_AUDIO_DEVICE_DEFAULT_RECORDING < SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK);
static SDL_AtomicInt last_device_instance_id; // increments on each device add to provide unique instance IDs static SDL_AtomicInt last_device_instance_id; // increments on each device add to provide unique instance IDs
static SDL_AudioDeviceID AssignAudioDeviceInstanceId(SDL_bool iscapture, SDL_bool islogical) static SDL_AudioDeviceID AssignAudioDeviceInstanceId(SDL_bool recording, SDL_bool islogical)
{ {
/* Assign an instance id! Start at 2, in case there are things from the SDL2 era that still think 1 is a special value. /* Assign an instance id! Start at 2, in case there are things from the SDL2 era that still think 1 is a special value.
Also, make sure we don't assign SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, etc. */ Also, make sure we don't assign SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, etc. */
// The bottom two bits of the instance id tells you if it's an output device (1<<0), and if it's a physical device (1<<1). // The bottom two bits of the instance id tells you if it's an playback device (1<<0), and if it's a physical device (1<<1).
const SDL_AudioDeviceID flags = (iscapture ? 0 : (1<<0)) | (islogical ? 0 : (1<<1)); const SDL_AudioDeviceID flags = (recording ? 0 : (1<<0)) | (islogical ? 0 : (1<<1));
const SDL_AudioDeviceID instance_id = (((SDL_AudioDeviceID) (SDL_AtomicIncRef(&last_device_instance_id) + 1)) << 2) | flags; const SDL_AudioDeviceID instance_id = (((SDL_AudioDeviceID) (SDL_AtomicIncRef(&last_device_instance_id) + 1)) << 2) | flags;
SDL_assert( (instance_id >= 2) && (instance_id < SDL_AUDIO_DEVICE_DEFAULT_CAPTURE) ); SDL_assert( (instance_id >= 2) && (instance_id < SDL_AUDIO_DEVICE_DEFAULT_RECORDING) );
return instance_id; return instance_id;
} }
@ -418,7 +418,7 @@ static SDL_AudioDevice *ObtainPhysicalAudioDevice(SDL_AudioDeviceID devid) // !
static SDL_AudioDevice *ObtainPhysicalAudioDeviceDefaultAllowed(SDL_AudioDeviceID devid) // !!! FIXME: SDL_ACQUIRE static SDL_AudioDevice *ObtainPhysicalAudioDeviceDefaultAllowed(SDL_AudioDeviceID devid) // !!! FIXME: SDL_ACQUIRE
{ {
const SDL_bool wants_default = ((devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) || (devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE)); const SDL_bool wants_default = ((devid == SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK) || (devid == SDL_AUDIO_DEVICE_DEFAULT_RECORDING));
if (!wants_default) { if (!wants_default) {
return ObtainPhysicalAudioDevice(devid); return ObtainPhysicalAudioDevice(devid);
} }
@ -427,10 +427,10 @@ static SDL_AudioDevice *ObtainPhysicalAudioDeviceDefaultAllowed(SDL_AudioDeviceI
while (SDL_TRUE) { while (SDL_TRUE) {
SDL_LockRWLockForReading(current_audio.device_hash_lock); SDL_LockRWLockForReading(current_audio.device_hash_lock);
if (orig_devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) { if (orig_devid == SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK) {
devid = current_audio.default_output_device_id; devid = current_audio.default_playback_device_id;
} else if (orig_devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE) { } else if (orig_devid == SDL_AUDIO_DEVICE_DEFAULT_RECORDING) {
devid = current_audio.default_capture_device_id; devid = current_audio.default_recording_device_id;
} }
SDL_UnlockRWLock(current_audio.device_hash_lock); SDL_UnlockRWLock(current_audio.device_hash_lock);
@ -447,9 +447,9 @@ static SDL_AudioDevice *ObtainPhysicalAudioDeviceDefaultAllowed(SDL_AudioDeviceI
// make sure the default didn't change while we were waiting for the lock... // make sure the default didn't change while we were waiting for the lock...
SDL_bool got_it = SDL_FALSE; SDL_bool got_it = SDL_FALSE;
SDL_LockRWLockForReading(current_audio.device_hash_lock); SDL_LockRWLockForReading(current_audio.device_hash_lock);
if ((orig_devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) && (devid == current_audio.default_output_device_id)) { if ((orig_devid == SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK) && (devid == current_audio.default_playback_device_id)) {
got_it = SDL_TRUE; got_it = SDL_TRUE;
} else if ((orig_devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE) && (devid == current_audio.default_capture_device_id)) { } else if ((orig_devid == SDL_AUDIO_DEVICE_DEFAULT_RECORDING) && (devid == current_audio.default_recording_device_id)) {
got_it = SDL_TRUE; got_it = SDL_TRUE;
} }
SDL_UnlockRWLock(current_audio.device_hash_lock); SDL_UnlockRWLock(current_audio.device_hash_lock);
@ -534,7 +534,7 @@ void UnrefPhysicalAudioDevice(SDL_AudioDevice *device)
// take it out of the device list. // take it out of the device list.
SDL_LockRWLockForWriting(current_audio.device_hash_lock); SDL_LockRWLockForWriting(current_audio.device_hash_lock);
if (SDL_RemoveFromHashTable(current_audio.device_hash, (const void *) (uintptr_t) device->instance_id)) { if (SDL_RemoveFromHashTable(current_audio.device_hash, (const void *) (uintptr_t) device->instance_id)) {
SDL_AtomicAdd(device->iscapture ? &current_audio.capture_device_count : &current_audio.output_device_count, -1); SDL_AtomicAdd(device->recording ? &current_audio.recording_device_count : &current_audio.playback_device_count, -1);
} }
SDL_UnlockRWLock(current_audio.device_hash_lock); SDL_UnlockRWLock(current_audio.device_hash_lock);
DestroyPhysicalAudioDevice(device); // ...and nuke it. DestroyPhysicalAudioDevice(device); // ...and nuke it.
@ -546,7 +546,7 @@ void RefPhysicalAudioDevice(SDL_AudioDevice *device)
SDL_AtomicIncRef(&device->refcount); SDL_AtomicIncRef(&device->refcount);
} }
static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool iscapture, const SDL_AudioSpec *spec, void *handle, SDL_AtomicInt *device_count) static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool recording, const SDL_AudioSpec *spec, void *handle, SDL_AtomicInt *device_count)
{ {
SDL_assert(name != NULL); SDL_assert(name != NULL);
@ -585,14 +585,14 @@ static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool isc
SDL_AtomicSet(&device->shutdown, 0); SDL_AtomicSet(&device->shutdown, 0);
SDL_AtomicSet(&device->zombie, 0); SDL_AtomicSet(&device->zombie, 0);
device->iscapture = iscapture; device->recording = recording;
SDL_copyp(&device->spec, spec); SDL_copyp(&device->spec, spec);
SDL_copyp(&device->default_spec, spec); SDL_copyp(&device->default_spec, spec);
device->sample_frames = GetDefaultSampleFramesFromFreq(device->spec.freq); device->sample_frames = GetDefaultSampleFramesFromFreq(device->spec.freq);
device->silence_value = SDL_GetSilenceValueForFormat(device->spec.format); device->silence_value = SDL_GetSilenceValueForFormat(device->spec.format);
device->handle = handle; device->handle = handle;
device->instance_id = AssignAudioDeviceInstanceId(iscapture, /*islogical=*/SDL_FALSE); device->instance_id = AssignAudioDeviceInstanceId(recording, /*islogical=*/SDL_FALSE);
SDL_LockRWLockForWriting(current_audio.device_hash_lock); SDL_LockRWLockForWriting(current_audio.device_hash_lock);
if (SDL_InsertIntoHashTable(current_audio.device_hash, (const void *) (uintptr_t) device->instance_id, device)) { if (SDL_InsertIntoHashTable(current_audio.device_hash, (const void *) (uintptr_t) device->instance_id, device)) {
@ -610,26 +610,26 @@ static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool isc
return device; return device;
} }
static SDL_AudioDevice *CreateAudioCaptureDevice(const char *name, const SDL_AudioSpec *spec, void *handle) static SDL_AudioDevice *CreateAudioRecordingDevice(const char *name, const SDL_AudioSpec *spec, void *handle)
{ {
SDL_assert(current_audio.impl.HasCaptureSupport); SDL_assert(current_audio.impl.HasRecordingSupport);
return CreatePhysicalAudioDevice(name, SDL_TRUE, spec, handle, &current_audio.capture_device_count); return CreatePhysicalAudioDevice(name, SDL_TRUE, spec, handle, &current_audio.recording_device_count);
} }
static SDL_AudioDevice *CreateAudioOutputDevice(const char *name, const SDL_AudioSpec *spec, void *handle) static SDL_AudioDevice *CreateAudioPlaybackDevice(const char *name, const SDL_AudioSpec *spec, void *handle)
{ {
return CreatePhysicalAudioDevice(name, SDL_FALSE, spec, handle, &current_audio.output_device_count); return CreatePhysicalAudioDevice(name, SDL_FALSE, spec, handle, &current_audio.playback_device_count);
} }
// The audio backends call this when a new device is plugged in. // The audio backends call this when a new device is plugged in.
SDL_AudioDevice *SDL_AddAudioDevice(const SDL_bool iscapture, const char *name, const SDL_AudioSpec *inspec, void *handle) SDL_AudioDevice *SDL_AddAudioDevice(const SDL_bool recording, const char *name, const SDL_AudioSpec *inspec, void *handle)
{ {
// device handles MUST be unique! If the target reuses the same handle for hardware with both input and output interfaces, wrap it in a pointer you SDL_malloc'd! // device handles MUST be unique! If the target reuses the same handle for hardware with both recording and playback interfaces, wrap it in a pointer you SDL_malloc'd!
SDL_assert(SDL_FindPhysicalAudioDeviceByHandle(handle) == NULL); SDL_assert(SDL_FindPhysicalAudioDeviceByHandle(handle) == NULL);
const SDL_AudioFormat default_format = iscapture ? DEFAULT_AUDIO_CAPTURE_FORMAT : DEFAULT_AUDIO_OUTPUT_FORMAT; const SDL_AudioFormat default_format = recording ? DEFAULT_AUDIO_RECORDING_FORMAT : DEFAULT_AUDIO_PLAYBACK_FORMAT;
const int default_channels = iscapture ? DEFAULT_AUDIO_CAPTURE_CHANNELS : DEFAULT_AUDIO_OUTPUT_CHANNELS; const int default_channels = recording ? DEFAULT_AUDIO_RECORDING_CHANNELS : DEFAULT_AUDIO_PLAYBACK_CHANNELS;
const int default_freq = iscapture ? DEFAULT_AUDIO_CAPTURE_FREQUENCY : DEFAULT_AUDIO_OUTPUT_FREQUENCY; const int default_freq = recording ? DEFAULT_AUDIO_RECORDING_FREQUENCY : DEFAULT_AUDIO_PLAYBACK_FREQUENCY;
SDL_AudioSpec spec; SDL_AudioSpec spec;
if (!inspec) { if (!inspec) {
@ -642,7 +642,7 @@ SDL_AudioDevice *SDL_AddAudioDevice(const SDL_bool iscapture, const char *name,
spec.freq = (inspec->freq != 0) ? inspec->freq : default_freq; spec.freq = (inspec->freq != 0) ? inspec->freq : default_freq;
} }
SDL_AudioDevice *device = iscapture ? CreateAudioCaptureDevice(name, &spec, handle) : CreateAudioOutputDevice(name, &spec, handle); SDL_AudioDevice *device = recording ? CreateAudioRecordingDevice(name, &spec, handle) : CreateAudioPlaybackDevice(name, &spec, handle);
// Add a device add event to the pending list, to be pushed when the event queue is pumped (away from any of our internal threads). // Add a device add event to the pending list, to be pushed when the event queue is pumped (away from any of our internal threads).
if (device) { if (device) {
@ -682,7 +682,7 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device)
SDL_LockRWLockForReading(current_audio.device_hash_lock); SDL_LockRWLockForReading(current_audio.device_hash_lock);
const SDL_AudioDeviceID devid = device->instance_id; const SDL_AudioDeviceID devid = device->instance_id;
const SDL_bool is_default_device = ((devid == current_audio.default_output_device_id) || (devid == current_audio.default_capture_device_id)); const SDL_bool is_default_device = ((devid == current_audio.default_playback_device_id) || (devid == current_audio.default_recording_device_id));
SDL_UnlockRWLock(current_audio.device_hash_lock); SDL_UnlockRWLock(current_audio.device_hash_lock);
const SDL_bool first_disconnect = SDL_AtomicCompareAndSwap(&device->zombie, 0, 1); const SDL_bool first_disconnect = SDL_AtomicCompareAndSwap(&device->zombie, 0, 1);
@ -694,9 +694,9 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device)
device->WaitDevice = ZombieWaitDevice; device->WaitDevice = ZombieWaitDevice;
device->GetDeviceBuf = ZombieGetDeviceBuf; device->GetDeviceBuf = ZombieGetDeviceBuf;
device->PlayDevice = ZombiePlayDevice; device->PlayDevice = ZombiePlayDevice;
device->WaitCaptureDevice = ZombieWaitDevice; device->WaitRecordingDevice = ZombieWaitDevice;
device->CaptureFromDevice = ZombieCaptureFromDevice; device->RecordDevice = ZombieRecordDevice;
device->FlushCapture = ZombieFlushCapture; device->FlushRecording = ZombieFlushRecording;
// on default devices, dump any logical devices that explicitly opened this device. Things that opened the system default can stay. // on default devices, dump any logical devices that explicitly opened this device. Things that opened the system default can stay.
// on non-default devices, dump everything. // on non-default devices, dump everything.
@ -746,8 +746,8 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device)
static void SDL_AudioThreadDeinit_Default(SDL_AudioDevice *device) { /* no-op. */ } static void SDL_AudioThreadDeinit_Default(SDL_AudioDevice *device) { /* no-op. */ }
static int SDL_AudioWaitDevice_Default(SDL_AudioDevice *device) { return 0; /* no-op. */ } static int SDL_AudioWaitDevice_Default(SDL_AudioDevice *device) { return 0; /* no-op. */ }
static int SDL_AudioPlayDevice_Default(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) { return 0; /* no-op. */ } static int SDL_AudioPlayDevice_Default(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) { return 0; /* no-op. */ }
static int SDL_AudioWaitCaptureDevice_Default(SDL_AudioDevice *device) { return 0; /* no-op. */ } static int SDL_AudioWaitRecordingDevice_Default(SDL_AudioDevice *device) { return 0; /* no-op. */ }
static void SDL_AudioFlushCapture_Default(SDL_AudioDevice *device) { /* no-op. */ } static void SDL_AudioFlushRecording_Default(SDL_AudioDevice *device) { /* no-op. */ }
static void SDL_AudioCloseDevice_Default(SDL_AudioDevice *device) { /* no-op. */ } static void SDL_AudioCloseDevice_Default(SDL_AudioDevice *device) { /* no-op. */ }
static void SDL_AudioDeinitializeStart_Default(void) { /* no-op. */ } static void SDL_AudioDeinitializeStart_Default(void) { /* no-op. */ }
static void SDL_AudioDeinitialize_Default(void) { /* no-op. */ } static void SDL_AudioDeinitialize_Default(void) { /* no-op. */ }
@ -755,18 +755,18 @@ static void SDL_AudioFreeDeviceHandle_Default(SDL_AudioDevice *device) { /* no-o
static void SDL_AudioThreadInit_Default(SDL_AudioDevice *device) static void SDL_AudioThreadInit_Default(SDL_AudioDevice *device)
{ {
SDL_SetThreadPriority(device->iscapture ? SDL_THREAD_PRIORITY_HIGH : SDL_THREAD_PRIORITY_TIME_CRITICAL); SDL_SetThreadPriority(device->recording ? SDL_THREAD_PRIORITY_HIGH : SDL_THREAD_PRIORITY_TIME_CRITICAL);
} }
static void SDL_AudioDetectDevices_Default(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) static void SDL_AudioDetectDevices_Default(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{ {
// you have to write your own implementation if these assertions fail. // you have to write your own implementation if these assertions fail.
SDL_assert(current_audio.impl.OnlyHasDefaultOutputDevice); SDL_assert(current_audio.impl.OnlyHasDefaultPlaybackDevice);
SDL_assert(current_audio.impl.OnlyHasDefaultCaptureDevice || !current_audio.impl.HasCaptureSupport); SDL_assert(current_audio.impl.OnlyHasDefaultRecordingDevice || !current_audio.impl.HasRecordingSupport);
*default_output = SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, NULL, (void *)((size_t)0x1)); *default_playback = SDL_AddAudioDevice(SDL_FALSE, DEFAULT_PLAYBACK_DEVNAME, NULL, (void *)((size_t)0x1));
if (current_audio.impl.HasCaptureSupport) { if (current_audio.impl.HasRecordingSupport) {
*default_capture = SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, NULL, (void *)((size_t)0x2)); *default_recording = SDL_AddAudioDevice(SDL_TRUE, DEFAULT_RECORDING_DEVNAME, NULL, (void *)((size_t)0x2));
} }
} }
@ -776,7 +776,7 @@ static Uint8 *SDL_AudioGetDeviceBuf_Default(SDL_AudioDevice *device, int *buffer
return NULL; return NULL;
} }
static int SDL_AudioCaptureFromDevice_Default(SDL_AudioDevice *device, void *buffer, int buflen) static int SDL_AudioRecordDevice_Default(SDL_AudioDevice *device, void *buffer, int buflen)
{ {
return SDL_Unsupported(); return SDL_Unsupported();
} }
@ -797,9 +797,9 @@ static void CompleteAudioEntryPoints(void)
FILL_STUB(WaitDevice); FILL_STUB(WaitDevice);
FILL_STUB(PlayDevice); FILL_STUB(PlayDevice);
FILL_STUB(GetDeviceBuf); FILL_STUB(GetDeviceBuf);
FILL_STUB(WaitCaptureDevice); FILL_STUB(WaitRecordingDevice);
FILL_STUB(CaptureFromDevice); FILL_STUB(RecordDevice);
FILL_STUB(FlushCapture); FILL_STUB(FlushRecording);
FILL_STUB(CloseDevice); FILL_STUB(CloseDevice);
FILL_STUB(FreeDeviceHandle); FILL_STUB(FreeDeviceHandle);
FILL_STUB(DeinitializeStart); FILL_STUB(DeinitializeStart);
@ -807,9 +807,9 @@ static void CompleteAudioEntryPoints(void)
#undef FILL_STUB #undef FILL_STUB
} }
static SDL_AudioDevice *GetFirstAddedAudioDevice(const SDL_bool iscapture) static SDL_AudioDevice *GetFirstAddedAudioDevice(const SDL_bool recording)
{ {
SDL_AudioDeviceID highest = (SDL_AudioDeviceID) SDL_AUDIO_DEVICE_DEFAULT_OUTPUT; // According to AssignAudioDeviceInstanceId, nothing can have a value this large. SDL_AudioDeviceID highest = (SDL_AudioDeviceID) SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK; // According to AssignAudioDeviceInstanceId, nothing can have a value this large.
SDL_AudioDevice *retval = NULL; SDL_AudioDevice *retval = NULL;
// (Device IDs increase as new devices are added, so the first device added has the lowest SDL_AudioDeviceID value.) // (Device IDs increase as new devices are added, so the first device added has the lowest SDL_AudioDeviceID value.)
@ -820,11 +820,11 @@ static SDL_AudioDevice *GetFirstAddedAudioDevice(const SDL_bool iscapture)
void *iter = NULL; void *iter = NULL;
while (SDL_IterateHashTable(current_audio.device_hash, &key, &value, &iter)) { while (SDL_IterateHashTable(current_audio.device_hash, &key, &value, &iter)) {
const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key; const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key;
// bit #0 of devid is set for output devices and unset for capture. // bit #0 of devid is set for playback devices and unset for recording.
// bit #1 of devid is set for physical devices and unset for logical. // bit #1 of devid is set for physical devices and unset for logical.
const SDL_bool devid_iscapture = !(devid & (1 << 0)); const SDL_bool devid_recording = !(devid & (1 << 0));
const SDL_bool isphysical = (devid & (1 << 1)); const SDL_bool isphysical = (devid & (1 << 1));
if (isphysical && (devid_iscapture == iscapture) && (devid < highest)) { if (isphysical && (devid_recording == recording) && (devid < highest)) {
highest = devid; highest = devid;
retval = (SDL_AudioDevice *) value; retval = (SDL_AudioDevice *) value;
} }
@ -837,7 +837,7 @@ static SDL_AudioDevice *GetFirstAddedAudioDevice(const SDL_bool iscapture)
static Uint32 HashAudioDeviceID(const void *key, void *data) static Uint32 HashAudioDeviceID(const void *key, void *data)
{ {
// shift right 2, to dump the first two bits, since these are flags // shift right 2, to dump the first two bits, since these are flags
// (capture vs playback, logical vs physical) and the rest are unique incrementing integers. // (recording vs playback, logical vs physical) and the rest are unique incrementing integers.
return ((Uint32) ((uintptr_t) key)) >> 2; return ((Uint32) ((uintptr_t) key)) >> 2;
} }
@ -964,27 +964,27 @@ int SDL_InitAudio(const char *driver_name)
CompleteAudioEntryPoints(); CompleteAudioEntryPoints();
// Make sure we have a list of devices available at startup... // Make sure we have a list of devices available at startup...
SDL_AudioDevice *default_output = NULL; SDL_AudioDevice *default_playback = NULL;
SDL_AudioDevice *default_capture = NULL; SDL_AudioDevice *default_recording = NULL;
current_audio.impl.DetectDevices(&default_output, &default_capture); current_audio.impl.DetectDevices(&default_playback, &default_recording);
// If no default was _ever_ specified, just take the first device we see, if any. // If no default was _ever_ specified, just take the first device we see, if any.
if (!default_output) { if (!default_playback) {
default_output = GetFirstAddedAudioDevice(/*iscapture=*/SDL_FALSE); default_playback = GetFirstAddedAudioDevice(/*recording=*/SDL_FALSE);
} }
if (!default_capture) { if (!default_recording) {
default_capture = GetFirstAddedAudioDevice(/*iscapture=*/SDL_TRUE); default_recording = GetFirstAddedAudioDevice(/*recording=*/SDL_TRUE);
} }
if (default_output) { if (default_playback) {
current_audio.default_output_device_id = default_output->instance_id; current_audio.default_playback_device_id = default_playback->instance_id;
RefPhysicalAudioDevice(default_output); // extra ref on default devices. RefPhysicalAudioDevice(default_playback); // extra ref on default devices.
} }
if (default_capture) { if (default_recording) {
current_audio.default_capture_device_id = default_capture->instance_id; current_audio.default_recording_device_id = default_recording->instance_id;
RefPhysicalAudioDevice(default_capture); // extra ref on default devices. RefPhysicalAudioDevice(default_recording); // extra ref on default devices.
} }
return 0; return 0;
@ -1009,8 +1009,8 @@ void SDL_QuitAudio(void)
current_audio.device_hash = NULL; current_audio.device_hash = NULL;
SDL_PendingAudioDeviceEvent *pending_events = current_audio.pending_events.next; SDL_PendingAudioDeviceEvent *pending_events = current_audio.pending_events.next;
current_audio.pending_events.next = NULL; current_audio.pending_events.next = NULL;
SDL_AtomicSet(&current_audio.output_device_count, 0); SDL_AtomicSet(&current_audio.playback_device_count, 0);
SDL_AtomicSet(&current_audio.capture_device_count, 0); SDL_AtomicSet(&current_audio.recording_device_count, 0);
SDL_UnlockRWLock(current_audio.device_hash_lock); SDL_UnlockRWLock(current_audio.device_hash_lock);
SDL_PendingAudioDeviceEvent *pending_next = NULL; SDL_PendingAudioDeviceEvent *pending_next = NULL;
@ -1053,17 +1053,17 @@ static void MixFloat32Audio(float *dst, const float *src, const int buffer_size)
} }
// Output device thread. This is split into chunks, so backends that need to control this directly can use the pieces they need without duplicating effort. // Playback device thread. This is split into chunks, so backends that need to control this directly can use the pieces they need without duplicating effort.
void SDL_OutputAudioThreadSetup(SDL_AudioDevice *device) void SDL_PlaybackAudioThreadSetup(SDL_AudioDevice *device)
{ {
SDL_assert(!device->iscapture); SDL_assert(!device->recording);
current_audio.impl.ThreadInit(device); current_audio.impl.ThreadInit(device);
} }
SDL_bool SDL_OutputAudioThreadIterate(SDL_AudioDevice *device) SDL_bool SDL_PlaybackAudioThreadIterate(SDL_AudioDevice *device)
{ {
SDL_assert(!device->iscapture); SDL_assert(!device->recording);
SDL_LockMutex(device->lock); SDL_LockMutex(device->lock);
@ -1171,9 +1171,9 @@ SDL_bool SDL_OutputAudioThreadIterate(SDL_AudioDevice *device)
return SDL_TRUE; // always go on if not shutting down, even if device failed. return SDL_TRUE; // always go on if not shutting down, even if device failed.
} }
void SDL_OutputAudioThreadShutdown(SDL_AudioDevice *device) void SDL_PlaybackAudioThreadShutdown(SDL_AudioDevice *device)
{ {
SDL_assert(!device->iscapture); SDL_assert(!device->recording);
const int frames = device->buffer_size / SDL_AUDIO_FRAMESIZE(device->spec); const int frames = device->buffer_size / SDL_AUDIO_FRAMESIZE(device->spec);
// Wait for the audio to drain if device didn't die. // Wait for the audio to drain if device didn't die.
if (!SDL_AtomicGet(&device->zombie)) { if (!SDL_AtomicGet(&device->zombie)) {
@ -1183,36 +1183,36 @@ void SDL_OutputAudioThreadShutdown(SDL_AudioDevice *device)
SDL_AudioThreadFinalize(device); SDL_AudioThreadFinalize(device);
} }
static int SDLCALL OutputAudioThread(void *devicep) // thread entry point static int SDLCALL PlaybackAudioThread(void *devicep) // thread entry point
{ {
SDL_AudioDevice *device = (SDL_AudioDevice *)devicep; SDL_AudioDevice *device = (SDL_AudioDevice *)devicep;
SDL_assert(device != NULL); SDL_assert(device != NULL);
SDL_assert(!device->iscapture); SDL_assert(!device->recording);
SDL_OutputAudioThreadSetup(device); SDL_PlaybackAudioThreadSetup(device);
do { do {
if (device->WaitDevice(device) < 0) { if (device->WaitDevice(device) < 0) {
SDL_AudioDeviceDisconnected(device); // doh. (but don't break out of the loop, just be a zombie for now!) SDL_AudioDeviceDisconnected(device); // doh. (but don't break out of the loop, just be a zombie for now!)
} }
} while (SDL_OutputAudioThreadIterate(device)); } while (SDL_PlaybackAudioThreadIterate(device));
SDL_OutputAudioThreadShutdown(device); SDL_PlaybackAudioThreadShutdown(device);
return 0; return 0;
} }
// Capture device thread. This is split into chunks, so backends that need to control this directly can use the pieces they need without duplicating effort. // Recording device thread. This is split into chunks, so backends that need to control this directly can use the pieces they need without duplicating effort.
void SDL_CaptureAudioThreadSetup(SDL_AudioDevice *device) void SDL_RecordingAudioThreadSetup(SDL_AudioDevice *device)
{ {
SDL_assert(device->iscapture); SDL_assert(device->recording);
current_audio.impl.ThreadInit(device); current_audio.impl.ThreadInit(device);
} }
SDL_bool SDL_CaptureAudioThreadIterate(SDL_AudioDevice *device) SDL_bool SDL_RecordingAudioThreadIterate(SDL_AudioDevice *device)
{ {
SDL_assert(device->iscapture); SDL_assert(device->recording);
SDL_LockMutex(device->lock); SDL_LockMutex(device->lock);
@ -1224,10 +1224,10 @@ SDL_bool SDL_CaptureAudioThreadIterate(SDL_AudioDevice *device)
SDL_bool failed = SDL_FALSE; SDL_bool failed = SDL_FALSE;
if (!device->logical_devices) { if (!device->logical_devices) {
device->FlushCapture(device); // nothing wants data, dump anything pending. device->FlushRecording(device); // nothing wants data, dump anything pending.
} else { } else {
// this SHOULD NOT BLOCK, as we are holding a lock right now. Block in WaitCaptureDevice! // this SHOULD NOT BLOCK, as we are holding a lock right now. Block in WaitRecordingDevice!
int br = device->CaptureFromDevice(device, device->work_buffer, device->buffer_size); int br = device->RecordDevice(device, device->work_buffer, device->buffer_size);
if (br < 0) { // uhoh, device failed for some reason! if (br < 0) { // uhoh, device failed for some reason!
failed = SDL_TRUE; failed = SDL_TRUE;
} else if (br > 0) { // queue the new data to each bound stream. } else if (br > 0) { // queue the new data to each bound stream.
@ -1238,7 +1238,7 @@ SDL_bool SDL_CaptureAudioThreadIterate(SDL_AudioDevice *device)
void *output_buffer = device->work_buffer; void *output_buffer = device->work_buffer;
// I don't know why someone would want a postmix on a capture device, but we offer it for API consistency. // I don't know why someone would want a postmix on a recording device, but we offer it for API consistency.
if (logdev->postmix) { if (logdev->postmix) {
// move to float format. // move to float format.
SDL_AudioSpec outspec; SDL_AudioSpec outspec;
@ -1281,33 +1281,33 @@ SDL_bool SDL_CaptureAudioThreadIterate(SDL_AudioDevice *device)
return SDL_TRUE; // always go on if not shutting down, even if device failed. return SDL_TRUE; // always go on if not shutting down, even if device failed.
} }
void SDL_CaptureAudioThreadShutdown(SDL_AudioDevice *device) void SDL_RecordingAudioThreadShutdown(SDL_AudioDevice *device)
{ {
SDL_assert(device->iscapture); SDL_assert(device->recording);
device->FlushCapture(device); device->FlushRecording(device);
current_audio.impl.ThreadDeinit(device); current_audio.impl.ThreadDeinit(device);
SDL_AudioThreadFinalize(device); SDL_AudioThreadFinalize(device);
} }
static int SDLCALL CaptureAudioThread(void *devicep) // thread entry point static int SDLCALL RecordingAudioThread(void *devicep) // thread entry point
{ {
SDL_AudioDevice *device = (SDL_AudioDevice *)devicep; SDL_AudioDevice *device = (SDL_AudioDevice *)devicep;
SDL_assert(device != NULL); SDL_assert(device != NULL);
SDL_assert(device->iscapture); SDL_assert(device->recording);
SDL_CaptureAudioThreadSetup(device); SDL_RecordingAudioThreadSetup(device);
do { do {
if (device->WaitCaptureDevice(device) < 0) { if (device->WaitRecordingDevice(device) < 0) {
SDL_AudioDeviceDisconnected(device); // doh. (but don't break out of the loop, just be a zombie for now!) SDL_AudioDeviceDisconnected(device); // doh. (but don't break out of the loop, just be a zombie for now!)
} }
} while (SDL_CaptureAudioThreadIterate(device)); } while (SDL_RecordingAudioThreadIterate(device));
SDL_CaptureAudioThreadShutdown(device); SDL_RecordingAudioThreadShutdown(device);
return 0; return 0;
} }
static SDL_AudioDeviceID *GetAudioDevices(int *count, SDL_bool iscapture) static SDL_AudioDeviceID *GetAudioDevices(int *count, SDL_bool recording)
{ {
SDL_AudioDeviceID *retval = NULL; SDL_AudioDeviceID *retval = NULL;
int num_devices = 0; int num_devices = 0;
@ -1315,7 +1315,7 @@ static SDL_AudioDeviceID *GetAudioDevices(int *count, SDL_bool iscapture)
if (SDL_GetCurrentAudioDriver()) { if (SDL_GetCurrentAudioDriver()) {
SDL_LockRWLockForReading(current_audio.device_hash_lock); SDL_LockRWLockForReading(current_audio.device_hash_lock);
{ {
num_devices = SDL_AtomicGet(iscapture ? &current_audio.capture_device_count : &current_audio.output_device_count); num_devices = SDL_AtomicGet(recording ? &current_audio.recording_device_count : &current_audio.playback_device_count);
retval = (SDL_AudioDeviceID *) SDL_malloc((num_devices + 1) * sizeof (SDL_AudioDeviceID)); retval = (SDL_AudioDeviceID *) SDL_malloc((num_devices + 1) * sizeof (SDL_AudioDeviceID));
if (retval) { if (retval) {
int devs_seen = 0; int devs_seen = 0;
@ -1324,11 +1324,11 @@ static SDL_AudioDeviceID *GetAudioDevices(int *count, SDL_bool iscapture)
void *iter = NULL; void *iter = NULL;
while (SDL_IterateHashTable(current_audio.device_hash, &key, &value, &iter)) { while (SDL_IterateHashTable(current_audio.device_hash, &key, &value, &iter)) {
const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key; const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key;
// bit #0 of devid is set for output devices and unset for capture. // bit #0 of devid is set for playback devices and unset for recording.
// bit #1 of devid is set for physical devices and unset for logical. // bit #1 of devid is set for physical devices and unset for logical.
const SDL_bool devid_iscapture = !(devid & (1<<0)); const SDL_bool devid_recording = !(devid & (1<<0));
const SDL_bool isphysical = (devid & (1<<1)); const SDL_bool isphysical = (devid & (1<<1));
if (isphysical && (devid_iscapture == iscapture)) { if (isphysical && (devid_recording == recording)) {
SDL_assert(devs_seen < num_devices); SDL_assert(devs_seen < num_devices);
retval[devs_seen++] = devid; retval[devs_seen++] = devid;
} }
@ -1353,12 +1353,12 @@ static SDL_AudioDeviceID *GetAudioDevices(int *count, SDL_bool iscapture)
return retval; return retval;
} }
SDL_AudioDeviceID *SDL_GetAudioOutputDevices(int *count) SDL_AudioDeviceID *SDL_GetAudioPlaybackDevices(int *count)
{ {
return GetAudioDevices(count, SDL_FALSE); return GetAudioDevices(count, SDL_FALSE);
} }
SDL_AudioDeviceID *SDL_GetAudioCaptureDevices(int *count) SDL_AudioDeviceID *SDL_GetAudioRecordingDevices(int *count)
{ {
return GetAudioDevices(count, SDL_TRUE); return GetAudioDevices(count, SDL_TRUE);
} }
@ -1527,10 +1527,10 @@ static SDL_AudioFormat ParseAudioFormatString(const char *string)
return 0; return 0;
} }
static void PrepareAudioFormat(SDL_bool iscapture, SDL_AudioSpec *spec) static void PrepareAudioFormat(SDL_bool recording, SDL_AudioSpec *spec)
{ {
if (spec->freq == 0) { if (spec->freq == 0) {
spec->freq = iscapture ? DEFAULT_AUDIO_CAPTURE_FREQUENCY : DEFAULT_AUDIO_OUTPUT_FREQUENCY; spec->freq = recording ? DEFAULT_AUDIO_RECORDING_FREQUENCY : DEFAULT_AUDIO_PLAYBACK_FREQUENCY;
const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY"); // !!! FIXME: should be a hint? const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY"); // !!! FIXME: should be a hint?
if (env) { if (env) {
@ -1542,7 +1542,7 @@ static void PrepareAudioFormat(SDL_bool iscapture, SDL_AudioSpec *spec)
} }
if (spec->channels == 0) { if (spec->channels == 0) {
spec->channels = iscapture ? DEFAULT_AUDIO_CAPTURE_CHANNELS : DEFAULT_AUDIO_OUTPUT_CHANNELS;; spec->channels = recording ? DEFAULT_AUDIO_RECORDING_CHANNELS : DEFAULT_AUDIO_PLAYBACK_CHANNELS;;
const char *env = SDL_getenv("SDL_AUDIO_CHANNELS"); const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
if (env) { if (env) {
const int val = SDL_atoi(env); const int val = SDL_atoi(env);
@ -1554,7 +1554,7 @@ static void PrepareAudioFormat(SDL_bool iscapture, SDL_AudioSpec *spec)
if (spec->format == 0) { if (spec->format == 0) {
const SDL_AudioFormat val = ParseAudioFormatString(SDL_getenv("SDL_AUDIO_FORMAT")); const SDL_AudioFormat val = ParseAudioFormatString(SDL_getenv("SDL_AUDIO_FORMAT"));
spec->format = (val != 0) ? val : (iscapture ? DEFAULT_AUDIO_CAPTURE_FORMAT : DEFAULT_AUDIO_OUTPUT_FORMAT); spec->format = (val != 0) ? val : (recording ? DEFAULT_AUDIO_RECORDING_FORMAT : DEFAULT_AUDIO_PLAYBACK_FORMAT);
} }
} }
@ -1568,7 +1568,7 @@ void SDL_UpdatedAudioDeviceFormat(SDL_AudioDevice *device)
char *SDL_GetAudioThreadName(SDL_AudioDevice *device, char *buf, size_t buflen) char *SDL_GetAudioThreadName(SDL_AudioDevice *device, char *buf, size_t buflen)
{ {
(void)SDL_snprintf(buf, buflen, "SDLAudio%c%d", (device->iscapture) ? 'C' : 'P', (int) device->instance_id); (void)SDL_snprintf(buf, buflen, "SDLAudio%c%d", (device->recording) ? 'C' : 'P', (int) device->instance_id);
return buf; return buf;
} }
@ -1591,13 +1591,13 @@ static int OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec
device->WaitDevice = current_audio.impl.WaitDevice; device->WaitDevice = current_audio.impl.WaitDevice;
device->PlayDevice = current_audio.impl.PlayDevice; device->PlayDevice = current_audio.impl.PlayDevice;
device->GetDeviceBuf = current_audio.impl.GetDeviceBuf; device->GetDeviceBuf = current_audio.impl.GetDeviceBuf;
device->WaitCaptureDevice = current_audio.impl.WaitCaptureDevice; device->WaitRecordingDevice = current_audio.impl.WaitRecordingDevice;
device->CaptureFromDevice = current_audio.impl.CaptureFromDevice; device->RecordDevice = current_audio.impl.RecordDevice;
device->FlushCapture = current_audio.impl.FlushCapture; device->FlushRecording = current_audio.impl.FlushRecording;
SDL_AudioSpec spec; SDL_AudioSpec spec;
SDL_copyp(&spec, inspec ? inspec : &device->default_spec); SDL_copyp(&spec, inspec ? inspec : &device->default_spec);
PrepareAudioFormat(device->iscapture, &spec); PrepareAudioFormat(device->recording, &spec);
/* We allow the device format to change if it's better than the current settings (by various definitions of "better"). This prevents /* We allow the device format to change if it's better than the current settings (by various definitions of "better"). This prevents
something low quality, like an old game using S8/8000Hz audio, from ruining a music thing playing at CD quality that tries to open later. something low quality, like an old game using S8/8000Hz audio, from ruining a music thing playing at CD quality that tries to open later.
@ -1636,7 +1636,7 @@ static int OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec
if (!current_audio.impl.ProvidesOwnCallbackThread) { if (!current_audio.impl.ProvidesOwnCallbackThread) {
char threadname[64]; char threadname[64];
SDL_GetAudioThreadName(device, threadname, sizeof (threadname)); SDL_GetAudioThreadName(device, threadname, sizeof (threadname));
device->thread = SDL_CreateThread(device->iscapture ? CaptureAudioThread : OutputAudioThread, threadname, device); device->thread = SDL_CreateThread(device->recording ? RecordingAudioThread : PlaybackAudioThread, threadname, device);
if (!device->thread) { if (!device->thread) {
ClosePhysicalAudioDevice(device); ClosePhysicalAudioDevice(device);
@ -1654,7 +1654,7 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp
return 0; return 0;
} }
SDL_bool wants_default = ((devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) || (devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE)); SDL_bool wants_default = ((devid == SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK) || (devid == SDL_AUDIO_DEVICE_DEFAULT_RECORDING));
// this will let you use a logical device to make a new logical device on the parent physical device. Could be useful? // this will let you use a logical device to make a new logical device on the parent physical device. Could be useful?
SDL_AudioDevice *device = NULL; SDL_AudioDevice *device = NULL;
@ -1682,7 +1682,7 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp
} else { } else {
RefPhysicalAudioDevice(device); // unref'd on successful SDL_CloseAudioDevice RefPhysicalAudioDevice(device); // unref'd on successful SDL_CloseAudioDevice
SDL_AtomicSet(&logdev->paused, 0); SDL_AtomicSet(&logdev->paused, 0);
retval = logdev->instance_id = AssignAudioDeviceInstanceId(device->iscapture, /*islogical=*/SDL_TRUE); retval = logdev->instance_id = AssignAudioDeviceInstanceId(device->recording, /*islogical=*/SDL_TRUE);
logdev->physical_device = device; logdev->physical_device = device;
logdev->opened_as_default = wants_default; logdev->opened_as_default = wants_default;
logdev->next = device->logical_devices; logdev->next = device->logical_devices;
@ -1758,7 +1758,7 @@ int SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallbac
logdev->postmix = callback; logdev->postmix = callback;
logdev->postmix_userdata = userdata; logdev->postmix_userdata = userdata;
if (device->iscapture) { if (device->recording) {
for (SDL_AudioStream *stream = logdev->bound_streams; stream; stream = stream->next_binding) { for (SDL_AudioStream *stream = logdev->bound_streams; stream; stream = stream->next_binding) {
// set the proper end of the stream to the device's format. // set the proper end of the stream to the device's format.
// SDL_SetAudioStreamFormat does a ton of validation just to memcpy an audiospec. // SDL_SetAudioStreamFormat does a ton of validation just to memcpy an audiospec.
@ -1836,7 +1836,7 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int
if (retval == 0) { if (retval == 0) {
// Now that everything is verified, chain everything together. // Now that everything is verified, chain everything together.
const SDL_bool iscapture = device->iscapture; const SDL_bool recording = device->recording;
for (int i = 0; i < num_streams; i++) { for (int i = 0; i < num_streams; i++) {
SDL_AudioStream *stream = streams[i]; SDL_AudioStream *stream = streams[i];
if (stream) { // shouldn't be NULL, but just in case... if (stream) { // shouldn't be NULL, but just in case...
@ -1848,7 +1848,7 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int
} }
logdev->bound_streams = stream; logdev->bound_streams = stream;
if (iscapture) { if (recording) {
SDL_copyp(&stream->src_spec, &device->spec); SDL_copyp(&stream->src_spec, &device->spec);
if (logdev->postmix) { if (logdev->postmix) {
stream->src_spec.format = SDL_AUDIO_F32; stream->src_spec.format = SDL_AUDIO_F32;
@ -1982,7 +1982,7 @@ SDL_AudioStream *SDL_OpenAudioDeviceStream(SDL_AudioDeviceID devid, const SDL_Au
SDL_AtomicSet(&logdev->paused, 1); // start the device paused, to match SDL2. SDL_AtomicSet(&logdev->paused, 1); // start the device paused, to match SDL2.
SDL_assert(device != NULL); SDL_assert(device != NULL);
const SDL_bool iscapture = device->iscapture; const SDL_bool recording = device->recording;
// if the app didn't request a format _at all_, just make a stream that does no conversion; they can query for it later. // if the app didn't request a format _at all_, just make a stream that does no conversion; they can query for it later.
SDL_AudioSpec tmpspec; SDL_AudioSpec tmpspec;
@ -1991,7 +1991,7 @@ SDL_AudioStream *SDL_OpenAudioDeviceStream(SDL_AudioDeviceID devid, const SDL_Au
spec = &tmpspec; spec = &tmpspec;
} }
if (iscapture) { if (recording) {
stream = SDL_CreateAudioStream(&device->spec, spec); stream = SDL_CreateAudioStream(&device->spec, spec);
} else { } else {
stream = SDL_CreateAudioStream(spec, &device->spec); stream = SDL_CreateAudioStream(spec, &device->spec);
@ -2011,7 +2011,7 @@ SDL_AudioStream *SDL_OpenAudioDeviceStream(SDL_AudioDeviceID devid, const SDL_Au
if (callback) { if (callback) {
int rc; int rc;
if (iscapture) { if (recording) {
rc = SDL_SetAudioStreamPutCallback(stream, callback, userdata); rc = SDL_SetAudioStreamPutCallback(stream, callback, userdata);
} else { } else {
rc = SDL_SetAudioStreamGetCallback(stream, callback, userdata); rc = SDL_SetAudioStreamGetCallback(stream, callback, userdata);
@ -2086,17 +2086,17 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device)
return; // uhoh. return; // uhoh.
} }
const SDL_bool iscapture = new_default_device->iscapture; const SDL_bool recording = new_default_device->recording;
// change the official default over right away, so new opens will go to the new device. // change the official default over right away, so new opens will go to the new device.
SDL_LockRWLockForWriting(current_audio.device_hash_lock); SDL_LockRWLockForWriting(current_audio.device_hash_lock);
const SDL_AudioDeviceID current_devid = iscapture ? current_audio.default_capture_device_id : current_audio.default_output_device_id; const SDL_AudioDeviceID current_devid = recording ? current_audio.default_recording_device_id : current_audio.default_playback_device_id;
const SDL_bool is_already_default = (new_default_device->instance_id == current_devid); const SDL_bool is_already_default = (new_default_device->instance_id == current_devid);
if (!is_already_default) { if (!is_already_default) {
if (iscapture) { if (recording) {
current_audio.default_capture_device_id = new_default_device->instance_id; current_audio.default_recording_device_id = new_default_device->instance_id;
} else { } else {
current_audio.default_output_device_id = new_default_device->instance_id; current_audio.default_playback_device_id = new_default_device->instance_id;
} }
} }
SDL_UnlockRWLock(current_audio.device_hash_lock); SDL_UnlockRWLock(current_audio.device_hash_lock);
@ -2122,7 +2122,7 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device)
if (current_default_device) { if (current_default_device) {
// migrate any logical devices that were opened as a default to the new physical device... // migrate any logical devices that were opened as a default to the new physical device...
SDL_assert(current_default_device->iscapture == iscapture); SDL_assert(current_default_device->recording == recording);
// See if we have to open the new physical device, and if so, find the best audiospec for it. // See if we have to open the new physical device, and if so, find the best audiospec for it.
SDL_AudioSpec spec; SDL_AudioSpec spec;
@ -2133,7 +2133,7 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device)
if (logdev->opened_as_default) { if (logdev->opened_as_default) {
needs_migration = SDL_TRUE; needs_migration = SDL_TRUE;
for (SDL_AudioStream *stream = logdev->bound_streams; stream; stream = stream->next_binding) { for (SDL_AudioStream *stream = logdev->bound_streams; stream; stream = stream->next_binding) {
const SDL_AudioSpec *streamspec = iscapture ? &stream->dst_spec : &stream->src_spec; const SDL_AudioSpec *streamspec = recording ? &stream->dst_spec : &stream->src_spec;
if (SDL_AUDIO_BITSIZE(streamspec->format) > SDL_AUDIO_BITSIZE(spec.format)) { if (SDL_AUDIO_BITSIZE(streamspec->format) > SDL_AUDIO_BITSIZE(spec.format)) {
spec.format = streamspec->format; spec.format = streamspec->format;
} }
@ -2350,7 +2350,7 @@ void SDL_UpdateAudio(void)
SDL_zero(event); SDL_zero(event);
event.type = i->type; event.type = i->type;
event.adevice.which = (Uint32) i->devid; event.adevice.which = (Uint32) i->devid;
event.adevice.iscapture = (i->devid & (1<<0)) ? 0 : 1; // bit #0 of devid is set for output devices and unset for capture. event.adevice.recording = (i->devid & (1<<0)) ? 0 : 1; // bit #0 of devid is set for playback devices and unset for recording.
SDL_PushEvent(&event); SDL_PushEvent(&event);
} }
SDL_free(i); SDL_free(i);

View File

@ -472,7 +472,7 @@ int SDL_SetAudioStreamFormat(SDL_AudioStream *stream, const SDL_AudioSpec *src_s
// quietly refuse to change the format of the end currently bound to a device. // quietly refuse to change the format of the end currently bound to a device.
if (stream->bound_device) { if (stream->bound_device) {
if (stream->bound_device->physical_device->iscapture) { if (stream->bound_device->physical_device->recording) {
src_spec = NULL; src_spec = NULL;
} else { } else {
dst_spec = NULL; dst_spec = NULL;

View File

@ -45,7 +45,7 @@
#define SDL_PATH_DEV_AUDIO "/dev/audio" #define SDL_PATH_DEV_AUDIO "/dev/audio"
#endif #endif
static void test_device(const SDL_bool iscapture, const char *fname, int flags, SDL_bool (*test)(int fd)) static void test_device(const SDL_bool recording, const char *fname, int flags, SDL_bool (*test)(int fd))
{ {
struct stat sb; struct stat sb;
const int audio_fd = open(fname, flags | O_CLOEXEC, 0); const int audio_fd = open(fname, flags | O_CLOEXEC, 0);
@ -63,7 +63,7 @@ static void test_device(const SDL_bool iscapture, const char *fname, int flags,
* information, making this information inaccessible at * information, making this information inaccessible at
* enumeration time * enumeration time
*/ */
SDL_AddAudioDevice(iscapture, fname, NULL, (void *)(uintptr_t)dummyhandle); SDL_AddAudioDevice(recording, fname, NULL, (void *)(uintptr_t)dummyhandle);
} }
} else { } else {
close(audio_fd); close(audio_fd);
@ -76,9 +76,9 @@ static SDL_bool test_stub(int fd)
return SDL_TRUE; return SDL_TRUE;
} }
static void SDL_EnumUnixAudioDevices_Internal(const SDL_bool iscapture, const SDL_bool classic, SDL_bool (*test)(int)) static void SDL_EnumUnixAudioDevices_Internal(const SDL_bool recording, const SDL_bool classic, SDL_bool (*test)(int))
{ {
const int flags = iscapture ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT; const int flags = recording ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT;
const char *audiodev; const char *audiodev;
char audiopath[1024]; char audiopath[1024];
@ -105,7 +105,7 @@ static void SDL_EnumUnixAudioDevices_Internal(const SDL_bool iscapture, const SD
} }
} }
} }
test_device(iscapture, audiodev, flags, test); test_device(recording, audiodev, flags, test);
if (SDL_strlen(audiodev) < (sizeof(audiopath) - 3)) { if (SDL_strlen(audiodev) < (sizeof(audiopath) - 3)) {
int instance = 0; int instance = 0;
@ -113,7 +113,7 @@ static void SDL_EnumUnixAudioDevices_Internal(const SDL_bool iscapture, const SD
(void)SDL_snprintf(audiopath, SDL_arraysize(audiopath), (void)SDL_snprintf(audiopath, SDL_arraysize(audiopath),
"%s%d", audiodev, instance); "%s%d", audiodev, instance);
instance++; instance++;
test_device(iscapture, audiopath, flags, test); test_device(recording, audiopath, flags, test);
} }
} }
} }

View File

@ -36,17 +36,17 @@
#endif #endif
// !!! FIXME: These are wordy and unlocalized... // !!! FIXME: These are wordy and unlocalized...
#define DEFAULT_OUTPUT_DEVNAME "System audio output device" #define DEFAULT_PLAYBACK_DEVNAME "System audio playback device"
#define DEFAULT_INPUT_DEVNAME "System audio capture device" #define DEFAULT_RECORDING_DEVNAME "System audio recording device"
// these are used when no better specifics are known. We default to CD audio quality. // these are used when no better specifics are known. We default to CD audio quality.
#define DEFAULT_AUDIO_OUTPUT_FORMAT SDL_AUDIO_S16 #define DEFAULT_AUDIO_PLAYBACK_FORMAT SDL_AUDIO_S16
#define DEFAULT_AUDIO_OUTPUT_CHANNELS 2 #define DEFAULT_AUDIO_PLAYBACK_CHANNELS 2
#define DEFAULT_AUDIO_OUTPUT_FREQUENCY 44100 #define DEFAULT_AUDIO_PLAYBACK_FREQUENCY 44100
#define DEFAULT_AUDIO_CAPTURE_FORMAT SDL_AUDIO_S16 #define DEFAULT_AUDIO_RECORDING_FORMAT SDL_AUDIO_S16
#define DEFAULT_AUDIO_CAPTURE_CHANNELS 1 #define DEFAULT_AUDIO_RECORDING_CHANNELS 1
#define DEFAULT_AUDIO_CAPTURE_FREQUENCY 44100 #define DEFAULT_AUDIO_RECORDING_FREQUENCY 44100
#define AUDIO_SPECS_EQUAL(x, y) (((x).format == (y).format) && ((x).channels == (y).channels) && ((x).freq == (y).freq)) #define AUDIO_SPECS_EQUAL(x, y) (((x).format == (y).format) && ((x).channels == (y).channels) && ((x).freq == (y).freq))
@ -69,7 +69,7 @@ extern void SDL_SetupAudioResampler(void);
/* Backends should call this as devices are added to the system (such as /* Backends should call this as devices are added to the system (such as
a USB headset being plugged in), and should also be called for a USB headset being plugged in), and should also be called for
for every device found during DetectDevices(). */ for every device found during DetectDevices(). */
extern SDL_AudioDevice *SDL_AddAudioDevice(const SDL_bool iscapture, const char *name, const SDL_AudioSpec *spec, void *handle); extern SDL_AudioDevice *SDL_AddAudioDevice(const SDL_bool recording, const char *name, const SDL_AudioSpec *spec, void *handle);
/* Backends should call this if an opened audio device is lost. /* Backends should call this if an opened audio device is lost.
This can happen due to i/o errors, or a device being unplugged, etc. */ This can happen due to i/o errors, or a device being unplugged, etc. */
@ -101,12 +101,12 @@ extern void RefPhysicalAudioDevice(SDL_AudioDevice *device);
extern void UnrefPhysicalAudioDevice(SDL_AudioDevice *device); extern void UnrefPhysicalAudioDevice(SDL_AudioDevice *device);
// These functions are the heart of the audio threads. Backends can call them directly if they aren't using the SDL-provided thread. // These functions are the heart of the audio threads. Backends can call them directly if they aren't using the SDL-provided thread.
extern void SDL_OutputAudioThreadSetup(SDL_AudioDevice *device); extern void SDL_PlaybackAudioThreadSetup(SDL_AudioDevice *device);
extern SDL_bool SDL_OutputAudioThreadIterate(SDL_AudioDevice *device); extern SDL_bool SDL_PlaybackAudioThreadIterate(SDL_AudioDevice *device);
extern void SDL_OutputAudioThreadShutdown(SDL_AudioDevice *device); extern void SDL_PlaybackAudioThreadShutdown(SDL_AudioDevice *device);
extern void SDL_CaptureAudioThreadSetup(SDL_AudioDevice *device); extern void SDL_RecordingAudioThreadSetup(SDL_AudioDevice *device);
extern SDL_bool SDL_CaptureAudioThreadIterate(SDL_AudioDevice *device); extern SDL_bool SDL_RecordingAudioThreadIterate(SDL_AudioDevice *device);
extern void SDL_CaptureAudioThreadShutdown(SDL_AudioDevice *device); extern void SDL_RecordingAudioThreadShutdown(SDL_AudioDevice *device);
extern void SDL_AudioThreadFinalize(SDL_AudioDevice *device); extern void SDL_AudioThreadFinalize(SDL_AudioDevice *device);
extern void ConvertAudioToFloat(float *dst, const void *src, int num_samples, SDL_AudioFormat src_fmt); extern void ConvertAudioToFloat(float *dst, const void *src, int num_samples, SDL_AudioFormat src_fmt);
@ -123,16 +123,16 @@ extern void OnAudioStreamDestroy(SDL_AudioStream *stream);
typedef struct SDL_AudioDriverImpl typedef struct SDL_AudioDriverImpl
{ {
void (*DetectDevices)(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture); void (*DetectDevices)(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording);
int (*OpenDevice)(SDL_AudioDevice *device); int (*OpenDevice)(SDL_AudioDevice *device);
void (*ThreadInit)(SDL_AudioDevice *device); // Called by audio thread at start void (*ThreadInit)(SDL_AudioDevice *device); // Called by audio thread at start
void (*ThreadDeinit)(SDL_AudioDevice *device); // Called by audio thread at end void (*ThreadDeinit)(SDL_AudioDevice *device); // Called by audio thread at end
int (*WaitDevice)(SDL_AudioDevice *device); int (*WaitDevice)(SDL_AudioDevice *device);
int (*PlayDevice)(SDL_AudioDevice *device, const Uint8 *buffer, int buflen); // buffer and buflen are always from GetDeviceBuf, passed here for convenience. int (*PlayDevice)(SDL_AudioDevice *device, const Uint8 *buffer, int buflen); // buffer and buflen are always from GetDeviceBuf, passed here for convenience.
Uint8 *(*GetDeviceBuf)(SDL_AudioDevice *device, int *buffer_size); Uint8 *(*GetDeviceBuf)(SDL_AudioDevice *device, int *buffer_size);
int (*WaitCaptureDevice)(SDL_AudioDevice *device); int (*WaitRecordingDevice)(SDL_AudioDevice *device);
int (*CaptureFromDevice)(SDL_AudioDevice *device, void *buffer, int buflen); int (*RecordDevice)(SDL_AudioDevice *device, void *buffer, int buflen);
void (*FlushCapture)(SDL_AudioDevice *device); void (*FlushRecording)(SDL_AudioDevice *device);
void (*CloseDevice)(SDL_AudioDevice *device); void (*CloseDevice)(SDL_AudioDevice *device);
void (*FreeDeviceHandle)(SDL_AudioDevice *device); // SDL is done with this device; free the handle from SDL_AddAudioDevice() void (*FreeDeviceHandle)(SDL_AudioDevice *device); // SDL is done with this device; free the handle from SDL_AddAudioDevice()
void (*DeinitializeStart)(void); // SDL calls this, then starts destroying objects, then calls Deinitialize. This is a good place to stop hotplug detection. void (*DeinitializeStart)(void); // SDL calls this, then starts destroying objects, then calls Deinitialize. This is a good place to stop hotplug detection.
@ -140,9 +140,9 @@ typedef struct SDL_AudioDriverImpl
// Some flags to push duplicate code into the core and reduce #ifdefs. // Some flags to push duplicate code into the core and reduce #ifdefs.
SDL_bool ProvidesOwnCallbackThread; // !!! FIXME: rename this, it's not a callback thread anymore. SDL_bool ProvidesOwnCallbackThread; // !!! FIXME: rename this, it's not a callback thread anymore.
SDL_bool HasCaptureSupport; SDL_bool HasRecordingSupport;
SDL_bool OnlyHasDefaultOutputDevice; SDL_bool OnlyHasDefaultPlaybackDevice;
SDL_bool OnlyHasDefaultCaptureDevice; // !!! FIXME: is there ever a time where you'd have a default output and not a default capture (or vice versa)? SDL_bool OnlyHasDefaultRecordingDevice; // !!! FIXME: is there ever a time where you'd have a default playback and not a default recording (or vice versa)?
} SDL_AudioDriverImpl; } SDL_AudioDriverImpl;
@ -159,16 +159,16 @@ typedef struct SDL_AudioDriver
const char *desc; // The description of this audio driver const char *desc; // The description of this audio driver
SDL_AudioDriverImpl impl; // the backend's interface SDL_AudioDriverImpl impl; // the backend's interface
SDL_RWLock *device_hash_lock; // A rwlock that protects `device_hash` SDL_RWLock *device_hash_lock; // A rwlock that protects `device_hash`
SDL_HashTable *device_hash; // the collection of currently-available audio devices (capture, playback, logical and physical!) SDL_HashTable *device_hash; // the collection of currently-available audio devices (recording, playback, logical and physical!)
SDL_AudioStream *existing_streams; // a list of all existing SDL_AudioStreams. SDL_AudioStream *existing_streams; // a list of all existing SDL_AudioStreams.
SDL_AudioDeviceID default_output_device_id; SDL_AudioDeviceID default_playback_device_id;
SDL_AudioDeviceID default_capture_device_id; SDL_AudioDeviceID default_recording_device_id;
SDL_PendingAudioDeviceEvent pending_events; SDL_PendingAudioDeviceEvent pending_events;
SDL_PendingAudioDeviceEvent *pending_events_tail; SDL_PendingAudioDeviceEvent *pending_events_tail;
// !!! FIXME: most (all?) of these don't have to be atomic. // !!! FIXME: most (all?) of these don't have to be atomic.
SDL_AtomicInt output_device_count; SDL_AtomicInt playback_device_count;
SDL_AtomicInt capture_device_count; SDL_AtomicInt recording_device_count;
SDL_AtomicInt shutting_down; // non-zero during SDL_Quit, so we known not to accept any last-minute device hotplugs. SDL_AtomicInt shutting_down; // non-zero during SDL_Quit, so we known not to accept any last-minute device hotplugs.
} SDL_AudioDriver; } SDL_AudioDriver;
@ -257,9 +257,9 @@ struct SDL_AudioDevice
int (*WaitDevice)(SDL_AudioDevice *device); int (*WaitDevice)(SDL_AudioDevice *device);
int (*PlayDevice)(SDL_AudioDevice *device, const Uint8 *buffer, int buflen); int (*PlayDevice)(SDL_AudioDevice *device, const Uint8 *buffer, int buflen);
Uint8 *(*GetDeviceBuf)(SDL_AudioDevice *device, int *buffer_size); Uint8 *(*GetDeviceBuf)(SDL_AudioDevice *device, int *buffer_size);
int (*WaitCaptureDevice)(SDL_AudioDevice *device); int (*WaitRecordingDevice)(SDL_AudioDevice *device);
int (*CaptureFromDevice)(SDL_AudioDevice *device, void *buffer, int buflen); int (*RecordDevice)(SDL_AudioDevice *device, void *buffer, int buflen);
void (*FlushCapture)(SDL_AudioDevice *device); void (*FlushRecording)(SDL_AudioDevice *device);
// human-readable name of the device. ("SoundBlaster Pro 16") // human-readable name of the device. ("SoundBlaster Pro 16")
char *name; char *name;
@ -289,8 +289,8 @@ struct SDL_AudioDevice
// non-zero if this was a disconnected device and we're waiting for it to be decommissioned. // non-zero if this was a disconnected device and we're waiting for it to be decommissioned.
SDL_AtomicInt zombie; SDL_AtomicInt zombie;
// SDL_TRUE if this is a capture device instead of an output device // SDL_TRUE if this is a recording device instead of an playback device
SDL_bool iscapture; SDL_bool recording;
// SDL_TRUE if audio thread can skip silence/mix/convert stages and just do a basic memcpy. // SDL_TRUE if audio thread can skip silence/mix/convert stages and just do a basic memcpy.
SDL_bool simple_copy; SDL_bool simple_copy;

View File

@ -96,7 +96,7 @@ static aaudio_data_callback_result_t AAUDIO_dataCallback(AAudioStream *stream, v
size_t callback_bytes = numFrames * framesize; size_t callback_bytes = numFrames * framesize;
size_t old_buffer_index = hidden->callback_bytes / device->buffer_size; size_t old_buffer_index = hidden->callback_bytes / device->buffer_size;
if (device->iscapture) { if (device->recording) {
const Uint8 *input = (const Uint8 *)audioData; const Uint8 *input = (const Uint8 *)audioData;
size_t available_bytes = hidden->mixbuf_bytes - (hidden->callback_bytes - hidden->processed_bytes); size_t available_bytes = hidden->mixbuf_bytes - (hidden->callback_bytes - hidden->processed_bytes);
size_t size = SDL_min(available_bytes, callback_bytes); size_t size = SDL_min(available_bytes, callback_bytes);
@ -228,7 +228,7 @@ static int AAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int b
return 0; return 0;
} }
static int AAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int AAUDIO_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
{ {
struct SDL_PrivateAudioData *hidden = device->hidden; struct SDL_PrivateAudioData *hidden = device->hidden;
@ -272,7 +272,7 @@ static void AAUDIO_CloseDevice(SDL_AudioDevice *device)
static int BuildAAudioStream(SDL_AudioDevice *device) static int BuildAAudioStream(SDL_AudioDevice *device)
{ {
struct SDL_PrivateAudioData *hidden = device->hidden; struct SDL_PrivateAudioData *hidden = device->hidden;
const SDL_bool iscapture = device->iscapture; const SDL_bool recording = device->recording;
aaudio_result_t res; aaudio_result_t res;
SDL_AtomicSet(&hidden->error_callback_triggered, 0); SDL_AtomicSet(&hidden->error_callback_triggered, 0);
@ -307,7 +307,7 @@ static int BuildAAudioStream(SDL_AudioDevice *device)
ctx.AAudioStreamBuilder_setChannelCount(builder, device->spec.channels); ctx.AAudioStreamBuilder_setChannelCount(builder, device->spec.channels);
#endif #endif
const aaudio_direction_t direction = (iscapture ? AAUDIO_DIRECTION_INPUT : AAUDIO_DIRECTION_OUTPUT); const aaudio_direction_t direction = (recording ? AAUDIO_DIRECTION_INPUT : AAUDIO_DIRECTION_OUTPUT);
ctx.AAudioStreamBuilder_setDirection(builder, direction); ctx.AAudioStreamBuilder_setDirection(builder, direction);
ctx.AAudioStreamBuilder_setErrorCallback(builder, AAUDIO_errorCallback, device); ctx.AAudioStreamBuilder_setErrorCallback(builder, AAUDIO_errorCallback, device);
ctx.AAudioStreamBuilder_setDataCallback(builder, AAUDIO_dataCallback, device); ctx.AAudioStreamBuilder_setDataCallback(builder, AAUDIO_dataCallback, device);
@ -360,9 +360,9 @@ static int BuildAAudioStream(SDL_AudioDevice *device)
hidden->processed_bytes = 0; hidden->processed_bytes = 0;
hidden->callback_bytes = 0; hidden->callback_bytes = 0;
hidden->semaphore = SDL_CreateSemaphore(iscapture ? 0 : hidden->num_buffers); hidden->semaphore = SDL_CreateSemaphore(recording ? 0 : hidden->num_buffers);
if (!hidden->semaphore) { if (!hidden->semaphore) {
LOGI("SDL Failed SDL_CreateSemaphore %s iscapture:%d", SDL_GetError(), iscapture); LOGI("SDL Failed SDL_CreateSemaphore %s recording:%d", SDL_GetError(), recording);
return -1; return -1;
} }
@ -372,7 +372,7 @@ static int BuildAAudioStream(SDL_AudioDevice *device)
res = ctx.AAudioStream_requestStart(hidden->stream); res = ctx.AAudioStream_requestStart(hidden->stream);
if (res != AAUDIO_OK) { if (res != AAUDIO_OK) {
LOGI("SDL Failed AAudioStream_requestStart %d iscapture:%d", res, iscapture); LOGI("SDL Failed AAudioStream_requestStart %d recording:%d", res, recording);
return SDL_SetError("%s : %s", __func__, ctx.AAudio_convertResultToText(res)); return SDL_SetError("%s : %s", __func__, ctx.AAudio_convertResultToText(res));
} }
@ -395,7 +395,7 @@ static int AAUDIO_OpenDevice(SDL_AudioDevice *device)
LOGI(__func__); LOGI(__func__);
if (device->iscapture) { if (device->recording) {
// !!! FIXME: make this non-blocking! // !!! FIXME: make this non-blocking!
SDL_AtomicInt permission_response; SDL_AtomicInt permission_response;
SDL_AtomicSet(&permission_response, 0); SDL_AtomicSet(&permission_response, 0);
@ -428,8 +428,8 @@ static SDL_bool PauseOneDevice(SDL_AudioDevice *device, void *userdata)
if (hidden->stream) { if (hidden->stream) {
aaudio_result_t res; aaudio_result_t res;
if (device->iscapture) { if (device->recording) {
// Pause() isn't implemented for 'capture', use Stop() // Pause() isn't implemented for recording, use Stop()
res = ctx.AAudioStream_requestStop(hidden->stream); res = ctx.AAudioStream_requestStop(hidden->stream);
} else { } else {
res = ctx.AAudioStream_requestPause(hidden->stream); res = ctx.AAudioStream_requestPause(hidden->stream);
@ -530,16 +530,16 @@ static SDL_bool AAUDIO_Init(SDL_AudioDriverImpl *impl)
impl->WaitDevice = AAUDIO_WaitDevice; impl->WaitDevice = AAUDIO_WaitDevice;
impl->PlayDevice = AAUDIO_PlayDevice; impl->PlayDevice = AAUDIO_PlayDevice;
impl->GetDeviceBuf = AAUDIO_GetDeviceBuf; impl->GetDeviceBuf = AAUDIO_GetDeviceBuf;
impl->WaitCaptureDevice = AAUDIO_WaitDevice; impl->WaitRecordingDevice = AAUDIO_WaitDevice;
impl->CaptureFromDevice = AAUDIO_CaptureFromDevice; impl->RecordDevice = AAUDIO_RecordDevice;
impl->HasCaptureSupport = SDL_TRUE; impl->HasRecordingSupport = SDL_TRUE;
#if ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES #if ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES
impl->DetectDevices = Android_StartAudioHotplug; impl->DetectDevices = Android_StartAudioHotplug;
#else #else
impl->OnlyHasDefaultOutputDevice = SDL_TRUE; impl->OnlyHasDefaultPlaybackDevice = SDL_TRUE;
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE; impl->OnlyHasDefaultRecordingDevice = SDL_TRUE;
#endif #endif
LOGI("SDL AAUDIO_Init OK"); LOGI("SDL AAUDIO_Init OK");

View File

@ -206,17 +206,17 @@ static int LoadALSALibrary(void)
typedef struct ALSA_Device typedef struct ALSA_Device
{ {
char *name; char *name;
SDL_bool iscapture; SDL_bool recording;
struct ALSA_Device *next; struct ALSA_Device *next;
} ALSA_Device; } ALSA_Device;
static const ALSA_Device default_output_handle = { static const ALSA_Device default_playback_handle = {
"default", "default",
SDL_FALSE, SDL_FALSE,
NULL NULL
}; };
static const ALSA_Device default_capture_handle = { static const ALSA_Device default_recording_handle = {
"default", "default",
SDL_TRUE, SDL_TRUE,
NULL NULL
@ -427,7 +427,7 @@ static Uint8 *ALSA_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
return device->hidden->mixbuf; return device->hidden->mixbuf;
} }
static int ALSA_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int ALSA_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
{ {
const int frame_size = SDL_AUDIO_FRAMESIZE(device->spec); const int frame_size = SDL_AUDIO_FRAMESIZE(device->spec);
SDL_assert((buflen % frame_size) == 0); SDL_assert((buflen % frame_size) == 0);
@ -451,12 +451,12 @@ static int ALSA_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buf
device->hidden->swizzle_func(device, buffer, total_frames - rc); device->hidden->swizzle_func(device, buffer, total_frames - rc);
} }
//SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: captured %d bytes", rc * frame_size); //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: recorded %d bytes", rc * frame_size);
return rc * frame_size; return rc * frame_size;
} }
static void ALSA_FlushCapture(SDL_AudioDevice *device) static void ALSA_FlushRecording(SDL_AudioDevice *device)
{ {
ALSA_snd_pcm_reset(device->hidden->pcm_handle); ALSA_snd_pcm_reset(device->hidden->pcm_handle);
} }
@ -531,7 +531,7 @@ static int ALSA_set_buffer_size(SDL_AudioDevice *device, snd_pcm_hw_params_t *pa
static int ALSA_OpenDevice(SDL_AudioDevice *device) static int ALSA_OpenDevice(SDL_AudioDevice *device)
{ {
const SDL_bool iscapture = device->iscapture; const SDL_bool recording = device->recording;
int status = 0; int status = 0;
// Initialize all variables that we clean on shutdown // Initialize all variables that we clean on shutdown
@ -545,7 +545,7 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device)
snd_pcm_t *pcm_handle = NULL; snd_pcm_t *pcm_handle = NULL;
status = ALSA_snd_pcm_open(&pcm_handle, status = ALSA_snd_pcm_open(&pcm_handle,
get_audio_device(device->handle, device->spec.channels), get_audio_device(device->handle, device->spec.channels),
iscapture ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, recording ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
SND_PCM_NONBLOCK); SND_PCM_NONBLOCK);
if (status < 0) { if (status < 0) {
@ -680,7 +680,7 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device)
SDL_UpdatedAudioDeviceFormat(device); SDL_UpdatedAudioDeviceFormat(device);
// Allocate mixing buffer // Allocate mixing buffer
if (!iscapture) { if (!recording) {
device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size);
if (!device->hidden->mixbuf) { if (!device->hidden->mixbuf) {
return -1; return -1;
@ -689,7 +689,7 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device)
} }
#if !SDL_ALSA_NON_BLOCKING #if !SDL_ALSA_NON_BLOCKING
if (!iscapture) { if (!recording) {
ALSA_snd_pcm_nonblock(pcm_handle, 0); ALSA_snd_pcm_nonblock(pcm_handle, 0);
} }
#endif #endif
@ -699,7 +699,7 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device)
return 0; // We're ready to rock and roll. :-) return 0; // We're ready to rock and roll. :-)
} }
static void add_device(const SDL_bool iscapture, const char *name, void *hint, ALSA_Device **pSeen) static void add_device(const SDL_bool recording, const char *name, void *hint, ALSA_Device **pSeen)
{ {
ALSA_Device *dev = SDL_malloc(sizeof(ALSA_Device)); ALSA_Device *dev = SDL_malloc(sizeof(ALSA_Device));
char *desc; char *desc;
@ -733,7 +733,7 @@ static void add_device(const SDL_bool iscapture, const char *name, void *hint, A
*ptr = '\0'; *ptr = '\0';
} }
//SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: adding %s device '%s' (%s)", iscapture ? "capture" : "output", name, desc); //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: adding %s device '%s' (%s)", recording ? "recording" : "playback", name, desc);
dev->name = SDL_strdup(name); dev->name = SDL_strdup(name);
if (!dev->name) { if (!dev->name) {
@ -748,19 +748,19 @@ static void add_device(const SDL_bool iscapture, const char *name, void *hint, A
// Note that spec is NULL, because we are required to open the device before // Note that spec is NULL, because we are required to open the device before
// acquiring the mix format, making this information inaccessible at // acquiring the mix format, making this information inaccessible at
// enumeration time // enumeration time
SDL_AddAudioDevice(iscapture, desc, NULL, dev); SDL_AddAudioDevice(recording, desc, NULL, dev);
if (hint) { if (hint) {
free(desc); // This should NOT be SDL_free() free(desc); // This should NOT be SDL_free()
} }
dev->iscapture = iscapture; dev->recording = recording;
dev->next = *pSeen; dev->next = *pSeen;
*pSeen = dev; *pSeen = dev;
} }
static ALSA_Device *hotplug_devices = NULL; static ALSA_Device *hotplug_devices = NULL;
static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_default_capture) static void ALSA_HotplugIteration(SDL_bool *has_default_playback, SDL_bool *has_default_recording)
{ {
void **hints = NULL; void **hints = NULL;
ALSA_Device *unseen = NULL; ALSA_Device *unseen = NULL;
@ -834,10 +834,10 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de
} }
if (is_default) { if (is_default) {
if (has_default_output && isoutput) { if (has_default_playback && isoutput) {
*has_default_output = SDL_TRUE; *has_default_playback = SDL_TRUE;
} else if (has_default_capture && isinput) { } else if (has_default_recording && isinput) {
*has_default_capture = SDL_TRUE; *has_default_recording = SDL_TRUE;
} }
free(name); // This should NOT be SDL_free() free(name); // This should NOT be SDL_free()
continue; continue;
@ -847,7 +847,7 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de
ALSA_Device *next; ALSA_Device *next;
for (ALSA_Device *dev = unseen; dev; dev = next) { for (ALSA_Device *dev = unseen; dev; dev = next) {
next = dev->next; next = dev->next;
if ((SDL_strcmp(dev->name, name) == 0) && (((isinput) && dev->iscapture) || ((isoutput) && !dev->iscapture))) { if ((SDL_strcmp(dev->name, name) == 0) && (((isinput) && dev->recording) || ((isoutput) && !dev->recording))) {
if (prev) { if (prev) {
prev->next = next; prev->next = next;
} else { } else {
@ -885,7 +885,7 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de
// report anything still in unseen as removed. // report anything still in unseen as removed.
ALSA_Device *next = NULL; ALSA_Device *next = NULL;
for (ALSA_Device *dev = unseen; dev; dev = next) { for (ALSA_Device *dev = unseen; dev; dev = next) {
//SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: removing %s device '%s'", dev->iscapture ? "capture" : "output", dev->name); //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: removing %s device '%s'", dev->recording ? "recording" : "playback", dev->name);
next = dev->next; next = dev->next;
SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandle(dev)); SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandle(dev));
SDL_free(dev->name); SDL_free(dev->name);
@ -916,17 +916,17 @@ static int SDLCALL ALSA_HotplugThread(void *arg)
} }
#endif #endif
static void ALSA_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) static void ALSA_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{ {
// ALSA doesn't have a concept of a changeable default device, afaik, so we expose a generic default // ALSA doesn't have a concept of a changeable default device, afaik, so we expose a generic default
// device here. It's the best we can do at this level. // device here. It's the best we can do at this level.
SDL_bool has_default_output = SDL_FALSE, has_default_capture = SDL_FALSE; SDL_bool has_default_playback = SDL_FALSE, has_default_recording = SDL_FALSE;
ALSA_HotplugIteration(&has_default_output, &has_default_capture); // run once now before a thread continues to check. ALSA_HotplugIteration(&has_default_playback, &has_default_recording); // run once now before a thread continues to check.
if (has_default_output) { if (has_default_playback) {
*default_output = SDL_AddAudioDevice(/*iscapture=*/SDL_FALSE, "ALSA default output device", NULL, (void*)&default_output_handle); *default_playback = SDL_AddAudioDevice(/*recording=*/SDL_FALSE, "ALSA default playback device", NULL, (void*)&default_playback_handle);
} }
if (has_default_capture) { if (has_default_recording) {
*default_capture = SDL_AddAudioDevice(/*iscapture=*/SDL_TRUE, "ALSA default capture device", NULL, (void*)&default_capture_handle); *default_recording = SDL_AddAudioDevice(/*recording=*/SDL_TRUE, "ALSA default recording device", NULL, (void*)&default_recording_handle);
} }
#if SDL_ALSA_HOTPLUG_THREAD #if SDL_ALSA_HOTPLUG_THREAD
@ -951,7 +951,7 @@ static void ALSA_DeinitializeStart(void)
// Shutting down! Clean up any data we've gathered. // Shutting down! Clean up any data we've gathered.
for (dev = hotplug_devices; dev; dev = next) { for (dev = hotplug_devices; dev; dev = next) {
//SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: at shutdown, removing %s device '%s'", dev->iscapture ? "capture" : "output", dev->name); //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: at shutdown, removing %s device '%s'", dev->recording ? "recording" : "playback", dev->name);
next = dev->next; next = dev->next;
SDL_free(dev->name); SDL_free(dev->name);
SDL_free(dev); SDL_free(dev);
@ -978,11 +978,11 @@ static SDL_bool ALSA_Init(SDL_AudioDriverImpl *impl)
impl->CloseDevice = ALSA_CloseDevice; impl->CloseDevice = ALSA_CloseDevice;
impl->DeinitializeStart = ALSA_DeinitializeStart; impl->DeinitializeStart = ALSA_DeinitializeStart;
impl->Deinitialize = ALSA_Deinitialize; impl->Deinitialize = ALSA_Deinitialize;
impl->WaitCaptureDevice = ALSA_WaitDevice; impl->WaitRecordingDevice = ALSA_WaitDevice;
impl->CaptureFromDevice = ALSA_CaptureFromDevice; impl->RecordDevice = ALSA_RecordDevice;
impl->FlushCapture = ALSA_FlushCapture; impl->FlushRecording = ALSA_FlushRecording;
impl->HasCaptureSupport = SDL_TRUE; impl->HasRecordingSupport = SDL_TRUE;
return SDL_TRUE; return SDL_TRUE;
} }

View File

@ -36,8 +36,8 @@ struct SDL_PrivateAudioData
int resume; // Resume device if it was paused automatically int resume; // Resume device if it was paused automatically
}; };
static SDL_AudioDevice *audioDevice = NULL; static SDL_AudioDevice *playbackDevice = NULL;
static SDL_AudioDevice *captureDevice = NULL; static SDL_AudioDevice *recordingDevice = NULL;
static int ANDROIDAUDIO_OpenDevice(SDL_AudioDevice *device) static int ANDROIDAUDIO_OpenDevice(SDL_AudioDevice *device)
{ {
@ -46,18 +46,18 @@ static int ANDROIDAUDIO_OpenDevice(SDL_AudioDevice *device)
return -1; return -1;
} }
const SDL_bool iscapture = device->iscapture; const SDL_bool recording = device->recording;
if (iscapture) { if (recording) {
if (captureDevice) { if (recordingDevice) {
return SDL_SetError("An audio capture device is already opened"); return SDL_SetError("An audio recording device is already opened");
} }
captureDevice = device; recordingDevice = device;
} else { } else {
if (audioDevice) { if (playbackDevice) {
return SDL_SetError("An audio playback device is already opened"); return SDL_SetError("An audio playback device is already opened");
} }
audioDevice = device; playbackDevice = device;
} }
SDL_AudioFormat test_format; SDL_AudioFormat test_format;
@ -97,14 +97,14 @@ static Uint8 *ANDROIDAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_siz
return Android_JNI_GetAudioBuffer(); return Android_JNI_GetAudioBuffer();
} }
static int ANDROIDAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int ANDROIDAUDIO_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
{ {
return Android_JNI_CaptureAudioBuffer(buffer, buflen); return Android_JNI_RecordAudioBuffer(buffer, buflen);
} }
static void ANDROIDAUDIO_FlushCapture(SDL_AudioDevice *device) static void ANDROIDAUDIO_FlushRecording(SDL_AudioDevice *device)
{ {
Android_JNI_FlushCapturedAudio(); Android_JNI_FlushRecordedAudio();
} }
static void ANDROIDAUDIO_CloseDevice(SDL_AudioDevice *device) static void ANDROIDAUDIO_CloseDevice(SDL_AudioDevice *device)
@ -113,13 +113,13 @@ static void ANDROIDAUDIO_CloseDevice(SDL_AudioDevice *device)
so it's safe to terminate the Java side buffer and AudioTrack so it's safe to terminate the Java side buffer and AudioTrack
*/ */
if (device->hidden) { if (device->hidden) {
Android_JNI_CloseAudioDevice(device->iscapture); Android_JNI_CloseAudioDevice(device->recording);
if (device->iscapture) { if (device->recording) {
SDL_assert(captureDevice == device); SDL_assert(recordingDevice == device);
captureDevice = NULL; recordingDevice = NULL;
} else { } else {
SDL_assert(audioDevice == device); SDL_assert(playbackDevice == device);
audioDevice = NULL; playbackDevice = NULL;
} }
SDL_free(device->hidden); SDL_free(device->hidden);
device->hidden = NULL; device->hidden = NULL;
@ -131,15 +131,15 @@ void ANDROIDAUDIO_PauseDevices(void)
{ {
// TODO: Handle multiple devices? // TODO: Handle multiple devices?
struct SDL_PrivateAudioData *hidden; struct SDL_PrivateAudioData *hidden;
if (audioDevice && audioDevice->hidden) { if (playbackDevice && playbackDevice->hidden) {
hidden = (struct SDL_PrivateAudioData *)audioDevice->hidden; hidden = (struct SDL_PrivateAudioData *)playbackDevice->hidden;
SDL_LockMutex(audioDevice->lock); SDL_LockMutex(playbackDevice->lock);
hidden->resume = SDL_TRUE; hidden->resume = SDL_TRUE;
} }
if (captureDevice && captureDevice->hidden) { if (recordingDevice && recordingDevice->hidden) {
hidden = (struct SDL_PrivateAudioData *)captureDevice->hidden; hidden = (struct SDL_PrivateAudioData *)recordingDevice->hidden;
SDL_LockMutex(captureDevice->lock); SDL_LockMutex(recordingDevice->lock);
hidden->resume = SDL_TRUE; hidden->resume = SDL_TRUE;
} }
} }
@ -149,26 +149,26 @@ void ANDROIDAUDIO_ResumeDevices(void)
{ {
// TODO: Handle multiple devices? // TODO: Handle multiple devices?
struct SDL_PrivateAudioData *hidden; struct SDL_PrivateAudioData *hidden;
if (audioDevice && audioDevice->hidden) { if (playbackDevice && playbackDevice->hidden) {
hidden = (struct SDL_PrivateAudioData *)audioDevice->hidden; hidden = (struct SDL_PrivateAudioData *)playbackDevice->hidden;
if (hidden->resume) { if (hidden->resume) {
hidden->resume = SDL_FALSE; hidden->resume = SDL_FALSE;
SDL_UnlockMutex(audioDevice->lock); SDL_UnlockMutex(playbackDevice->lock);
} }
} }
if (captureDevice && captureDevice->hidden) { if (recordingDevice && recordingDevice->hidden) {
hidden = (struct SDL_PrivateAudioData *)captureDevice->hidden; hidden = (struct SDL_PrivateAudioData *)recordingDevice->hidden;
if (hidden->resume) { if (hidden->resume) {
hidden->resume = SDL_FALSE; hidden->resume = SDL_FALSE;
SDL_UnlockMutex(captureDevice->lock); SDL_UnlockMutex(recordingDevice->lock);
} }
} }
} }
static SDL_bool ANDROIDAUDIO_Init(SDL_AudioDriverImpl *impl) static SDL_bool ANDROIDAUDIO_Init(SDL_AudioDriverImpl *impl)
{ {
// !!! FIXME: if on Android API < 24, DetectDevices and Deinitialize should be NULL and OnlyHasDefaultOutputDevice and OnlyHasDefaultCaptureDevice should be SDL_TRUE, since audio device enum and hotplug appears to require Android 7.0+. // !!! FIXME: if on Android API < 24, DetectDevices and Deinitialize should be NULL and OnlyHasDefaultPlaybackDevice and OnlyHasDefaultRecordingDevice should be SDL_TRUE, since audio device enum and hotplug appears to require Android 7.0+.
impl->ThreadInit = Android_AudioThreadInit; impl->ThreadInit = Android_AudioThreadInit;
impl->DetectDevices = Android_StartAudioHotplug; impl->DetectDevices = Android_StartAudioHotplug;
impl->DeinitializeStart = Android_StopAudioHotplug; impl->DeinitializeStart = Android_StopAudioHotplug;
@ -176,10 +176,10 @@ static SDL_bool ANDROIDAUDIO_Init(SDL_AudioDriverImpl *impl)
impl->PlayDevice = ANDROIDAUDIO_PlayDevice; impl->PlayDevice = ANDROIDAUDIO_PlayDevice;
impl->GetDeviceBuf = ANDROIDAUDIO_GetDeviceBuf; impl->GetDeviceBuf = ANDROIDAUDIO_GetDeviceBuf;
impl->CloseDevice = ANDROIDAUDIO_CloseDevice; impl->CloseDevice = ANDROIDAUDIO_CloseDevice;
impl->CaptureFromDevice = ANDROIDAUDIO_CaptureFromDevice; impl->RecordDevice = ANDROIDAUDIO_RecordDevice;
impl->FlushCapture = ANDROIDAUDIO_FlushCapture; impl->FlushRecording = ANDROIDAUDIO_FlushRecording;
impl->HasCaptureSupport = SDL_TRUE; impl->HasRecordingSupport = SDL_TRUE;
return SDL_TRUE; return SDL_TRUE;
} }

View File

@ -48,19 +48,19 @@
typedef struct SDLCoreAudioHandle typedef struct SDLCoreAudioHandle
{ {
AudioDeviceID devid; AudioDeviceID devid;
SDL_bool iscapture; SDL_bool recording;
} SDLCoreAudioHandle; } SDLCoreAudioHandle;
static SDL_bool TestCoreAudioDeviceHandleCallback(SDL_AudioDevice *device, void *handle) static SDL_bool TestCoreAudioDeviceHandleCallback(SDL_AudioDevice *device, void *handle)
{ {
const SDLCoreAudioHandle *a = (const SDLCoreAudioHandle *) device->handle; const SDLCoreAudioHandle *a = (const SDLCoreAudioHandle *) device->handle;
const SDLCoreAudioHandle *b = (const SDLCoreAudioHandle *) handle; const SDLCoreAudioHandle *b = (const SDLCoreAudioHandle *) handle;
return (a->devid == b->devid) && (!!a->iscapture == !!b->iscapture); return (a->devid == b->devid) && (!!a->recording == !!b->recording);
} }
static SDL_AudioDevice *FindCoreAudioDeviceByHandle(const AudioDeviceID devid, const SDL_bool iscapture) static SDL_AudioDevice *FindCoreAudioDeviceByHandle(const AudioDeviceID devid, const SDL_bool recording)
{ {
SDLCoreAudioHandle handle = { devid, iscapture }; SDLCoreAudioHandle handle = { devid, recording };
return SDL_FindPhysicalAudioDeviceByCallback(TestCoreAudioDeviceHandleCallback, &handle); return SDL_FindPhysicalAudioDeviceByCallback(TestCoreAudioDeviceHandleCallback, &handle);
} }
@ -70,13 +70,13 @@ static const AudioObjectPropertyAddress devlist_address = {
kAudioObjectPropertyElementMain kAudioObjectPropertyElementMain
}; };
static const AudioObjectPropertyAddress default_output_device_address = { static const AudioObjectPropertyAddress default_playback_device_address = {
kAudioHardwarePropertyDefaultOutputDevice, kAudioHardwarePropertyDefaultOutputDevice,
kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMain kAudioObjectPropertyElementMain
}; };
static const AudioObjectPropertyAddress default_input_device_address = { static const AudioObjectPropertyAddress default_recording_device_address = {
kAudioHardwarePropertyDefaultInputDevice, kAudioHardwarePropertyDefaultInputDevice,
kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMain kAudioObjectPropertyElementMain
@ -146,20 +146,20 @@ static void RefreshPhysicalDevices(void)
} }
// any non-zero items remaining in `devs` are new devices to be added. // any non-zero items remaining in `devs` are new devices to be added.
for (int iscapture = 0; iscapture < 2; iscapture++) { for (int recording = 0; recording < 2; recording++) {
const AudioObjectPropertyAddress addr = { const AudioObjectPropertyAddress addr = {
kAudioDevicePropertyStreamConfiguration, kAudioDevicePropertyStreamConfiguration,
iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, recording ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
kAudioObjectPropertyElementMain kAudioObjectPropertyElementMain
}; };
const AudioObjectPropertyAddress nameaddr = { const AudioObjectPropertyAddress nameaddr = {
kAudioObjectPropertyName, kAudioObjectPropertyName,
iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, recording ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
kAudioObjectPropertyElementMain kAudioObjectPropertyElementMain
}; };
const AudioObjectPropertyAddress freqaddr = { const AudioObjectPropertyAddress freqaddr = {
kAudioDevicePropertyNominalSampleRate, kAudioDevicePropertyNominalSampleRate,
iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, recording ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
kAudioObjectPropertyElementMain kAudioObjectPropertyElementMain
}; };
@ -224,15 +224,13 @@ static void RefreshPhysicalDevices(void)
name[len] = '\0'; name[len] = '\0';
#if DEBUG_COREAUDIO #if DEBUG_COREAUDIO
SDL_Log("COREAUDIO: Found %s device #%d: '%s' (devid %d)\n", SDL_Log("COREAUDIO: Found %s device #%d: '%s' (devid %d)\n", ((recording) ? "recording" : "playback"), (int)i, name, (int)dev);
((iscapture) ? "capture" : "output"),
(int)i, name, (int)dev);
#endif #endif
SDLCoreAudioHandle *newhandle = (SDLCoreAudioHandle *) SDL_calloc(1, sizeof (*newhandle)); SDLCoreAudioHandle *newhandle = (SDLCoreAudioHandle *) SDL_calloc(1, sizeof (*newhandle));
if (newhandle) { if (newhandle) {
newhandle->devid = dev; newhandle->devid = dev;
newhandle->iscapture = iscapture ? SDL_TRUE : SDL_FALSE; newhandle->recording = recording ? SDL_TRUE : SDL_FALSE;
SDL_AudioDevice *device = SDL_AddAudioDevice(newhandle->iscapture, name, &spec, newhandle); SDL_AudioDevice *device = SDL_AddAudioDevice(newhandle->recording, name, &spec, newhandle);
if (device) { if (device) {
AudioObjectAddPropertyListener(dev, &alive_address, DeviceAliveNotification, device); AudioObjectAddPropertyListener(dev, &alive_address, DeviceAliveNotification, device);
} else { } else {
@ -254,35 +252,35 @@ static OSStatus DeviceListChangedNotification(AudioObjectID systemObj, UInt32 nu
return noErr; return noErr;
} }
static OSStatus DefaultAudioDeviceChangedNotification(const SDL_bool iscapture, AudioObjectID inObjectID, const AudioObjectPropertyAddress *addr) static OSStatus DefaultAudioDeviceChangedNotification(const SDL_bool recording, AudioObjectID inObjectID, const AudioObjectPropertyAddress *addr)
{ {
AudioDeviceID devid; AudioDeviceID devid;
UInt32 size = sizeof(devid); UInt32 size = sizeof(devid);
if (AudioObjectGetPropertyData(inObjectID, addr, 0, NULL, &size, &devid) == noErr) { if (AudioObjectGetPropertyData(inObjectID, addr, 0, NULL, &size, &devid) == noErr) {
SDL_DefaultAudioDeviceChanged(FindCoreAudioDeviceByHandle(devid, iscapture)); SDL_DefaultAudioDeviceChanged(FindCoreAudioDeviceByHandle(devid, recording));
} }
return noErr; return noErr;
} }
static OSStatus DefaultOutputDeviceChangedNotification(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *inUserData) static OSStatus DefaultPlaybackDeviceChangedNotification(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *inUserData)
{ {
#if DEBUG_COREAUDIO #if DEBUG_COREAUDIO
SDL_Log("COREAUDIO: default output device changed!"); SDL_Log("COREAUDIO: default playback device changed!");
#endif #endif
SDL_assert(inNumberAddresses == 1); SDL_assert(inNumberAddresses == 1);
return DefaultAudioDeviceChangedNotification(SDL_FALSE, inObjectID, inAddresses); return DefaultAudioDeviceChangedNotification(SDL_FALSE, inObjectID, inAddresses);
} }
static OSStatus DefaultInputDeviceChangedNotification(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *inUserData) static OSStatus DefaultRecordingDeviceChangedNotification(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *inUserData)
{ {
#if DEBUG_COREAUDIO #if DEBUG_COREAUDIO
SDL_Log("COREAUDIO: default input device changed!"); SDL_Log("COREAUDIO: default recording device changed!");
#endif #endif
SDL_assert(inNumberAddresses == 1); SDL_assert(inNumberAddresses == 1);
return DefaultAudioDeviceChangedNotification(SDL_TRUE, inObjectID, inAddresses); return DefaultAudioDeviceChangedNotification(SDL_TRUE, inObjectID, inAddresses);
} }
static void COREAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) static void COREAUDIO_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{ {
RefreshPhysicalDevices(); RefreshPhysicalDevices();
@ -293,22 +291,22 @@ static void COREAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioD
AudioDeviceID devid; AudioDeviceID devid;
size = sizeof(AudioDeviceID); size = sizeof(AudioDeviceID);
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &default_output_device_address, 0, NULL, &size, &devid) == noErr) { if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &default_playback_device_address, 0, NULL, &size, &devid) == noErr) {
SDL_AudioDevice *device = FindCoreAudioDeviceByHandle(devid, SDL_FALSE); SDL_AudioDevice *device = FindCoreAudioDeviceByHandle(devid, SDL_FALSE);
if (device) { if (device) {
*default_output = device; *default_playback = device;
} }
} }
AudioObjectAddPropertyListener(kAudioObjectSystemObject, &default_output_device_address, DefaultOutputDeviceChangedNotification, NULL); AudioObjectAddPropertyListener(kAudioObjectSystemObject, &default_playback_device_address, DefaultPlaybackDeviceChangedNotification, NULL);
size = sizeof(AudioDeviceID); size = sizeof(AudioDeviceID);
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &default_input_device_address, 0, NULL, &size, &devid) == noErr) { if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &default_recording_device_address, 0, NULL, &size, &devid) == noErr) {
SDL_AudioDevice *device = FindCoreAudioDeviceByHandle(devid, SDL_TRUE); SDL_AudioDevice *device = FindCoreAudioDeviceByHandle(devid, SDL_TRUE);
if (device) { if (device) {
*default_capture = device; *default_recording = device;
} }
} }
AudioObjectAddPropertyListener(kAudioObjectSystemObject, &default_input_device_address, DefaultInputDeviceChangedNotification, NULL); AudioObjectAddPropertyListener(kAudioObjectSystemObject, &default_recording_device_address, DefaultRecordingDeviceChangedNotification, NULL);
} }
#else // iOS-specific section follows. #else // iOS-specific section follows.
@ -387,18 +385,18 @@ static void InterruptionEnd(SDL_AudioDevice *device)
typedef struct typedef struct
{ {
int output; int playback;
int capture; int recording;
} CountOpenAudioDevicesData; } CountOpenAudioDevicesData;
static SDL_bool CountOpenAudioDevices(SDL_AudioDevice *device, void *userdata) static SDL_bool CountOpenAudioDevices(SDL_AudioDevice *device, void *userdata)
{ {
CountOpenAudioDevicesData *data = (CountOpenAudioDevicesData *) userdata; CountOpenAudioDevicesData *data = (CountOpenAudioDevicesData *) userdata;
if (device->hidden != NULL) { // assume it's open if hidden != NULL if (device->hidden != NULL) { // assume it's open if hidden != NULL
if (device->iscapture) { if (device->recording) {
data->capture++; data->recording++;
} else { } else {
data->output++; data->playback++;
} }
} }
return SDL_FALSE; // keep enumerating until all devices have been checked. return SDL_FALSE; // keep enumerating until all devices have been checked.
@ -437,9 +435,9 @@ static SDL_bool UpdateAudioSession(SDL_AudioDevice *device, SDL_bool open, SDL_b
category = AVAudioSessionCategoryPlayAndRecord; category = AVAudioSessionCategoryPlayAndRecord;
} }
} }
} else if (data.output && data.capture) { } else if (data.playback && data.recording) {
category = AVAudioSessionCategoryPlayAndRecord; category = AVAudioSessionCategoryPlayAndRecord;
} else if (data.capture) { } else if (data.recording) {
category = AVAudioSessionCategoryRecord; category = AVAudioSessionCategoryRecord;
} }
@ -492,7 +490,7 @@ static SDL_bool UpdateAudioSession(SDL_AudioDevice *device, SDL_bool open, SDL_b
} }
} }
if ((data.output || data.capture) && !session_active) { if ((data.playback || data.recording) && !session_active) {
if (![session setActive:YES error:&err]) { if (![session setActive:YES error:&err]) {
if ([err code] == AVAudioSessionErrorCodeResourceNotAvailable && if ([err code] == AVAudioSessionErrorCodeResourceNotAvailable &&
category == AVAudioSessionCategoryPlayAndRecord) { category == AVAudioSessionCategoryPlayAndRecord) {
@ -505,7 +503,7 @@ static SDL_bool UpdateAudioSession(SDL_AudioDevice *device, SDL_bool open, SDL_b
} }
session_active = SDL_TRUE; session_active = SDL_TRUE;
ResumeAudioDevices(); ResumeAudioDevices();
} else if (!data.output && !data.capture && session_active) { } else if (!data.playback && !data.recording && session_active) {
PauseAudioDevices(); PauseAudioDevices();
[session setActive:NO error:nil]; [session setActive:NO error:nil];
session_active = SDL_FALSE; session_active = SDL_FALSE;
@ -553,7 +551,7 @@ static SDL_bool UpdateAudioSession(SDL_AudioDevice *device, SDL_bool open, SDL_b
static int COREAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) static int COREAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size)
{ {
AudioQueueBufferRef current_buffer = device->hidden->current_buffer; AudioQueueBufferRef current_buffer = device->hidden->current_buffer;
SDL_assert(current_buffer != NULL); // should have been called from OutputBufferReadyCallback SDL_assert(current_buffer != NULL); // should have been called from PlaybackBufferReadyCallback
SDL_assert(buffer == (Uint8 *) current_buffer->mAudioData); SDL_assert(buffer == (Uint8 *) current_buffer->mAudioData);
current_buffer->mAudioDataByteSize = current_buffer->mAudioDataBytesCapacity; current_buffer->mAudioDataByteSize = current_buffer->mAudioDataBytesCapacity;
device->hidden->current_buffer = NULL; device->hidden->current_buffer = NULL;
@ -564,19 +562,19 @@ static int COREAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, in
static Uint8 *COREAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) static Uint8 *COREAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
{ {
AudioQueueBufferRef current_buffer = device->hidden->current_buffer; AudioQueueBufferRef current_buffer = device->hidden->current_buffer;
SDL_assert(current_buffer != NULL); // should have been called from OutputBufferReadyCallback SDL_assert(current_buffer != NULL); // should have been called from PlaybackBufferReadyCallback
SDL_assert(current_buffer->mAudioData != NULL); SDL_assert(current_buffer->mAudioData != NULL);
*buffer_size = (int) current_buffer->mAudioDataBytesCapacity; *buffer_size = (int) current_buffer->mAudioDataBytesCapacity;
return (Uint8 *) current_buffer->mAudioData; return (Uint8 *) current_buffer->mAudioData;
} }
static void OutputBufferReadyCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) static void PlaybackBufferReadyCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer)
{ {
SDL_AudioDevice *device = (SDL_AudioDevice *)inUserData; SDL_AudioDevice *device = (SDL_AudioDevice *)inUserData;
SDL_assert(inBuffer != NULL); // ...right? SDL_assert(inBuffer != NULL); // ...right?
SDL_assert(device->hidden->current_buffer == NULL); // shouldn't have anything pending SDL_assert(device->hidden->current_buffer == NULL); // shouldn't have anything pending
device->hidden->current_buffer = inBuffer; device->hidden->current_buffer = inBuffer;
const SDL_bool okay = SDL_OutputAudioThreadIterate(device); const SDL_bool okay = SDL_PlaybackAudioThreadIterate(device);
SDL_assert((device->hidden->current_buffer == NULL) || !okay); // PlayDevice should have enqueued and cleaned it out, unless we failed or shutdown. SDL_assert((device->hidden->current_buffer == NULL) || !okay); // PlayDevice should have enqueued and cleaned it out, unless we failed or shutdown.
// buffer is unexpectedly here? We're probably dying, but try to requeue this buffer with silence. // buffer is unexpectedly here? We're probably dying, but try to requeue this buffer with silence.
@ -588,10 +586,10 @@ static void OutputBufferReadyCallback(void *inUserData, AudioQueueRef inAQ, Audi
} }
} }
static int COREAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int COREAUDIO_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
{ {
AudioQueueBufferRef current_buffer = device->hidden->current_buffer; AudioQueueBufferRef current_buffer = device->hidden->current_buffer;
SDL_assert(current_buffer != NULL); // should have been called from InputBufferReadyCallback SDL_assert(current_buffer != NULL); // should have been called from RecordingBufferReadyCallback
SDL_assert(current_buffer->mAudioData != NULL); SDL_assert(current_buffer->mAudioData != NULL);
SDL_assert(buflen >= (int) current_buffer->mAudioDataByteSize); // `cpy` makes sure this won't overflow a buffer, but we _will_ drop samples if this assertion fails! SDL_assert(buflen >= (int) current_buffer->mAudioDataByteSize); // `cpy` makes sure this won't overflow a buffer, but we _will_ drop samples if this assertion fails!
const int cpy = SDL_min(buflen, (int) current_buffer->mAudioDataByteSize); const int cpy = SDL_min(buflen, (int) current_buffer->mAudioDataByteSize);
@ -601,7 +599,7 @@ static int COREAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, in
return cpy; return cpy;
} }
static void COREAUDIO_FlushCapture(SDL_AudioDevice *device) static void COREAUDIO_FlushRecording(SDL_AudioDevice *device)
{ {
AudioQueueBufferRef current_buffer = device->hidden->current_buffer; AudioQueueBufferRef current_buffer = device->hidden->current_buffer;
if (current_buffer != NULL) { // also gets called at shutdown, when no buffer is available. if (current_buffer != NULL) { // also gets called at shutdown, when no buffer is available.
@ -611,7 +609,7 @@ static void COREAUDIO_FlushCapture(SDL_AudioDevice *device)
} }
} }
static void InputBufferReadyCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, static void RecordingBufferReadyCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer,
const AudioTimeStamp *inStartTime, UInt32 inNumberPacketDescriptions, const AudioTimeStamp *inStartTime, UInt32 inNumberPacketDescriptions,
const AudioStreamPacketDescription *inPacketDescs) const AudioStreamPacketDescription *inPacketDescs)
{ {
@ -620,12 +618,12 @@ static void InputBufferReadyCallback(void *inUserData, AudioQueueRef inAQ, Audio
SDL_assert(inBuffer != NULL); // ...right? SDL_assert(inBuffer != NULL); // ...right?
SDL_assert(device->hidden->current_buffer == NULL); // shouldn't have anything pending SDL_assert(device->hidden->current_buffer == NULL); // shouldn't have anything pending
device->hidden->current_buffer = inBuffer; device->hidden->current_buffer = inBuffer;
SDL_CaptureAudioThreadIterate(device); SDL_RecordingAudioThreadIterate(device);
// buffer is unexpectedly here? We're probably dying, but try to requeue this buffer anyhow. // buffer is unexpectedly here? We're probably dying, but try to requeue this buffer anyhow.
if (device->hidden->current_buffer != NULL) { if (device->hidden->current_buffer != NULL) {
SDL_assert(SDL_AtomicGet(&device->shutdown) != 0); SDL_assert(SDL_AtomicGet(&device->shutdown) != 0);
COREAUDIO_FlushCapture(device); // just flush it manually, which will requeue it. COREAUDIO_FlushRecording(device); // just flush it manually, which will requeue it.
} }
} }
@ -680,7 +678,7 @@ static int PrepareDevice(SDL_AudioDevice *device)
UInt32 alive = 0; UInt32 alive = 0;
size = sizeof(alive); size = sizeof(alive);
addr.mSelector = kAudioDevicePropertyDeviceIsAlive; addr.mSelector = kAudioDevicePropertyDeviceIsAlive;
addr.mScope = device->iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; addr.mScope = device->recording ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;
result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &alive); result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &alive);
CHECK_RESULT("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)"); CHECK_RESULT("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)");
if (!alive) { if (!alive) {
@ -705,7 +703,7 @@ static int AssignDeviceToAudioQueue(SDL_AudioDevice *device)
{ {
const AudioObjectPropertyAddress prop = { const AudioObjectPropertyAddress prop = {
kAudioDevicePropertyDeviceUID, kAudioDevicePropertyDeviceUID,
device->iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, device->recording ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
kAudioObjectPropertyElementMain kAudioObjectPropertyElementMain
}; };
@ -726,16 +724,16 @@ static int AssignDeviceToAudioQueue(SDL_AudioDevice *device)
static int PrepareAudioQueue(SDL_AudioDevice *device) static int PrepareAudioQueue(SDL_AudioDevice *device)
{ {
const AudioStreamBasicDescription *strdesc = &device->hidden->strdesc; const AudioStreamBasicDescription *strdesc = &device->hidden->strdesc;
const SDL_bool iscapture = device->iscapture; const SDL_bool recording = device->recording;
OSStatus result; OSStatus result;
SDL_assert(CFRunLoopGetCurrent() != NULL); SDL_assert(CFRunLoopGetCurrent() != NULL);
if (iscapture) { if (recording) {
result = AudioQueueNewInput(strdesc, InputBufferReadyCallback, device, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0, &device->hidden->audioQueue); result = AudioQueueNewInput(strdesc, RecordingBufferReadyCallback, device, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0, &device->hidden->audioQueue);
CHECK_RESULT("AudioQueueNewInput"); CHECK_RESULT("AudioQueueNewInput");
} else { } else {
result = AudioQueueNewOutput(strdesc, OutputBufferReadyCallback, device, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0, &device->hidden->audioQueue); result = AudioQueueNewOutput(strdesc, PlaybackBufferReadyCallback, device, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0, &device->hidden->audioQueue);
CHECK_RESULT("AudioQueueNewOutput"); CHECK_RESULT("AudioQueueNewOutput");
} }
@ -827,10 +825,10 @@ static int AudioQueueThreadEntry(void *arg)
{ {
SDL_AudioDevice *device = (SDL_AudioDevice *)arg; SDL_AudioDevice *device = (SDL_AudioDevice *)arg;
if (device->iscapture) { if (device->recording) {
SDL_CaptureAudioThreadSetup(device); SDL_RecordingAudioThreadSetup(device);
} else { } else {
SDL_OutputAudioThreadSetup(device); SDL_PlaybackAudioThreadSetup(device);
} }
if (PrepareAudioQueue(device) < 0) { if (PrepareAudioQueue(device) < 0) {
@ -842,18 +840,18 @@ static int AudioQueueThreadEntry(void *arg)
// init was successful, alert parent thread and start running... // init was successful, alert parent thread and start running...
SDL_PostSemaphore(device->hidden->ready_semaphore); SDL_PostSemaphore(device->hidden->ready_semaphore);
// This would be WaitDevice/WaitCaptureDevice in the normal SDL audio thread, but we get *BufferReadyCallback calls here to know when to iterate. // This would be WaitDevice/WaitRecordingDevice in the normal SDL audio thread, but we get *BufferReadyCallback calls here to know when to iterate.
while (!SDL_AtomicGet(&device->shutdown)) { while (!SDL_AtomicGet(&device->shutdown)) {
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.10, 1); CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.10, 1);
} }
if (device->iscapture) { if (device->recording) {
SDL_CaptureAudioThreadShutdown(device); SDL_RecordingAudioThreadShutdown(device);
} else { } else {
// Drain off any pending playback. // Drain off any pending playback.
const CFTimeInterval secs = (((CFTimeInterval)device->sample_frames) / ((CFTimeInterval)device->spec.freq)) * 2.0; const CFTimeInterval secs = (((CFTimeInterval)device->sample_frames) / ((CFTimeInterval)device->spec.freq)) * 2.0;
CFRunLoopRunInMode(kCFRunLoopDefaultMode, secs, 0); CFRunLoopRunInMode(kCFRunLoopDefaultMode, secs, 0);
SDL_OutputAudioThreadShutdown(device); SDL_PlaybackAudioThreadShutdown(device);
} }
return 0; return 0;
@ -878,7 +876,7 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device)
[session setPreferredSampleRate:device->spec.freq error:nil]; [session setPreferredSampleRate:device->spec.freq error:nil];
device->spec.freq = (int)session.sampleRate; device->spec.freq = (int)session.sampleRate;
#ifdef SDL_PLATFORM_TVOS #ifdef SDL_PLATFORM_TVOS
if (device->iscapture) { if (device->recording) {
[session setPreferredInputNumberOfChannels:device->spec.channels error:nil]; [session setPreferredInputNumberOfChannels:device->spec.channels error:nil];
device->spec.channels = (int)session.preferredInputNumberOfChannels; device->spec.channels = (int)session.preferredInputNumberOfChannels;
} else { } else {
@ -974,8 +972,8 @@ static void COREAUDIO_DeinitializeStart(void)
{ {
#ifdef MACOSX_COREAUDIO #ifdef MACOSX_COREAUDIO
AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &devlist_address, DeviceListChangedNotification, NULL); AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &devlist_address, DeviceListChangedNotification, NULL);
AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &default_output_device_address, DefaultOutputDeviceChangedNotification, NULL); AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &default_playback_device_address, DefaultPlaybackDeviceChangedNotification, NULL);
AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &default_input_device_address, DefaultInputDeviceChangedNotification, NULL); AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &default_recording_device_address, DefaultRecordingDeviceChangedNotification, NULL);
#endif #endif
} }
@ -984,8 +982,8 @@ static SDL_bool COREAUDIO_Init(SDL_AudioDriverImpl *impl)
impl->OpenDevice = COREAUDIO_OpenDevice; impl->OpenDevice = COREAUDIO_OpenDevice;
impl->PlayDevice = COREAUDIO_PlayDevice; impl->PlayDevice = COREAUDIO_PlayDevice;
impl->GetDeviceBuf = COREAUDIO_GetDeviceBuf; impl->GetDeviceBuf = COREAUDIO_GetDeviceBuf;
impl->CaptureFromDevice = COREAUDIO_CaptureFromDevice; impl->RecordDevice = COREAUDIO_RecordDevice;
impl->FlushCapture = COREAUDIO_FlushCapture; impl->FlushRecording = COREAUDIO_FlushRecording;
impl->CloseDevice = COREAUDIO_CloseDevice; impl->CloseDevice = COREAUDIO_CloseDevice;
impl->DeinitializeStart = COREAUDIO_DeinitializeStart; impl->DeinitializeStart = COREAUDIO_DeinitializeStart;
@ -993,12 +991,12 @@ static SDL_bool COREAUDIO_Init(SDL_AudioDriverImpl *impl)
impl->DetectDevices = COREAUDIO_DetectDevices; impl->DetectDevices = COREAUDIO_DetectDevices;
impl->FreeDeviceHandle = COREAUDIO_FreeDeviceHandle; impl->FreeDeviceHandle = COREAUDIO_FreeDeviceHandle;
#else #else
impl->OnlyHasDefaultOutputDevice = SDL_TRUE; impl->OnlyHasDefaultPlaybackDevice = SDL_TRUE;
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE; impl->OnlyHasDefaultRecordingDevice = SDL_TRUE;
#endif #endif
impl->ProvidesOwnCallbackThread = SDL_TRUE; impl->ProvidesOwnCallbackThread = SDL_TRUE;
impl->HasCaptureSupport = SDL_TRUE; impl->HasRecordingSupport = SDL_TRUE;
return SDL_TRUE; return SDL_TRUE;
} }

View File

@ -170,7 +170,7 @@ static void DSOUND_FreeDeviceHandle(SDL_AudioDevice *device)
// FindAllDevs is presumably only used on WinXP; Vista and later can use IMMDevice for better results. // FindAllDevs is presumably only used on WinXP; Vista and later can use IMMDevice for better results.
typedef struct FindAllDevsData typedef struct FindAllDevsData
{ {
SDL_bool iscapture; SDL_bool recording;
SDL_AudioDevice **default_device; SDL_AudioDevice **default_device;
LPCGUID default_device_guid; LPCGUID default_device_guid;
} FindAllDevsData; } FindAllDevsData;
@ -189,7 +189,7 @@ static BOOL CALLBACK FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVO
* device before getting the channel mask and output format, making * device before getting the channel mask and output format, making
* this information inaccessible at enumeration time * this information inaccessible at enumeration time
*/ */
SDL_AudioDevice *device = SDL_AddAudioDevice(data->iscapture, str, NULL, cpyguid); SDL_AudioDevice *device = SDL_AddAudioDevice(data->recording, str, NULL, cpyguid);
if (device && data->default_device && data->default_device_guid) { if (device && data->default_device && data->default_device_guid) {
if (SDL_memcmp(cpyguid, data->default_device_guid, sizeof (GUID)) == 0) { if (SDL_memcmp(cpyguid, data->default_device_guid, sizeof (GUID)) == 0) {
*data->default_device = device; *data->default_device = device;
@ -202,11 +202,11 @@ static BOOL CALLBACK FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVO
return TRUE; // keep enumerating. return TRUE; // keep enumerating.
} }
static void DSOUND_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) static void DSOUND_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{ {
#ifdef HAVE_MMDEVICEAPI_H #ifdef HAVE_MMDEVICEAPI_H
if (SupportsIMMDevice) { if (SupportsIMMDevice) {
SDL_IMMDevice_EnumerateEndpoints(default_output, default_capture); SDL_IMMDevice_EnumerateEndpoints(default_playback, default_recording);
} else } else
#endif #endif
{ {
@ -216,13 +216,13 @@ static void DSOUND_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevi
FindAllDevsData data; FindAllDevsData data;
GUID guid; GUID guid;
data.iscapture = SDL_TRUE; data.recording = SDL_TRUE;
data.default_device = default_capture; data.default_device = default_recording;
data.default_device_guid = (pGetDeviceID(&SDL_DSDEVID_DefaultCapture, &guid) == DS_OK) ? &guid : NULL; data.default_device_guid = (pGetDeviceID(&SDL_DSDEVID_DefaultCapture, &guid) == DS_OK) ? &guid : NULL;
pDirectSoundCaptureEnumerateW(FindAllDevs, &data); pDirectSoundCaptureEnumerateW(FindAllDevs, &data);
data.iscapture = SDL_FALSE; data.recording = SDL_FALSE;
data.default_device = default_output; data.default_device = default_playback;
data.default_device_guid = (pGetDeviceID(&SDL_DSDEVID_DefaultPlayback, &guid) == DS_OK) ? &guid : NULL; data.default_device_guid = (pGetDeviceID(&SDL_DSDEVID_DefaultPlayback, &guid) == DS_OK) ? &guid : NULL;
pDirectSoundEnumerateW(FindAllDevs, &data); pDirectSoundEnumerateW(FindAllDevs, &data);
} }
@ -333,7 +333,7 @@ static Uint8 *DSOUND_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
return device->hidden->locked_buf; return device->hidden->locked_buf;
} }
static int DSOUND_WaitCaptureDevice(SDL_AudioDevice *device) static int DSOUND_WaitRecordingDevice(SDL_AudioDevice *device)
{ {
struct SDL_PrivateAudioData *h = device->hidden; struct SDL_PrivateAudioData *h = device->hidden;
while (!SDL_AtomicGet(&device->shutdown)) { while (!SDL_AtomicGet(&device->shutdown)) {
@ -349,7 +349,7 @@ static int DSOUND_WaitCaptureDevice(SDL_AudioDevice *device)
return 0; return 0;
} }
static int DSOUND_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int DSOUND_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
{ {
struct SDL_PrivateAudioData *h = device->hidden; struct SDL_PrivateAudioData *h = device->hidden;
DWORD ptr1len, ptr2len; DWORD ptr1len, ptr2len;
@ -376,7 +376,7 @@ static int DSOUND_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int b
return (int) ptr1len; return (int) ptr1len;
} }
static void DSOUND_FlushCapture(SDL_AudioDevice *device) static void DSOUND_FlushRecording(SDL_AudioDevice *device)
{ {
struct SDL_PrivateAudioData *h = device->hidden; struct SDL_PrivateAudioData *h = device->hidden;
DWORD junk, cursor; DWORD junk, cursor;
@ -409,7 +409,7 @@ static void DSOUND_CloseDevice(SDL_AudioDevice *device)
/* This function tries to create a secondary audio buffer, and returns the /* This function tries to create a secondary audio buffer, and returns the
number of audio chunks available in the created buffer. This is for number of audio chunks available in the created buffer. This is for
playback devices, not capture. playback devices, not recording.
*/ */
static int CreateSecondary(SDL_AudioDevice *device, const DWORD bufsize, WAVEFORMATEX *wfmt) static int CreateSecondary(SDL_AudioDevice *device, const DWORD bufsize, WAVEFORMATEX *wfmt)
{ {
@ -450,7 +450,7 @@ static int CreateSecondary(SDL_AudioDevice *device, const DWORD bufsize, WAVEFOR
/* This function tries to create a capture buffer, and returns the /* This function tries to create a capture buffer, and returns the
number of audio chunks available in the created buffer. This is for number of audio chunks available in the created buffer. This is for
capture devices, not playback. recording devices, not playback.
*/ */
static int CreateCaptureBuffer(SDL_AudioDevice *device, const DWORD bufsize, WAVEFORMATEX *wfmt) static int CreateCaptureBuffer(SDL_AudioDevice *device, const DWORD bufsize, WAVEFORMATEX *wfmt)
{ {
@ -513,7 +513,7 @@ static int DSOUND_OpenDevice(SDL_AudioDevice *device)
SDL_assert(guid != NULL); SDL_assert(guid != NULL);
HRESULT result; HRESULT result;
if (device->iscapture) { if (device->recording) {
result = pDirectSoundCaptureCreate8(guid, &device->hidden->capture, NULL); result = pDirectSoundCaptureCreate8(guid, &device->hidden->capture, NULL);
if (result != DS_OK) { if (result != DS_OK) {
return SetDSerror("DirectSoundCaptureCreate8", result); return SetDSerror("DirectSoundCaptureCreate8", result);
@ -603,7 +603,7 @@ static int DSOUND_OpenDevice(SDL_AudioDevice *device)
wfmt.Format.nBlockAlign = wfmt.Format.nChannels * (wfmt.Format.wBitsPerSample / 8); wfmt.Format.nBlockAlign = wfmt.Format.nChannels * (wfmt.Format.wBitsPerSample / 8);
wfmt.Format.nAvgBytesPerSec = wfmt.Format.nSamplesPerSec * wfmt.Format.nBlockAlign; wfmt.Format.nAvgBytesPerSec = wfmt.Format.nSamplesPerSec * wfmt.Format.nBlockAlign;
const int rc = device->iscapture ? CreateCaptureBuffer(device, bufsize, (WAVEFORMATEX *)&wfmt) : CreateSecondary(device, bufsize, (WAVEFORMATEX *)&wfmt); const int rc = device->recording ? CreateCaptureBuffer(device, bufsize, (WAVEFORMATEX *)&wfmt) : CreateSecondary(device, bufsize, (WAVEFORMATEX *)&wfmt);
if (rc == 0) { if (rc == 0) {
device->hidden->num_buffers = numchunks; device->hidden->num_buffers = numchunks;
break; break;
@ -660,15 +660,15 @@ static SDL_bool DSOUND_Init(SDL_AudioDriverImpl *impl)
impl->PlayDevice = DSOUND_PlayDevice; impl->PlayDevice = DSOUND_PlayDevice;
impl->WaitDevice = DSOUND_WaitDevice; impl->WaitDevice = DSOUND_WaitDevice;
impl->GetDeviceBuf = DSOUND_GetDeviceBuf; impl->GetDeviceBuf = DSOUND_GetDeviceBuf;
impl->WaitCaptureDevice = DSOUND_WaitCaptureDevice; impl->WaitRecordingDevice = DSOUND_WaitRecordingDevice;
impl->CaptureFromDevice = DSOUND_CaptureFromDevice; impl->RecordDevice = DSOUND_RecordDevice;
impl->FlushCapture = DSOUND_FlushCapture; impl->FlushRecording = DSOUND_FlushRecording;
impl->CloseDevice = DSOUND_CloseDevice; impl->CloseDevice = DSOUND_CloseDevice;
impl->FreeDeviceHandle = DSOUND_FreeDeviceHandle; impl->FreeDeviceHandle = DSOUND_FreeDeviceHandle;
impl->DeinitializeStart = DSOUND_DeinitializeStart; impl->DeinitializeStart = DSOUND_DeinitializeStart;
impl->Deinitialize = DSOUND_Deinitialize; impl->Deinitialize = DSOUND_Deinitialize;
impl->HasCaptureSupport = SDL_TRUE; impl->HasRecordingSupport = SDL_TRUE;
return SDL_TRUE; return SDL_TRUE;
} }

View File

@ -58,7 +58,7 @@ static Uint8 *DISKAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
return device->hidden->mixbuf; return device->hidden->mixbuf;
} }
static int DISKAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int DISKAUDIO_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
{ {
struct SDL_PrivateAudioData *h = device->hidden; struct SDL_PrivateAudioData *h = device->hidden;
const int origbuflen = buflen; const int origbuflen = buflen;
@ -79,7 +79,7 @@ static int DISKAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, in
return origbuflen; return origbuflen;
} }
static void DISKAUDIO_FlushCapture(SDL_AudioDevice *device) static void DISKAUDIO_FlushRecording(SDL_AudioDevice *device)
{ {
// no op...we don't advance the file pointer or anything. // no op...we don't advance the file pointer or anything.
} }
@ -96,19 +96,19 @@ static void DISKAUDIO_CloseDevice(SDL_AudioDevice *device)
} }
} }
static const char *get_filename(const SDL_bool iscapture) static const char *get_filename(const SDL_bool recording)
{ {
const char *devname = SDL_getenv(iscapture ? DISKENVR_INFILE : DISKENVR_OUTFILE); const char *devname = SDL_getenv(recording ? DISKENVR_INFILE : DISKENVR_OUTFILE);
if (!devname) { if (!devname) {
devname = iscapture ? DISKDEFAULT_INFILE : DISKDEFAULT_OUTFILE; devname = recording ? DISKDEFAULT_INFILE : DISKDEFAULT_OUTFILE;
} }
return devname; return devname;
} }
static int DISKAUDIO_OpenDevice(SDL_AudioDevice *device) static int DISKAUDIO_OpenDevice(SDL_AudioDevice *device)
{ {
SDL_bool iscapture = device->iscapture; SDL_bool recording = device->recording;
const char *fname = get_filename(iscapture); const char *fname = get_filename(recording);
const char *envr = SDL_getenv(DISKENVR_IODELAY); const char *envr = SDL_getenv(DISKENVR_IODELAY);
device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden));
@ -123,13 +123,13 @@ static int DISKAUDIO_OpenDevice(SDL_AudioDevice *device)
} }
// Open the "audio device" // Open the "audio device"
device->hidden->io = SDL_IOFromFile(fname, iscapture ? "rb" : "wb"); device->hidden->io = SDL_IOFromFile(fname, recording ? "rb" : "wb");
if (!device->hidden->io) { if (!device->hidden->io) {
return -1; return -1;
} }
// Allocate mixing buffer // Allocate mixing buffer
if (!iscapture) { if (!recording) {
device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size);
if (!device->hidden->mixbuf) { if (!device->hidden->mixbuf) {
return -1; return -1;
@ -138,30 +138,30 @@ static int DISKAUDIO_OpenDevice(SDL_AudioDevice *device)
} }
SDL_LogCritical(SDL_LOG_CATEGORY_AUDIO, "You are using the SDL disk i/o audio driver!"); SDL_LogCritical(SDL_LOG_CATEGORY_AUDIO, "You are using the SDL disk i/o audio driver!");
SDL_LogCritical(SDL_LOG_CATEGORY_AUDIO, " %s file [%s].\n", iscapture ? "Reading from" : "Writing to", fname); SDL_LogCritical(SDL_LOG_CATEGORY_AUDIO, " %s file [%s].\n", recording ? "Reading from" : "Writing to", fname);
return 0; // We're ready to rock and roll. :-) return 0; // We're ready to rock and roll. :-)
} }
static void DISKAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) static void DISKAUDIO_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{ {
*default_output = SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, NULL, (void *)0x1); *default_playback = SDL_AddAudioDevice(SDL_FALSE, DEFAULT_PLAYBACK_DEVNAME, NULL, (void *)0x1);
*default_capture = SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, NULL, (void *)0x2); *default_recording = SDL_AddAudioDevice(SDL_TRUE, DEFAULT_RECORDING_DEVNAME, NULL, (void *)0x2);
} }
static SDL_bool DISKAUDIO_Init(SDL_AudioDriverImpl *impl) static SDL_bool DISKAUDIO_Init(SDL_AudioDriverImpl *impl)
{ {
impl->OpenDevice = DISKAUDIO_OpenDevice; impl->OpenDevice = DISKAUDIO_OpenDevice;
impl->WaitDevice = DISKAUDIO_WaitDevice; impl->WaitDevice = DISKAUDIO_WaitDevice;
impl->WaitCaptureDevice = DISKAUDIO_WaitDevice; impl->WaitRecordingDevice = DISKAUDIO_WaitDevice;
impl->PlayDevice = DISKAUDIO_PlayDevice; impl->PlayDevice = DISKAUDIO_PlayDevice;
impl->GetDeviceBuf = DISKAUDIO_GetDeviceBuf; impl->GetDeviceBuf = DISKAUDIO_GetDeviceBuf;
impl->CaptureFromDevice = DISKAUDIO_CaptureFromDevice; impl->RecordDevice = DISKAUDIO_RecordDevice;
impl->FlushCapture = DISKAUDIO_FlushCapture; impl->FlushRecording = DISKAUDIO_FlushRecording;
impl->CloseDevice = DISKAUDIO_CloseDevice; impl->CloseDevice = DISKAUDIO_CloseDevice;
impl->DetectDevices = DISKAUDIO_DetectDevices; impl->DetectDevices = DISKAUDIO_DetectDevices;
impl->HasCaptureSupport = SDL_TRUE; impl->HasRecordingSupport = SDL_TRUE;
return SDL_TRUE; return SDL_TRUE;
} }

View File

@ -39,7 +39,7 @@
#include "../SDL_audiodev_c.h" #include "../SDL_audiodev_c.h"
#include "SDL_dspaudio.h" #include "SDL_dspaudio.h"
static void DSP_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) static void DSP_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{ {
SDL_EnumUnixAudioDevices(SDL_FALSE, NULL); SDL_EnumUnixAudioDevices(SDL_FALSE, NULL);
} }
@ -74,7 +74,7 @@ static int DSP_OpenDevice(SDL_AudioDevice *device)
} }
// Open the audio device; we hardcode the device path in `device->name` for lack of better info, so use that. // Open the audio device; we hardcode the device path in `device->name` for lack of better info, so use that.
const int flags = ((device->iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); const int flags = ((device->recording) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
device->hidden->audio_fd = open(device->name, flags | O_CLOEXEC, 0); device->hidden->audio_fd = open(device->name, flags | O_CLOEXEC, 0);
if (device->hidden->audio_fd < 0) { if (device->hidden->audio_fd < 0) {
return SDL_SetError("Couldn't open %s: %s", device->name, strerror(errno)); return SDL_SetError("Couldn't open %s: %s", device->name, strerror(errno));
@ -188,7 +188,7 @@ static int DSP_OpenDevice(SDL_AudioDevice *device)
#endif #endif
// Allocate mixing buffer // Allocate mixing buffer
if (!device->iscapture) { if (!device->recording) {
device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size);
if (!device->hidden->mixbuf) { if (!device->hidden->mixbuf) {
return -1; return -1;
@ -201,7 +201,7 @@ static int DSP_OpenDevice(SDL_AudioDevice *device)
static int DSP_WaitDevice(SDL_AudioDevice *device) static int DSP_WaitDevice(SDL_AudioDevice *device)
{ {
const unsigned long ioctlreq = device->iscapture ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE; const unsigned long ioctlreq = device->recording ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE;
struct SDL_PrivateAudioData *h = device->hidden; struct SDL_PrivateAudioData *h = device->hidden;
while (!SDL_AtomicGet(&device->shutdown)) { while (!SDL_AtomicGet(&device->shutdown)) {
@ -242,12 +242,12 @@ static Uint8 *DSP_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
return device->hidden->mixbuf; return device->hidden->mixbuf;
} }
static int DSP_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int DSP_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
{ {
return (int)read(device->hidden->audio_fd, buffer, buflen); return (int)read(device->hidden->audio_fd, buffer, buflen);
} }
static void DSP_FlushCapture(SDL_AudioDevice *device) static void DSP_FlushRecording(SDL_AudioDevice *device)
{ {
struct SDL_PrivateAudioData *h = device->hidden; struct SDL_PrivateAudioData *h = device->hidden;
audio_buf_info info; audio_buf_info info;
@ -287,11 +287,11 @@ static SDL_bool DSP_Init(SDL_AudioDriverImpl *impl)
impl->PlayDevice = DSP_PlayDevice; impl->PlayDevice = DSP_PlayDevice;
impl->GetDeviceBuf = DSP_GetDeviceBuf; impl->GetDeviceBuf = DSP_GetDeviceBuf;
impl->CloseDevice = DSP_CloseDevice; impl->CloseDevice = DSP_CloseDevice;
impl->WaitCaptureDevice = DSP_WaitDevice; impl->WaitRecordingDevice = DSP_WaitDevice;
impl->CaptureFromDevice = DSP_CaptureFromDevice; impl->RecordDevice = DSP_RecordDevice;
impl->FlushCapture = DSP_FlushCapture; impl->FlushRecording = DSP_FlushRecording;
impl->HasCaptureSupport = SDL_TRUE; impl->HasRecordingSupport = SDL_TRUE;
return SDL_TRUE; return SDL_TRUE;
} }

View File

@ -43,7 +43,7 @@ static int DUMMYAUDIO_OpenDevice(SDL_AudioDevice *device)
return -1; return -1;
} }
if (!device->iscapture) { if (!device->recording) {
device->hidden->mixbuf = (Uint8 *) SDL_malloc(device->buffer_size); device->hidden->mixbuf = (Uint8 *) SDL_malloc(device->buffer_size);
if (!device->hidden->mixbuf) { if (!device->hidden->mixbuf) {
return -1; return -1;
@ -69,7 +69,7 @@ static Uint8 *DUMMYAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
return device->hidden->mixbuf; return device->hidden->mixbuf;
} }
static int DUMMYAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int DUMMYAUDIO_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
{ {
// always return a full buffer of silence. // always return a full buffer of silence.
SDL_memset(buffer, device->silence_value, buflen); SDL_memset(buffer, device->silence_value, buflen);
@ -82,12 +82,12 @@ static SDL_bool DUMMYAUDIO_Init(SDL_AudioDriverImpl *impl)
impl->CloseDevice = DUMMYAUDIO_CloseDevice; impl->CloseDevice = DUMMYAUDIO_CloseDevice;
impl->WaitDevice = DUMMYAUDIO_WaitDevice; impl->WaitDevice = DUMMYAUDIO_WaitDevice;
impl->GetDeviceBuf = DUMMYAUDIO_GetDeviceBuf; impl->GetDeviceBuf = DUMMYAUDIO_GetDeviceBuf;
impl->WaitCaptureDevice = DUMMYAUDIO_WaitDevice; impl->WaitRecordingDevice = DUMMYAUDIO_WaitDevice;
impl->CaptureFromDevice = DUMMYAUDIO_CaptureFromDevice; impl->RecordDevice = DUMMYAUDIO_RecordDevice;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE; impl->OnlyHasDefaultPlaybackDevice = SDL_TRUE;
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE; impl->OnlyHasDefaultRecordingDevice = SDL_TRUE;
impl->HasCaptureSupport = SDL_TRUE; impl->HasRecordingSupport = SDL_TRUE;
return SDL_TRUE; return SDL_TRUE;
} }

View File

@ -41,11 +41,11 @@ static int EMSCRIPTENAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buff
const int framelen = SDL_AUDIO_FRAMESIZE(device->spec); const int framelen = SDL_AUDIO_FRAMESIZE(device->spec);
MAIN_THREAD_EM_ASM({ MAIN_THREAD_EM_ASM({
var SDL3 = Module['SDL3']; var SDL3 = Module['SDL3'];
var numChannels = SDL3.audio.currentOutputBuffer['numberOfChannels']; var numChannels = SDL3.audio_playback.currentPlaybackBuffer['numberOfChannels'];
for (var c = 0; c < numChannels; ++c) { for (var c = 0; c < numChannels; ++c) {
var channelData = SDL3.audio.currentOutputBuffer['getChannelData'](c); var channelData = SDL3.audio_playback.currentPlaybackBuffer['getChannelData'](c);
if (channelData.length != $1) { if (channelData.length != $1) {
throw 'Web Audio output buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!'; throw 'Web Audio playback buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!';
} }
for (var j = 0; j < $1; ++j) { for (var j = 0; j < $1; ++j) {
@ -57,20 +57,20 @@ static int EMSCRIPTENAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buff
} }
static void EMSCRIPTENAUDIO_FlushCapture(SDL_AudioDevice *device) static void EMSCRIPTENAUDIO_FlushRecording(SDL_AudioDevice *device)
{ {
// Do nothing, the new data will just be dropped. // Do nothing, the new data will just be dropped.
} }
static int EMSCRIPTENAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int EMSCRIPTENAUDIO_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
{ {
MAIN_THREAD_EM_ASM({ MAIN_THREAD_EM_ASM({
var SDL3 = Module['SDL3']; var SDL3 = Module['SDL3'];
var numChannels = SDL3.capture.currentCaptureBuffer.numberOfChannels; var numChannels = SDL3.audio_recording.currentRecordingBuffer.numberOfChannels;
for (var c = 0; c < numChannels; ++c) { for (var c = 0; c < numChannels; ++c) {
var channelData = SDL3.capture.currentCaptureBuffer.getChannelData(c); var channelData = SDL3.audio_recording.currentRecordingBuffer.getChannelData(c);
if (channelData.length != $1) { if (channelData.length != $1) {
throw 'Web Audio capture buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!'; throw 'Web Audio recording buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!';
} }
if (numChannels == 1) { // fastpath this a little for the common (mono) case. if (numChannels == 1) { // fastpath this a little for the common (mono) case.
@ -97,37 +97,37 @@ static void EMSCRIPTENAUDIO_CloseDevice(SDL_AudioDevice *device)
MAIN_THREAD_EM_ASM({ MAIN_THREAD_EM_ASM({
var SDL3 = Module['SDL3']; var SDL3 = Module['SDL3'];
if ($0) { if ($0) {
if (SDL3.capture.silenceTimer !== undefined) { if (SDL3.audio_recording.silenceTimer !== undefined) {
clearInterval(SDL3.capture.silenceTimer); clearInterval(SDL3.audio_recording.silenceTimer);
} }
if (SDL3.capture.stream !== undefined) { if (SDL3.audio_recording.stream !== undefined) {
var tracks = SDL3.capture.stream.getAudioTracks(); var tracks = SDL3.audio_recording.stream.getAudioTracks();
for (var i = 0; i < tracks.length; i++) { for (var i = 0; i < tracks.length; i++) {
SDL3.capture.stream.removeTrack(tracks[i]); SDL3.audio_recording.stream.removeTrack(tracks[i]);
} }
} }
if (SDL3.capture.scriptProcessorNode !== undefined) { if (SDL3.audio_recording.scriptProcessorNode !== undefined) {
SDL3.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {}; SDL3.audio_recording.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {};
SDL3.capture.scriptProcessorNode.disconnect(); SDL3.audio_recording.scriptProcessorNode.disconnect();
} }
if (SDL3.capture.mediaStreamNode !== undefined) { if (SDL3.audio_recording.mediaStreamNode !== undefined) {
SDL3.capture.mediaStreamNode.disconnect(); SDL3.audio_recording.mediaStreamNode.disconnect();
} }
SDL3.capture = undefined; SDL3.audio_recording = undefined;
} else { } else {
if (SDL3.audio.scriptProcessorNode != undefined) { if (SDL3.audio_playback.scriptProcessorNode != undefined) {
SDL3.audio.scriptProcessorNode.disconnect(); SDL3.audio_playback.scriptProcessorNode.disconnect();
} }
if (SDL3.audio.silenceTimer !== undefined) { if (SDL3.audio_playback.silenceTimer !== undefined) {
clearInterval(SDL3.audio.silenceTimer); clearInterval(SDL3.audio_playback.silenceTimer);
} }
SDL3.audio = undefined; SDL3.audio_playback = undefined;
} }
if ((SDL3.audioContext !== undefined) && (SDL3.audio === undefined) && (SDL3.capture === undefined)) { if ((SDL3.audioContext !== undefined) && (SDL3.audio_playback === undefined) && (SDL3.audio_recording === undefined)) {
SDL3.audioContext.close(); SDL3.audioContext.close();
SDL3.audioContext = undefined; SDL3.audioContext = undefined;
} }
}, device->iscapture); }, device->recording);
SDL_free(device->hidden->mixbuf); SDL_free(device->hidden->mixbuf);
SDL_free(device->hidden); SDL_free(device->hidden);
@ -149,9 +149,9 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device)
} }
var SDL3 = Module['SDL3']; var SDL3 = Module['SDL3'];
if (!$0) { if (!$0) {
SDL3.audio = {}; SDL3.audio_playback = {};
} else { } else {
SDL3.capture = {}; SDL3.audio_recording = {};
} }
if (!SDL3.audioContext) { if (!SDL3.audioContext) {
@ -167,7 +167,7 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device)
} }
} }
return SDL3.audioContext === undefined ? -1 : 0; return SDL3.audioContext === undefined ? -1 : 0;
}, device->iscapture); }, device->recording);
if (result < 0) { if (result < 0) {
return SDL_SetError("Web Audio API is not available!"); return SDL_SetError("Web Audio API is not available!");
@ -186,7 +186,7 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device)
SDL_UpdatedAudioDeviceFormat(device); SDL_UpdatedAudioDeviceFormat(device);
if (!device->iscapture) { if (!device->recording) {
device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size);
if (!device->hidden->mixbuf) { if (!device->hidden->mixbuf) {
return -1; return -1;
@ -194,18 +194,18 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device)
SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size);
} }
if (device->iscapture) { if (device->recording) {
/* The idea is to take the capture media stream, hook it up to an /* The idea is to take the recording media stream, hook it up to an
audio graph where we can pass it through a ScriptProcessorNode audio graph where we can pass it through a ScriptProcessorNode
to access the raw PCM samples and push them to the SDL app's to access the raw PCM samples and push them to the SDL app's
callback. From there, we "process" the audio data into silence callback. From there, we "process" the audio data into silence
and forget about it. and forget about it.
This should, strictly speaking, use MediaRecorder for capture, but This should, strictly speaking, use MediaRecorder for recording, but
this API is cleaner to use and better supported, and fires a this API is cleaner to use and better supported, and fires a
callback whenever there's enough data to fire down into the app. callback whenever there's enough data to fire down into the app.
The downside is that we are spending CPU time silencing a buffer The downside is that we are spending CPU time silencing a buffer
that the audiocontext uselessly mixes into any output. On the that the audiocontext uselessly mixes into any playback. On the
upside, both of those things are not only run in native code in upside, both of those things are not only run in native code in
the browser, they're probably SIMD code, too. MediaRecorder the browser, they're probably SIMD code, too. MediaRecorder
feels like it's a pretty inefficient tapdance in similar ways, feels like it's a pretty inefficient tapdance in similar ways,
@ -214,67 +214,67 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device)
MAIN_THREAD_EM_ASM({ MAIN_THREAD_EM_ASM({
var SDL3 = Module['SDL3']; var SDL3 = Module['SDL3'];
var have_microphone = function(stream) { var have_microphone = function(stream) {
//console.log('SDL audio capture: we have a microphone! Replacing silence callback.'); //console.log('SDL audio recording: we have a microphone! Replacing silence callback.');
if (SDL3.capture.silenceTimer !== undefined) { if (SDL3.audio_recording.silenceTimer !== undefined) {
clearInterval(SDL3.capture.silenceTimer); clearInterval(SDL3.audio_recording.silenceTimer);
SDL3.capture.silenceTimer = undefined; SDL3.audio_recording.silenceTimer = undefined;
SDL3.capture.silenceBuffer = undefined SDL3.audio_recording.silenceBuffer = undefined
} }
SDL3.capture.mediaStreamNode = SDL3.audioContext.createMediaStreamSource(stream); SDL3.audio_recording.mediaStreamNode = SDL3.audioContext.createMediaStreamSource(stream);
SDL3.capture.scriptProcessorNode = SDL3.audioContext.createScriptProcessor($1, $0, 1); SDL3.audio_recording.scriptProcessorNode = SDL3.audioContext.createScriptProcessor($1, $0, 1);
SDL3.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) { SDL3.audio_recording.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {
if ((SDL3 === undefined) || (SDL3.capture === undefined)) { return; } if ((SDL3 === undefined) || (SDL3.audio_recording === undefined)) { return; }
audioProcessingEvent.outputBuffer.getChannelData(0).fill(0.0); audioProcessingEvent.outputBuffer.getChannelData(0).fill(0.0);
SDL3.capture.currentCaptureBuffer = audioProcessingEvent.inputBuffer; SDL3.audio_recording.currentRecordingBuffer = audioProcessingEvent.inputBuffer;
dynCall('vi', $2, [$3]); dynCall('vi', $2, [$3]);
}; };
SDL3.capture.mediaStreamNode.connect(SDL3.capture.scriptProcessorNode); SDL3.audio_recording.mediaStreamNode.connect(SDL3.audio_recording.scriptProcessorNode);
SDL3.capture.scriptProcessorNode.connect(SDL3.audioContext.destination); SDL3.audio_recording.scriptProcessorNode.connect(SDL3.audioContext.destination);
SDL3.capture.stream = stream; SDL3.audio_recording.stream = stream;
}; };
var no_microphone = function(error) { var no_microphone = function(error) {
//console.log('SDL audio capture: we DO NOT have a microphone! (' + error.name + ')...leaving silence callback running.'); //console.log('SDL audio recording: we DO NOT have a microphone! (' + error.name + ')...leaving silence callback running.');
}; };
// we write silence to the audio callback until the microphone is available (user approves use, etc). // we write silence to the audio callback until the microphone is available (user approves use, etc).
SDL3.capture.silenceBuffer = SDL3.audioContext.createBuffer($0, $1, SDL3.audioContext.sampleRate); SDL3.audio_recording.silenceBuffer = SDL3.audioContext.createBuffer($0, $1, SDL3.audioContext.sampleRate);
SDL3.capture.silenceBuffer.getChannelData(0).fill(0.0); SDL3.audio_recording.silenceBuffer.getChannelData(0).fill(0.0);
var silence_callback = function() { var silence_callback = function() {
SDL3.capture.currentCaptureBuffer = SDL3.capture.silenceBuffer; SDL3.audio_recording.currentRecordingBuffer = SDL3.audio_recording.silenceBuffer;
dynCall('vi', $2, [$3]); dynCall('vi', $2, [$3]);
}; };
SDL3.capture.silenceTimer = setInterval(silence_callback, ($1 / SDL3.audioContext.sampleRate) * 1000); SDL3.audio_recording.silenceTimer = setInterval(silence_callback, ($1 / SDL3.audioContext.sampleRate) * 1000);
if ((navigator.mediaDevices !== undefined) && (navigator.mediaDevices.getUserMedia !== undefined)) { if ((navigator.mediaDevices !== undefined) && (navigator.mediaDevices.getUserMedia !== undefined)) {
navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then(have_microphone).catch(no_microphone); navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then(have_microphone).catch(no_microphone);
} else if (navigator.webkitGetUserMedia !== undefined) { } else if (navigator.webkitGetUserMedia !== undefined) {
navigator.webkitGetUserMedia({ audio: true, video: false }, have_microphone, no_microphone); navigator.webkitGetUserMedia({ audio: true, video: false }, have_microphone, no_microphone);
} }
}, device->spec.channels, device->sample_frames, SDL_CaptureAudioThreadIterate, device); }, device->spec.channels, device->sample_frames, SDL_RecordingAudioThreadIterate, device);
} else { } else {
// setup a ScriptProcessorNode // setup a ScriptProcessorNode
MAIN_THREAD_EM_ASM({ MAIN_THREAD_EM_ASM({
var SDL3 = Module['SDL3']; var SDL3 = Module['SDL3'];
SDL3.audio.scriptProcessorNode = SDL3.audioContext['createScriptProcessor']($1, 0, $0); SDL3.audio_playback.scriptProcessorNode = SDL3.audioContext['createScriptProcessor']($1, 0, $0);
SDL3.audio.scriptProcessorNode['onaudioprocess'] = function (e) { SDL3.audio_playback.scriptProcessorNode['onaudioprocess'] = function (e) {
if ((SDL3 === undefined) || (SDL3.audio === undefined)) { return; } if ((SDL3 === undefined) || (SDL3.audio_playback === undefined)) { return; }
// if we're actually running the node, we don't need the fake callback anymore, so kill it. // if we're actually running the node, we don't need the fake callback anymore, so kill it.
if (SDL3.audio.silenceTimer !== undefined) { if (SDL3.audio_playback.silenceTimer !== undefined) {
clearInterval(SDL3.audio.silenceTimer); clearInterval(SDL3.audio_playback.silenceTimer);
SDL3.audio.silenceTimer = undefined; SDL3.audio_playback.silenceTimer = undefined;
SDL3.audio.silenceBuffer = undefined; SDL3.audio_playback.silenceBuffer = undefined;
} }
SDL3.audio.currentOutputBuffer = e['outputBuffer']; SDL3.audio_playback.currentPlaybackBuffer = e['outputBuffer'];
dynCall('vi', $2, [$3]); dynCall('vi', $2, [$3]);
}; };
SDL3.audio.scriptProcessorNode['connect'](SDL3.audioContext['destination']); SDL3.audio_playback.scriptProcessorNode['connect'](SDL3.audioContext['destination']);
if (SDL3.audioContext.state === 'suspended') { // uhoh, autoplay is blocked. if (SDL3.audioContext.state === 'suspended') { // uhoh, autoplay is blocked.
SDL3.audio.silenceBuffer = SDL3.audioContext.createBuffer($0, $1, SDL3.audioContext.sampleRate); SDL3.audio_playback.silenceBuffer = SDL3.audioContext.createBuffer($0, $1, SDL3.audioContext.sampleRate);
SDL3.audio.silenceBuffer.getChannelData(0).fill(0.0); SDL3.audio_playback.silenceBuffer.getChannelData(0).fill(0.0);
var silence_callback = function() { var silence_callback = function() {
if ((typeof navigator.userActivation) !== 'undefined') { // Almost everything modern except Firefox (as of August 2023) if ((typeof navigator.userActivation) !== 'undefined') { // Almost everything modern except Firefox (as of August 2023)
if (navigator.userActivation.hasBeenActive) { if (navigator.userActivation.hasBeenActive) {
@ -284,14 +284,14 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device)
// the buffer that gets filled here just gets ignored, so the app can make progress // the buffer that gets filled here just gets ignored, so the app can make progress
// and/or avoid flooding audio queues until we can actually play audio. // and/or avoid flooding audio queues until we can actually play audio.
SDL3.audio.currentOutputBuffer = SDL3.audio.silenceBuffer; SDL3.audio_playback.currentPlaybackBuffer = SDL3.audio_playback.silenceBuffer;
dynCall('vi', $2, [$3]); dynCall('vi', $2, [$3]);
SDL3.audio.currentOutputBuffer = undefined; SDL3.audio_playback.currentPlaybackBuffer = undefined;
}; };
SDL3.audio.silenceTimer = setInterval(silence_callback, ($1 / SDL3.audioContext.sampleRate) * 1000); SDL3.audio_playback.silenceTimer = setInterval(silence_callback, ($1 / SDL3.audioContext.sampleRate) * 1000);
} }
}, device->spec.channels, device->sample_frames, SDL_OutputAudioThreadIterate, device); }, device->spec.channels, device->sample_frames, SDL_PlaybackAudioThreadIterate, device);
} }
return 0; return 0;
@ -299,16 +299,16 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device)
static SDL_bool EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl *impl) static SDL_bool EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl *impl)
{ {
SDL_bool available, capture_available; SDL_bool available, recording_available;
impl->OpenDevice = EMSCRIPTENAUDIO_OpenDevice; impl->OpenDevice = EMSCRIPTENAUDIO_OpenDevice;
impl->CloseDevice = EMSCRIPTENAUDIO_CloseDevice; impl->CloseDevice = EMSCRIPTENAUDIO_CloseDevice;
impl->GetDeviceBuf = EMSCRIPTENAUDIO_GetDeviceBuf; impl->GetDeviceBuf = EMSCRIPTENAUDIO_GetDeviceBuf;
impl->PlayDevice = EMSCRIPTENAUDIO_PlayDevice; impl->PlayDevice = EMSCRIPTENAUDIO_PlayDevice;
impl->FlushCapture = EMSCRIPTENAUDIO_FlushCapture; impl->FlushRecording = EMSCRIPTENAUDIO_FlushRecording;
impl->CaptureFromDevice = EMSCRIPTENAUDIO_CaptureFromDevice; impl->RecordDevice = EMSCRIPTENAUDIO_RecordDevice;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE; impl->OnlyHasDefaultPlaybackDevice = SDL_TRUE;
// technically, this is just runs in idle time in the main thread, but it's close enough to a "thread" for our purposes. // technically, this is just runs in idle time in the main thread, but it's close enough to a "thread" for our purposes.
impl->ProvidesOwnCallbackThread = SDL_TRUE; impl->ProvidesOwnCallbackThread = SDL_TRUE;
@ -327,7 +327,7 @@ static SDL_bool EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl *impl)
SDL_SetError("No audio context available"); SDL_SetError("No audio context available");
} }
capture_available = available && MAIN_THREAD_EM_ASM_INT({ recording_available = available && MAIN_THREAD_EM_ASM_INT({
if ((typeof(navigator.mediaDevices) !== 'undefined') && (typeof(navigator.mediaDevices.getUserMedia) !== 'undefined')) { if ((typeof(navigator.mediaDevices) !== 'undefined') && (typeof(navigator.mediaDevices.getUserMedia) !== 'undefined')) {
return true; return true;
} else if (typeof(navigator.webkitGetUserMedia) !== 'undefined') { } else if (typeof(navigator.webkitGetUserMedia) !== 'undefined') {
@ -336,8 +336,8 @@ static SDL_bool EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl *impl)
return false; return false;
}); });
impl->HasCaptureSupport = capture_available; impl->HasRecordingSupport = recording_available;
impl->OnlyHasDefaultCaptureDevice = capture_available; impl->OnlyHasDefaultRecordingDevice = recording_available;
return available; return available;
} }

View File

@ -63,7 +63,7 @@ static void FillSound(void *data, void *stream, size_t len, const media_raw_audi
SDL_assert(device->hidden->current_buffer_len == 0); SDL_assert(device->hidden->current_buffer_len == 0);
device->hidden->current_buffer = (Uint8 *) stream; device->hidden->current_buffer = (Uint8 *) stream;
device->hidden->current_buffer_len = (int) len; device->hidden->current_buffer_len = (int) len;
SDL_OutputAudioThreadIterate(device); SDL_PlaybackAudioThreadIterate(device);
} }
static void HAIKUAUDIO_CloseDevice(SDL_AudioDevice *device) static void HAIKUAUDIO_CloseDevice(SDL_AudioDevice *device)
@ -207,7 +207,7 @@ static SDL_bool HAIKUAUDIO_Init(SDL_AudioDriverImpl *impl)
impl->CloseDevice = HAIKUAUDIO_CloseDevice; impl->CloseDevice = HAIKUAUDIO_CloseDevice;
impl->Deinitialize = HAIKUAUDIO_Deinitialize; impl->Deinitialize = HAIKUAUDIO_Deinitialize;
impl->ProvidesOwnCallbackThread = SDL_TRUE; impl->ProvidesOwnCallbackThread = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE; impl->OnlyHasDefaultPlaybackDevice = SDL_TRUE;
return SDL_TRUE; return SDL_TRUE;
} }

View File

@ -170,7 +170,7 @@ static int jackBufferSizeCallback(jack_nframes_t nframes, void *arg)
static int jackProcessPlaybackCallback(jack_nframes_t nframes, void *arg) static int jackProcessPlaybackCallback(jack_nframes_t nframes, void *arg)
{ {
SDL_assert(nframes == ((SDL_AudioDevice *)arg)->sample_frames); SDL_assert(nframes == ((SDL_AudioDevice *)arg)->sample_frames);
SDL_OutputAudioThreadIterate((SDL_AudioDevice *)arg); SDL_PlaybackAudioThreadIterate((SDL_AudioDevice *)arg);
return 0; return 0;
} }
@ -201,14 +201,14 @@ static Uint8 *JACK_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
return (Uint8 *)device->hidden->iobuffer; return (Uint8 *)device->hidden->iobuffer;
} }
static int jackProcessCaptureCallback(jack_nframes_t nframes, void *arg) static int jackProcessRecordingCallback(jack_nframes_t nframes, void *arg)
{ {
SDL_assert(nframes == ((SDL_AudioDevice *)arg)->sample_frames); SDL_assert(nframes == ((SDL_AudioDevice *)arg)->sample_frames);
SDL_CaptureAudioThreadIterate((SDL_AudioDevice *)arg); SDL_RecordingAudioThreadIterate((SDL_AudioDevice *)arg);
return 0; return 0;
} }
static int JACK_CaptureFromDevice(SDL_AudioDevice *device, void *vbuffer, int buflen) static int JACK_RecordDevice(SDL_AudioDevice *device, void *vbuffer, int buflen)
{ {
float *buffer = (float *) vbuffer; float *buffer = (float *) vbuffer;
jack_port_t **ports = device->hidden->sdlports; jack_port_t **ports = device->hidden->sdlports;
@ -230,7 +230,7 @@ static int JACK_CaptureFromDevice(SDL_AudioDevice *device, void *vbuffer, int bu
return buflen; return buflen;
} }
static void JACK_FlushCapture(SDL_AudioDevice *device) static void JACK_FlushRecording(SDL_AudioDevice *device)
{ {
// do nothing, the data will just be replaced next callback. // do nothing, the data will just be replaced next callback.
} }
@ -277,15 +277,15 @@ static const char *GetJackAppName(void)
static int JACK_OpenDevice(SDL_AudioDevice *device) static int JACK_OpenDevice(SDL_AudioDevice *device)
{ {
/* Note that JACK uses "output" for capture devices (they output audio /* Note that JACK uses "output" for recording devices (they output audio
data to us) and "input" for playback (we input audio data to them). data to us) and "input" for playback (we input audio data to them).
Likewise, SDL's playback port will be "output" (we write data out) Likewise, SDL's playback port will be "output" (we write data out)
and capture will be "input" (we read data in). */ and recording will be "input" (we read data in). */
SDL_bool iscapture = device->iscapture; const SDL_bool recording = device->recording;
const unsigned long sysportflags = iscapture ? JackPortIsOutput : JackPortIsInput; const unsigned long sysportflags = recording ? JackPortIsOutput : JackPortIsInput;
const unsigned long sdlportflags = iscapture ? JackPortIsInput : JackPortIsOutput; const unsigned long sdlportflags = recording ? JackPortIsInput : JackPortIsOutput;
const JackProcessCallback callback = iscapture ? jackProcessCaptureCallback : jackProcessPlaybackCallback; const JackProcessCallback callback = recording ? jackProcessRecordingCallback : jackProcessPlaybackCallback;
const char *sdlportstr = iscapture ? "input" : "output"; const char *sdlportstr = recording ? "input" : "output";
const char **devports = NULL; const char **devports = NULL;
int *audio_ports; int *audio_ports;
jack_client_t *client = NULL; jack_client_t *client = NULL;
@ -339,7 +339,7 @@ static int JACK_OpenDevice(SDL_AudioDevice *device)
SDL_UpdatedAudioDeviceFormat(device); SDL_UpdatedAudioDeviceFormat(device);
if (!device->iscapture) { if (!recording) {
device->hidden->iobuffer = (float *)SDL_calloc(1, device->buffer_size); device->hidden->iobuffer = (float *)SDL_calloc(1, device->buffer_size);
if (!device->hidden->iobuffer) { if (!device->hidden->iobuffer) {
SDL_free(audio_ports); SDL_free(audio_ports);
@ -385,8 +385,8 @@ static int JACK_OpenDevice(SDL_AudioDevice *device)
// once activated, we can connect all the ports. // once activated, we can connect all the ports.
for (i = 0; i < channels; i++) { for (i = 0; i < channels; i++) {
const char *sdlport = JACK_jack_port_name(device->hidden->sdlports[i]); const char *sdlport = JACK_jack_port_name(device->hidden->sdlports[i]);
const char *srcport = iscapture ? devports[audio_ports[i]] : sdlport; const char *srcport = recording ? devports[audio_ports[i]] : sdlport;
const char *dstport = iscapture ? sdlport : devports[audio_ports[i]]; const char *dstport = recording ? sdlport : devports[audio_ports[i]];
if (JACK_jack_connect(client, srcport, dstport) != 0) { if (JACK_jack_connect(client, srcport, dstport) != 0) {
SDL_free(audio_ports); SDL_free(audio_ports);
return SDL_SetError("Couldn't connect JACK ports: %s => %s", srcport, dstport); return SDL_SetError("Couldn't connect JACK ports: %s => %s", srcport, dstport);
@ -427,11 +427,11 @@ static SDL_bool JACK_Init(SDL_AudioDriverImpl *impl)
impl->PlayDevice = JACK_PlayDevice; impl->PlayDevice = JACK_PlayDevice;
impl->CloseDevice = JACK_CloseDevice; impl->CloseDevice = JACK_CloseDevice;
impl->Deinitialize = JACK_Deinitialize; impl->Deinitialize = JACK_Deinitialize;
impl->CaptureFromDevice = JACK_CaptureFromDevice; impl->RecordDevice = JACK_RecordDevice;
impl->FlushCapture = JACK_FlushCapture; impl->FlushRecording = JACK_FlushRecording;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE; impl->OnlyHasDefaultPlaybackDevice = SDL_TRUE;
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE; impl->OnlyHasDefaultRecordingDevice = SDL_TRUE;
impl->HasCaptureSupport = SDL_TRUE; impl->HasRecordingSupport = SDL_TRUE;
impl->ProvidesOwnCallbackThread = SDL_TRUE; impl->ProvidesOwnCallbackThread = SDL_TRUE;
return SDL_TRUE; return SDL_TRUE;

View File

@ -269,10 +269,10 @@ static SDL_bool N3DSAUDIO_Init(SDL_AudioDriverImpl *impl)
impl->GetDeviceBuf = N3DSAUDIO_GetDeviceBuf; impl->GetDeviceBuf = N3DSAUDIO_GetDeviceBuf;
impl->CloseDevice = N3DSAUDIO_CloseDevice; impl->CloseDevice = N3DSAUDIO_CloseDevice;
impl->ThreadInit = N3DSAUDIO_ThreadInit; impl->ThreadInit = N3DSAUDIO_ThreadInit;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE; impl->OnlyHasDefaultPlaybackDevice = SDL_TRUE;
// Should be possible, but micInit would fail // Should be possible, but micInit would fail
impl->HasCaptureSupport = SDL_FALSE; impl->HasRecordingSupport = SDL_FALSE;
return SDL_TRUE; return SDL_TRUE;
} }

View File

@ -39,7 +39,7 @@
//#define DEBUG_AUDIO //#define DEBUG_AUDIO
static void NETBSDAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) static void NETBSDAUDIO_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{ {
SDL_EnumUnixAudioDevices(SDL_FALSE, NULL); SDL_EnumUnixAudioDevices(SDL_FALSE, NULL);
} }
@ -56,7 +56,7 @@ static void NETBSDAUDIO_Status(SDL_AudioDevice *device)
return; return;
} }
prinfo = device->iscapture ? &info.record : &info.play; prinfo = device->recording ? &info.record : &info.play;
fprintf(stderr, "\n" fprintf(stderr, "\n"
"[%s info]\n" "[%s info]\n"
@ -73,7 +73,7 @@ static void NETBSDAUDIO_Status(SDL_AudioDevice *device)
"waiting : %s\n" "waiting : %s\n"
"active : %s\n" "active : %s\n"
"", "",
device->iscapture ? "record" : "play", device->recording ? "record" : "play",
prinfo->buffer_size, prinfo->buffer_size,
prinfo->sample_rate, prinfo->sample_rate,
prinfo->channels, prinfo->channels,
@ -116,7 +116,7 @@ static void NETBSDAUDIO_Status(SDL_AudioDevice *device)
static int NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device) static int NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device)
{ {
const SDL_bool iscapture = device->iscapture; const SDL_bool recording = device->recording;
while (!SDL_AtomicGet(&device->shutdown)) { while (!SDL_AtomicGet(&device->shutdown)) {
audio_info_t info; audio_info_t info;
const int rc = ioctl(device->hidden->audio_fd, AUDIO_GETINFO, &info); const int rc = ioctl(device->hidden->audio_fd, AUDIO_GETINFO, &info);
@ -128,10 +128,10 @@ static int NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device)
fprintf(stderr, "netbsdaudio WaitDevice ioctl failed (unrecoverable): %s\n", strerror(errno)); fprintf(stderr, "netbsdaudio WaitDevice ioctl failed (unrecoverable): %s\n", strerror(errno));
return -1; return -1;
} }
const size_t remain = (size_t)((iscapture ? info.record.seek : info.play.seek) * SDL_AUDIO_BYTESIZE(device->spec.format)); const size_t remain = (size_t)((recording ? info.record.seek : info.play.seek) * SDL_AUDIO_BYTESIZE(device->spec.format));
if (!iscapture && (remain >= device->buffer_size)) { if (!recording && (remain >= device->buffer_size)) {
SDL_Delay(10); SDL_Delay(10);
} else if (iscapture && (remain < device->buffer_size)) { } else if (recording && (remain < device->buffer_size)) {
SDL_Delay(10); SDL_Delay(10);
} else { } else {
break; // ready to go! break; // ready to go!
@ -160,7 +160,7 @@ static Uint8 *NETBSDAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size
return device->hidden->mixbuf; return device->hidden->mixbuf;
} }
static int NETBSDAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *vbuffer, int buflen) static int NETBSDAUDIO_RecordDevice(SDL_AudioDevice *device, void *vbuffer, int buflen)
{ {
Uint8 *buffer = (Uint8 *)vbuffer; Uint8 *buffer = (Uint8 *)vbuffer;
const int br = read(device->hidden->audio_fd, buffer, buflen); const int br = read(device->hidden->audio_fd, buffer, buflen);
@ -171,12 +171,12 @@ static int NETBSDAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *vbuffer,
} }
#ifdef DEBUG_AUDIO #ifdef DEBUG_AUDIO
fprintf(stderr, "Captured %d bytes of audio data\n", br); fprintf(stderr, "Recorded %d bytes of audio data\n", br);
#endif #endif
return br; return br;
} }
static void NETBSDAUDIO_FlushCapture(SDL_AudioDevice *device) static void NETBSDAUDIO_FlushRecording(SDL_AudioDevice *device)
{ {
struct SDL_PrivateAudioData *h = device->hidden; struct SDL_PrivateAudioData *h = device->hidden;
audio_info_t info; audio_info_t info;
@ -208,10 +208,10 @@ static void NETBSDAUDIO_CloseDevice(SDL_AudioDevice *device)
static int NETBSDAUDIO_OpenDevice(SDL_AudioDevice *device) static int NETBSDAUDIO_OpenDevice(SDL_AudioDevice *device)
{ {
const SDL_bool iscapture = device->iscapture; const SDL_bool recording = device->recording;
int encoding = AUDIO_ENCODING_NONE; int encoding = AUDIO_ENCODING_NONE;
audio_info_t info, hwinfo; audio_info_t info, hwinfo;
struct audio_prinfo *prinfo = iscapture ? &info.record : &info.play; struct audio_prinfo *prinfo = recording ? &info.record : &info.play;
// Initialize all variables that we clean on shutdown // Initialize all variables that we clean on shutdown
device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden));
@ -220,7 +220,7 @@ static int NETBSDAUDIO_OpenDevice(SDL_AudioDevice *device)
} }
// Open the audio device; we hardcode the device path in `device->name` for lack of better info, so use that. // Open the audio device; we hardcode the device path in `device->name` for lack of better info, so use that.
const int flags = ((device->iscapture) ? O_RDONLY : O_WRONLY); const int flags = ((device->recording) ? O_RDONLY : O_WRONLY);
device->hidden->audio_fd = open(device->name, flags | O_CLOEXEC); device->hidden->audio_fd = open(device->name, flags | O_CLOEXEC);
if (device->hidden->audio_fd < 0) { if (device->hidden->audio_fd < 0) {
return SDL_SetError("Couldn't open %s: %s", device->name, strerror(errno)); return SDL_SetError("Couldn't open %s: %s", device->name, strerror(errno));
@ -231,7 +231,7 @@ static int NETBSDAUDIO_OpenDevice(SDL_AudioDevice *device)
#ifdef AUDIO_GETFORMAT // Introduced in NetBSD 9.0 #ifdef AUDIO_GETFORMAT // Introduced in NetBSD 9.0
if (ioctl(device->hidden->audio_fd, AUDIO_GETFORMAT, &hwinfo) != -1) { if (ioctl(device->hidden->audio_fd, AUDIO_GETFORMAT, &hwinfo) != -1) {
// Use the device's native sample rate so the kernel doesn't have to resample. // Use the device's native sample rate so the kernel doesn't have to resample.
device->spec.freq = iscapture ? hwinfo.record.sample_rate : hwinfo.play.sample_rate; device->spec.freq = recording ? hwinfo.record.sample_rate : hwinfo.play.sample_rate;
} }
#endif #endif
@ -289,7 +289,7 @@ static int NETBSDAUDIO_OpenDevice(SDL_AudioDevice *device)
SDL_UpdatedAudioDeviceFormat(device); SDL_UpdatedAudioDeviceFormat(device);
if (!iscapture) { if (!recording) {
// Allocate mixing buffer // Allocate mixing buffer
device->hidden->mixlen = device->buffer_size; device->hidden->mixlen = device->buffer_size;
device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->hidden->mixlen); device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->hidden->mixlen);
@ -312,11 +312,11 @@ static SDL_bool NETBSDAUDIO_Init(SDL_AudioDriverImpl *impl)
impl->PlayDevice = NETBSDAUDIO_PlayDevice; impl->PlayDevice = NETBSDAUDIO_PlayDevice;
impl->GetDeviceBuf = NETBSDAUDIO_GetDeviceBuf; impl->GetDeviceBuf = NETBSDAUDIO_GetDeviceBuf;
impl->CloseDevice = NETBSDAUDIO_CloseDevice; impl->CloseDevice = NETBSDAUDIO_CloseDevice;
impl->WaitCaptureDevice = NETBSDAUDIO_WaitDevice; impl->WaitRecordingDevice = NETBSDAUDIO_WaitDevice;
impl->CaptureFromDevice = NETBSDAUDIO_CaptureFromDevice; impl->RecordDevice = NETBSDAUDIO_RecordDevice;
impl->FlushCapture = NETBSDAUDIO_FlushCapture; impl->FlushRecording = NETBSDAUDIO_FlushRecording;
impl->HasCaptureSupport = SDL_TRUE; impl->HasRecordingSupport = SDL_TRUE;
return SDL_TRUE; return SDL_TRUE;
} }

View File

@ -107,10 +107,10 @@ static const char *sldevaudioplayerstr = "SLES Audio Player";
#define SLES_DEV_AUDIO_RECORDER sldevaudiorecorderstr #define SLES_DEV_AUDIO_RECORDER sldevaudiorecorderstr
#define SLES_DEV_AUDIO_PLAYER sldevaudioplayerstr #define SLES_DEV_AUDIO_PLAYER sldevaudioplayerstr
static void OPENSLES_DetectDevices( int iscapture ) static void OPENSLES_DetectDevices( int recording )
{ {
LOGI( "openSLES_DetectDevices()" ); LOGI( "openSLES_DetectDevices()" );
if ( iscapture ) if ( recording )
addfn( SLES_DEV_AUDIO_RECORDER ); addfn( SLES_DEV_AUDIO_RECORDER );
else else
addfn( SLES_DEV_AUDIO_PLAYER ); addfn( SLES_DEV_AUDIO_PLAYER );
@ -622,12 +622,12 @@ static int OPENSLES_OpenDevice(SDL_AudioDevice *device)
return -1; return -1;
} }
if (device->iscapture) { if (device->recording) {
LOGI("OPENSLES_OpenDevice() for capture"); LOGI("OPENSLES_OpenDevice() for recording");
return OPENSLES_CreatePCMRecorder(device); return OPENSLES_CreatePCMRecorder(device);
} else { } else {
int ret; int ret;
LOGI("OPENSLES_OpenDevice() for playing"); LOGI("OPENSLES_OpenDevice() for playback");
ret = OPENSLES_CreatePCMPlayer(device); ret = OPENSLES_CreatePCMPlayer(device);
if (ret < 0) { if (ret < 0) {
// Another attempt to open the device with a lower frequency // Another attempt to open the device with a lower frequency
@ -699,7 +699,7 @@ static Uint8 *OPENSLES_GetDeviceBuf(SDL_AudioDevice *device, int *bufsize)
return audiodata->pmixbuff[audiodata->next_buffer]; return audiodata->pmixbuff[audiodata->next_buffer];
} }
static int OPENSLES_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int OPENSLES_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
{ {
struct SDL_PrivateAudioData *audiodata = device->hidden; struct SDL_PrivateAudioData *audiodata = device->hidden;
@ -726,8 +726,8 @@ static void OPENSLES_CloseDevice(SDL_AudioDevice *device)
{ {
// struct SDL_PrivateAudioData *audiodata = device->hidden; // struct SDL_PrivateAudioData *audiodata = device->hidden;
if (device->hidden) { if (device->hidden) {
if (device->iscapture) { if (device->recording) {
LOGI("OPENSLES_CloseDevice() for capture"); LOGI("OPENSLES_CloseDevice() for recording");
OPENSLES_DestroyPCMRecorder(device); OPENSLES_DestroyPCMRecorder(device);
} else { } else {
LOGI("OPENSLES_CloseDevice() for playing"); LOGI("OPENSLES_CloseDevice() for playing");
@ -756,15 +756,15 @@ static SDL_bool OPENSLES_Init(SDL_AudioDriverImpl *impl)
impl->WaitDevice = OPENSLES_WaitDevice; impl->WaitDevice = OPENSLES_WaitDevice;
impl->PlayDevice = OPENSLES_PlayDevice; impl->PlayDevice = OPENSLES_PlayDevice;
impl->GetDeviceBuf = OPENSLES_GetDeviceBuf; impl->GetDeviceBuf = OPENSLES_GetDeviceBuf;
impl->WaitCaptureDevice = OPENSLES_WaitDevice; impl->WaitRecordingDevice = OPENSLES_WaitDevice;
impl->CaptureFromDevice = OPENSLES_CaptureFromDevice; impl->RecordDevice = OPENSLES_RecordDevice;
impl->CloseDevice = OPENSLES_CloseDevice; impl->CloseDevice = OPENSLES_CloseDevice;
impl->Deinitialize = OPENSLES_DestroyEngine; impl->Deinitialize = OPENSLES_DestroyEngine;
// and the capabilities // and the capabilities
impl->HasCaptureSupport = SDL_TRUE; impl->HasRecordingSupport = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE; impl->OnlyHasDefaultPlaybackDevice = SDL_TRUE;
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE; impl->OnlyHasDefaultRecordingDevice = SDL_TRUE;
LOGI("OPENSLES_Init() - success"); LOGI("OPENSLES_Init() - success");

View File

@ -313,7 +313,7 @@ struct io_node
struct spa_list link; struct spa_list link;
Uint32 id; Uint32 id;
SDL_bool is_capture; SDL_bool recording;
SDL_AudioSpec spec; SDL_AudioSpec spec;
const char *name; // Friendly name const char *name; // Friendly name
@ -356,7 +356,7 @@ static SDL_bool io_list_check_add(struct io_node *node)
spa_list_append(&hotplug_io_list, &node->link); spa_list_append(&hotplug_io_list, &node->link);
if (hotplug_events_enabled) { if (hotplug_events_enabled) {
SDL_AddAudioDevice(node->is_capture, node->name, &node->spec, PW_ID_TO_HANDLE(node->id)); SDL_AddAudioDevice(node->recording, node->name, &node->spec, PW_ID_TO_HANDLE(node->id));
} }
dup_found: dup_found:
@ -706,15 +706,15 @@ static void registry_event_global_callback(void *object, uint32_t id, uint32_t p
const char *node_desc; const char *node_desc;
const char *node_path; const char *node_path;
struct io_node *io; struct io_node *io;
SDL_bool is_capture; SDL_bool recording;
int desc_buffer_len; int desc_buffer_len;
int path_buffer_len; int path_buffer_len;
// Just want sink and capture // Just want sink and source
if (!SDL_strcasecmp(media_class, "Audio/Sink")) { if (!SDL_strcasecmp(media_class, "Audio/Sink")) {
is_capture = SDL_FALSE; recording = SDL_FALSE;
} else if (!SDL_strcasecmp(media_class, "Audio/Source")) { } else if (!SDL_strcasecmp(media_class, "Audio/Source")) {
is_capture = SDL_TRUE; recording = SDL_TRUE;
} else { } else {
return; return;
} }
@ -740,7 +740,7 @@ static void registry_event_global_callback(void *object, uint32_t id, uint32_t p
// Begin setting the node properties // Begin setting the node properties
io->id = id; io->id = id;
io->is_capture = is_capture; io->recording = recording;
io->spec.format = SDL_AUDIO_F32; // Pipewire uses floats internally, other formats require conversion. io->spec.format = SDL_AUDIO_F32; // Pipewire uses floats internally, other formats require conversion.
io->name = io->buf; io->name = io->buf;
io->path = io->buf + desc_buffer_len; io->path = io->buf + desc_buffer_len;
@ -858,7 +858,7 @@ static void hotplug_loop_destroy(void)
} }
} }
static void PIPEWIRE_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) static void PIPEWIRE_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{ {
struct io_node *io; struct io_node *io;
@ -870,14 +870,14 @@ static void PIPEWIRE_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDe
} }
spa_list_for_each (io, &hotplug_io_list, link) { spa_list_for_each (io, &hotplug_io_list, link) {
SDL_AudioDevice *device = SDL_AddAudioDevice(io->is_capture, io->name, &io->spec, PW_ID_TO_HANDLE(io->id)); SDL_AudioDevice *device = SDL_AddAudioDevice(io->recording, io->name, &io->spec, PW_ID_TO_HANDLE(io->id));
if (pipewire_default_sink_id && SDL_strcmp(io->path, pipewire_default_sink_id) == 0) { if (pipewire_default_sink_id && SDL_strcmp(io->path, pipewire_default_sink_id) == 0) {
if (!io->is_capture) { if (!io->recording) {
*default_output = device; *default_playback = device;
} }
} else if (pipewire_default_source_id && SDL_strcmp(io->path, pipewire_default_source_id) == 0) { } else if (pipewire_default_source_id && SDL_strcmp(io->path, pipewire_default_source_id) == 0) {
if (io->is_capture) { if (io->recording) {
*default_capture = device; *default_recording = device;
} }
} }
} }
@ -969,7 +969,7 @@ static void initialize_spa_info(const SDL_AudioSpec *spec, struct spa_audio_info
static Uint8 *PIPEWIRE_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) static Uint8 *PIPEWIRE_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
{ {
// See if a buffer is available. If this returns NULL, SDL_OutputAudioThreadIterate will return SDL_FALSE, but since we own the thread, it won't kill playback. // See if a buffer is available. If this returns NULL, SDL_PlaybackAudioThreadIterate will return SDL_FALSE, but since we own the thread, it won't kill playback.
// !!! FIXME: It's not clear to me if this ever returns NULL or if this was just defensive coding. // !!! FIXME: It's not clear to me if this ever returns NULL or if this was just defensive coding.
struct pw_stream *stream = device->hidden->stream; struct pw_stream *stream = device->hidden->stream;
@ -1005,10 +1005,10 @@ static int PIPEWIRE_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int
static void output_callback(void *data) static void output_callback(void *data)
{ {
SDL_OutputAudioThreadIterate((SDL_AudioDevice *)data); SDL_PlaybackAudioThreadIterate((SDL_AudioDevice *)data);
} }
static void PIPEWIRE_FlushCapture(SDL_AudioDevice *device) static void PIPEWIRE_FlushRecording(SDL_AudioDevice *device)
{ {
struct pw_stream *stream = device->hidden->stream; struct pw_stream *stream = device->hidden->stream;
struct pw_buffer *pw_buf = PIPEWIRE_pw_stream_dequeue_buffer(stream); struct pw_buffer *pw_buf = PIPEWIRE_pw_stream_dequeue_buffer(stream);
@ -1017,7 +1017,7 @@ static void PIPEWIRE_FlushCapture(SDL_AudioDevice *device)
} }
} }
static int PIPEWIRE_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int PIPEWIRE_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
{ {
struct pw_stream *stream = device->hidden->stream; struct pw_stream *stream = device->hidden->stream;
struct pw_buffer *pw_buf = PIPEWIRE_pw_stream_dequeue_buffer(stream); struct pw_buffer *pw_buf = PIPEWIRE_pw_stream_dequeue_buffer(stream);
@ -1046,14 +1046,14 @@ static int PIPEWIRE_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int
static void input_callback(void *data) static void input_callback(void *data)
{ {
SDL_CaptureAudioThreadIterate((SDL_AudioDevice *)data); SDL_RecordingAudioThreadIterate((SDL_AudioDevice *)data);
} }
static void stream_add_buffer_callback(void *data, struct pw_buffer *buffer) static void stream_add_buffer_callback(void *data, struct pw_buffer *buffer)
{ {
SDL_AudioDevice *device = (SDL_AudioDevice *) data; SDL_AudioDevice *device = (SDL_AudioDevice *) data;
if (device->iscapture == SDL_FALSE) { if (device->recording == SDL_FALSE) {
/* Clamp the output spec samples and size to the max size of the Pipewire buffer. /* Clamp the output spec samples and size to the max size of the Pipewire buffer.
If they exceed the maximum size of the Pipewire buffer, double buffering will be used. */ If they exceed the maximum size of the Pipewire buffer, double buffering will be used. */
if (device->buffer_size > buffer->buffer->datas[0].maxsize) { if (device->buffer_size > buffer->buffer->datas[0].maxsize) {
@ -1110,7 +1110,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
struct pw_properties *props; struct pw_properties *props;
const char *app_name, *icon_name, *app_id, *stream_name, *stream_role, *error; const char *app_name, *icon_name, *app_id, *stream_name, *stream_role, *error;
Uint32 node_id = !device->handle ? PW_ID_ANY : PW_HANDLE_TO_ID(device->handle); Uint32 node_id = !device->handle ? PW_ID_ANY : PW_HANDLE_TO_ID(device->handle);
const SDL_bool iscapture = device->iscapture; const SDL_bool recording = device->recording;
int res; int res;
// Clamp the period size to sane values // Clamp the period size to sane values
@ -1192,7 +1192,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
} }
PIPEWIRE_pw_properties_set(props, PW_KEY_MEDIA_TYPE, "Audio"); PIPEWIRE_pw_properties_set(props, PW_KEY_MEDIA_TYPE, "Audio");
PIPEWIRE_pw_properties_set(props, PW_KEY_MEDIA_CATEGORY, iscapture ? "Capture" : "Playback"); PIPEWIRE_pw_properties_set(props, PW_KEY_MEDIA_CATEGORY, recording ? "Capture" : "Playback");
PIPEWIRE_pw_properties_set(props, PW_KEY_MEDIA_ROLE, stream_role); PIPEWIRE_pw_properties_set(props, PW_KEY_MEDIA_ROLE, stream_role);
PIPEWIRE_pw_properties_set(props, PW_KEY_APP_NAME, app_name); PIPEWIRE_pw_properties_set(props, PW_KEY_APP_NAME, app_name);
PIPEWIRE_pw_properties_set(props, PW_KEY_APP_ICON_NAME, icon_name); PIPEWIRE_pw_properties_set(props, PW_KEY_APP_ICON_NAME, icon_name);
@ -1217,13 +1217,13 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
// Create the new stream // Create the new stream
priv->stream = PIPEWIRE_pw_stream_new_simple(PIPEWIRE_pw_thread_loop_get_loop(priv->loop), stream_name, props, priv->stream = PIPEWIRE_pw_stream_new_simple(PIPEWIRE_pw_thread_loop_get_loop(priv->loop), stream_name, props,
iscapture ? &stream_input_events : &stream_output_events, device); recording ? &stream_input_events : &stream_output_events, device);
if (!priv->stream) { if (!priv->stream) {
return SDL_SetError("Pipewire: Failed to create stream (%i)", errno); return SDL_SetError("Pipewire: Failed to create stream (%i)", errno);
} }
// The target node is passed via PW_KEY_TARGET_OBJECT; target_id is a legacy parameter and must be PW_ID_ANY. // The target node is passed via PW_KEY_TARGET_OBJECT; target_id is a legacy parameter and must be PW_ID_ANY.
res = PIPEWIRE_pw_stream_connect(priv->stream, iscapture ? PW_DIRECTION_INPUT : PW_DIRECTION_OUTPUT, PW_ID_ANY, STREAM_FLAGS, res = PIPEWIRE_pw_stream_connect(priv->stream, recording ? PW_DIRECTION_INPUT : PW_DIRECTION_OUTPUT, PW_ID_ANY, STREAM_FLAGS,
&params, 1); &params, 1);
if (res != 0) { if (res != 0) {
return SDL_SetError("Pipewire: Failed to connect stream"); return SDL_SetError("Pipewire: Failed to connect stream");
@ -1314,11 +1314,11 @@ static SDL_bool PipewireInitialize(SDL_AudioDriverImpl *impl, SDL_bool check_pre
impl->Deinitialize = PIPEWIRE_Deinitialize; impl->Deinitialize = PIPEWIRE_Deinitialize;
impl->PlayDevice = PIPEWIRE_PlayDevice; impl->PlayDevice = PIPEWIRE_PlayDevice;
impl->GetDeviceBuf = PIPEWIRE_GetDeviceBuf; impl->GetDeviceBuf = PIPEWIRE_GetDeviceBuf;
impl->CaptureFromDevice = PIPEWIRE_CaptureFromDevice; impl->RecordDevice = PIPEWIRE_RecordDevice;
impl->FlushCapture = PIPEWIRE_FlushCapture; impl->FlushRecording = PIPEWIRE_FlushRecording;
impl->CloseDevice = PIPEWIRE_CloseDevice; impl->CloseDevice = PIPEWIRE_CloseDevice;
impl->HasCaptureSupport = SDL_TRUE; impl->HasRecordingSupport = SDL_TRUE;
impl->ProvidesOwnCallbackThread = SDL_TRUE; impl->ProvidesOwnCallbackThread = SDL_TRUE;
return SDL_TRUE; return SDL_TRUE;

View File

@ -150,7 +150,7 @@ static SDL_bool PS2AUDIO_Init(SDL_AudioDriverImpl *impl)
impl->CloseDevice = PS2AUDIO_CloseDevice; impl->CloseDevice = PS2AUDIO_CloseDevice;
impl->ThreadInit = PS2AUDIO_ThreadInit; impl->ThreadInit = PS2AUDIO_ThreadInit;
impl->Deinitialize = PS2AUDIO_Deinitialize; impl->Deinitialize = PS2AUDIO_Deinitialize;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE; impl->OnlyHasDefaultPlaybackDevice = SDL_TRUE;
return SDL_TRUE; // this audio target is available. return SDL_TRUE; // this audio target is available.
} }

View File

@ -170,9 +170,9 @@ static SDL_bool PSPAUDIO_Init(SDL_AudioDriverImpl *impl)
impl->GetDeviceBuf = PSPAUDIO_GetDeviceBuf; impl->GetDeviceBuf = PSPAUDIO_GetDeviceBuf;
impl->CloseDevice = PSPAUDIO_CloseDevice; impl->CloseDevice = PSPAUDIO_CloseDevice;
impl->ThreadInit = PSPAUDIO_ThreadInit; impl->ThreadInit = PSPAUDIO_ThreadInit;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE; impl->OnlyHasDefaultPlaybackDevice = SDL_TRUE;
//impl->HasCaptureSupport = SDL_TRUE; //impl->HasRecordingSupport = SDL_TRUE;
//impl->OnlyHasDefaultCaptureDevice = SDL_TRUE; //impl->OnlyHasDefaultRecordingDevice = SDL_TRUE;
return SDL_TRUE; return SDL_TRUE;
} }

View File

@ -493,14 +493,14 @@ static Uint8 *PULSEAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
static void ReadCallback(pa_stream *p, size_t nbytes, void *userdata) static void ReadCallback(pa_stream *p, size_t nbytes, void *userdata)
{ {
//SDL_Log("PULSEAUDIO READ CALLBACK! nbytes=%u", (unsigned int) nbytes); //SDL_Log("PULSEAUDIO READ CALLBACK! nbytes=%u", (unsigned int) nbytes);
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // the capture code queries what it needs, we just need to signal to end any wait PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // the recording code queries what it needs, we just need to signal to end any wait
} }
static int PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device) static int PULSEAUDIO_WaitRecordingDevice(SDL_AudioDevice *device)
{ {
struct SDL_PrivateAudioData *h = device->hidden; struct SDL_PrivateAudioData *h = device->hidden;
if (h->capturebuf) { if (h->recordingbuf) {
return 0; // there's still data available to read. return 0; // there's still data available to read.
} }
@ -511,7 +511,7 @@ static int PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device)
while (!SDL_AtomicGet(&device->shutdown)) { while (!SDL_AtomicGet(&device->shutdown)) {
PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop);
if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) { if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) {
//SDL_Log("PULSEAUDIO DEVICE FAILURE IN WAITCAPTUREDEVICE!"); //SDL_Log("PULSEAUDIO DEVICE FAILURE IN WAITRECORDINGDEVICE!");
retval = -1; retval = -1;
break; break;
} else if (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0) { } else if (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0) {
@ -523,10 +523,10 @@ static int PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device)
if (!data) { // If NULL, then the buffer had a hole, ignore that if (!data) { // If NULL, then the buffer had a hole, ignore that
PULSEAUDIO_pa_stream_drop(h->stream); // drop this fragment. PULSEAUDIO_pa_stream_drop(h->stream); // drop this fragment.
} else { } else {
// store this fragment's data for use with CaptureFromDevice // store this fragment's data for use with RecordDevice
//SDL_Log("PULSEAUDIO: captured %d new bytes", (int) nbytes); //SDL_Log("PULSEAUDIO: recorded %d new bytes", (int) nbytes);
h->capturebuf = (const Uint8 *)data; h->recordingbuf = (const Uint8 *)data;
h->capturelen = nbytes; h->recordinglen = nbytes;
break; break;
} }
} }
@ -537,20 +537,20 @@ static int PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device)
return retval; return retval;
} }
static int PULSEAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int PULSEAUDIO_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
{ {
struct SDL_PrivateAudioData *h = device->hidden; struct SDL_PrivateAudioData *h = device->hidden;
if (h->capturebuf) { if (h->recordingbuf) {
const int cpy = SDL_min(buflen, h->capturelen); const int cpy = SDL_min(buflen, h->recordinglen);
if (cpy > 0) { if (cpy > 0) {
//SDL_Log("PULSEAUDIO: fed %d captured bytes", cpy); //SDL_Log("PULSEAUDIO: fed %d recorded bytes", cpy);
SDL_memcpy(buffer, h->capturebuf, cpy); SDL_memcpy(buffer, h->recordingbuf, cpy);
h->capturebuf += cpy; h->recordingbuf += cpy;
h->capturelen -= cpy; h->recordinglen -= cpy;
} }
if (h->capturelen == 0) { if (h->recordinglen == 0) {
h->capturebuf = NULL; h->recordingbuf = NULL;
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); // don't know if you _have_ to lock for this, but just in case. PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); // don't know if you _have_ to lock for this, but just in case.
PULSEAUDIO_pa_stream_drop(h->stream); // done with this fragment. PULSEAUDIO_pa_stream_drop(h->stream); // done with this fragment.
PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop);
@ -561,7 +561,7 @@ static int PULSEAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, i
return 0; return 0;
} }
static void PULSEAUDIO_FlushCapture(SDL_AudioDevice *device) static void PULSEAUDIO_FlushRecording(SDL_AudioDevice *device)
{ {
struct SDL_PrivateAudioData *h = device->hidden; struct SDL_PrivateAudioData *h = device->hidden;
const void *data = NULL; const void *data = NULL;
@ -569,16 +569,16 @@ static void PULSEAUDIO_FlushCapture(SDL_AudioDevice *device)
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
if (h->capturebuf) { if (h->recordingbuf) {
PULSEAUDIO_pa_stream_drop(h->stream); PULSEAUDIO_pa_stream_drop(h->stream);
h->capturebuf = NULL; h->recordingbuf = NULL;
h->capturelen = 0; h->recordinglen = 0;
} }
while (!SDL_AtomicGet(&device->shutdown) && (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0)) { while (!SDL_AtomicGet(&device->shutdown) && (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0)) {
PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop);
if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) { if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) {
//SDL_Log("PULSEAUDIO DEVICE FAILURE IN FLUSHCAPTURE!"); //SDL_Log("PULSEAUDIO DEVICE FAILURE IN FLUSHRECORDING!");
SDL_AudioDeviceDisconnected(device); SDL_AudioDeviceDisconnected(device);
break; break;
} }
@ -598,7 +598,7 @@ static void PULSEAUDIO_CloseDevice(SDL_AudioDevice *device)
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
if (device->hidden->stream) { if (device->hidden->stream) {
if (device->hidden->capturebuf) { if (device->hidden->recordingbuf) {
PULSEAUDIO_pa_stream_drop(device->hidden->stream); PULSEAUDIO_pa_stream_drop(device->hidden->stream);
} }
PULSEAUDIO_pa_stream_disconnect(device->hidden->stream); PULSEAUDIO_pa_stream_disconnect(device->hidden->stream);
@ -618,7 +618,7 @@ static void PulseStreamStateChangeCallback(pa_stream *stream, void *userdata)
static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
{ {
const SDL_bool iscapture = device->iscapture; const SDL_bool recording = device->recording;
struct SDL_PrivateAudioData *h = NULL; struct SDL_PrivateAudioData *h = NULL;
SDL_AudioFormat test_format; SDL_AudioFormat test_format;
const SDL_AudioFormat *closefmts; const SDL_AudioFormat *closefmts;
@ -681,7 +681,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
SDL_UpdatedAudioDeviceFormat(device); SDL_UpdatedAudioDeviceFormat(device);
// Allocate mixing buffer // Allocate mixing buffer
if (!iscapture) { if (!recording) {
h->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); h->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size);
if (!h->mixbuf) { if (!h->mixbuf) {
return -1; return -1;
@ -693,7 +693,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
paspec.rate = device->spec.freq; paspec.rate = device->spec.freq;
// Reduced prebuffering compared to the defaults. // Reduced prebuffering compared to the defaults.
paattr.fragsize = device->buffer_size; // despite the name, this is only used for capture devices, according to PulseAudio docs! paattr.fragsize = device->buffer_size; // despite the name, this is only used for recording devices, according to PulseAudio docs!
paattr.tlength = device->buffer_size; paattr.tlength = device->buffer_size;
paattr.prebuf = -1; paattr.prebuf = -1;
paattr.maxlength = -1; paattr.maxlength = -1;
@ -725,7 +725,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
flags |= PA_STREAM_DONT_MOVE; flags |= PA_STREAM_DONT_MOVE;
const char *device_path = ((PulseDeviceHandle *) device->handle)->device_path; const char *device_path = ((PulseDeviceHandle *) device->handle)->device_path;
if (iscapture) { if (recording) {
PULSEAUDIO_pa_stream_set_read_callback(h->stream, ReadCallback, h); PULSEAUDIO_pa_stream_set_read_callback(h->stream, ReadCallback, h);
rc = PULSEAUDIO_pa_stream_connect_record(h->stream, device_path, &paattr, flags); rc = PULSEAUDIO_pa_stream_connect_record(h->stream, device_path, &paattr, flags);
} else { } else {
@ -749,7 +749,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
if (!actual_bufattr) { if (!actual_bufattr) {
retval = SDL_SetError("Could not determine connected PulseAudio stream's buffer attributes"); retval = SDL_SetError("Could not determine connected PulseAudio stream's buffer attributes");
} else { } else {
device->buffer_size = (int) iscapture ? actual_bufattr->tlength : actual_bufattr->fragsize; device->buffer_size = (int) recording ? actual_bufattr->tlength : actual_bufattr->fragsize;
device->sample_frames = device->buffer_size / SDL_AUDIO_FRAMESIZE(device->spec); device->sample_frames = device->buffer_size / SDL_AUDIO_FRAMESIZE(device->spec);
} }
} }
@ -786,7 +786,7 @@ static SDL_AudioFormat PulseFormatToSDLFormat(pa_sample_format_t format)
} }
} }
static void AddPulseAudioDevice(const SDL_bool iscapture, const char *description, const char *name, const uint32_t index, const pa_sample_spec *sample_spec) static void AddPulseAudioDevice(const SDL_bool recording, const char *description, const char *name, const uint32_t index, const pa_sample_spec *sample_spec)
{ {
SDL_AudioSpec spec; SDL_AudioSpec spec;
spec.format = PulseFormatToSDLFormat(sample_spec->format); spec.format = PulseFormatToSDLFormat(sample_spec->format);
@ -800,11 +800,11 @@ static void AddPulseAudioDevice(const SDL_bool iscapture, const char *descriptio
} else { } else {
handle->device_index = index; handle->device_index = index;
} }
SDL_AddAudioDevice(iscapture, description, &spec, handle); SDL_AddAudioDevice(recording, description, &spec, handle);
} }
} }
// This is called when PulseAudio adds an output ("sink") device. // This is called when PulseAudio adds an playback ("sink") device.
static void SinkInfoCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data) static void SinkInfoCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data)
{ {
if (i) { if (i) {
@ -813,7 +813,7 @@ static void SinkInfoCallback(pa_context *c, const pa_sink_info *i, int is_last,
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
} }
// This is called when PulseAudio adds a capture ("source") device. // This is called when PulseAudio adds a recording ("source") device.
static void SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_last, void *data) static void SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_last, void *data)
{ {
// Maybe skip "monitor" sources. These are just output from other sinks. // Maybe skip "monitor" sources. These are just output from other sinks.
@ -958,7 +958,7 @@ static int SDLCALL HotplugThread(void *data)
return 0; return 0;
} }
static void PULSEAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) static void PULSEAUDIO_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{ {
SDL_Semaphore *ready_sem = SDL_CreateSemaphore(0); SDL_Semaphore *ready_sem = SDL_CreateSemaphore(0);
@ -969,11 +969,11 @@ static void PULSEAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_Audio
PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop);
if (default_sink_path) { if (default_sink_path) {
*default_output = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_sink_path); *default_playback = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_sink_path);
} }
if (default_source_path) { if (default_source_path) {
*default_capture = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_source_path); *default_recording = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_source_path);
} }
// ok, we have a sane list, let's set up hotplug notifications now... // ok, we have a sane list, let's set up hotplug notifications now...
@ -1035,12 +1035,12 @@ static SDL_bool PULSEAUDIO_Init(SDL_AudioDriverImpl *impl)
impl->CloseDevice = PULSEAUDIO_CloseDevice; impl->CloseDevice = PULSEAUDIO_CloseDevice;
impl->DeinitializeStart = PULSEAUDIO_DeinitializeStart; impl->DeinitializeStart = PULSEAUDIO_DeinitializeStart;
impl->Deinitialize = PULSEAUDIO_Deinitialize; impl->Deinitialize = PULSEAUDIO_Deinitialize;
impl->WaitCaptureDevice = PULSEAUDIO_WaitCaptureDevice; impl->WaitRecordingDevice = PULSEAUDIO_WaitRecordingDevice;
impl->CaptureFromDevice = PULSEAUDIO_CaptureFromDevice; impl->RecordDevice = PULSEAUDIO_RecordDevice;
impl->FlushCapture = PULSEAUDIO_FlushCapture; impl->FlushRecording = PULSEAUDIO_FlushRecording;
impl->FreeDeviceHandle = PULSEAUDIO_FreeDeviceHandle; impl->FreeDeviceHandle = PULSEAUDIO_FreeDeviceHandle;
impl->HasCaptureSupport = SDL_TRUE; impl->HasRecordingSupport = SDL_TRUE;
return SDL_TRUE; return SDL_TRUE;
} }

View File

@ -37,8 +37,8 @@ struct SDL_PrivateAudioData
int bytes_requested; // bytes of data the hardware wants _now_. int bytes_requested; // bytes of data the hardware wants _now_.
const Uint8 *capturebuf; const Uint8 *recordingbuf;
int capturelen; int recordinglen;
}; };
#endif // SDL_pulseaudio_h_ #endif // SDL_pulseaudio_h_

View File

@ -93,7 +93,7 @@ static int QSA_WaitDevice(SDL_AudioDevice *device)
// For example, Vortex 8820 audio driver stucks on second DAC because // For example, Vortex 8820 audio driver stucks on second DAC because
// it doesn't exist ! // it doesn't exist !
const int result = SDL_IOReady(device->hidden->audio_fd, const int result = SDL_IOReady(device->hidden->audio_fd,
device->iscapture ? SDL_IOR_READ : SDL_IOR_WRITE, device->recording ? SDL_IOR_READ : SDL_IOR_WRITE,
2 * 1000); 2 * 1000);
switch (result) { switch (result) {
case -1: case -1:
@ -140,14 +140,14 @@ static int QSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int bufl
} else if ((errno == EINVAL) || (errno == EIO)) { } else if ((errno == EINVAL) || (errno == EIO)) {
snd_pcm_channel_status_t cstatus; snd_pcm_channel_status_t cstatus;
SDL_zero(cstatus); SDL_zero(cstatus);
cstatus.channel = device->iscapture ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK; cstatus.channel = device->recording ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK;
int status = snd_pcm_plugin_status(device->hidden->audio_handle, &cstatus); int status = snd_pcm_plugin_status(device->hidden->audio_handle, &cstatus);
if (status < 0) { if (status < 0) {
QSA_SetError("snd_pcm_plugin_status", status); QSA_SetError("snd_pcm_plugin_status", status);
return -1; return -1;
} else if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) || (cstatus.status == SND_PCM_STATUS_READY)) { } else if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) || (cstatus.status == SND_PCM_STATUS_READY)) {
status = snd_pcm_plugin_prepare(device->hidden->audio_handle, device->iscapture ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK); status = snd_pcm_plugin_prepare(device->hidden->audio_handle, device->recording ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK);
if (status < 0) { if (status < 0) {
QSA_SetError("snd_pcm_plugin_prepare", status); QSA_SetError("snd_pcm_plugin_prepare", status);
return -1; return -1;
@ -178,8 +178,8 @@ static void QSA_CloseDevice(SDL_AudioDevice *device)
if (device->hidden) { if (device->hidden) {
if (device->hidden->audio_handle) { if (device->hidden->audio_handle) {
#if _NTO_VERSION < 710 #if _NTO_VERSION < 710
// Finish playing available samples or cancel unread samples during capture // Finish playing available samples or cancel unread samples during recording
snd_pcm_plugin_flush(device->hidden->audio_handle, device->iscapture ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK); snd_pcm_plugin_flush(device->hidden->audio_handle, device->recording ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK);
#endif #endif
snd_pcm_close(device->hidden->audio_handle); snd_pcm_close(device->hidden->audio_handle);
} }
@ -192,15 +192,15 @@ static void QSA_CloseDevice(SDL_AudioDevice *device)
static int QSA_OpenDevice(SDL_AudioDevice *device) static int QSA_OpenDevice(SDL_AudioDevice *device)
{ {
if (device->iscapture) { if (device->recording) {
return SDL_SetError("SDL capture support isn't available on QNX atm"); // !!! FIXME: most of this code has support for capture devices, but there's no CaptureFromDevice, etc functions. Fill them in! return SDL_SetError("SDL recording support isn't available on QNX atm"); // !!! FIXME: most of this code has support for recording devices, but there's no RecordDevice, etc functions. Fill them in!
} }
SDL_assert(device->handle != NULL); // NULL used to mean "system default device" in SDL2; it does not mean that in SDL3. SDL_assert(device->handle != NULL); // NULL used to mean "system default device" in SDL2; it does not mean that in SDL3.
const Uint32 sdlhandle = (Uint32) ((size_t) device->handle); const Uint32 sdlhandle = (Uint32) ((size_t) device->handle);
const uint32_t cardno = (uint32_t) (sdlhandle & 0xFFFF); const uint32_t cardno = (uint32_t) (sdlhandle & 0xFFFF);
const uint32_t deviceno = (uint32_t) ((sdlhandle >> 16) & 0xFFFF); const uint32_t deviceno = (uint32_t) ((sdlhandle >> 16) & 0xFFFF);
const SDL_bool iscapture = device->iscapture; const SDL_bool recording = device->recording;
int status = 0; int status = 0;
// Initialize all variables that we clean on shutdown // Initialize all variables that we clean on shutdown
@ -214,7 +214,7 @@ static int QSA_OpenDevice(SDL_AudioDevice *device)
QSA_InitAudioParams(&cparams); QSA_InitAudioParams(&cparams);
// Open requested audio device // Open requested audio device
status = snd_pcm_open(&device->hidden->audio_handle, cardno, deviceno, iscapture ? SND_PCM_OPEN_CAPTURE : SND_PCM_OPEN_PLAYBACK); status = snd_pcm_open(&device->hidden->audio_handle, cardno, deviceno, recording ? SND_PCM_OPEN_CAPTURE : SND_PCM_OPEN_PLAYBACK);
if (status < 0) { if (status < 0) {
device->hidden->audio_handle = NULL; device->hidden->audio_handle = NULL;
return QSA_SetError("snd_pcm_open", status); return QSA_SetError("snd_pcm_open", status);
@ -263,7 +263,7 @@ static int QSA_OpenDevice(SDL_AudioDevice *device)
// Make sure channel is setup right one last time // Make sure channel is setup right one last time
snd_pcm_channel_setup_t csetup; snd_pcm_channel_setup_t csetup;
SDL_zero(csetup); SDL_zero(csetup);
csetup.channel = iscapture ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK; csetup.channel = recording ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK;
if (snd_pcm_plugin_setup(device->hidden->audio_handle, &csetup) < 0) { if (snd_pcm_plugin_setup(device->hidden->audio_handle, &csetup) < 0) {
return SDL_SetError("QSA: Unable to setup channel"); return SDL_SetError("QSA: Unable to setup channel");
} }
@ -312,7 +312,7 @@ static SDL_AudioFormat QnxFormatToSDLFormat(const int32_t qnxfmt)
return SDL_AUDIO_S16; // oh well. return SDL_AUDIO_S16; // oh well.
} }
static void QSA_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) static void QSA_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{ {
// Detect amount of available devices // Detect amount of available devices
// this value can be changed in the runtime // this value can be changed in the runtime
@ -350,13 +350,13 @@ static void QSA_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice
SDL_snprintf(fullname, sizeof (fullname), "%s d%d", name, (int) deviceno); SDL_snprintf(fullname, sizeof (fullname), "%s d%d", name, (int) deviceno);
// Check if this device id could play anything // Check if this device id could play anything
SDL_bool iscapture = SDL_FALSE; SDL_bool recording = SDL_FALSE;
status = snd_pcm_open(&handle, card, deviceno, SND_PCM_OPEN_PLAYBACK); status = snd_pcm_open(&handle, card, deviceno, SND_PCM_OPEN_PLAYBACK);
if (status != EOK) { // no? See if it's a capture device instead. if (status != EOK) { // no? See if it's a recording device instead.
#if 0 // !!! FIXME: most of this code has support for capture devices, but there's no CaptureFromDevice, etc functions. Fill them in! #if 0 // !!! FIXME: most of this code has support for recording devices, but there's no RecordDevice, etc functions. Fill them in!
status = snd_pcm_open(&handle, card, deviceno, SND_PCM_OPEN_CAPTURE); status = snd_pcm_open(&handle, card, deviceno, SND_PCM_OPEN_CAPTURE);
if (status == EOK) { if (status == EOK) {
iscapture = SDL_TRUE; recording = SDL_TRUE;
} }
#endif #endif
} }
@ -366,7 +366,7 @@ static void QSA_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice
SDL_AudioSpec *pspec = &spec; SDL_AudioSpec *pspec = &spec;
snd_pcm_channel_setup_t csetup; snd_pcm_channel_setup_t csetup;
SDL_zero(csetup); SDL_zero(csetup);
csetup.channel = iscapture ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK; csetup.channel = recording ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK;
if (snd_pcm_plugin_setup(device->hidden->audio_handle, &csetup) < 0) { if (snd_pcm_plugin_setup(device->hidden->audio_handle, &csetup) < 0) {
pspec = NULL; // go on without spec info. pspec = NULL; // go on without spec info.
@ -382,7 +382,7 @@ static void QSA_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice
SDL_assert(card <= 0xFFFF); SDL_assert(card <= 0xFFFF);
SDL_assert(deviceno <= 0xFFFF); SDL_assert(deviceno <= 0xFFFF);
const Uint32 sdlhandle = ((Uint32) card) | (((Uint32) deviceno) << 16); const Uint32 sdlhandle = ((Uint32) card) | (((Uint32) deviceno) << 16);
SDL_AddAudioDevice(iscapture, fullname, pspec, (void *) ((size_t) sdlhandle)); SDL_AddAudioDevice(recording, fullname, pspec, (void *) ((size_t) sdlhandle));
} }
} else { } else {
// Check if we got end of devices list // Check if we got end of devices list
@ -407,7 +407,7 @@ static void QSA_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice
SDL_assert(cardno <= 0xFFFF); SDL_assert(cardno <= 0xFFFF);
SDL_assert(deviceno <= 0xFFFF); SDL_assert(deviceno <= 0xFFFF);
const Uint32 sdlhandle = ((Uint32) card) | (((Uint32) deviceno) << 16); const Uint32 sdlhandle = ((Uint32) card) | (((Uint32) deviceno) << 16);
*default_output = SDL_FindPhysicalAudioDeviceByHandle((void *) ((size_t) sdlhandle)); *default_playback = SDL_FindPhysicalAudioDeviceByHandle((void *) ((size_t) sdlhandle));
} }
if (snd_pcm_open_preferred(&handle, &cardno, &deviceno, SND_PCM_OPEN_CAPTURE) == 0) { if (snd_pcm_open_preferred(&handle, &cardno, &deviceno, SND_PCM_OPEN_CAPTURE) == 0) {
@ -416,7 +416,7 @@ static void QSA_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice
SDL_assert(cardno <= 0xFFFF); SDL_assert(cardno <= 0xFFFF);
SDL_assert(deviceno <= 0xFFFF); SDL_assert(deviceno <= 0xFFFF);
const Uint32 sdlhandle = ((Uint32) card) | (((Uint32) deviceno) << 16); const Uint32 sdlhandle = ((Uint32) card) | (((Uint32) deviceno) << 16);
*default_capture = SDL_FindPhysicalAudioDeviceByHandle((void *) ((size_t) sdlhandle)); *default_recording = SDL_FindPhysicalAudioDeviceByHandle((void *) ((size_t) sdlhandle));
} }
} }
@ -436,8 +436,8 @@ static SDL_bool QSA_Init(SDL_AudioDriverImpl * impl)
impl->CloseDevice = QSA_CloseDevice; impl->CloseDevice = QSA_CloseDevice;
impl->Deinitialize = QSA_Deinitialize; impl->Deinitialize = QSA_Deinitialize;
// !!! FIXME: most of this code has support for capture devices, but there's no CaptureFromDevice, etc functions. Fill them in! // !!! FIXME: most of this code has support for recording devices, but there's no RecordDevice, etc functions. Fill them in!
//impl->HasCaptureSupport = SDL_TRUE; //impl->HasRecordingSupport = SDL_TRUE;
return SDL_TRUE; return SDL_TRUE;
} }

View File

@ -149,22 +149,22 @@ static int LoadSNDIOLibrary(void)
static int SNDIO_WaitDevice(SDL_AudioDevice *device) static int SNDIO_WaitDevice(SDL_AudioDevice *device)
{ {
const SDL_bool iscapture = device->iscapture; const SDL_bool recording = device->recording;
while (!SDL_AtomicGet(&device->shutdown)) { while (!SDL_AtomicGet(&device->shutdown)) {
if (SNDIO_sio_eof(device->hidden->dev)) { if (SNDIO_sio_eof(device->hidden->dev)) {
return -1; return -1;
} }
const int nfds = SNDIO_sio_pollfd(device->hidden->dev, device->hidden->pfd, iscapture ? POLLIN : POLLOUT); const int nfds = SNDIO_sio_pollfd(device->hidden->dev, device->hidden->pfd, recording ? POLLIN : POLLOUT);
if (nfds <= 0 || poll(device->hidden->pfd, nfds, 10) < 0) { if (nfds <= 0 || poll(device->hidden->pfd, nfds, 10) < 0) {
return -1; return -1;
} }
const int revents = SNDIO_sio_revents(device->hidden->dev, device->hidden->pfd); const int revents = SNDIO_sio_revents(device->hidden->dev, device->hidden->pfd);
if (iscapture && (revents & POLLIN)) { if (recording && (revents & POLLIN)) {
break; break;
} else if (!iscapture && (revents & POLLOUT)) { } else if (!recording && (revents & POLLOUT)) {
break; break;
} else if (revents & POLLHUP) { } else if (revents & POLLHUP) {
return -1; return -1;
@ -187,9 +187,9 @@ static int SNDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int bu
return 0; return 0;
} }
static int SNDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int SNDIO_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
{ {
// We set capture devices non-blocking; this can safely return 0 in SDL3, but we'll check for EOF to cause a device disconnect. // We set recording devices non-blocking; this can safely return 0 in SDL3, but we'll check for EOF to cause a device disconnect.
const size_t br = SNDIO_sio_read(device->hidden->dev, buffer, buflen); const size_t br = SNDIO_sio_read(device->hidden->dev, buffer, buflen);
if ((br == 0) && SNDIO_sio_eof(device->hidden->dev)) { if ((br == 0) && SNDIO_sio_eof(device->hidden->dev)) {
return -1; return -1;
@ -197,7 +197,7 @@ static int SNDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int bu
return (int) br; return (int) br;
} }
static void SNDIO_FlushCapture(SDL_AudioDevice *device) static void SNDIO_FlushRecording(SDL_AudioDevice *device)
{ {
char buf[512]; char buf[512];
while (!SDL_AtomicGet(&device->shutdown) && (SNDIO_sio_read(device->hidden->dev, buf, sizeof(buf)) > 0)) { while (!SDL_AtomicGet(&device->shutdown) && (SNDIO_sio_read(device->hidden->dev, buf, sizeof(buf)) > 0)) {
@ -234,9 +234,9 @@ static int SNDIO_OpenDevice(SDL_AudioDevice *device)
// !!! FIXME: we really should standardize this on a specific SDL hint. // !!! FIXME: we really should standardize this on a specific SDL hint.
const char *audiodev = SDL_getenv("AUDIODEV"); const char *audiodev = SDL_getenv("AUDIODEV");
// Capture devices must be non-blocking for SNDIO_FlushCapture // Recording devices must be non-blocking for SNDIO_FlushRecording
device->hidden->dev = SNDIO_sio_open(audiodev ? audiodev : SIO_DEVANY, device->hidden->dev = SNDIO_sio_open(audiodev ? audiodev : SIO_DEVANY,
device->iscapture ? SIO_REC : SIO_PLAY, device->iscapture); device->recording ? SIO_REC : SIO_PLAY, device->recording);
if (!device->hidden->dev) { if (!device->hidden->dev) {
return SDL_SetError("sio_open() failed"); return SDL_SetError("sio_open() failed");
} }
@ -324,10 +324,10 @@ static void SNDIO_Deinitialize(void)
UnloadSNDIOLibrary(); UnloadSNDIOLibrary();
} }
static void SNDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) static void SNDIO_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{ {
*default_output = SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, NULL, (void *)0x1); *default_playback = SDL_AddAudioDevice(SDL_FALSE, DEFAULT_PLAYBACK_DEVNAME, NULL, (void *)0x1);
*default_capture = SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, NULL, (void *)0x2); *default_recording = SDL_AddAudioDevice(SDL_TRUE, DEFAULT_RECORDING_DEVNAME, NULL, (void *)0x2);
} }
static SDL_bool SNDIO_Init(SDL_AudioDriverImpl *impl) static SDL_bool SNDIO_Init(SDL_AudioDriverImpl *impl)
@ -341,13 +341,13 @@ static SDL_bool SNDIO_Init(SDL_AudioDriverImpl *impl)
impl->PlayDevice = SNDIO_PlayDevice; impl->PlayDevice = SNDIO_PlayDevice;
impl->GetDeviceBuf = SNDIO_GetDeviceBuf; impl->GetDeviceBuf = SNDIO_GetDeviceBuf;
impl->CloseDevice = SNDIO_CloseDevice; impl->CloseDevice = SNDIO_CloseDevice;
impl->WaitCaptureDevice = SNDIO_WaitDevice; impl->WaitRecordingDevice = SNDIO_WaitDevice;
impl->CaptureFromDevice = SNDIO_CaptureFromDevice; impl->RecordDevice = SNDIO_RecordDevice;
impl->FlushCapture = SNDIO_FlushCapture; impl->FlushRecording = SNDIO_FlushRecording;
impl->Deinitialize = SNDIO_Deinitialize; impl->Deinitialize = SNDIO_Deinitialize;
impl->DetectDevices = SNDIO_DetectDevices; impl->DetectDevices = SNDIO_DetectDevices;
impl->HasCaptureSupport = SDL_TRUE; impl->HasRecordingSupport = SDL_TRUE;
return SDL_TRUE; return SDL_TRUE;
} }

View File

@ -37,7 +37,7 @@
#define SCE_AUDIO_SAMPLE_ALIGN(s) (((s) + 63) & ~63) #define SCE_AUDIO_SAMPLE_ALIGN(s) (((s) + 63) & ~63)
#define SCE_AUDIO_MAX_VOLUME 0x8000 #define SCE_AUDIO_MAX_VOLUME 0x8000
static int VITAAUD_OpenCaptureDevice(SDL_AudioDevice *device) static int VITAAUD_OpenRecordingDevice(SDL_AudioDevice *device)
{ {
device->spec.freq = 16000; device->spec.freq = 16000;
device->spec.channels = 1; device->spec.channels = 1;
@ -79,8 +79,8 @@ static int VITAAUD_OpenDevice(SDL_AudioDevice *device)
return SDL_SetError("Unsupported audio format"); return SDL_SetError("Unsupported audio format");
} }
if (device->iscapture) { if (device->recording) {
return VITAAUD_OpenCaptureDevice(device); return VITAAUD_OpenRecordingDevice(device);
} }
// The sample count must be a multiple of 64. // The sample count must be a multiple of 64.
@ -154,7 +154,7 @@ static void VITAAUD_CloseDevice(SDL_AudioDevice *device)
{ {
if (device->hidden) { if (device->hidden) {
if (device->hidden->port >= 0) { if (device->hidden->port >= 0) {
if (device->iscapture) { if (device->recording) {
sceAudioInReleasePort(device->hidden->port); sceAudioInReleasePort(device->hidden->port);
} else { } else {
sceAudioOutReleasePort(device->hidden->port); sceAudioOutReleasePort(device->hidden->port);
@ -162,7 +162,7 @@ static void VITAAUD_CloseDevice(SDL_AudioDevice *device)
device->hidden->port = -1; device->hidden->port = -1;
} }
if (!device->iscapture && device->hidden->rawbuf) { if (!device->recording && device->hidden->rawbuf) {
SDL_aligned_free(device->hidden->rawbuf); // this uses SDL_aligned_alloc(), not SDL_malloc() SDL_aligned_free(device->hidden->rawbuf); // this uses SDL_aligned_alloc(), not SDL_malloc()
device->hidden->rawbuf = NULL; device->hidden->rawbuf = NULL;
} }
@ -171,7 +171,7 @@ static void VITAAUD_CloseDevice(SDL_AudioDevice *device)
} }
} }
static int VITAAUD_WaitCaptureDevice(SDL_AudioDevice *device) static int VITAAUD_WaitRecordingDevice(SDL_AudioDevice *device)
{ {
// there's only a blocking call to obtain more data, so we'll just sleep as // there's only a blocking call to obtain more data, so we'll just sleep as
// long as a buffer would run. // long as a buffer would run.
@ -182,18 +182,18 @@ static int VITAAUD_WaitCaptureDevice(SDL_AudioDevice *device)
return 0; return 0;
} }
static int VITAAUD_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int VITAAUD_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
{ {
int ret; int ret;
SDL_assert(buflen == device->buffer_size); SDL_assert(buflen == device->buffer_size);
ret = sceAudioInInput(device->hidden->port, buffer); ret = sceAudioInInput(device->hidden->port, buffer);
if (ret < 0) { if (ret < 0) {
return SDL_SetError("Failed to capture from device: %x", ret); return SDL_SetError("Failed to record from device: %x", ret);
} }
return device->buffer_size; return device->buffer_size;
} }
static void VITAAUD_FlushCapture(SDL_AudioDevice *device) static void VITAAUD_FlushRecording(SDL_AudioDevice *device)
{ {
// just grab the latest and dump it. // just grab the latest and dump it.
sceAudioInInput(device->hidden->port, device->work_buffer); sceAudioInInput(device->hidden->port, device->work_buffer);
@ -219,13 +219,13 @@ static SDL_bool VITAAUD_Init(SDL_AudioDriverImpl *impl)
impl->GetDeviceBuf = VITAAUD_GetDeviceBuf; impl->GetDeviceBuf = VITAAUD_GetDeviceBuf;
impl->CloseDevice = VITAAUD_CloseDevice; impl->CloseDevice = VITAAUD_CloseDevice;
impl->ThreadInit = VITAAUD_ThreadInit; impl->ThreadInit = VITAAUD_ThreadInit;
impl->WaitCaptureDevice = VITAAUD_WaitCaptureDevice; impl->WaitRecordingDevice = VITAAUD_WaitRecordingDevice;
impl->FlushCapture = VITAAUD_FlushCapture; impl->FlushRecording = VITAAUD_FlushRecording;
impl->CaptureFromDevice = VITAAUD_CaptureFromDevice; impl->RecordDevice = VITAAUD_RecordDevice;
impl->HasCaptureSupport = SDL_TRUE; impl->HasRecordingSupport = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE; impl->OnlyHasDefaultPlaybackDevice = SDL_TRUE;
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE; impl->OnlyHasDefaultRecordingDevice = SDL_TRUE;
return SDL_TRUE; return SDL_TRUE;
} }

View File

@ -253,24 +253,24 @@ static void DeinitManagementThread(void)
typedef struct typedef struct
{ {
SDL_AudioDevice **default_output; SDL_AudioDevice **default_playback;
SDL_AudioDevice **default_capture; SDL_AudioDevice **default_recording;
} mgmtthrtask_DetectDevicesData; } mgmtthrtask_DetectDevicesData;
static int mgmtthrtask_DetectDevices(void *userdata) static int mgmtthrtask_DetectDevices(void *userdata)
{ {
mgmtthrtask_DetectDevicesData *data = (mgmtthrtask_DetectDevicesData *)userdata; mgmtthrtask_DetectDevicesData *data = (mgmtthrtask_DetectDevicesData *)userdata;
WASAPI_EnumerateEndpoints(data->default_output, data->default_capture); WASAPI_EnumerateEndpoints(data->default_playback, data->default_recording);
return 0; return 0;
} }
static void WASAPI_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) static void WASAPI_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{ {
int rc; int rc;
// this blocks because it needs to finish before the audio subsystem inits // this blocks because it needs to finish before the audio subsystem inits
mgmtthrtask_DetectDevicesData data; mgmtthrtask_DetectDevicesData data;
data.default_output = default_output; data.default_playback = default_playback;
data.default_capture = default_capture; data.default_recording = default_recording;
WASAPI_ProxyToManagementThread(mgmtthrtask_DetectDevices, &data, &rc); WASAPI_ProxyToManagementThread(mgmtthrtask_DetectDevices, &data, &rc);
} }
@ -471,9 +471,9 @@ static int WASAPI_WaitDevice(SDL_AudioDevice *device)
UINT32 padding = 0; UINT32 padding = 0;
if (!WasapiFailed(device, IAudioClient_GetCurrentPadding(device->hidden->client, &padding))) { if (!WasapiFailed(device, IAudioClient_GetCurrentPadding(device->hidden->client, &padding))) {
//SDL_Log("WASAPI EVENT! padding=%u maxpadding=%u", (unsigned int)padding, (unsigned int)maxpadding);*/ //SDL_Log("WASAPI EVENT! padding=%u maxpadding=%u", (unsigned int)padding, (unsigned int)maxpadding);*/
if (device->iscapture && (padding > 0)) { if (device->recording && (padding > 0)) {
break; break;
} else if (!device->iscapture && (padding <= maxpadding)) { } else if (!device->recording && (padding <= maxpadding)) {
break; break;
} }
} }
@ -487,7 +487,7 @@ static int WASAPI_WaitDevice(SDL_AudioDevice *device)
return 0; return 0;
} }
static int WASAPI_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int WASAPI_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
{ {
BYTE *ptr = NULL; BYTE *ptr = NULL;
UINT32 frames = 0; UINT32 frames = 0;
@ -524,7 +524,7 @@ static int WASAPI_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int b
return -1; // unrecoverable error. return -1; // unrecoverable error.
} }
static void WASAPI_FlushCapture(SDL_AudioDevice *device) static void WASAPI_FlushRecording(SDL_AudioDevice *device)
{ {
BYTE *ptr = NULL; BYTE *ptr = NULL;
UINT32 frames = 0; UINT32 frames = 0;
@ -706,7 +706,7 @@ static int mgmtthrtask_PrepDevice(void *userdata)
device->hidden->framesize = SDL_AUDIO_FRAMESIZE(device->spec); device->hidden->framesize = SDL_AUDIO_FRAMESIZE(device->spec);
if (device->iscapture) { if (device->recording) {
IAudioCaptureClient *capture = NULL; IAudioCaptureClient *capture = NULL;
ret = IAudioClient_GetService(client, &SDL_IID_IAudioCaptureClient, (void **)&capture); ret = IAudioClient_GetService(client, &SDL_IID_IAudioCaptureClient, (void **)&capture);
if (FAILED(ret)) { if (FAILED(ret)) {
@ -720,7 +720,7 @@ static int mgmtthrtask_PrepDevice(void *userdata)
return WIN_SetErrorFromHRESULT("WASAPI can't start capture", ret); return WIN_SetErrorFromHRESULT("WASAPI can't start capture", ret);
} }
WASAPI_FlushCapture(device); // MSDN says you should flush capture endpoint right after startup. WASAPI_FlushRecording(device); // MSDN says you should flush the recording endpoint right after startup.
} else { } else {
IAudioRenderClient *render = NULL; IAudioRenderClient *render = NULL;
ret = IAudioClient_GetService(client, &SDL_IID_IAudioRenderClient, (void **)&render); ret = IAudioClient_GetService(client, &SDL_IID_IAudioRenderClient, (void **)&render);
@ -757,7 +757,7 @@ static int WASAPI_OpenDevice(SDL_AudioDevice *device)
} }
/* Ready, but possibly waiting for async device activation. /* Ready, but possibly waiting for async device activation.
Until activation is successful, we will report silence from capture Until activation is successful, we will report silence from recording
devices and ignore data on playback devices. Upon activation, we'll make devices and ignore data on playback devices. Upon activation, we'll make
sure any bound audio streams are adjusted for the final device format. */ sure any bound audio streams are adjusted for the final device format. */
@ -816,15 +816,15 @@ static SDL_bool WASAPI_Init(SDL_AudioDriverImpl *impl)
impl->PlayDevice = WASAPI_PlayDevice; impl->PlayDevice = WASAPI_PlayDevice;
impl->WaitDevice = WASAPI_WaitDevice; impl->WaitDevice = WASAPI_WaitDevice;
impl->GetDeviceBuf = WASAPI_GetDeviceBuf; impl->GetDeviceBuf = WASAPI_GetDeviceBuf;
impl->WaitCaptureDevice = WASAPI_WaitDevice; impl->WaitRecordingDevice = WASAPI_WaitDevice;
impl->CaptureFromDevice = WASAPI_CaptureFromDevice; impl->RecordDevice = WASAPI_RecordDevice;
impl->FlushCapture = WASAPI_FlushCapture; impl->FlushRecording = WASAPI_FlushRecording;
impl->CloseDevice = WASAPI_CloseDevice; impl->CloseDevice = WASAPI_CloseDevice;
impl->DeinitializeStart = WASAPI_DeinitializeStart; impl->DeinitializeStart = WASAPI_DeinitializeStart;
impl->Deinitialize = WASAPI_Deinitialize; impl->Deinitialize = WASAPI_Deinitialize;
impl->FreeDeviceHandle = WASAPI_FreeDeviceHandle; impl->FreeDeviceHandle = WASAPI_FreeDeviceHandle;
impl->HasCaptureSupport = SDL_TRUE; impl->HasRecordingSupport = SDL_TRUE;
return SDL_TRUE; return SDL_TRUE;
} }

View File

@ -59,7 +59,7 @@ int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, in
int WASAPI_PlatformInit(void); int WASAPI_PlatformInit(void);
void WASAPI_PlatformDeinit(void); void WASAPI_PlatformDeinit(void);
void WASAPI_PlatformDeinitializeStart(void); void WASAPI_PlatformDeinitializeStart(void);
void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture); void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording);
int WASAPI_ActivateDevice(SDL_AudioDevice *device); int WASAPI_ActivateDevice(SDL_AudioDevice *device);
void WASAPI_PlatformThreadInit(SDL_AudioDevice *device); // this happens on the audio device thread, not the management thread. void WASAPI_PlatformThreadInit(SDL_AudioDevice *device); // this happens on the audio device thread, not the management thread.
void WASAPI_PlatformThreadDeinit(SDL_AudioDevice *device); // this happens on the audio device thread, not the management thread. void WASAPI_PlatformThreadDeinit(SDL_AudioDevice *device); // this happens on the audio device thread, not the management thread.

View File

@ -142,7 +142,7 @@ void WASAPI_PlatformThreadInit(SDL_AudioDevice *device)
DWORD idx = 0; DWORD idx = 0;
device->hidden->task = pAvSetMmThreadCharacteristicsW(L"Pro Audio", &idx); device->hidden->task = pAvSetMmThreadCharacteristicsW(L"Pro Audio", &idx);
} else { } else {
SDL_SetThreadPriority(device->iscapture ? SDL_THREAD_PRIORITY_HIGH : SDL_THREAD_PRIORITY_TIME_CRITICAL); SDL_SetThreadPriority(device->recording ? SDL_THREAD_PRIORITY_HIGH : SDL_THREAD_PRIORITY_TIME_CRITICAL);
} }
} }
@ -164,7 +164,7 @@ void WASAPI_PlatformThreadDeinit(SDL_AudioDevice *device)
int WASAPI_ActivateDevice(SDL_AudioDevice *device) int WASAPI_ActivateDevice(SDL_AudioDevice *device)
{ {
IMMDevice *immdevice = NULL; IMMDevice *immdevice = NULL;
if (SDL_IMMDevice_Get(device, &immdevice, device->iscapture) < 0) { if (SDL_IMMDevice_Get(device, &immdevice, device->recording) < 0) {
device->hidden->client = NULL; device->hidden->client = NULL;
return -1; // This is already set by SDL_IMMDevice_Get return -1; // This is already set by SDL_IMMDevice_Get
} }
@ -186,9 +186,9 @@ int WASAPI_ActivateDevice(SDL_AudioDevice *device)
return 0; // good to go. return 0; // good to go.
} }
void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{ {
SDL_IMMDevice_EnumerateEndpoints(default_output, default_capture); SDL_IMMDevice_EnumerateEndpoints(default_playback, default_recording);
} }
void WASAPI_PlatformDeleteActivationHandler(void *handler) void WASAPI_PlatformDeleteActivationHandler(void *handler)

View File

@ -66,7 +66,7 @@ static SDL_AudioDevice *FindWinRTAudioDevice(LPCWSTR devid)
class SDL_WasapiDeviceEventHandler class SDL_WasapiDeviceEventHandler
{ {
public: public:
SDL_WasapiDeviceEventHandler(const SDL_bool _iscapture); SDL_WasapiDeviceEventHandler(const SDL_bool _recording);
~SDL_WasapiDeviceEventHandler(); ~SDL_WasapiDeviceEventHandler();
void OnDeviceAdded(DeviceWatcher ^ sender, DeviceInformation ^ args); void OnDeviceAdded(DeviceWatcher ^ sender, DeviceInformation ^ args);
void OnDeviceRemoved(DeviceWatcher ^ sender, DeviceInformationUpdate ^ args); void OnDeviceRemoved(DeviceWatcher ^ sender, DeviceInformationUpdate ^ args);
@ -78,7 +78,7 @@ class SDL_WasapiDeviceEventHandler
private: private:
SDL_Semaphore *completed_semaphore; SDL_Semaphore *completed_semaphore;
const SDL_bool iscapture; const SDL_bool recording;
DeviceWatcher ^ watcher; DeviceWatcher ^ watcher;
Windows::Foundation::EventRegistrationToken added_handler; Windows::Foundation::EventRegistrationToken added_handler;
Windows::Foundation::EventRegistrationToken removed_handler; Windows::Foundation::EventRegistrationToken removed_handler;
@ -87,14 +87,14 @@ class SDL_WasapiDeviceEventHandler
Windows::Foundation::EventRegistrationToken default_changed_handler; Windows::Foundation::EventRegistrationToken default_changed_handler;
}; };
SDL_WasapiDeviceEventHandler::SDL_WasapiDeviceEventHandler(const SDL_bool _iscapture) SDL_WasapiDeviceEventHandler::SDL_WasapiDeviceEventHandler(const SDL_bool _recording)
: iscapture(_iscapture), completed_semaphore(SDL_CreateSemaphore(0)) : recording(_recording), completed_semaphore(SDL_CreateSemaphore(0))
{ {
if (!completed_semaphore) { if (!completed_semaphore) {
return; // uhoh. return; // uhoh.
} }
Platform::String ^ selector = _iscapture ? MediaDevice::GetAudioCaptureSelector() : MediaDevice::GetAudioRenderSelector(); Platform::String ^ selector = _recording ? MediaDevice::GetAudioCaptureSelector() : MediaDevice::GetAudioRenderSelector();
Platform::Collections::Vector<Platform::String ^> properties; Platform::Collections::Vector<Platform::String ^> properties;
properties.Append(SDL_PKEY_AudioEngine_DeviceFormat); properties.Append(SDL_PKEY_AudioEngine_DeviceFormat);
watcher = DeviceInformation::CreateWatcher(selector, properties.GetView()); watcher = DeviceInformation::CreateWatcher(selector, properties.GetView());
@ -106,7 +106,7 @@ SDL_WasapiDeviceEventHandler::SDL_WasapiDeviceEventHandler(const SDL_bool _iscap
removed_handler = watcher->Removed += ref new TypedEventHandler<DeviceWatcher ^, DeviceInformationUpdate ^>([this](DeviceWatcher ^ sender, DeviceInformationUpdate ^ args) { OnDeviceRemoved(sender, args); }); removed_handler = watcher->Removed += ref new TypedEventHandler<DeviceWatcher ^, DeviceInformationUpdate ^>([this](DeviceWatcher ^ sender, DeviceInformationUpdate ^ args) { OnDeviceRemoved(sender, args); });
updated_handler = watcher->Updated += ref new TypedEventHandler<DeviceWatcher ^, DeviceInformationUpdate ^>([this](DeviceWatcher ^ sender, DeviceInformationUpdate ^ args) { OnDeviceUpdated(sender, args); }); updated_handler = watcher->Updated += ref new TypedEventHandler<DeviceWatcher ^, DeviceInformationUpdate ^>([this](DeviceWatcher ^ sender, DeviceInformationUpdate ^ args) { OnDeviceUpdated(sender, args); });
completed_handler = watcher->EnumerationCompleted += ref new TypedEventHandler<DeviceWatcher ^, Platform::Object ^>([this](DeviceWatcher ^ sender, Platform::Object ^ args) { OnEnumerationCompleted(sender, args); }); completed_handler = watcher->EnumerationCompleted += ref new TypedEventHandler<DeviceWatcher ^, Platform::Object ^>([this](DeviceWatcher ^ sender, Platform::Object ^ args) { OnEnumerationCompleted(sender, args); });
if (iscapture) { if (recording) {
default_changed_handler = MediaDevice::DefaultAudioCaptureDeviceChanged += ref new TypedEventHandler<Platform::Object ^, DefaultAudioCaptureDeviceChangedEventArgs ^>([this](Platform::Object ^ sender, DefaultAudioCaptureDeviceChangedEventArgs ^ args) { OnDefaultCaptureDeviceChanged(sender, args); }); default_changed_handler = MediaDevice::DefaultAudioCaptureDeviceChanged += ref new TypedEventHandler<Platform::Object ^, DefaultAudioCaptureDeviceChangedEventArgs ^>([this](Platform::Object ^ sender, DefaultAudioCaptureDeviceChangedEventArgs ^ args) { OnDefaultCaptureDeviceChanged(sender, args); });
} else { } else {
default_changed_handler = MediaDevice::DefaultAudioRenderDeviceChanged += ref new TypedEventHandler<Platform::Object ^, DefaultAudioRenderDeviceChangedEventArgs ^>([this](Platform::Object ^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args) { OnDefaultRenderDeviceChanged(sender, args); }); default_changed_handler = MediaDevice::DefaultAudioRenderDeviceChanged += ref new TypedEventHandler<Platform::Object ^, DefaultAudioRenderDeviceChangedEventArgs ^>([this](Platform::Object ^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args) { OnDefaultRenderDeviceChanged(sender, args); });
@ -130,7 +130,7 @@ SDL_WasapiDeviceEventHandler::~SDL_WasapiDeviceEventHandler()
completed_semaphore = nullptr; completed_semaphore = nullptr;
} }
if (iscapture) { if (recording) {
MediaDevice::DefaultAudioCaptureDeviceChanged -= default_changed_handler; MediaDevice::DefaultAudioCaptureDeviceChanged -= default_changed_handler;
} else { } else {
MediaDevice::DefaultAudioRenderDeviceChanged -= default_changed_handler; MediaDevice::DefaultAudioRenderDeviceChanged -= default_changed_handler;
@ -165,7 +165,7 @@ void SDL_WasapiDeviceEventHandler::OnDeviceAdded(DeviceWatcher ^ sender, DeviceI
LPWSTR devid = SDL_wcsdup(info->Id->Data()); LPWSTR devid = SDL_wcsdup(info->Id->Data());
if (devid) { if (devid) {
SDL_AddAudioDevice(this->iscapture, utf8dev, spec.channels ? &spec : NULL, devid); SDL_AddAudioDevice(this->recording, utf8dev, spec.channels ? &spec : NULL, devid);
} }
SDL_free(utf8dev); SDL_free(utf8dev);
} }
@ -192,13 +192,13 @@ void SDL_WasapiDeviceEventHandler::OnEnumerationCompleted(DeviceWatcher ^ sender
void SDL_WasapiDeviceEventHandler::OnDefaultRenderDeviceChanged(Platform::Object ^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args) void SDL_WasapiDeviceEventHandler::OnDefaultRenderDeviceChanged(Platform::Object ^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args)
{ {
SDL_assert(!this->iscapture); SDL_assert(!this->recording);
SDL_DefaultAudioDeviceChanged(FindWinRTAudioDevice(args->Id->Data())); SDL_DefaultAudioDeviceChanged(FindWinRTAudioDevice(args->Id->Data()));
} }
void SDL_WasapiDeviceEventHandler::OnDefaultCaptureDeviceChanged(Platform::Object ^ sender, DefaultAudioCaptureDeviceChangedEventArgs ^ args) void SDL_WasapiDeviceEventHandler::OnDefaultCaptureDeviceChanged(Platform::Object ^ sender, DefaultAudioCaptureDeviceChangedEventArgs ^ args)
{ {
SDL_assert(this->iscapture); SDL_assert(this->recording);
SDL_DefaultAudioDeviceChanged(FindWinRTAudioDevice(args->Id->Data())); SDL_DefaultAudioDeviceChanged(FindWinRTAudioDevice(args->Id->Data()));
} }
@ -212,7 +212,7 @@ void SDL_WasapiDeviceEventHandler::WaitForCompletion()
} }
static SDL_WasapiDeviceEventHandler *playback_device_event_handler; static SDL_WasapiDeviceEventHandler *playback_device_event_handler;
static SDL_WasapiDeviceEventHandler *capture_device_event_handler; static SDL_WasapiDeviceEventHandler *recording_device_event_handler;
int WASAPI_PlatformInit(void) int WASAPI_PlatformInit(void)
{ {
@ -223,8 +223,8 @@ static void StopWasapiHotplug(void)
{ {
delete playback_device_event_handler; delete playback_device_event_handler;
playback_device_event_handler = nullptr; playback_device_event_handler = nullptr;
delete capture_device_event_handler; delete recording_device_event_handler;
capture_device_event_handler = nullptr; recording_device_event_handler = nullptr;
} }
void WASAPI_PlatformDeinit(void) void WASAPI_PlatformDeinit(void)
@ -238,7 +238,7 @@ void WASAPI_PlatformDeinitializeStart(void)
} }
void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{ {
Platform::String ^ defdevid; Platform::String ^ defdevid;
@ -249,14 +249,14 @@ void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice
playback_device_event_handler->WaitForCompletion(); playback_device_event_handler->WaitForCompletion();
defdevid = MediaDevice::GetDefaultAudioRenderId(AudioDeviceRole::Default); defdevid = MediaDevice::GetDefaultAudioRenderId(AudioDeviceRole::Default);
if (defdevid) { if (defdevid) {
*default_output = FindWinRTAudioDevice(defdevid->Data()); *default_playback = FindWinRTAudioDevice(defdevid->Data());
} }
capture_device_event_handler = new SDL_WasapiDeviceEventHandler(SDL_TRUE); recording_device_event_handler = new SDL_WasapiDeviceEventHandler(SDL_TRUE);
capture_device_event_handler->WaitForCompletion(); recording_device_event_handler->WaitForCompletion();
defdevid = MediaDevice::GetDefaultAudioCaptureId(AudioDeviceRole::Default); defdevid = MediaDevice::GetDefaultAudioCaptureId(AudioDeviceRole::Default);
if (defdevid) { if (defdevid) {
*default_capture = FindWinRTAudioDevice(defdevid->Data()); *default_recording = FindWinRTAudioDevice(defdevid->Data());
} }
} }
@ -344,7 +344,7 @@ int WASAPI_ActivateDevice(SDL_AudioDevice *device)
void WASAPI_PlatformThreadInit(SDL_AudioDevice *device) void WASAPI_PlatformThreadInit(SDL_AudioDevice *device)
{ {
// !!! FIXME: set this thread to "Pro Audio" priority. // !!! FIXME: set this thread to "Pro Audio" priority.
SDL_SetThreadPriority(device->iscapture ? SDL_THREAD_PRIORITY_HIGH : SDL_THREAD_PRIORITY_TIME_CRITICAL); SDL_SetThreadPriority(device->recording ? SDL_THREAD_PRIORITY_HIGH : SDL_THREAD_PRIORITY_TIME_CRITICAL);
} }
void WASAPI_PlatformThreadDeinit(SDL_AudioDevice *device) void WASAPI_PlatformThreadDeinit(SDL_AudioDevice *device)

View File

@ -760,7 +760,7 @@ void SDL_CameraThreadSetup(SDL_CameraDevice *device)
{ {
// Set thread priority to THREAD_PRIORITY_VIDEO // Set thread priority to THREAD_PRIORITY_VIDEO
extern void Android_JNI_CameraSetThreadPriority(int, int); extern void Android_JNI_CameraSetThreadPriority(int, int);
Android_JNI_CameraSetThreadPriority(device->iscapture, device); Android_JNI_CameraSetThreadPriority(device->recording, device);
}*/ }*/
#else #else
// The camera capture is always a high priority thread // The camera capture is always a high priority thread
@ -897,7 +897,7 @@ SDL_bool SDL_CameraThreadIterate(SDL_CameraDevice *device)
void SDL_CameraThreadShutdown(SDL_CameraDevice *device) void SDL_CameraThreadShutdown(SDL_CameraDevice *device)
{ {
//device->FlushCapture(device); //device->FlushRecording(device);
//camera_driver.impl.ThreadDeinit(device); //camera_driver.impl.ThreadDeinit(device);
//SDL_CameraThreadFinalize(device); //SDL_CameraThreadFinalize(device);
} }

View File

@ -238,11 +238,11 @@ JNIEXPORT void JNICALL SDL_JAVA_AUDIO_INTERFACE(nativeSetupJNI)(
JNIEnv *env, jclass jcls); JNIEnv *env, jclass jcls);
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
SDL_JAVA_AUDIO_INTERFACE(addAudioDevice)(JNIEnv *env, jclass jcls, jboolean is_capture, jstring name, SDL_JAVA_AUDIO_INTERFACE(addAudioDevice)(JNIEnv *env, jclass jcls, jboolean recording, jstring name,
jint device_id); jint device_id);
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
SDL_JAVA_AUDIO_INTERFACE(removeAudioDevice)(JNIEnv *env, jclass jcls, jboolean is_capture, SDL_JAVA_AUDIO_INTERFACE(removeAudioDevice)(JNIEnv *env, jclass jcls, jboolean recording,
jint device_id); jint device_id);
static JNINativeMethod SDLAudioManager_tab[] = { static JNINativeMethod SDLAudioManager_tab[] = {
@ -364,11 +364,11 @@ static jmethodID midAudioWriteByteBuffer;
static jmethodID midAudioWriteShortBuffer; static jmethodID midAudioWriteShortBuffer;
static jmethodID midAudioWriteFloatBuffer; static jmethodID midAudioWriteFloatBuffer;
static jmethodID midAudioClose; static jmethodID midAudioClose;
static jmethodID midCaptureOpen; static jmethodID midRecordingOpen;
static jmethodID midCaptureReadByteBuffer; static jmethodID midRecordingReadByteBuffer;
static jmethodID midCaptureReadShortBuffer; static jmethodID midRecordingReadShortBuffer;
static jmethodID midCaptureReadFloatBuffer; static jmethodID midRecordingReadFloatBuffer;
static jmethodID midCaptureClose; static jmethodID midRecordingClose;
static jmethodID midAudioSetThreadPriority; static jmethodID midAudioSetThreadPriority;
/* controller manager */ /* controller manager */
@ -709,15 +709,15 @@ JNIEXPORT void JNICALL SDL_JAVA_AUDIO_INTERFACE(nativeSetupJNI)(JNIEnv *env, jcl
"audioWriteFloatBuffer", "([F)V"); "audioWriteFloatBuffer", "([F)V");
midAudioClose = (*env)->GetStaticMethodID(env, mAudioManagerClass, midAudioClose = (*env)->GetStaticMethodID(env, mAudioManagerClass,
"audioClose", "()V"); "audioClose", "()V");
midCaptureOpen = (*env)->GetStaticMethodID(env, mAudioManagerClass, midRecordingOpen = (*env)->GetStaticMethodID(env, mAudioManagerClass,
"captureOpen", "(IIIII)[I"); "captureOpen", "(IIIII)[I");
midCaptureReadByteBuffer = (*env)->GetStaticMethodID(env, mAudioManagerClass, midRecordingReadByteBuffer = (*env)->GetStaticMethodID(env, mAudioManagerClass,
"captureReadByteBuffer", "([BZ)I"); "captureReadByteBuffer", "([BZ)I");
midCaptureReadShortBuffer = (*env)->GetStaticMethodID(env, mAudioManagerClass, midRecordingReadShortBuffer = (*env)->GetStaticMethodID(env, mAudioManagerClass,
"captureReadShortBuffer", "([SZ)I"); "captureReadShortBuffer", "([SZ)I");
midCaptureReadFloatBuffer = (*env)->GetStaticMethodID(env, mAudioManagerClass, midRecordingReadFloatBuffer = (*env)->GetStaticMethodID(env, mAudioManagerClass,
"captureReadFloatBuffer", "([FZ)I"); "captureReadFloatBuffer", "([FZ)I");
midCaptureClose = (*env)->GetStaticMethodID(env, mAudioManagerClass, midRecordingClose = (*env)->GetStaticMethodID(env, mAudioManagerClass,
"captureClose", "()V"); "captureClose", "()V");
midAudioSetThreadPriority = (*env)->GetStaticMethodID(env, mAudioManagerClass, midAudioSetThreadPriority = (*env)->GetStaticMethodID(env, mAudioManagerClass,
"audioSetThreadPriority", "(ZI)V"); "audioSetThreadPriority", "(ZI)V");
@ -725,8 +725,8 @@ JNIEXPORT void JNICALL SDL_JAVA_AUDIO_INTERFACE(nativeSetupJNI)(JNIEnv *env, jcl
if (!midRegisterAudioDeviceCallback || !midUnregisterAudioDeviceCallback || !midAudioOpen || if (!midRegisterAudioDeviceCallback || !midUnregisterAudioDeviceCallback || !midAudioOpen ||
!midAudioWriteByteBuffer || !midAudioWriteShortBuffer || !midAudioWriteFloatBuffer || !midAudioWriteByteBuffer || !midAudioWriteShortBuffer || !midAudioWriteFloatBuffer ||
!midAudioClose || !midAudioClose ||
!midCaptureOpen || !midCaptureReadByteBuffer || !midCaptureReadShortBuffer || !midRecordingOpen || !midRecordingReadByteBuffer || !midRecordingReadShortBuffer ||
!midCaptureReadFloatBuffer || !midCaptureClose || !midAudioSetThreadPriority) { !midRecordingReadFloatBuffer || !midRecordingClose || !midAudioSetThreadPriority) {
__android_log_print(ANDROID_LOG_WARN, "SDL", __android_log_print(ANDROID_LOG_WARN, "SDL",
"Missing some Java callbacks, do you have the latest version of SDLAudioManager.java?"); "Missing some Java callbacks, do you have the latest version of SDLAudioManager.java?");
} }
@ -1009,7 +1009,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeAddTouch)(
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
SDL_JAVA_AUDIO_INTERFACE(addAudioDevice)(JNIEnv *env, jclass jcls, jboolean is_capture, SDL_JAVA_AUDIO_INTERFACE(addAudioDevice)(JNIEnv *env, jclass jcls, jboolean recording,
jstring name, jint device_id) jstring name, jint device_id)
{ {
#if ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES #if ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES
@ -1017,7 +1017,7 @@ SDL_JAVA_AUDIO_INTERFACE(addAudioDevice)(JNIEnv *env, jclass jcls, jboolean is_c
void *handle = (void *)((size_t)device_id); void *handle = (void *)((size_t)device_id);
if (!SDL_FindPhysicalAudioDeviceByHandle(handle)) { if (!SDL_FindPhysicalAudioDeviceByHandle(handle)) {
const char *utf8name = (*env)->GetStringUTFChars(env, name, NULL); const char *utf8name = (*env)->GetStringUTFChars(env, name, NULL);
SDL_AddAudioDevice(is_capture, SDL_strdup(utf8name), NULL, handle); SDL_AddAudioDevice(recording, SDL_strdup(utf8name), NULL, handle);
(*env)->ReleaseStringUTFChars(env, name, utf8name); (*env)->ReleaseStringUTFChars(env, name, utf8name);
} }
} }
@ -1025,12 +1025,12 @@ SDL_JAVA_AUDIO_INTERFACE(addAudioDevice)(JNIEnv *env, jclass jcls, jboolean is_c
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
SDL_JAVA_AUDIO_INTERFACE(removeAudioDevice)(JNIEnv *env, jclass jcls, jboolean is_capture, SDL_JAVA_AUDIO_INTERFACE(removeAudioDevice)(JNIEnv *env, jclass jcls, jboolean recording,
jint device_id) jint device_id)
{ {
#if ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES #if ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES
if (SDL_GetCurrentAudioDriver() != NULL) { if (SDL_GetCurrentAudioDriver() != NULL) {
SDL_Log("Removing device with handle %d, capture %d", device_id, is_capture); SDL_Log("Removing device with handle %d, recording %d", device_id, recording);
SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandle((void *)((size_t)device_id))); SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandle((void *)((size_t)device_id)));
} }
#endif #endif
@ -1595,15 +1595,15 @@ SDL_bool Android_JNI_GetAccelerometerValues(float values[3])
static int audioBufferFormat = 0; static int audioBufferFormat = 0;
static jobject audioBuffer = NULL; static jobject audioBuffer = NULL;
static void *audioBufferPinned = NULL; static void *audioBufferPinned = NULL;
static int captureBufferFormat = 0; static int recordingBufferFormat = 0;
static jobject captureBuffer = NULL; static jobject recordingBuffer = NULL;
void Android_StartAudioHotplug(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) void Android_StartAudioHotplug(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{ {
JNIEnv *env = Android_JNI_GetEnv(); JNIEnv *env = Android_JNI_GetEnv();
// this will fire the callback for each existing device right away (which will eventually SDL_AddAudioDevice), and again later when things change. // this will fire the callback for each existing device right away (which will eventually SDL_AddAudioDevice), and again later when things change.
(*env)->CallStaticVoidMethod(env, mAudioManagerClass, midRegisterAudioDeviceCallback); (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midRegisterAudioDeviceCallback);
*default_output = *default_capture = NULL; // !!! FIXME: how do you decide the default device id? *default_playback = *default_recording = NULL; // !!! FIXME: how do you decide the default device id?
} }
void Android_StopAudioHotplug(void) void Android_StopAudioHotplug(void)
@ -1614,7 +1614,7 @@ void Android_StopAudioHotplug(void)
int Android_JNI_OpenAudioDevice(SDL_AudioDevice *device) int Android_JNI_OpenAudioDevice(SDL_AudioDevice *device)
{ {
const SDL_bool iscapture = device->iscapture; const SDL_bool recording = device->recording;
SDL_AudioSpec *spec = &device->spec; SDL_AudioSpec *spec = &device->spec;
const int device_id = (int) ((size_t) device->handle); const int device_id = (int) ((size_t) device->handle);
int audioformat; int audioformat;
@ -1639,11 +1639,11 @@ int Android_JNI_OpenAudioDevice(SDL_AudioDevice *device)
return SDL_SetError("Unsupported audio format: 0x%x", spec->format); return SDL_SetError("Unsupported audio format: 0x%x", spec->format);
} }
if (iscapture) { if (recording) {
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device for capture"); __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device for recording");
result = (*env)->CallStaticObjectMethod(env, mAudioManagerClass, midCaptureOpen, spec->freq, audioformat, spec->channels, device->sample_frames, device_id); result = (*env)->CallStaticObjectMethod(env, mAudioManagerClass, midRecordingOpen, spec->freq, audioformat, spec->channels, device->sample_frames, device_id);
} else { } else {
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device for output"); __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device for playback");
result = (*env)->CallStaticObjectMethod(env, mAudioManagerClass, midAudioOpen, spec->freq, audioformat, spec->channels, device->sample_frames, device_id); result = (*env)->CallStaticObjectMethod(env, mAudioManagerClass, midAudioOpen, spec->freq, audioformat, spec->channels, device->sample_frames, device_id);
} }
if (!result) { if (!result) {
@ -1712,15 +1712,15 @@ int Android_JNI_OpenAudioDevice(SDL_AudioDevice *device)
return SDL_OutOfMemory(); return SDL_OutOfMemory();
} }
if (iscapture) { if (recording) {
captureBufferFormat = audioformat; recordingBufferFormat = audioformat;
captureBuffer = jbufobj; recordingBuffer = jbufobj;
} else { } else {
audioBufferFormat = audioformat; audioBufferFormat = audioformat;
audioBuffer = jbufobj; audioBuffer = jbufobj;
} }
if (!iscapture) { if (!recording) {
isCopy = JNI_FALSE; isCopy = JNI_FALSE;
switch (audioformat) { switch (audioformat) {
@ -1780,103 +1780,103 @@ void Android_JNI_WriteAudioBuffer(void)
/* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */ /* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */
} }
int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen) int Android_JNI_RecordAudioBuffer(void *buffer, int buflen)
{ {
JNIEnv *env = Android_JNI_GetEnv(); JNIEnv *env = Android_JNI_GetEnv();
jboolean isCopy = JNI_FALSE; jboolean isCopy = JNI_FALSE;
jint br = -1; jint br = -1;
switch (captureBufferFormat) { switch (recordingBufferFormat) {
case ENCODING_PCM_8BIT: case ENCODING_PCM_8BIT:
SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == buflen); SDL_assert((*env)->GetArrayLength(env, (jshortArray)recordingBuffer) == buflen);
br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_TRUE); br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midRecordingReadByteBuffer, (jbyteArray)recordingBuffer, JNI_TRUE);
if (br > 0) { if (br > 0) {
jbyte *ptr = (*env)->GetByteArrayElements(env, (jbyteArray)captureBuffer, &isCopy); jbyte *ptr = (*env)->GetByteArrayElements(env, (jbyteArray)recordingBuffer, &isCopy);
SDL_memcpy(buffer, ptr, br); SDL_memcpy(buffer, ptr, br);
(*env)->ReleaseByteArrayElements(env, (jbyteArray)captureBuffer, ptr, JNI_ABORT); (*env)->ReleaseByteArrayElements(env, (jbyteArray)recordingBuffer, ptr, JNI_ABORT);
} }
break; break;
case ENCODING_PCM_16BIT: case ENCODING_PCM_16BIT:
SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == (buflen / sizeof(Sint16))); SDL_assert((*env)->GetArrayLength(env, (jshortArray)recordingBuffer) == (buflen / sizeof(Sint16)));
br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_TRUE); br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midRecordingReadShortBuffer, (jshortArray)recordingBuffer, JNI_TRUE);
if (br > 0) { if (br > 0) {
jshort *ptr = (*env)->GetShortArrayElements(env, (jshortArray)captureBuffer, &isCopy); jshort *ptr = (*env)->GetShortArrayElements(env, (jshortArray)recordingBuffer, &isCopy);
br *= sizeof(Sint16); br *= sizeof(Sint16);
SDL_memcpy(buffer, ptr, br); SDL_memcpy(buffer, ptr, br);
(*env)->ReleaseShortArrayElements(env, (jshortArray)captureBuffer, ptr, JNI_ABORT); (*env)->ReleaseShortArrayElements(env, (jshortArray)recordingBuffer, ptr, JNI_ABORT);
} }
break; break;
case ENCODING_PCM_FLOAT: case ENCODING_PCM_FLOAT:
SDL_assert((*env)->GetArrayLength(env, (jfloatArray)captureBuffer) == (buflen / sizeof(float))); SDL_assert((*env)->GetArrayLength(env, (jfloatArray)recordingBuffer) == (buflen / sizeof(float)));
br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadFloatBuffer, (jfloatArray)captureBuffer, JNI_TRUE); br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midRecordingReadFloatBuffer, (jfloatArray)recordingBuffer, JNI_TRUE);
if (br > 0) { if (br > 0) {
jfloat *ptr = (*env)->GetFloatArrayElements(env, (jfloatArray)captureBuffer, &isCopy); jfloat *ptr = (*env)->GetFloatArrayElements(env, (jfloatArray)recordingBuffer, &isCopy);
br *= sizeof(float); br *= sizeof(float);
SDL_memcpy(buffer, ptr, br); SDL_memcpy(buffer, ptr, br);
(*env)->ReleaseFloatArrayElements(env, (jfloatArray)captureBuffer, ptr, JNI_ABORT); (*env)->ReleaseFloatArrayElements(env, (jfloatArray)recordingBuffer, ptr, JNI_ABORT);
} }
break; break;
default: default:
__android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: unhandled capture buffer format"); __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: unhandled recording buffer format");
break; break;
} }
return br; return br;
} }
void Android_JNI_FlushCapturedAudio(void) void Android_JNI_FlushRecordedAudio(void)
{ {
JNIEnv *env = Android_JNI_GetEnv(); JNIEnv *env = Android_JNI_GetEnv();
#if 0 /* !!! FIXME: this needs API 23, or it'll do blocking reads and never end. */ #if 0 /* !!! FIXME: this needs API 23, or it'll do blocking reads and never end. */
switch (captureBufferFormat) { switch (recordingBufferFormat) {
case ENCODING_PCM_8BIT: case ENCODING_PCM_8BIT:
{ {
const jint len = (*env)->GetArrayLength(env, (jbyteArray)captureBuffer); const jint len = (*env)->GetArrayLength(env, (jbyteArray)recordingBuffer);
while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE) == len) { /* spin */ } while ((*env)->CallStaticIntMethod(env, mActivityClass, midRecordingReadByteBuffer, (jbyteArray)recordingBuffer, JNI_FALSE) == len) { /* spin */ }
} }
break; break;
case ENCODING_PCM_16BIT: case ENCODING_PCM_16BIT:
{ {
const jint len = (*env)->GetArrayLength(env, (jshortArray)captureBuffer); const jint len = (*env)->GetArrayLength(env, (jshortArray)recordingBuffer);
while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE) == len) { /* spin */ } while ((*env)->CallStaticIntMethod(env, mActivityClass, midRecordingReadShortBuffer, (jshortArray)recordingBuffer, JNI_FALSE) == len) { /* spin */ }
} }
break; break;
case ENCODING_PCM_FLOAT: case ENCODING_PCM_FLOAT:
{ {
const jint len = (*env)->GetArrayLength(env, (jfloatArray)captureBuffer); const jint len = (*env)->GetArrayLength(env, (jfloatArray)recordingBuffer);
while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadFloatBuffer, (jfloatArray)captureBuffer, JNI_FALSE) == len) { /* spin */ } while ((*env)->CallStaticIntMethod(env, mActivityClass, midRecordingReadFloatBuffer, (jfloatArray)recordingBuffer, JNI_FALSE) == len) { /* spin */ }
} }
break; break;
default: default:
__android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: flushing unhandled capture buffer format"); __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: flushing unhandled recording buffer format");
break; break;
} }
#else #else
switch (captureBufferFormat) { switch (recordingBufferFormat) {
case ENCODING_PCM_8BIT: case ENCODING_PCM_8BIT:
(*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE); (*env)->CallStaticIntMethod(env, mAudioManagerClass, midRecordingReadByteBuffer, (jbyteArray)recordingBuffer, JNI_FALSE);
break; break;
case ENCODING_PCM_16BIT: case ENCODING_PCM_16BIT:
(*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE); (*env)->CallStaticIntMethod(env, mAudioManagerClass, midRecordingReadShortBuffer, (jshortArray)recordingBuffer, JNI_FALSE);
break; break;
case ENCODING_PCM_FLOAT: case ENCODING_PCM_FLOAT:
(*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadFloatBuffer, (jfloatArray)captureBuffer, JNI_FALSE); (*env)->CallStaticIntMethod(env, mAudioManagerClass, midRecordingReadFloatBuffer, (jfloatArray)recordingBuffer, JNI_FALSE);
break; break;
default: default:
__android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: flushing unhandled capture buffer format"); __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: flushing unhandled recording buffer format");
break; break;
} }
#endif #endif
} }
void Android_JNI_CloseAudioDevice(const int iscapture) void Android_JNI_CloseAudioDevice(const int recording)
{ {
JNIEnv *env = Android_JNI_GetEnv(); JNIEnv *env = Android_JNI_GetEnv();
if (iscapture) { if (recording) {
(*env)->CallStaticVoidMethod(env, mAudioManagerClass, midCaptureClose); (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midRecordingClose);
if (captureBuffer) { if (recordingBuffer) {
(*env)->DeleteGlobalRef(env, captureBuffer); (*env)->DeleteGlobalRef(env, recordingBuffer);
captureBuffer = NULL; recordingBuffer = NULL;
} }
} else { } else {
(*env)->CallStaticVoidMethod(env, mAudioManagerClass, midAudioClose); (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midAudioClose);
@ -1888,15 +1888,15 @@ void Android_JNI_CloseAudioDevice(const int iscapture)
} }
} }
static void Android_JNI_AudioSetThreadPriority(int iscapture, int device_id) static void Android_JNI_AudioSetThreadPriority(int recording, int device_id)
{ {
JNIEnv *env = Android_JNI_GetEnv(); JNIEnv *env = Android_JNI_GetEnv();
(*env)->CallStaticVoidMethod(env, mAudioManagerClass, midAudioSetThreadPriority, iscapture, device_id); (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midAudioSetThreadPriority, recording, device_id);
} }
void Android_AudioThreadInit(SDL_AudioDevice *device) void Android_AudioThreadInit(SDL_AudioDevice *device)
{ {
Android_JNI_AudioSetThreadPriority((int) device->iscapture, (int)device->instance_id); Android_JNI_AudioSetThreadPriority((int) device->recording, (int)device->instance_id);
} }
/* Test for an exception and call SDL_SetError with its detail if one occurs */ /* Test for an exception and call SDL_SetError with its detail if one occurs */

View File

@ -52,15 +52,15 @@ extern SDL_DisplayOrientation Android_JNI_GetDisplayNaturalOrientation(void);
extern SDL_DisplayOrientation Android_JNI_GetDisplayCurrentOrientation(void); extern SDL_DisplayOrientation Android_JNI_GetDisplayCurrentOrientation(void);
/* Audio support */ /* Audio support */
void Android_StartAudioHotplug(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture); void Android_StartAudioHotplug(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording);
void Android_StopAudioHotplug(void); void Android_StopAudioHotplug(void);
extern void Android_AudioThreadInit(SDL_AudioDevice *device); extern void Android_AudioThreadInit(SDL_AudioDevice *device);
extern int Android_JNI_OpenAudioDevice(SDL_AudioDevice *device); extern int Android_JNI_OpenAudioDevice(SDL_AudioDevice *device);
extern void *Android_JNI_GetAudioBuffer(void); extern void *Android_JNI_GetAudioBuffer(void);
extern void Android_JNI_WriteAudioBuffer(void); extern void Android_JNI_WriteAudioBuffer(void);
extern int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen); extern int Android_JNI_RecordAudioBuffer(void *buffer, int buflen);
extern void Android_JNI_FlushCapturedAudio(void); extern void Android_JNI_FlushRecordedAudio(void);
extern void Android_JNI_CloseAudioDevice(const int iscapture); extern void Android_JNI_CloseAudioDevice(const int recording);
/* Detecting device type */ /* Detecting device type */
extern SDL_bool Android_IsDeXMode(void); extern SDL_bool Android_IsDeXMode(void);

View File

@ -120,7 +120,7 @@ void SDL_IMMDevice_FreeDeviceHandle(SDL_AudioDevice *device)
} }
} }
static SDL_AudioDevice *SDL_IMMDevice_Add(const SDL_bool iscapture, const char *devname, WAVEFORMATEXTENSIBLE *fmt, LPCWSTR devid, GUID *dsoundguid) static SDL_AudioDevice *SDL_IMMDevice_Add(const SDL_bool recording, const char *devname, WAVEFORMATEXTENSIBLE *fmt, LPCWSTR devid, GUID *dsoundguid)
{ {
/* You can have multiple endpoints on a device that are mutually exclusive ("Speakers" vs "Line Out" or whatever). /* You can have multiple endpoints on a device that are mutually exclusive ("Speakers" vs "Line Out" or whatever).
In a perfect world, things that are unplugged won't be in this collection. The only gotcha is probably for In a perfect world, things that are unplugged won't be in this collection. The only gotcha is probably for
@ -164,7 +164,7 @@ static SDL_AudioDevice *SDL_IMMDevice_Add(const SDL_bool iscapture, const char *
spec.freq = fmt->Format.nSamplesPerSec; spec.freq = fmt->Format.nSamplesPerSec;
spec.format = SDL_WaveFormatExToSDLFormat((WAVEFORMATEX *)fmt); spec.format = SDL_WaveFormatExToSDLFormat((WAVEFORMATEX *)fmt);
device = SDL_AddAudioDevice(iscapture, devname, &spec, handle); device = SDL_AddAudioDevice(recording, devname, &spec, handle);
if (!device) { if (!device) {
SDL_free(handle->immdevice_id); SDL_free(handle->immdevice_id);
SDL_free(handle); SDL_free(handle);
@ -248,14 +248,14 @@ static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_OnDeviceStateChanged(IM
if (SUCCEEDED(IMMDevice_QueryInterface(device, &SDL_IID_IMMEndpoint, (void **)&endpoint))) { if (SUCCEEDED(IMMDevice_QueryInterface(device, &SDL_IID_IMMEndpoint, (void **)&endpoint))) {
EDataFlow flow; EDataFlow flow;
if (SUCCEEDED(IMMEndpoint_GetDataFlow(endpoint, &flow))) { if (SUCCEEDED(IMMEndpoint_GetDataFlow(endpoint, &flow))) {
const SDL_bool iscapture = (flow == eCapture); const SDL_bool recording = (flow == eCapture);
if (dwNewState == DEVICE_STATE_ACTIVE) { if (dwNewState == DEVICE_STATE_ACTIVE) {
char *utf8dev; char *utf8dev;
WAVEFORMATEXTENSIBLE fmt; WAVEFORMATEXTENSIBLE fmt;
GUID dsoundguid; GUID dsoundguid;
GetMMDeviceInfo(device, &utf8dev, &fmt, &dsoundguid); GetMMDeviceInfo(device, &utf8dev, &fmt, &dsoundguid);
if (utf8dev) { if (utf8dev) {
SDL_IMMDevice_Add(iscapture, utf8dev, &fmt, pwstrDeviceId, &dsoundguid); SDL_IMMDevice_Add(recording, utf8dev, &fmt, pwstrDeviceId, &dsoundguid);
SDL_free(utf8dev); SDL_free(utf8dev);
} }
} else { } else {
@ -336,7 +336,7 @@ void SDL_IMMDevice_Quit(void)
WIN_CoUninitialize(); WIN_CoUninitialize();
} }
int SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, SDL_bool iscapture) int SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, SDL_bool recording)
{ {
const Uint64 timeout = SDL_GetTicks() + 8000; /* intel's audio drivers can fail for up to EIGHT SECONDS after a device is connected or we wake from sleep. */ const Uint64 timeout = SDL_GetTicks() + 8000; /* intel's audio drivers can fail for up to EIGHT SECONDS after a device is connected or we wake from sleep. */
@ -361,13 +361,13 @@ int SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, SDL_bool i
} }
static void EnumerateEndpointsForFlow(const SDL_bool iscapture, SDL_AudioDevice **default_device) static void EnumerateEndpointsForFlow(const SDL_bool recording, SDL_AudioDevice **default_device)
{ {
/* Note that WASAPI separates "adapter devices" from "audio endpoint devices" /* Note that WASAPI separates "adapter devices" from "audio endpoint devices"
...one adapter device ("SoundBlaster Pro") might have multiple endpoint devices ("Speakers", "Line-Out"). */ ...one adapter device ("SoundBlaster Pro") might have multiple endpoint devices ("Speakers", "Line-Out"). */
IMMDeviceCollection *collection = NULL; IMMDeviceCollection *collection = NULL;
if (FAILED(IMMDeviceEnumerator_EnumAudioEndpoints(enumerator, iscapture ? eCapture : eRender, DEVICE_STATE_ACTIVE, &collection))) { if (FAILED(IMMDeviceEnumerator_EnumAudioEndpoints(enumerator, recording ? eCapture : eRender, DEVICE_STATE_ACTIVE, &collection))) {
return; return;
} }
@ -380,7 +380,7 @@ static void EnumerateEndpointsForFlow(const SDL_bool iscapture, SDL_AudioDevice
LPWSTR default_devid = NULL; LPWSTR default_devid = NULL;
if (default_device) { if (default_device) {
IMMDevice *default_immdevice = NULL; IMMDevice *default_immdevice = NULL;
const EDataFlow dataflow = iscapture ? eCapture : eRender; const EDataFlow dataflow = recording ? eCapture : eRender;
if (SUCCEEDED(IMMDeviceEnumerator_GetDefaultAudioEndpoint(enumerator, dataflow, SDL_IMMDevice_role, &default_immdevice))) { if (SUCCEEDED(IMMDeviceEnumerator_GetDefaultAudioEndpoint(enumerator, dataflow, SDL_IMMDevice_role, &default_immdevice))) {
LPWSTR devid = NULL; LPWSTR devid = NULL;
if (SUCCEEDED(IMMDevice_GetId(default_immdevice, &devid))) { if (SUCCEEDED(IMMDevice_GetId(default_immdevice, &devid))) {
@ -403,7 +403,7 @@ static void EnumerateEndpointsForFlow(const SDL_bool iscapture, SDL_AudioDevice
SDL_zero(dsoundguid); SDL_zero(dsoundguid);
GetMMDeviceInfo(immdevice, &devname, &fmt, &dsoundguid); GetMMDeviceInfo(immdevice, &devname, &fmt, &dsoundguid);
if (devname) { if (devname) {
SDL_AudioDevice *sdldevice = SDL_IMMDevice_Add(iscapture, devname, &fmt, devid, &dsoundguid); SDL_AudioDevice *sdldevice = SDL_IMMDevice_Add(recording, devname, &fmt, devid, &dsoundguid);
if (default_device && default_devid && SDL_wcscmp(default_devid, devid) == 0) { if (default_device && default_devid && SDL_wcscmp(default_devid, devid) == 0) {
*default_device = sdldevice; *default_device = sdldevice;
} }
@ -420,10 +420,10 @@ static void EnumerateEndpointsForFlow(const SDL_bool iscapture, SDL_AudioDevice
IMMDeviceCollection_Release(collection); IMMDeviceCollection_Release(collection);
} }
void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{ {
EnumerateEndpointsForFlow(SDL_FALSE, default_output); /* playback */ EnumerateEndpointsForFlow(SDL_FALSE, default_playback);
EnumerateEndpointsForFlow(SDL_TRUE, default_capture); /* capture */ EnumerateEndpointsForFlow(SDL_TRUE, default_recording);
/* if this fails, we just won't get hotplug events. Carry on anyhow. */ /* if this fails, we just won't get hotplug events. Carry on anyhow. */
IMMDeviceEnumerator_RegisterEndpointNotificationCallback(enumerator, (IMMNotificationClient *)&notification_client); IMMDeviceEnumerator_RegisterEndpointNotificationCallback(enumerator, (IMMNotificationClient *)&notification_client);

View File

@ -36,8 +36,8 @@ typedef struct SDL_IMMDevice_callbacks
int SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks); int SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks);
void SDL_IMMDevice_Quit(void); void SDL_IMMDevice_Quit(void);
int SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, SDL_bool iscapture); int SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, SDL_bool recording);
void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture); void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording);
LPGUID SDL_IMMDevice_GetDirectSoundGUID(SDL_AudioDevice *device); LPGUID SDL_IMMDevice_GetDirectSoundGUID(SDL_AudioDevice *device);
LPCWSTR SDL_IMMDevice_GetDevID(SDL_AudioDevice *device); LPCWSTR SDL_IMMDevice_GetDevID(SDL_AudioDevice *device);
void SDL_IMMDevice_FreeDeviceHandle(SDL_AudioDevice *device); void SDL_IMMDevice_FreeDeviceHandle(SDL_AudioDevice *device);

View File

@ -166,11 +166,11 @@ SDL3_0.0.0 {
SDL_GetAndroidSDKVersion; SDL_GetAndroidSDKVersion;
SDL_GetAssertionHandler; SDL_GetAssertionHandler;
SDL_GetAssertionReport; SDL_GetAssertionReport;
SDL_GetAudioCaptureDevices;
SDL_GetAudioDeviceFormat; SDL_GetAudioDeviceFormat;
SDL_GetAudioDeviceName; SDL_GetAudioDeviceName;
SDL_GetAudioDriver; SDL_GetAudioDriver;
SDL_GetAudioOutputDevices; SDL_GetAudioPlaybackDevices;
SDL_GetAudioRecordingDevices;
SDL_GetAudioStreamAvailable; SDL_GetAudioStreamAvailable;
SDL_GetAudioStreamData; SDL_GetAudioStreamData;
SDL_GetAudioStreamDevice; SDL_GetAudioStreamDevice;

View File

@ -191,11 +191,11 @@
#define SDL_GetAndroidSDKVersion SDL_GetAndroidSDKVersion_REAL #define SDL_GetAndroidSDKVersion SDL_GetAndroidSDKVersion_REAL
#define SDL_GetAssertionHandler SDL_GetAssertionHandler_REAL #define SDL_GetAssertionHandler SDL_GetAssertionHandler_REAL
#define SDL_GetAssertionReport SDL_GetAssertionReport_REAL #define SDL_GetAssertionReport SDL_GetAssertionReport_REAL
#define SDL_GetAudioCaptureDevices SDL_GetAudioCaptureDevices_REAL
#define SDL_GetAudioDeviceFormat SDL_GetAudioDeviceFormat_REAL #define SDL_GetAudioDeviceFormat SDL_GetAudioDeviceFormat_REAL
#define SDL_GetAudioDeviceName SDL_GetAudioDeviceName_REAL #define SDL_GetAudioDeviceName SDL_GetAudioDeviceName_REAL
#define SDL_GetAudioDriver SDL_GetAudioDriver_REAL #define SDL_GetAudioDriver SDL_GetAudioDriver_REAL
#define SDL_GetAudioOutputDevices SDL_GetAudioOutputDevices_REAL #define SDL_GetAudioPlaybackDevices SDL_GetAudioPlaybackDevices_REAL
#define SDL_GetAudioRecordingDevices SDL_GetAudioRecordingDevices_REAL
#define SDL_GetAudioStreamAvailable SDL_GetAudioStreamAvailable_REAL #define SDL_GetAudioStreamAvailable SDL_GetAudioStreamAvailable_REAL
#define SDL_GetAudioStreamData SDL_GetAudioStreamData_REAL #define SDL_GetAudioStreamData SDL_GetAudioStreamData_REAL
#define SDL_GetAudioStreamDevice SDL_GetAudioStreamDevice_REAL #define SDL_GetAudioStreamDevice SDL_GetAudioStreamDevice_REAL

View File

@ -211,11 +211,11 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_GamepadSensorEnabled,(SDL_Gamepad *a, SDL_SensorTyp
SDL_DYNAPI_PROC(int,SDL_GetAndroidSDKVersion,(void),(),return) SDL_DYNAPI_PROC(int,SDL_GetAndroidSDKVersion,(void),(),return)
SDL_DYNAPI_PROC(SDL_AssertionHandler,SDL_GetAssertionHandler,(void **a),(a),return) SDL_DYNAPI_PROC(SDL_AssertionHandler,SDL_GetAssertionHandler,(void **a),(a),return)
SDL_DYNAPI_PROC(const SDL_AssertData*,SDL_GetAssertionReport,(void),(),return) SDL_DYNAPI_PROC(const SDL_AssertData*,SDL_GetAssertionReport,(void),(),return)
SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioCaptureDevices,(int *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_GetAudioDeviceFormat,(SDL_AudioDeviceID a, SDL_AudioSpec *b, int *c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_GetAudioDeviceFormat,(SDL_AudioDeviceID a, SDL_AudioSpec *b, int *c),(a,b,c),return)
SDL_DYNAPI_PROC(const char*,SDL_GetAudioDeviceName,(SDL_AudioDeviceID a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetAudioDeviceName,(SDL_AudioDeviceID a),(a),return)
SDL_DYNAPI_PROC(const char*,SDL_GetAudioDriver,(int a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetAudioDriver,(int a),(a),return)
SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioOutputDevices,(int *a),(a),return) SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioPlaybackDevices,(int *a),(a),return)
SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioRecordingDevices,(int *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_GetAudioStreamAvailable,(SDL_AudioStream *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetAudioStreamAvailable,(SDL_AudioStream *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_GetAudioStreamData,(SDL_AudioStream *a, void *b, int c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_GetAudioStreamData,(SDL_AudioStream *a, void *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(SDL_AudioDeviceID,SDL_GetAudioStreamDevice,(SDL_AudioStream *a),(a),return) SDL_DYNAPI_PROC(SDL_AudioDeviceID,SDL_GetAudioStreamDevice,(SDL_AudioStream *a),(a),return)

View File

@ -581,7 +581,7 @@ static void SDL_LogEvent(const SDL_Event *event)
break; break;
#undef PRINT_DROP_EVENT #undef PRINT_DROP_EVENT
#define PRINT_AUDIODEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u iscapture=%s)", (uint)event->adevice.timestamp, (uint)event->adevice.which, event->adevice.iscapture ? "true" : "false") #define PRINT_AUDIODEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u recording=%s)", (uint)event->adevice.timestamp, (uint)event->adevice.which, event->adevice.recording ? "true" : "false")
SDL_EVENT_CASE(SDL_EVENT_AUDIO_DEVICE_ADDED) SDL_EVENT_CASE(SDL_EVENT_AUDIO_DEVICE_ADDED)
PRINT_AUDIODEV_EVENT(event); PRINT_AUDIODEV_EVENT(event);
break; break;

View File

@ -1466,7 +1466,7 @@ SDL_bool SDLTest_CommonInit(SDLTest_CommonState *state)
} }
const SDL_AudioSpec spec = { state->audio_format, state->audio_channels, state->audio_freq }; const SDL_AudioSpec spec = { state->audio_format, state->audio_channels, state->audio_freq };
state->audio_id = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec); state->audio_id = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec);
if (!state->audio_id) { if (!state->audio_id) {
SDL_Log("Couldn't open audio: %s\n", SDL_GetError()); SDL_Log("Couldn't open audio: %s\n", SDL_GetError());
return SDL_FALSE; return SDL_FALSE;

View File

@ -266,7 +266,7 @@ file(GLOB TESTAUTOMATION_SOURCE_FILES testautomation*.c)
add_sdl_test_executable(testautomation NONINTERACTIVE NONINTERACTIVE_TIMEOUT 120 NEEDS_RESOURCES NO_C90 SOURCES ${TESTAUTOMATION_SOURCE_FILES}) add_sdl_test_executable(testautomation NONINTERACTIVE NONINTERACTIVE_TIMEOUT 120 NEEDS_RESOURCES NO_C90 SOURCES ${TESTAUTOMATION_SOURCE_FILES})
add_sdl_test_executable(testmultiaudio NEEDS_RESOURCES TESTUTILS SOURCES testmultiaudio.c) add_sdl_test_executable(testmultiaudio NEEDS_RESOURCES TESTUTILS SOURCES testmultiaudio.c)
add_sdl_test_executable(testaudiohotplug NEEDS_RESOURCES TESTUTILS SOURCES testaudiohotplug.c) add_sdl_test_executable(testaudiohotplug NEEDS_RESOURCES TESTUTILS SOURCES testaudiohotplug.c)
add_sdl_test_executable(testaudiocapture MAIN_CALLBACKS SOURCES testaudiocapture.c) add_sdl_test_executable(testaudiorecording MAIN_CALLBACKS SOURCES testaudiorecording.c)
add_sdl_test_executable(testatomic NONINTERACTIVE SOURCES testatomic.c) add_sdl_test_executable(testatomic NONINTERACTIVE SOURCES testatomic.c)
add_sdl_test_executable(testintersections SOURCES testintersections.c) add_sdl_test_executable(testintersections SOURCES testintersections.c)
add_sdl_test_executable(testrelative SOURCES testrelative.c) add_sdl_test_executable(testrelative SOURCES testrelative.c)

View File

@ -109,7 +109,7 @@ int SDL_AppInit(void **appstate, int argc, char *argv[])
SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver()); SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &wave.spec, NULL, NULL); stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &wave.spec, NULL, NULL);
if (!stream) { if (!stream) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create audio stream: %s\n", SDL_GetError()); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create audio stream: %s\n", SDL_GetError());
return SDL_APP_FAILURE; return SDL_APP_FAILURE;

View File

@ -1,3 +1,15 @@
/*
Copyright (C) 1997-2024 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
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely.
*/
#define SDL_MAIN_USE_CALLBACKS 1 #define SDL_MAIN_USE_CALLBACKS 1
#include <SDL3/SDL_test.h> #include <SDL3/SDL_test.h>
#include <SDL3/SDL_test_common.h> #include <SDL3/SDL_test_common.h>
@ -19,9 +31,9 @@ typedef enum ThingType
{ {
THING_NULL, THING_NULL,
THING_PHYSDEV, THING_PHYSDEV,
THING_PHYSDEV_CAPTURE, THING_PHYSDEV_RECORDING,
THING_LOGDEV, THING_LOGDEV,
THING_LOGDEV_CAPTURE, THING_LOGDEV_RECORDING,
THING_TRASHCAN, THING_TRASHCAN,
THING_STREAM, THING_STREAM,
THING_POOF, THING_POOF,
@ -38,13 +50,13 @@ struct Thing
union { union {
struct { struct {
SDL_AudioDeviceID devid; SDL_AudioDeviceID devid;
SDL_bool iscapture; SDL_bool recording;
SDL_AudioSpec spec; SDL_AudioSpec spec;
char *name; char *name;
} physdev; } physdev;
struct { struct {
SDL_AudioDeviceID devid; SDL_AudioDeviceID devid;
SDL_bool iscapture; SDL_bool recording;
SDL_AudioSpec spec; SDL_AudioSpec spec;
Thing *physdev; Thing *physdev;
SDL_bool visualizer_enabled; SDL_bool visualizer_enabled;
@ -268,7 +280,7 @@ static void DestroyThing(Thing *thing)
case THING_TRASHCAN: break; case THING_TRASHCAN: break;
case THING_LOGDEV: case THING_LOGDEV:
case THING_LOGDEV_CAPTURE: case THING_LOGDEV_RECORDING:
SDL_CloseAudioDevice(thing->data.logdev.devid); SDL_CloseAudioDevice(thing->data.logdev.devid);
if (state->renderers[0] != NULL) { if (state->renderers[0] != NULL) {
SDL_DestroyTexture(thing->data.logdev.visualizer); SDL_DestroyTexture(thing->data.logdev.visualizer);
@ -278,7 +290,7 @@ static void DestroyThing(Thing *thing)
break; break;
case THING_PHYSDEV: case THING_PHYSDEV:
case THING_PHYSDEV_CAPTURE: case THING_PHYSDEV_RECORDING:
SDL_free(thing->data.physdev.name); SDL_free(thing->data.physdev.name);
break; break;
@ -537,7 +549,7 @@ static void StreamThing_ondrag(Thing *thing, int button, float x, float y)
if (button == SDL_BUTTON_RIGHT) { /* this is kinda hacky, but use this to disconnect from a playing source. */ if (button == SDL_BUTTON_RIGHT) { /* this is kinda hacky, but use this to disconnect from a playing source. */
if (thing->line_connected_to) { if (thing->line_connected_to) {
SDL_UnbindAudioStream(thing->data.stream.stream); /* unbind from current device */ SDL_UnbindAudioStream(thing->data.stream.stream); /* unbind from current device */
if (thing->line_connected_to->what == THING_LOGDEV_CAPTURE) { if (thing->line_connected_to->what == THING_LOGDEV_RECORDING) {
SDL_FlushAudioStream(thing->data.stream.stream); SDL_FlushAudioStream(thing->data.stream.stream);
} }
thing->line_connected_to = NULL; thing->line_connected_to = NULL;
@ -550,19 +562,19 @@ static void StreamThing_ondrop(Thing *thing, int button, float x, float y)
if (droppable_highlighted_thing) { if (droppable_highlighted_thing) {
if (droppable_highlighted_thing->what == THING_TRASHCAN) { if (droppable_highlighted_thing->what == THING_TRASHCAN) {
TrashThing(thing); TrashThing(thing);
} else if (((droppable_highlighted_thing->what == THING_LOGDEV) || (droppable_highlighted_thing->what == THING_LOGDEV_CAPTURE)) && (droppable_highlighted_thing != thing->line_connected_to)) { } else if (((droppable_highlighted_thing->what == THING_LOGDEV) || (droppable_highlighted_thing->what == THING_LOGDEV_RECORDING)) && (droppable_highlighted_thing != thing->line_connected_to)) {
/* connect to a logical device! */ /* connect to a logical device! */
SDL_Log("Binding audio stream ('%s') to logical device %u", thing->titlebar, (unsigned int) droppable_highlighted_thing->data.logdev.devid); SDL_Log("Binding audio stream ('%s') to logical device %u", thing->titlebar, (unsigned int) droppable_highlighted_thing->data.logdev.devid);
if (thing->line_connected_to) { if (thing->line_connected_to) {
SDL_UnbindAudioStream(thing->data.stream.stream); /* unbind from current device */ SDL_UnbindAudioStream(thing->data.stream.stream); /* unbind from current device */
if (thing->line_connected_to->what == THING_LOGDEV_CAPTURE) { if (thing->line_connected_to->what == THING_LOGDEV_RECORDING) {
SDL_FlushAudioStream(thing->data.stream.stream); SDL_FlushAudioStream(thing->data.stream.stream);
} }
} }
SDL_BindAudioStream(droppable_highlighted_thing->data.logdev.devid, thing->data.stream.stream); /* bind to new device! */ SDL_BindAudioStream(droppable_highlighted_thing->data.logdev.devid, thing->data.stream.stream); /* bind to new device! */
thing->data.stream.total_bytes = SDL_GetAudioStreamAvailable(thing->data.stream.stream); thing->data.stream.total_bytes = SDL_GetAudioStreamAvailable(thing->data.stream.stream);
thing->progress = 0.0f; /* ontick will adjust this if we're on an output device.*/ thing->progress = 0.0f; /* ontick will adjust this if we're on a playback device.*/
thing->data.stream.next_level_update = SDL_GetTicks() + 100; thing->data.stream.next_level_update = SDL_GetTicks() + 100;
thing->line_connected_to = droppable_highlighted_thing; thing->line_connected_to = droppable_highlighted_thing;
} }
@ -592,7 +604,7 @@ static void StreamThing_ondraw(Thing *thing, SDL_Renderer *renderer)
static Thing *CreateStreamThing(const SDL_AudioSpec *spec, const Uint8 *buf, const Uint32 buflen, const char *fname, const float x, const float y) static Thing *CreateStreamThing(const SDL_AudioSpec *spec, const Uint8 *buf, const Uint32 buflen, const char *fname, const float x, const float y)
{ {
static const ThingType can_be_dropped_onto[] = { THING_TRASHCAN, THING_LOGDEV, THING_LOGDEV_CAPTURE, THING_NULL }; static const ThingType can_be_dropped_onto[] = { THING_TRASHCAN, THING_LOGDEV, THING_LOGDEV_RECORDING, THING_NULL };
Thing *thing = CreateThing(THING_STREAM, x, y, 0, -1, -1, soundboard_texture, fname); Thing *thing = CreateThing(THING_STREAM, x, y, 0, -1, -1, soundboard_texture, fname);
if (thing) { if (thing) {
SDL_Log("Adding audio stream for %s", fname ? fname : "(null)"); SDL_Log("Adding audio stream for %s", fname ? fname : "(null)");
@ -725,7 +737,7 @@ static Thing *CreateLogicalDeviceThing(Thing *parent, const SDL_AudioDeviceID wh
static void DeviceThing_ondrag(Thing *thing, int button, float x, float y) static void DeviceThing_ondrag(Thing *thing, int button, float x, float y)
{ {
if ((button == SDL_BUTTON_MIDDLE) && (thing->what == THING_LOGDEV_CAPTURE)) { /* drag out a new stream. This is a UX mess. :/ */ if ((button == SDL_BUTTON_MIDDLE) && (thing->what == THING_LOGDEV_RECORDING)) { /* drag out a new stream. This is a UX mess. :/ */
dragging_thing = CreateStreamThing(&thing->data.logdev.spec, NULL, 0, NULL, x, y); dragging_thing = CreateStreamThing(&thing->data.logdev.spec, NULL, 0, NULL, x, y);
if (dragging_thing) { if (dragging_thing) {
dragging_thing->data.stream.next_level_update = SDL_GetTicks() + 100; dragging_thing->data.stream.next_level_update = SDL_GetTicks() + 100;
@ -733,7 +745,7 @@ static void DeviceThing_ondrag(Thing *thing, int button, float x, float y)
dragging_thing->line_connected_to = thing; dragging_thing->line_connected_to = thing;
} }
} else if (button == SDL_BUTTON_RIGHT) { /* drag out a new logical device. */ } else if (button == SDL_BUTTON_RIGHT) { /* drag out a new logical device. */
const SDL_AudioDeviceID which = ((thing->what == THING_LOGDEV) || (thing->what == THING_LOGDEV_CAPTURE)) ? thing->data.logdev.devid : thing->data.physdev.devid; const SDL_AudioDeviceID which = ((thing->what == THING_LOGDEV) || (thing->what == THING_LOGDEV_RECORDING)) ? thing->data.logdev.devid : thing->data.physdev.devid;
const SDL_AudioDeviceID devid = SDL_OpenAudioDevice(which, NULL); const SDL_AudioDeviceID devid = SDL_OpenAudioDevice(which, NULL);
dragging_thing = devid ? CreateLogicalDeviceThing(thing, devid, x - (thing->rect.w / 2), y - (thing->rect.h / 2)) : NULL; dragging_thing = devid ? CreateLogicalDeviceThing(thing, devid, x - (thing->rect.w / 2), y - (thing->rect.h / 2)) : NULL;
} }
@ -745,7 +757,7 @@ static void SetLogicalDeviceTitlebar(Thing *thing)
int frames = 0; int frames = 0;
SDL_GetAudioDeviceFormat(thing->data.logdev.devid, spec, &frames); SDL_GetAudioDeviceFormat(thing->data.logdev.devid, spec, &frames);
SDL_free(thing->titlebar); SDL_free(thing->titlebar);
SDL_asprintf(&thing->titlebar, "Logical device #%u (%s, %s, %s, %uHz, %d frames)", (unsigned int) thing->data.logdev.devid, thing->data.logdev.iscapture ? "CAPTURE" : "OUTPUT", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames); SDL_asprintf(&thing->titlebar, "Logical device #%u (%s, %s, %s, %uHz, %d frames)", (unsigned int) thing->data.logdev.devid, thing->data.logdev.recording ? "RECORDING" : "PLAYBACK", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames);
} }
static void LogicalDeviceThing_ondrop(Thing *thing, int button, float x, float y) static void LogicalDeviceThing_ondrop(Thing *thing, int button, float x, float y)
@ -889,15 +901,15 @@ static void LogicalDeviceThing_ondraw(Thing *thing, SDL_Renderer *renderer)
static Thing *CreateLogicalDeviceThing(Thing *parent, const SDL_AudioDeviceID which, const float x, const float y) static Thing *CreateLogicalDeviceThing(Thing *parent, const SDL_AudioDeviceID which, const float x, const float y)
{ {
static const ThingType can_be_dropped_onto[] = { THING_TRASHCAN, THING_NULL }; static const ThingType can_be_dropped_onto[] = { THING_TRASHCAN, THING_NULL };
Thing *physthing = ((parent->what == THING_LOGDEV) || (parent->what == THING_LOGDEV_CAPTURE)) ? parent->data.logdev.physdev : parent; Thing *physthing = ((parent->what == THING_LOGDEV) || (parent->what == THING_LOGDEV_RECORDING)) ? parent->data.logdev.physdev : parent;
const SDL_bool iscapture = physthing->data.physdev.iscapture; const SDL_bool recording = physthing->data.physdev.recording;
Thing *thing; Thing *thing;
SDL_Log("Adding logical audio device %u", (unsigned int) which); SDL_Log("Adding logical audio device %u", (unsigned int) which);
thing = CreateThing(iscapture ? THING_LOGDEV_CAPTURE : THING_LOGDEV, x, y, 5, -1, -1, logdev_texture, NULL); thing = CreateThing(recording ? THING_LOGDEV_RECORDING : THING_LOGDEV, x, y, 5, -1, -1, logdev_texture, NULL);
if (thing) { if (thing) {
thing->data.logdev.devid = which; thing->data.logdev.devid = which;
thing->data.logdev.iscapture = iscapture; thing->data.logdev.recording = recording;
thing->data.logdev.physdev = physthing; thing->data.logdev.physdev = physthing;
thing->data.logdev.visualizer = SDL_CreateTexture(state->renderers[0], SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, VISUALIZER_WIDTH, VISUALIZER_HEIGHT); thing->data.logdev.visualizer = SDL_CreateTexture(state->renderers[0], SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, VISUALIZER_WIDTH, VISUALIZER_HEIGHT);
thing->data.logdev.postmix_lock = SDL_CreateMutex(); thing->data.logdev.postmix_lock = SDL_CreateMutex();
@ -922,12 +934,12 @@ static void SetPhysicalDeviceTitlebar(Thing *thing)
SDL_AudioSpec *spec = &thing->data.physdev.spec; SDL_AudioSpec *spec = &thing->data.physdev.spec;
SDL_GetAudioDeviceFormat(thing->data.physdev.devid, spec, &frames); SDL_GetAudioDeviceFormat(thing->data.physdev.devid, spec, &frames);
SDL_free(thing->titlebar); SDL_free(thing->titlebar);
if (thing->data.physdev.devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE) { if (thing->data.physdev.devid == SDL_AUDIO_DEVICE_DEFAULT_RECORDING) {
SDL_asprintf(&thing->titlebar, "Default system device (CAPTURE, %s, %s, %uHz, %d frames)", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames); SDL_asprintf(&thing->titlebar, "Default system device (RECORDING, %s, %s, %uHz, %d frames)", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames);
} else if (thing->data.physdev.devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) { } else if (thing->data.physdev.devid == SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK) {
SDL_asprintf(&thing->titlebar, "Default system device (OUTPUT, %s, %s, %uHz, %d frames)", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames); SDL_asprintf(&thing->titlebar, "Default system device (PLAYBACK, %s, %s, %uHz, %d frames)", AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames);
} else { } else {
SDL_asprintf(&thing->titlebar, "Physical device #%u (%s, \"%s\", %s, %s, %uHz, %d frames)", (unsigned int) thing->data.physdev.devid, thing->data.physdev.iscapture ? "CAPTURE" : "OUTPUT", thing->data.physdev.name, AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames); SDL_asprintf(&thing->titlebar, "Physical device #%u (%s, \"%s\", %s, %s, %uHz, %d frames)", (unsigned int) thing->data.physdev.devid, thing->data.physdev.recording ? "RECORDING" : "PLAYBACK", thing->data.physdev.name, AudioFmtToString(spec->format), AudioChansToStr(spec->channels), (unsigned int) spec->freq, frames);
} }
} }
@ -956,7 +968,7 @@ static void PhysicalDeviceThing_ontick(Thing *thing, Uint64 now)
} }
static Thing *CreatePhysicalDeviceThing(const SDL_AudioDeviceID which, const SDL_bool iscapture) static Thing *CreatePhysicalDeviceThing(const SDL_AudioDeviceID which, const SDL_bool recording)
{ {
static const ThingType can_be_dropped_onto[] = { THING_TRASHCAN, THING_NULL }; static const ThingType can_be_dropped_onto[] = { THING_TRASHCAN, THING_NULL };
static float next_physdev_x = 0; static float next_physdev_x = 0;
@ -969,10 +981,10 @@ static Thing *CreatePhysicalDeviceThing(const SDL_AudioDeviceID which, const SDL
} }
SDL_Log("Adding physical audio device %u", (unsigned int) which); SDL_Log("Adding physical audio device %u", (unsigned int) which);
thing = CreateThing(iscapture ? THING_PHYSDEV_CAPTURE : THING_PHYSDEV, next_physdev_x, 170, 5, -1, -1, physdev_texture, NULL); thing = CreateThing(recording ? THING_PHYSDEV_RECORDING : THING_PHYSDEV, next_physdev_x, 170, 5, -1, -1, physdev_texture, NULL);
if (thing) { if (thing) {
thing->data.physdev.devid = which; thing->data.physdev.devid = which;
thing->data.physdev.iscapture = iscapture; thing->data.physdev.recording = recording;
thing->data.physdev.name = SDL_strdup(SDL_GetAudioDeviceName(which)); thing->data.physdev.name = SDL_strdup(SDL_GetAudioDeviceName(which));
thing->ondrag = DeviceThing_ondrag; thing->ondrag = DeviceThing_ondrag;
thing->ondrop = PhysicalDeviceThing_ondrop; thing->ondrop = PhysicalDeviceThing_ondrop;
@ -982,7 +994,7 @@ static Thing *CreatePhysicalDeviceThing(const SDL_AudioDeviceID which, const SDL
SetPhysicalDeviceTitlebar(thing); SetPhysicalDeviceTitlebar(thing);
if (SDL_GetTicks() <= (app_ready_ticks + 2000)) { /* assume this is the initial batch if it happens in the first two seconds. */ if (SDL_GetTicks() <= (app_ready_ticks + 2000)) { /* assume this is the initial batch if it happens in the first two seconds. */
RepositionRowOfThings(THING_PHYSDEV, 10.0f); /* don't rearrange them after the initial add. */ RepositionRowOfThings(THING_PHYSDEV, 10.0f); /* don't rearrange them after the initial add. */
RepositionRowOfThings(THING_PHYSDEV_CAPTURE, 170.0f); /* don't rearrange them after the initial add. */ RepositionRowOfThings(THING_PHYSDEV_RECORDING, 170.0f); /* don't rearrange them after the initial add. */
next_physdev_x = 0.0f; next_physdev_x = 0.0f;
} else { } else {
next_physdev_x += physdev_texture->w * 1.5f; next_physdev_x += physdev_texture->w * 1.5f;
@ -999,9 +1011,9 @@ static Thing *CreateTrashcanThing(void)
return CreateThing(THING_TRASHCAN, winw - trashcan_texture->w, winh - trashcan_texture->h, 10, -1, -1, trashcan_texture, "Drag things here to remove them."); return CreateThing(THING_TRASHCAN, winw - trashcan_texture->w, winh - trashcan_texture->h, 10, -1, -1, trashcan_texture, "Drag things here to remove them.");
} }
static Thing *CreateDefaultPhysicalDevice(const SDL_bool iscapture) static Thing *CreateDefaultPhysicalDevice(const SDL_bool recording)
{ {
return CreatePhysicalDeviceThing(iscapture ? SDL_AUDIO_DEVICE_DEFAULT_CAPTURE : SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, iscapture); return CreatePhysicalDeviceThing(recording ? SDL_AUDIO_DEVICE_DEFAULT_RECORDING : SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, recording);
} }
static void TickThings(void) static void TickThings(void)
@ -1188,7 +1200,7 @@ int SDL_AppEvent(void *appstate, const SDL_Event *event)
break; break;
case SDL_EVENT_AUDIO_DEVICE_ADDED: case SDL_EVENT_AUDIO_DEVICE_ADDED:
CreatePhysicalDeviceThing(event->adevice.which, event->adevice.iscapture); CreatePhysicalDeviceThing(event->adevice.which, event->adevice.recording);
break; break;
case SDL_EVENT_AUDIO_DEVICE_REMOVED: { case SDL_EVENT_AUDIO_DEVICE_REMOVED: {
@ -1197,10 +1209,10 @@ int SDL_AppEvent(void *appstate, const SDL_Event *event)
SDL_Log("Removing audio device %u", (unsigned int) which); SDL_Log("Removing audio device %u", (unsigned int) which);
for (i = things; i; i = next) { for (i = things; i; i = next) {
next = i->next; next = i->next;
if (((i->what == THING_PHYSDEV) || (i->what == THING_PHYSDEV_CAPTURE)) && (i->data.physdev.devid == which)) { if (((i->what == THING_PHYSDEV) || (i->what == THING_PHYSDEV_RECORDING)) && (i->data.physdev.devid == which)) {
TrashThing(i); TrashThing(i);
next = things; /* in case we mangled the list. */ next = things; /* in case we mangled the list. */
} else if (((i->what == THING_LOGDEV) || (i->what == THING_LOGDEV_CAPTURE)) && (i->data.logdev.devid == which)) { } else if (((i->what == THING_LOGDEV) || (i->what == THING_LOGDEV_RECORDING)) && (i->data.logdev.devid == which)) {
TrashThing(i); TrashThing(i);
next = things; /* in case we mangled the list. */ next = things; /* in case we mangled the list. */
} }

View File

@ -52,9 +52,9 @@ static void poked(int sig)
done = 1; done = 1;
} }
static const char *devtypestr(int iscapture) static const char *devtypestr(int recording)
{ {
return iscapture ? "capture" : "output"; return recording ? "capture" : "output";
} }
static void iteration(void) static void iteration(void)
@ -70,16 +70,16 @@ static void iteration(void)
} }
} else if (e.type == SDL_EVENT_AUDIO_DEVICE_ADDED) { } else if (e.type == SDL_EVENT_AUDIO_DEVICE_ADDED) {
const SDL_AudioDeviceID which = (SDL_AudioDeviceID) e.adevice.which; const SDL_AudioDeviceID which = (SDL_AudioDeviceID) e.adevice.which;
const SDL_bool iscapture = e.adevice.iscapture ? SDL_TRUE : SDL_FALSE; const SDL_bool recording = e.adevice.recording ? SDL_TRUE : SDL_FALSE;
const char *name = SDL_GetAudioDeviceName(which); const char *name = SDL_GetAudioDeviceName(which);
if (name) { if (name) {
SDL_Log("New %s audio device at id %u: %s", devtypestr(iscapture), (unsigned int)which, name); SDL_Log("New %s audio device at id %u: %s", devtypestr(recording), (unsigned int)which, name);
} else { } else {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Got new %s device, id %u, but failed to get the name: %s", SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Got new %s device, id %u, but failed to get the name: %s",
devtypestr(iscapture), (unsigned int)which, SDL_GetError()); devtypestr(recording), (unsigned int)which, SDL_GetError());
continue; continue;
} }
if (!iscapture) { if (!recording) {
SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(which, &spec, NULL, NULL); SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(which, &spec, NULL, NULL);
if (!stream) { if (!stream) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create/bind an audio stream to %u ('%s'): %s", (unsigned int) which, name, SDL_GetError()); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create/bind an audio stream to %u ('%s'): %s", (unsigned int) which, name, SDL_GetError());
@ -94,7 +94,7 @@ static void iteration(void)
} }
} else if (e.type == SDL_EVENT_AUDIO_DEVICE_REMOVED) { } else if (e.type == SDL_EVENT_AUDIO_DEVICE_REMOVED) {
dev = (SDL_AudioDeviceID)e.adevice.which; dev = (SDL_AudioDeviceID)e.adevice.which;
SDL_Log("%s device %u removed.\n", devtypestr(e.adevice.iscapture), (unsigned int)dev); SDL_Log("%s device %u removed.\n", devtypestr(e.adevice.recording), (unsigned int)dev);
/* !!! FIXME: we need to keep track of our streams and destroy them here. */ /* !!! FIXME: we need to keep track of our streams and destroy them here. */
} }
} }

View File

@ -14,13 +14,13 @@
#include <SDL3/SDL_test.h> #include <SDL3/SDL_test.h>
static void static void
print_devices(SDL_bool iscapture) print_devices(SDL_bool recording)
{ {
SDL_AudioSpec spec; SDL_AudioSpec spec;
const char *typestr = ((iscapture) ? "capture" : "output"); const char *typestr = (recording ? "recording" : "playback");
int n = 0; int n = 0;
int frames; int frames;
SDL_AudioDeviceID *devices = iscapture ? SDL_GetAudioCaptureDevices(&n) : SDL_GetAudioOutputDevices(&n); SDL_AudioDeviceID *devices = recording ? SDL_GetAudioRecordingDevices(&n) : SDL_GetAudioPlaybackDevices(&n);
if (!devices) { if (!devices) {
SDL_Log(" Driver failed to report %s devices: %s\n\n", typestr, SDL_GetError()); SDL_Log(" Driver failed to report %s devices: %s\n\n", typestr, SDL_GetError());
@ -94,20 +94,20 @@ int main(int argc, char **argv)
print_devices(SDL_FALSE); print_devices(SDL_FALSE);
print_devices(SDL_TRUE); print_devices(SDL_TRUE);
if (SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, &frames) < 0) { if (SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, &frames) < 0) {
SDL_Log("Error when calling SDL_GetAudioDeviceFormat(default output): %s\n", SDL_GetError()); SDL_Log("Error when calling SDL_GetAudioDeviceFormat(default playback): %s\n", SDL_GetError());
} else { } else {
SDL_Log("Default Output Device:\n"); SDL_Log("Default Playback Device:\n");
SDL_Log("Sample Rate: %d\n", spec.freq); SDL_Log("Sample Rate: %d\n", spec.freq);
SDL_Log("Channels: %d\n", spec.channels); SDL_Log("Channels: %d\n", spec.channels);
SDL_Log("SDL_AudioFormat: %X\n", spec.format); SDL_Log("SDL_AudioFormat: %X\n", spec.format);
SDL_Log("Buffer Size: %d frames\n", frames); SDL_Log("Buffer Size: %d frames\n", frames);
} }
if (SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_CAPTURE, &spec, &frames) < 0) { if (SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_RECORDING, &spec, &frames) < 0) {
SDL_Log("Error when calling SDL_GetAudioDeviceFormat(default capture): %s\n", SDL_GetError()); SDL_Log("Error when calling SDL_GetAudioDeviceFormat(default recording): %s\n", SDL_GetError());
} else { } else {
SDL_Log("Default Capture Device:\n"); SDL_Log("Default Recording Device:\n");
SDL_Log("Sample Rate: %d\n", spec.freq); SDL_Log("Sample Rate: %d\n", spec.freq);
SDL_Log("Channels: %d\n", spec.channels); SDL_Log("Channels: %d\n", spec.channels);
SDL_Log("SDL_AudioFormat: %X\n", spec.format); SDL_Log("SDL_AudioFormat: %X\n", spec.format);

View File

@ -27,7 +27,7 @@ int SDL_AppInit(void **appstate, int argc, char **argv)
SDL_AudioSpec outspec; SDL_AudioSpec outspec;
SDL_AudioSpec inspec; SDL_AudioSpec inspec;
SDL_AudioDeviceID device; SDL_AudioDeviceID device;
SDL_AudioDeviceID want_device = SDL_AUDIO_DEVICE_DEFAULT_CAPTURE; SDL_AudioDeviceID want_device = SDL_AUDIO_DEVICE_DEFAULT_RECORDING;
const char *devname = NULL; const char *devname = NULL;
int i; int i;
@ -69,7 +69,7 @@ int SDL_AppInit(void **appstate, int argc, char **argv)
return SDL_APP_SUCCESS; return SDL_APP_SUCCESS;
} }
if (SDL_CreateWindowAndRenderer("testaudiocapture", 320, 240, 0, &window, &renderer) < 0) { if (SDL_CreateWindowAndRenderer("testaudiorecording", 320, 240, 0, &window, &renderer) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create SDL window and renderer: %s\n", SDL_GetError()); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create SDL window and renderer: %s\n", SDL_GetError());
return SDL_APP_SUCCESS; return SDL_APP_SUCCESS;
} }
@ -79,28 +79,28 @@ int SDL_AppInit(void **appstate, int argc, char **argv)
SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver()); SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
devices = SDL_GetAudioCaptureDevices(NULL); devices = SDL_GetAudioRecordingDevices(NULL);
for (i = 0; devices[i] != 0; i++) { for (i = 0; devices[i] != 0; i++) {
const char *name = SDL_GetAudioDeviceName(devices[i]); const char *name = SDL_GetAudioDeviceName(devices[i]);
SDL_Log(" Capture device #%d: '%s'\n", i, name); SDL_Log(" Recording device #%d: '%s'\n", i, name);
if (devname && (SDL_strcmp(devname, name) == 0)) { if (devname && (SDL_strcmp(devname, name) == 0)) {
want_device = devices[i]; want_device = devices[i];
} }
} }
if (devname && (want_device == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE)) { if (devname && (want_device == SDL_AUDIO_DEVICE_DEFAULT_RECORDING)) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Didn't see a capture device named '%s', using the system default instead.\n", devname); SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Didn't see a recording device named '%s', using the system default instead.\n", devname);
devname = NULL; devname = NULL;
} }
/* DirectSound can fail in some instances if you open the same hardware /* DirectSound can fail in some instances if you open the same hardware
for both capture and output and didn't open the output end first, for both recording and output and didn't open the output end first,
according to the docs, so if you're doing something like this, always according to the docs, so if you're doing something like this, always
open your capture devices second in case you land in those bizarre open your recording devices second in case you land in those bizarre
circumstances. */ circumstances. */
SDL_Log("Opening default playback device...\n"); SDL_Log("Opening default playback device...\n");
device = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, NULL); device = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, NULL);
if (!device) { if (!device) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for playback: %s!\n", SDL_GetError()); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for playback: %s!\n", SDL_GetError());
return SDL_APP_FAILURE; return SDL_APP_FAILURE;
@ -116,24 +116,24 @@ int SDL_AppInit(void **appstate, int argc, char **argv)
return SDL_APP_FAILURE; return SDL_APP_FAILURE;
} }
SDL_Log("Opening capture device %s%s%s...\n", SDL_Log("Opening recording device %s%s%s...\n",
devname ? "'" : "", devname ? "'" : "",
devname ? devname : "[[default]]", devname ? devname : "[[default]]",
devname ? "'" : ""); devname ? "'" : "");
device = SDL_OpenAudioDevice(want_device, NULL); device = SDL_OpenAudioDevice(want_device, NULL);
if (!device) { if (!device) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for capture: %s!\n", SDL_GetError()); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for recording: %s!\n", SDL_GetError());
return SDL_APP_FAILURE; return SDL_APP_FAILURE;
} }
SDL_PauseAudioDevice(device); SDL_PauseAudioDevice(device);
SDL_GetAudioDeviceFormat(device, &inspec, NULL); SDL_GetAudioDeviceFormat(device, &inspec, NULL);
stream_in = SDL_CreateAudioStream(&inspec, &inspec); stream_in = SDL_CreateAudioStream(&inspec, &inspec);
if (!stream_in) { if (!stream_in) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create an audio stream for capture: %s!\n", SDL_GetError()); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create an audio stream for recording: %s!\n", SDL_GetError());
return SDL_APP_FAILURE; return SDL_APP_FAILURE;
} else if (SDL_BindAudioStream(device, stream_in) == -1) { } else if (SDL_BindAudioStream(device, stream_in) == -1) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't bind an audio stream for capture: %s!\n", SDL_GetError()); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't bind an audio stream for recording: %s!\n", SDL_GetError());
return SDL_APP_FAILURE; return SDL_APP_FAILURE;
} }
@ -178,7 +178,7 @@ int SDL_AppIterate(void *appstate)
SDL_RenderClear(renderer); SDL_RenderClear(renderer);
SDL_RenderPresent(renderer); SDL_RenderPresent(renderer);
/* Feed any new data we captured to the output stream. It'll play when we unpause the device. */ /* Feed any new data we recorded to the output stream. It'll play when we unpause the device. */
while (SDL_GetAudioStreamAvailable(stream_in) > 0) { while (SDL_GetAudioStreamAvailable(stream_in) > 0) {
Uint8 buf[1024]; Uint8 buf[1024];
const int br = SDL_GetAudioStreamData(stream_in, buf, sizeof(buf)); const int br = SDL_GetAudioStreamData(stream_in, buf, sizeof(buf));

View File

@ -200,11 +200,11 @@ static int audio_initOpenCloseQuitAudio(void *arg)
/* Call Open (maybe multiple times) */ /* Call Open (maybe multiple times) */
for (k = 0; k <= j; k++) { for (k = 0; k <= j; k++) {
result = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &desired); result = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &desired);
if (k == 0) { if (k == 0) {
g_audio_id = result; g_audio_id = result;
} }
SDLTest_AssertPass("Call to SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, desired_spec_%d), call %d", j, k + 1); SDLTest_AssertPass("Call to SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, desired_spec_%d), call %d", j, k + 1);
SDLTest_AssertCheck(result > 0, "Verify return value; expected: > 0, got: %d", result); SDLTest_AssertCheck(result > 0, "Verify return value; expected: > 0, got: %d", result);
} }
@ -290,9 +290,9 @@ static int audio_pauseUnpauseAudio(void *arg)
} }
/* Call Open */ /* Call Open */
g_audio_id = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &desired); g_audio_id = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &desired);
result = g_audio_id; result = g_audio_id;
SDLTest_AssertPass("Call to SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, desired_spec_%d)", j); SDLTest_AssertPass("Call to SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, desired_spec_%d)", j);
SDLTest_AssertCheck(result > 0, "Verify return value; expected > 0 got: %d", result); SDLTest_AssertCheck(result > 0, "Verify return value; expected > 0 got: %d", result);
#if 0 /* !!! FIXME: maybe update this? */ #if 0 /* !!! FIXME: maybe update this? */
@ -356,7 +356,7 @@ static int audio_pauseUnpauseAudio(void *arg)
} }
/** /**
* Enumerate and name available audio devices (output and capture). * Enumerate and name available audio devices (playback and recording).
* *
* \sa SDL_GetNumAudioDevices * \sa SDL_GetNumAudioDevices
* \sa SDL_GetAudioDeviceName * \sa SDL_GetAudioDeviceName
@ -368,12 +368,12 @@ static int audio_enumerateAndNameAudioDevices(void *arg)
const char *name; const char *name;
SDL_AudioDeviceID *devices = NULL; SDL_AudioDeviceID *devices = NULL;
/* Iterate over types: t=0 output device, t=1 input/capture device */ /* Iterate over types: t=0 playback device, t=1 recording device */
for (t = 0; t < 2; t++) { for (t = 0; t < 2; t++) {
/* Get number of devices. */ /* Get number of devices. */
devices = (t) ? SDL_GetAudioCaptureDevices(&n) : SDL_GetAudioOutputDevices(&n); devices = (t) ? SDL_GetAudioRecordingDevices(&n) : SDL_GetAudioPlaybackDevices(&n);
SDLTest_AssertPass("Call to SDL_GetAudio%sDevices(%i)", (t) ? "Capture" : "Output", t); SDLTest_AssertPass("Call to SDL_GetAudio%sDevices(%i)", (t) ? "Recording" : "Playback", t);
SDLTest_Log("Number of %s devices < 0, reported as %i", (t) ? "capture" : "output", n); SDLTest_Log("Number of %s devices < 0, reported as %i", (t) ? "recording" : "playback", n);
SDLTest_AssertCheck(n >= 0, "Validate result is >= 0, got: %i", n); SDLTest_AssertCheck(n >= 0, "Validate result is >= 0, got: %i", n);
/* List devices. */ /* List devices. */
@ -1369,7 +1369,7 @@ cleanup:
/* Audio test cases */ /* Audio test cases */
static const SDLTest_TestCaseReference audioTest1 = { static const SDLTest_TestCaseReference audioTest1 = {
audio_enumerateAndNameAudioDevices, "audio_enumerateAndNameAudioDevices", "Enumerate and name available audio devices (output and capture)", TEST_ENABLED audio_enumerateAndNameAudioDevices, "audio_enumerateAndNameAudioDevices", "Enumerate and name available audio devices (playback and recording)", TEST_ENABLED
}; };
static const SDLTest_TestCaseReference audioTest2 = { static const SDLTest_TestCaseReference audioTest2 = {

View File

@ -1171,7 +1171,7 @@ static AVCodecContext *OpenAudioStream(AVFormatContext *ic, int stream, const AV
} }
SDL_AudioSpec spec = { SDL_AUDIO_F32, codecpar->ch_layout.nb_channels, codecpar->sample_rate }; SDL_AudioSpec spec = { SDL_AUDIO_F32, codecpar->ch_layout.nb_channels, codecpar->sample_rate };
audio = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, NULL, NULL); audio = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, NULL, NULL);
if (audio) { if (audio) {
SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(audio)); SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(audio));
} else { } else {

View File

@ -180,9 +180,9 @@ int main(int argc, char **argv)
filename = GetResourceFilename(filename, "sample.wav"); filename = GetResourceFilename(filename, "sample.wav");
devices = SDL_GetAudioOutputDevices(&devcount); devices = SDL_GetAudioPlaybackDevices(&devcount);
if (!devices) { if (!devices) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Don't see any specific audio devices!"); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Don't see any specific audio playback devices!");
} else { } else {
/* Load the wave file into memory */ /* Load the wave file into memory */
if (SDL_LoadWAV(filename, &spec, &sound, &soundlen) == -1) { if (SDL_LoadWAV(filename, &spec, &sound, &soundlen) == -1) {

View File

@ -178,9 +178,9 @@ int main(int argc, char *argv[])
SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver()); SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
devices = SDL_GetAudioOutputDevices(&devcount); devices = SDL_GetAudioPlaybackDevices(&devcount);
if (!devices) { if (!devices) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GetAudioOutputDevices() failed: %s\n", SDL_GetError()); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GetAudioPlaybackDevices() failed: %s\n", SDL_GetError());
devcount = 0; devcount = 0;
} }