Skip to content

Commit

Permalink
android: Reworked audio backends for SDL3 audio API.
Browse files Browse the repository at this point in the history
This involved moving an `#ifdef` out of SDL_audio.c for thread priority,
so the default ThreadInit now does the usual stuff for non-Android platforms,
the Android platforms provide an implementatin of ThreadInit with their
side of the `#ifdef` and other platforms that implement ThreadInit
incorporated the appropriate code...which is why WASAPI is touched in here.

The Android bits compile, but have not been tested, and there was some
reworkings in the Java bits, so this might need some further fixes still.
  • Loading branch information
icculus committed Jul 26, 2023
1 parent 7c01639 commit f32724b
Show file tree
Hide file tree
Showing 10 changed files with 473 additions and 708 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ public class SDLAudioManager {
protected static AudioRecord mAudioRecord;
protected static Context mContext;

private static final int[] NO_DEVICES = {};

private static AudioDeviceCallback mAudioDeviceCallback;

public static void initialize() {
Expand All @@ -36,7 +34,7 @@ public static void initialize() {
@Override
public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
for (AudioDeviceInfo deviceInfo : addedDevices) {
addAudioDevice(deviceInfo.isSink(), deviceInfo.getId());
addAudioDevice(deviceInfo.isSink(), deviceInfo.getProductName().toString(), deviceInfo.getId());
}
}

Expand All @@ -52,13 +50,10 @@ public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {

public static void setContext(Context context) {
mContext = context;
if (context != null) {
registerAudioDeviceCallback();
}
}

public static void release(Context context) {
unregisterAudioDeviceCallback(context);
// no-op atm
}

// Audio
Expand Down Expand Up @@ -311,62 +306,17 @@ private static AudioDeviceInfo getOutputAudioDeviceInfo(int deviceId) {
return null;
}

private static void registerAudioDeviceCallback() {
public static void registerAudioDeviceCallback() {
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
audioManager.registerAudioDeviceCallback(mAudioDeviceCallback, null);
}
}

private static void unregisterAudioDeviceCallback(Context context) {
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.unregisterAudioDeviceCallback(mAudioDeviceCallback);
}
}

private static int[] ArrayListToArray(ArrayList<Integer> integers)
{
int[] ret = new int[integers.size()];
for (int i=0; i < ret.length; i++) {
ret[i] = integers.get(i).intValue();
}
return ret;
}

/**
* This method is called by SDL using JNI.
*/
public static int[] getAudioOutputDevices() {
public static void unregisterAudioDeviceCallback() {
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
ArrayList<Integer> arrlist = new ArrayList<Integer>();
for (AudioDeviceInfo dev : audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)) {
/* Device cannot be opened */
if (dev.getType() == AudioDeviceInfo.TYPE_TELEPHONY) {
continue;
}
arrlist.add(dev.getId());
}
return ArrayListToArray(arrlist);
} else {
return NO_DEVICES;
}
}

/**
* This method is called by SDL using JNI.
*/
public static int[] getAudioInputDevices() {
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
ArrayList<Integer> arrlist = new ArrayList<Integer>();
for (AudioDeviceInfo dev : audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)) {
arrlist.add(dev.getId());
}
return ArrayListToArray(arrlist);
} else {
return NO_DEVICES;
audioManager.unregisterAudioDeviceCallback(mAudioDeviceCallback);
}
}

Expand Down Expand Up @@ -535,6 +485,6 @@ public static void audioSetThreadPriority(boolean iscapture, int device_id) {

public static native void removeAudioDevice(boolean isCapture, int deviceId);

public static native void addAudioDevice(boolean isCapture, int deviceId);
public static native void addAudioDevice(boolean isCapture, String name, int deviceId);

}
26 changes: 5 additions & 21 deletions src/audio/SDL_audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@
#include "../thread/SDL_systhread.h"
#include "../SDL_utils_c.h"

extern void Android_JNI_AudioSetThreadPriority(int, int); // we need this on Android in the audio device threads.

// Available audio drivers
static const AudioBootStrap *const bootstrap[] = {
#ifdef SDL_AUDIO_DRIVER_PULSEAUDIO
Expand Down Expand Up @@ -412,7 +410,6 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device)

// stubs for audio drivers that don't need a specific entry point...

static void SDL_AudioThreadInit_Default(SDL_AudioDevice *device) { /* no-op. */ }
static void SDL_AudioThreadDeinit_Default(SDL_AudioDevice *device) { /* no-op. */ }
static void SDL_AudioWaitDevice_Default(SDL_AudioDevice *device) { /* no-op. */ }
static void SDL_AudioPlayDevice_Default(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) { /* no-op. */ }
Expand All @@ -422,6 +419,11 @@ static void SDL_AudioCloseDevice_Default(SDL_AudioDevice *device) { /* no-op. */
static void SDL_AudioDeinitialize_Default(void) { /* no-op. */ }
static void SDL_AudioFreeDeviceHandle_Default(SDL_AudioDevice *device) { /* no-op. */ }

static void SDL_AudioThreadInit_Default(SDL_AudioDevice *device)
{
SDL_SetThreadPriority(device->iscapture ? SDL_THREAD_PRIORITY_HIGH : SDL_THREAD_PRIORITY_TIME_CRITICAL);
}

static void SDL_AudioDetectDevices_Default(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture)
{
// you have to write your own implementation if these assertions fail.
Expand Down Expand Up @@ -679,15 +681,6 @@ void SDL_AudioThreadFinalize(SDL_AudioDevice *device)
void SDL_OutputAudioThreadSetup(SDL_AudioDevice *device)
{
SDL_assert(!device->iscapture);

// The audio mixing is always a high priority thread
#ifdef SDL_AUDIO_DRIVER_ANDROID
Android_JNI_AudioSetThreadPriority(SDL_FALSE, device->id);
#else
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_TIME_CRITICAL);
#endif

// Perform any thread setup
current_audio.impl.ThreadInit(device);
}

Expand Down Expand Up @@ -781,14 +774,6 @@ static int SDLCALL OutputAudioThread(void *devicep) // thread entry point
void SDL_CaptureAudioThreadSetup(SDL_AudioDevice *device)
{
SDL_assert(device->iscapture);

// Audio capture is always a high priority thread (!!! FIXME: _should_ it be?)
#ifdef SDL_AUDIO_DRIVER_ANDROID
Android_JNI_AudioSetThreadPriority(SDL_TRUE, device->id);
#else
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
#endif

current_audio.impl.ThreadInit(device);
}

Expand Down Expand Up @@ -1068,7 +1053,6 @@ int SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec)

if ((devid == 0) && is_default) {
return SDL_SetError("No default audio device available");
return 0;
}

SDL_AudioDevice *device = ObtainPhysicalAudioDevice(devid);
Expand Down
Loading

0 comments on commit f32724b

Please sign in to comment.