Separated out SDL Android java code so audio, controller, and filesystem APIs can be used independently of the SDL activity, in Qt apps for example.
parent
ad86eff1a8
commit
53b2c91d26
|
@ -56,24 +56,17 @@ public class SDLActivity extends Activity {
|
|||
public static boolean mSeparateMouseAndTouch;
|
||||
|
||||
// Main components
|
||||
protected static Context mContext;
|
||||
protected static SDLActivity mSingleton;
|
||||
protected static SDLSurface mSurface;
|
||||
protected static View mTextEdit;
|
||||
protected static boolean mScreenKeyboardShown;
|
||||
protected static ViewGroup mLayout;
|
||||
protected static SDLJoystickHandler mJoystickHandler;
|
||||
protected static SDLHapticHandler mHapticHandler;
|
||||
protected static SDLClipboardHandler mClipboardHandler;
|
||||
|
||||
|
||||
// This is what SDL runs in. It invokes SDL_main(), eventually
|
||||
protected static Thread mSDLThread;
|
||||
|
||||
// Audio
|
||||
protected static AudioTrack mAudioTrack;
|
||||
protected static AudioRecord mAudioRecord;
|
||||
|
||||
/**
|
||||
* This method returns the name of the shared object with the application entry point
|
||||
* It can be overridden by derived classes.
|
||||
|
@ -136,17 +129,12 @@ public class SDLActivity extends Activity {
|
|||
public static void initialize() {
|
||||
// The static nature of the singleton and Android quirkyness force us to initialize everything here
|
||||
// Otherwise, when exiting the app and returning to it, these variables *keep* their pre exit values
|
||||
mContext = null;
|
||||
mSingleton = null;
|
||||
mSurface = null;
|
||||
mTextEdit = null;
|
||||
mLayout = null;
|
||||
mJoystickHandler = null;
|
||||
mHapticHandler = null;
|
||||
mClipboardHandler = null;
|
||||
mSDLThread = null;
|
||||
mAudioTrack = null;
|
||||
mAudioRecord = null;
|
||||
mExitCalledFromJava = false;
|
||||
mBrokenLibraries = false;
|
||||
mIsResumedCalled = false;
|
||||
|
@ -157,9 +145,6 @@ public class SDLActivity extends Activity {
|
|||
}
|
||||
|
||||
// Setup
|
||||
public static void setContext(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
Log.v(TAG, "Device: " + android.os.Build.DEVICE);
|
||||
|
@ -167,11 +152,6 @@ public class SDLActivity extends Activity {
|
|||
Log.v(TAG, "onCreate()");
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
SDLActivity.initialize();
|
||||
|
||||
// So we can call stuff from static callbacks
|
||||
mContext = mSingleton = this;
|
||||
|
||||
// Load shared libraries
|
||||
String errorMsgBrokenLib = "";
|
||||
try {
|
||||
|
@ -209,16 +189,14 @@ public class SDLActivity extends Activity {
|
|||
}
|
||||
|
||||
// Set up JNI
|
||||
SDLActivity.nativeSetupJNI();
|
||||
SDL.setupJNI();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 16) {
|
||||
mJoystickHandler = new SDLJoystickHandler_API16();
|
||||
} else if (Build.VERSION.SDK_INT >= 12) {
|
||||
mJoystickHandler = new SDLJoystickHandler_API12();
|
||||
} else {
|
||||
mJoystickHandler = new SDLJoystickHandler();
|
||||
}
|
||||
mHapticHandler = new SDLHapticHandler();
|
||||
// Initialize state
|
||||
SDL.initialize();
|
||||
|
||||
// So we can call stuff from static callbacks
|
||||
mSingleton = this;
|
||||
SDL.setContext(this);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
mClipboardHandler = new SDLClipboardHandler_API11();
|
||||
|
@ -461,7 +439,7 @@ public class SDLActivity extends Activity {
|
|||
protected static class SDLCommandHandler extends Handler {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
Context context = getContext();
|
||||
Context context = SDL.getContext();
|
||||
if (context == null) {
|
||||
Log.e(TAG, "error handling message, getContext() returned null");
|
||||
return;
|
||||
|
@ -529,12 +507,6 @@ public class SDLActivity extends Activity {
|
|||
public static native void nativeResume();
|
||||
public static native void onNativeDropFile(String filename);
|
||||
public static native void onNativeResize(int x, int y, int format, float rate);
|
||||
public static native int onNativePadDown(int device_id, int keycode);
|
||||
public static native int onNativePadUp(int device_id, int keycode);
|
||||
public static native void onNativeJoy(int device_id, int axis,
|
||||
float value);
|
||||
public static native void onNativeHat(int device_id, int hat_id,
|
||||
int x, int y);
|
||||
public static native void onNativeKeyDown(int keycode);
|
||||
public static native void onNativeKeyUp(int keycode);
|
||||
public static native void onNativeKeyboardFocusLost();
|
||||
|
@ -546,12 +518,6 @@ public class SDLActivity extends Activity {
|
|||
public static native void onNativeClipboardChanged();
|
||||
public static native void onNativeSurfaceChanged();
|
||||
public static native void onNativeSurfaceDestroyed();
|
||||
public static native int nativeAddJoystick(int device_id, String name, String desc,
|
||||
int is_accelerometer, int nbuttons,
|
||||
int naxes, int nhats, int nballs);
|
||||
public static native int nativeRemoveJoystick(int device_id);
|
||||
public static native int nativeAddHaptic(int device_id, String name);
|
||||
public static native int nativeRemoveHaptic(int device_id);
|
||||
public static native String nativeGetHint(String name);
|
||||
|
||||
/**
|
||||
|
@ -632,7 +598,7 @@ public class SDLActivity extends Activity {
|
|||
return false;
|
||||
}
|
||||
|
||||
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
InputMethodManager imm = (InputMethodManager) SDL.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
if (imm.isAcceptingText()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -654,7 +620,7 @@ public class SDLActivity extends Activity {
|
|||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static Context getContext() {
|
||||
return mContext;
|
||||
return SDL.getContext();
|
||||
}
|
||||
|
||||
static class ShowTextInputTask implements Runnable {
|
||||
|
@ -681,7 +647,7 @@ public class SDLActivity extends Activity {
|
|||
params.topMargin = y;
|
||||
|
||||
if (mTextEdit == null) {
|
||||
mTextEdit = new DummyEdit(getContext());
|
||||
mTextEdit = new DummyEdit(SDL.getContext());
|
||||
|
||||
mLayout.addView(mTextEdit, params);
|
||||
} else {
|
||||
|
@ -691,7 +657,7 @@ public class SDLActivity extends Activity {
|
|||
mTextEdit.setVisibility(View.VISIBLE);
|
||||
mTextEdit.requestFocus();
|
||||
|
||||
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
InputMethodManager imm = (InputMethodManager) SDL.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.showSoftInput(mTextEdit, 0);
|
||||
|
||||
mScreenKeyboardShown = true;
|
||||
|
@ -731,156 +697,6 @@ public class SDLActivity extends Activity {
|
|||
return SDLActivity.mSurface.getNativeSurface();
|
||||
}
|
||||
|
||||
// Audio
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static int audioOpen(int sampleRate, boolean is16Bit, boolean isStereo, int desiredFrames) {
|
||||
int channelConfig = isStereo ? AudioFormat.CHANNEL_CONFIGURATION_STEREO : AudioFormat.CHANNEL_CONFIGURATION_MONO;
|
||||
int audioFormat = is16Bit ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT;
|
||||
int frameSize = (isStereo ? 2 : 1) * (is16Bit ? 2 : 1);
|
||||
|
||||
Log.v(TAG, "SDL audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + (sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer");
|
||||
|
||||
// Let the user pick a larger buffer if they really want -- but ye
|
||||
// gods they probably shouldn't, the minimums are horrifyingly high
|
||||
// latency already
|
||||
desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize);
|
||||
|
||||
if (mAudioTrack == null) {
|
||||
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
|
||||
channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM);
|
||||
|
||||
// Instantiating AudioTrack can "succeed" without an exception and the track may still be invalid
|
||||
// Ref: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/media/java/android/media/AudioTrack.java
|
||||
// Ref: http://developer.android.com/reference/android/media/AudioTrack.html#getState()
|
||||
|
||||
if (mAudioTrack.getState() != AudioTrack.STATE_INITIALIZED) {
|
||||
Log.e(TAG, "Failed during initialization of Audio Track");
|
||||
mAudioTrack = null;
|
||||
return -1;
|
||||
}
|
||||
|
||||
mAudioTrack.play();
|
||||
}
|
||||
|
||||
Log.v(TAG, "SDL audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + (mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static void audioWriteShortBuffer(short[] buffer) {
|
||||
for (int i = 0; i < buffer.length; ) {
|
||||
int result = mAudioTrack.write(buffer, i, buffer.length - i);
|
||||
if (result > 0) {
|
||||
i += result;
|
||||
} else if (result == 0) {
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch(InterruptedException e) {
|
||||
// Nom nom
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "SDL audio: error return from write(short)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static void audioWriteByteBuffer(byte[] buffer) {
|
||||
for (int i = 0; i < buffer.length; ) {
|
||||
int result = mAudioTrack.write(buffer, i, buffer.length - i);
|
||||
if (result > 0) {
|
||||
i += result;
|
||||
} else if (result == 0) {
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch(InterruptedException e) {
|
||||
// Nom nom
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "SDL audio: error return from write(byte)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static int captureOpen(int sampleRate, boolean is16Bit, boolean isStereo, int desiredFrames) {
|
||||
int channelConfig = isStereo ? AudioFormat.CHANNEL_CONFIGURATION_STEREO : AudioFormat.CHANNEL_CONFIGURATION_MONO;
|
||||
int audioFormat = is16Bit ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT;
|
||||
int frameSize = (isStereo ? 2 : 1) * (is16Bit ? 2 : 1);
|
||||
|
||||
Log.v(TAG, "SDL capture: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + (sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer");
|
||||
|
||||
// Let the user pick a larger buffer if they really want -- but ye
|
||||
// gods they probably shouldn't, the minimums are horrifyingly high
|
||||
// latency already
|
||||
desiredFrames = Math.max(desiredFrames, (AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize);
|
||||
|
||||
if (mAudioRecord == null) {
|
||||
mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, sampleRate,
|
||||
channelConfig, audioFormat, desiredFrames * frameSize);
|
||||
|
||||
// see notes about AudioTrack state in audioOpen(), above. Probably also applies here.
|
||||
if (mAudioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
|
||||
Log.e(TAG, "Failed during initialization of AudioRecord");
|
||||
mAudioRecord.release();
|
||||
mAudioRecord = null;
|
||||
return -1;
|
||||
}
|
||||
|
||||
mAudioRecord.startRecording();
|
||||
}
|
||||
|
||||
Log.v(TAG, "SDL capture: got " + ((mAudioRecord.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioRecord.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + (mAudioRecord.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** This method is called by SDL using JNI. */
|
||||
public static int captureReadShortBuffer(short[] buffer, boolean blocking) {
|
||||
// !!! FIXME: this is available in API Level 23. Until then, we always block. :(
|
||||
//return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
|
||||
return mAudioRecord.read(buffer, 0, buffer.length);
|
||||
}
|
||||
|
||||
/** This method is called by SDL using JNI. */
|
||||
public static int captureReadByteBuffer(byte[] buffer, boolean blocking) {
|
||||
// !!! FIXME: this is available in API Level 23. Until then, we always block. :(
|
||||
//return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
|
||||
return mAudioRecord.read(buffer, 0, buffer.length);
|
||||
}
|
||||
|
||||
|
||||
/** This method is called by SDL using JNI. */
|
||||
public static void audioClose() {
|
||||
if (mAudioTrack != null) {
|
||||
mAudioTrack.stop();
|
||||
mAudioTrack.release();
|
||||
mAudioTrack = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** This method is called by SDL using JNI. */
|
||||
public static void captureClose() {
|
||||
if (mAudioRecord != null) {
|
||||
mAudioRecord.stop();
|
||||
mAudioRecord.release();
|
||||
mAudioRecord = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Input
|
||||
|
||||
/**
|
||||
|
@ -900,67 +716,20 @@ public class SDLActivity extends Activity {
|
|||
return Arrays.copyOf(filtered, used);
|
||||
}
|
||||
|
||||
// Joystick glue code, just a series of stubs that redirect to the SDLJoystickHandler instance
|
||||
public static boolean handleJoystickMotionEvent(MotionEvent event) {
|
||||
return mJoystickHandler.handleMotionEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static void pollInputDevices() {
|
||||
if (SDLActivity.mSDLThread != null) {
|
||||
mJoystickHandler.pollInputDevices();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static void pollHapticDevices() {
|
||||
if (SDLActivity.mSDLThread != null) {
|
||||
mHapticHandler.pollHapticDevices();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static void hapticRun(int device_id, int length) {
|
||||
if (SDLActivity.mSDLThread != null) {
|
||||
mHapticHandler.run(device_id, length);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a given device is considered a possible SDL joystick
|
||||
public static boolean isDeviceSDLJoystick(int deviceId) {
|
||||
InputDevice device = InputDevice.getDevice(deviceId);
|
||||
// We cannot use InputDevice.isVirtual before API 16, so let's accept
|
||||
// only nonnegative device ids (VIRTUAL_KEYBOARD equals -1)
|
||||
if ((device == null) || (deviceId < 0)) {
|
||||
return false;
|
||||
}
|
||||
int sources = device.getSources();
|
||||
return (((sources & InputDevice.SOURCE_CLASS_JOYSTICK) == InputDevice.SOURCE_CLASS_JOYSTICK) ||
|
||||
((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) ||
|
||||
((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
|
||||
);
|
||||
}
|
||||
|
||||
// APK expansion files support
|
||||
|
||||
/** com.android.vending.expansion.zipfile.ZipResourceFile object or null. */
|
||||
private Object expansionFile;
|
||||
private static Object expansionFile;
|
||||
|
||||
/** com.android.vending.expansion.zipfile.ZipResourceFile's getInputStream() or null. */
|
||||
private Method expansionFileMethod;
|
||||
private static Method expansionFileMethod;
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
* @return an InputStream on success or null if no expansion file was used.
|
||||
* @throws IOException on errors. Message is set for the SDL error message.
|
||||
*/
|
||||
public InputStream openAPKExpansionInputStream(String fileName) throws IOException {
|
||||
public static InputStream openAPKExpansionInputStream(String fileName) throws IOException {
|
||||
// Get a ZipResourceFile representing a merger of both the main and patch files
|
||||
if (expansionFile == null) {
|
||||
String mainHint = nativeGetHint("SDL_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION");
|
||||
|
@ -987,7 +756,7 @@ public class SDLActivity extends Activity {
|
|||
// not a part of Android SDK we access it using reflection
|
||||
expansionFile = Class.forName("com.android.vending.expansion.zipfile.APKExpansionSupport")
|
||||
.getMethod("getAPKExpansionZipFile", Context.class, int.class, int.class)
|
||||
.invoke(null, this, mainVersion, patchVersion);
|
||||
.invoke(null, SDL.getContext(), mainVersion, patchVersion);
|
||||
|
||||
expansionFileMethod = expansionFile.getClass()
|
||||
.getMethod("getInputStream", String.class);
|
||||
|
@ -1452,14 +1221,14 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
|||
// Furthermore, it's possible a game controller has SOURCE_KEYBOARD and
|
||||
// SOURCE_JOYSTICK, while its key events arrive from the keyboard source
|
||||
// So, retrieve the device itself and check all of its sources
|
||||
if (SDLActivity.isDeviceSDLJoystick(event.getDeviceId())) {
|
||||
if (SDLControllerManager.isDeviceSDLJoystick(event.getDeviceId())) {
|
||||
// Note that we process events with specific key codes here
|
||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||
if (SDLActivity.onNativePadDown(event.getDeviceId(), keyCode) == 0) {
|
||||
if (SDLControllerManager.onNativePadDown(event.getDeviceId(), keyCode) == 0) {
|
||||
return true;
|
||||
}
|
||||
} else if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||
if (SDLActivity.onNativePadUp(event.getDeviceId(), keyCode) == 0) {
|
||||
if (SDLControllerManager.onNativePadUp(event.getDeviceId(), keyCode) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1759,331 +1528,6 @@ class SDLInputConnection extends BaseInputConnection {
|
|||
}
|
||||
}
|
||||
|
||||
/* A null joystick handler for API level < 12 devices (the accelerometer is handled separately) */
|
||||
class SDLJoystickHandler {
|
||||
|
||||
/**
|
||||
* Handles given MotionEvent.
|
||||
* @param event the event to be handled.
|
||||
* @return if given event was processed.
|
||||
*/
|
||||
public boolean handleMotionEvent(MotionEvent event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles adding and removing of input devices.
|
||||
*/
|
||||
public void pollInputDevices() {
|
||||
}
|
||||
}
|
||||
|
||||
/* Actual joystick functionality available for API >= 12 devices */
|
||||
class SDLJoystickHandler_API12 extends SDLJoystickHandler {
|
||||
|
||||
static class SDLJoystick {
|
||||
public int device_id;
|
||||
public String name;
|
||||
public String desc;
|
||||
public ArrayList<InputDevice.MotionRange> axes;
|
||||
public ArrayList<InputDevice.MotionRange> hats;
|
||||
}
|
||||
static class RangeComparator implements Comparator<InputDevice.MotionRange> {
|
||||
@Override
|
||||
public int compare(InputDevice.MotionRange arg0, InputDevice.MotionRange arg1) {
|
||||
return arg0.getAxis() - arg1.getAxis();
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<SDLJoystick> mJoysticks;
|
||||
|
||||
public SDLJoystickHandler_API12() {
|
||||
|
||||
mJoysticks = new ArrayList<SDLJoystick>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pollInputDevices() {
|
||||
int[] deviceIds = InputDevice.getDeviceIds();
|
||||
// It helps processing the device ids in reverse order
|
||||
// For example, in the case of the XBox 360 wireless dongle,
|
||||
// so the first controller seen by SDL matches what the receiver
|
||||
// considers to be the first controller
|
||||
|
||||
for(int i=deviceIds.length-1; i>-1; i--) {
|
||||
SDLJoystick joystick = getJoystick(deviceIds[i]);
|
||||
if (joystick == null) {
|
||||
joystick = new SDLJoystick();
|
||||
InputDevice joystickDevice = InputDevice.getDevice(deviceIds[i]);
|
||||
if (SDLActivity.isDeviceSDLJoystick(deviceIds[i])) {
|
||||
joystick.device_id = deviceIds[i];
|
||||
joystick.name = joystickDevice.getName();
|
||||
joystick.desc = getJoystickDescriptor(joystickDevice);
|
||||
joystick.axes = new ArrayList<InputDevice.MotionRange>();
|
||||
joystick.hats = new ArrayList<InputDevice.MotionRange>();
|
||||
|
||||
List<InputDevice.MotionRange> ranges = joystickDevice.getMotionRanges();
|
||||
Collections.sort(ranges, new RangeComparator());
|
||||
for (InputDevice.MotionRange range : ranges ) {
|
||||
if ((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
|
||||
if (range.getAxis() == MotionEvent.AXIS_HAT_X ||
|
||||
range.getAxis() == MotionEvent.AXIS_HAT_Y) {
|
||||
joystick.hats.add(range);
|
||||
}
|
||||
else {
|
||||
joystick.axes.add(range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mJoysticks.add(joystick);
|
||||
SDLActivity.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc, 0, -1,
|
||||
joystick.axes.size(), joystick.hats.size()/2, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check removed devices */
|
||||
ArrayList<Integer> removedDevices = new ArrayList<Integer>();
|
||||
for(int i=0; i < mJoysticks.size(); i++) {
|
||||
int device_id = mJoysticks.get(i).device_id;
|
||||
int j;
|
||||
for (j=0; j < deviceIds.length; j++) {
|
||||
if (device_id == deviceIds[j]) break;
|
||||
}
|
||||
if (j == deviceIds.length) {
|
||||
removedDevices.add(Integer.valueOf(device_id));
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i < removedDevices.size(); i++) {
|
||||
int device_id = removedDevices.get(i).intValue();
|
||||
SDLActivity.nativeRemoveJoystick(device_id);
|
||||
for (int j=0; j < mJoysticks.size(); j++) {
|
||||
if (mJoysticks.get(j).device_id == device_id) {
|
||||
mJoysticks.remove(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected SDLJoystick getJoystick(int device_id) {
|
||||
for(int i=0; i < mJoysticks.size(); i++) {
|
||||
if (mJoysticks.get(i).device_id == device_id) {
|
||||
return mJoysticks.get(i);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleMotionEvent(MotionEvent event) {
|
||||
if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) != 0) {
|
||||
int actionPointerIndex = event.getActionIndex();
|
||||
int action = event.getActionMasked();
|
||||
switch(action) {
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
SDLJoystick joystick = getJoystick(event.getDeviceId());
|
||||
if ( joystick != null ) {
|
||||
for (int i = 0; i < joystick.axes.size(); i++) {
|
||||
InputDevice.MotionRange range = joystick.axes.get(i);
|
||||
/* Normalize the value to -1...1 */
|
||||
float value = ( event.getAxisValue( range.getAxis(), actionPointerIndex) - range.getMin() ) / range.getRange() * 2.0f - 1.0f;
|
||||
SDLActivity.onNativeJoy(joystick.device_id, i, value );
|
||||
}
|
||||
for (int i = 0; i < joystick.hats.size(); i+=2) {
|
||||
int hatX = Math.round(event.getAxisValue( joystick.hats.get(i).getAxis(), actionPointerIndex ) );
|
||||
int hatY = Math.round(event.getAxisValue( joystick.hats.get(i+1).getAxis(), actionPointerIndex ) );
|
||||
SDLActivity.onNativeHat(joystick.device_id, i/2, hatX, hatY );
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getJoystickDescriptor(InputDevice joystickDevice) {
|
||||
return joystickDevice.getName();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SDLJoystickHandler_API16 extends SDLJoystickHandler_API12 {
|
||||
|
||||
@Override
|
||||
public String getJoystickDescriptor(InputDevice joystickDevice) {
|
||||
String desc = joystickDevice.getDescriptor();
|
||||
|
||||
if (desc != null && desc != "") {
|
||||
return desc;
|
||||
}
|
||||
|
||||
return super.getJoystickDescriptor(joystickDevice);
|
||||
}
|
||||
}
|
||||
|
||||
class SDLGenericMotionListener_API12 implements View.OnGenericMotionListener {
|
||||
// Generic Motion (mouse hover, joystick...) events go here
|
||||
@Override
|
||||
public boolean onGenericMotion(View v, MotionEvent event) {
|
||||
float x, y;
|
||||
int action;
|
||||
|
||||
switch ( event.getSource() ) {
|
||||
case InputDevice.SOURCE_JOYSTICK:
|
||||
case InputDevice.SOURCE_GAMEPAD:
|
||||
case InputDevice.SOURCE_DPAD:
|
||||
return SDLActivity.handleJoystickMotionEvent(event);
|
||||
|
||||
case InputDevice.SOURCE_MOUSE:
|
||||
if (!SDLActivity.mSeparateMouseAndTouch) {
|
||||
break;
|
||||
}
|
||||
action = event.getActionMasked();
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_SCROLL:
|
||||
x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);
|
||||
y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);
|
||||
SDLActivity.onNativeMouse(0, action, x, y);
|
||||
return true;
|
||||
|
||||
case MotionEvent.ACTION_HOVER_MOVE:
|
||||
x = event.getX(0);
|
||||
y = event.getY(0);
|
||||
|
||||
SDLActivity.onNativeMouse(0, action, x, y);
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Event was not managed
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class SDLHapticHandler {
|
||||
|
||||
class SDLHaptic {
|
||||
public int device_id;
|
||||
public String name;
|
||||
public Vibrator vib;
|
||||
}
|
||||
|
||||
private ArrayList<SDLHaptic> mHaptics;
|
||||
|
||||
public SDLHapticHandler() {
|
||||
mHaptics = new ArrayList<SDLHaptic>();
|
||||
}
|
||||
|
||||
public void run(int device_id, int length) {
|
||||
SDLHaptic haptic = getHaptic(device_id);
|
||||
if (haptic != null) {
|
||||
haptic.vib.vibrate (length);
|
||||
}
|
||||
}
|
||||
|
||||
public void pollHapticDevices() {
|
||||
|
||||
final int deviceId_VIBRATOR_SERVICE = 999999;
|
||||
boolean hasVibratorService = false;
|
||||
|
||||
int[] deviceIds = InputDevice.getDeviceIds();
|
||||
// It helps processing the device ids in reverse order
|
||||
// For example, in the case of the XBox 360 wireless dongle,
|
||||
// so the first controller seen by SDL matches what the receiver
|
||||
// considers to be the first controller
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 16)
|
||||
{
|
||||
for (int i = deviceIds.length-1; i > -1; i--) {
|
||||
SDLHaptic haptic = getHaptic(deviceIds[i]);
|
||||
if (haptic == null) {
|
||||
InputDevice device = InputDevice.getDevice(deviceIds[i]);
|
||||
Vibrator vib = device.getVibrator();
|
||||
if (vib.hasVibrator()) {
|
||||
haptic = new SDLHaptic();
|
||||
haptic.device_id = deviceIds[i];
|
||||
haptic.name = device.getName();
|
||||
haptic.vib = vib;
|
||||
mHaptics.add(haptic);
|
||||
SDLActivity.nativeAddHaptic(haptic.device_id, haptic.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check VIBRATOR_SERVICE */
|
||||
Vibrator vib = (Vibrator) SDLActivity.mSingleton.getContext().getSystemService(Context.VIBRATOR_SERVICE);
|
||||
if (vib != null) {
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
hasVibratorService = vib.hasVibrator();
|
||||
} else {
|
||||
hasVibratorService = true;
|
||||
}
|
||||
|
||||
if (hasVibratorService) {
|
||||
SDLHaptic haptic = getHaptic(deviceId_VIBRATOR_SERVICE);
|
||||
if (haptic == null) {
|
||||
haptic = new SDLHaptic();
|
||||
haptic.device_id = deviceId_VIBRATOR_SERVICE;
|
||||
haptic.name = "VIBRATOR_SERVICE";
|
||||
haptic.vib = vib;
|
||||
mHaptics.add(haptic);
|
||||
SDLActivity.nativeAddHaptic(haptic.device_id, haptic.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check removed devices */
|
||||
ArrayList<Integer> removedDevices = new ArrayList<Integer>();
|
||||
for(int i=0; i < mHaptics.size(); i++) {
|
||||
int device_id = mHaptics.get(i).device_id;
|
||||
int j;
|
||||
for (j=0; j < deviceIds.length; j++) {
|
||||
if (device_id == deviceIds[j]) break;
|
||||
}
|
||||
|
||||
if (device_id == deviceId_VIBRATOR_SERVICE && hasVibratorService) {
|
||||
// don't remove the vibrator if it is still present
|
||||
} else if (j == deviceIds.length) {
|
||||
removedDevices.add(device_id);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i < removedDevices.size(); i++) {
|
||||
int device_id = removedDevices.get(i);
|
||||
SDLActivity.nativeRemoveHaptic(device_id);
|
||||
for (int j=0; j < mHaptics.size(); j++) {
|
||||
if (mHaptics.get(j).device_id == device_id) {
|
||||
mHaptics.remove(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected SDLHaptic getHaptic(int device_id) {
|
||||
for(int i=0; i < mHaptics.size(); i++) {
|
||||
if (mHaptics.get(i).device_id == device_id) {
|
||||
return mHaptics.get(i);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface SDLClipboardHandler {
|
||||
|
||||
public boolean clipboardHasText();
|
||||
|
@ -2100,7 +1544,7 @@ class SDLClipboardHandler_API11 implements
|
|||
protected android.content.ClipboardManager mClipMgr;
|
||||
|
||||
SDLClipboardHandler_API11() {
|
||||
mClipMgr = (android.content.ClipboardManager) SDLActivity.mSingleton.getContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
mClipMgr = (android.content.ClipboardManager) SDL.getContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
mClipMgr.addPrimaryClipChangedListener(this);
|
||||
}
|
||||
|
||||
|
@ -2139,7 +1583,7 @@ class SDLClipboardHandler_Old implements
|
|||
protected android.text.ClipboardManager mClipMgrOld;
|
||||
|
||||
SDLClipboardHandler_Old() {
|
||||
mClipMgrOld = (android.text.ClipboardManager) SDLActivity.mSingleton.getContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
mClipMgrOld = (android.text.ClipboardManager) SDL.getContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2164,4 +1608,3 @@ class SDLClipboardHandler_Old implements
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
#define CONCAT1(prefix, class, function) CONCAT2(prefix, class, function)
|
||||
#define CONCAT2(prefix, class, function) Java_ ## prefix ## _ ## class ## _ ## function
|
||||
#define SDL_JAVA_INTERFACE(function) CONCAT1(SDL_JAVA_PREFIX, SDLActivity, function)
|
||||
#define SDL_JAVA_AUDIO_INTERFACE(function) CONCAT1(SDL_JAVA_PREFIX, SDLAudioManager, function)
|
||||
#define SDL_JAVA_CONTROLLER_INTERFACE(function) CONCAT1(SDL_JAVA_PREFIX, SDLControllerManager, function)
|
||||
#define SDL_JAVA_INTERFACE_INPUT_CONNECTION(function) CONCAT1(SDL_JAVA_PREFIX, SDLInputConnection, function)
|
||||
|
||||
|
||||
|
@ -75,39 +77,6 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeResize)(
|
|||
JNIEnv* env, jclass jcls,
|
||||
jint width, jint height, jint format, jfloat rate);
|
||||
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(onNativePadDown)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jint keycode);
|
||||
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(onNativePadUp)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jint keycode);
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeJoy)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jint axis, jfloat value);
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeHat)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jint hat_id, jint x, jint y);
|
||||
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeAddJoystick)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jstring device_name, jstring device_desc, jint is_accelerometer,
|
||||
jint nbuttons, jint naxes, jint nhats, jint nballs);
|
||||
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeRemoveJoystick)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id);
|
||||
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeAddHaptic)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jstring device_name);
|
||||
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeRemoveHaptic)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id);
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(
|
||||
JNIEnv* env, jclass jcls);
|
||||
|
||||
|
@ -166,6 +135,48 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeSetComposingTex
|
|||
JNIEnv* env, jclass cls,
|
||||
jstring text, jint newCursorPosition);
|
||||
|
||||
/* Java class SDLAudioManager */
|
||||
JNIEXPORT void JNICALL SDL_JAVA_AUDIO_INTERFACE(nativeSetupJNI)(
|
||||
JNIEnv *env, jclass jcls);
|
||||
|
||||
/* Java class SDLControllerManager */
|
||||
JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(
|
||||
JNIEnv *env, jclass jcls);
|
||||
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jint keycode);
|
||||
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jint keycode);
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoy)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jint axis, jfloat value);
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jint hat_id, jint x, jint y);
|
||||
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jstring device_name, jstring device_desc, jint is_accelerometer,
|
||||
jint nbuttons, jint naxes, jint nhats, jint nballs);
|
||||
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id);
|
||||
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jstring device_name);
|
||||
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id);
|
||||
|
||||
|
||||
|
||||
/* Uncomment this to log messages entering and exiting methods in this file */
|
||||
/* #define DEBUG_JNI */
|
||||
|
@ -189,17 +200,6 @@ static jclass mActivityClass;
|
|||
|
||||
/* method signatures */
|
||||
static jmethodID midGetNativeSurface;
|
||||
static jmethodID midAudioOpen;
|
||||
static jmethodID midAudioWriteShortBuffer;
|
||||
static jmethodID midAudioWriteByteBuffer;
|
||||
static jmethodID midAudioClose;
|
||||
static jmethodID midCaptureOpen;
|
||||
static jmethodID midCaptureReadShortBuffer;
|
||||
static jmethodID midCaptureReadByteBuffer;
|
||||
static jmethodID midCaptureClose;
|
||||
static jmethodID midPollInputDevices;
|
||||
static jmethodID midPollHapticDevices;
|
||||
static jmethodID midHapticRun;
|
||||
static jmethodID midSetActivityTitle;
|
||||
static jmethodID midSetOrientation;
|
||||
static jmethodID midGetContext;
|
||||
|
@ -210,7 +210,28 @@ static jmethodID midIsScreenKeyboardShown;
|
|||
static jmethodID midClipboardSetText;
|
||||
static jmethodID midClipboardGetText;
|
||||
static jmethodID midClipboardHasText;
|
||||
static jmethodID midOpenAPKExpansionInputStream;
|
||||
|
||||
/* audio manager */
|
||||
static jclass mAudioManagerClass;
|
||||
|
||||
/* method signatures */
|
||||
static jmethodID midAudioOpen;
|
||||
static jmethodID midAudioWriteShortBuffer;
|
||||
static jmethodID midAudioWriteByteBuffer;
|
||||
static jmethodID midAudioClose;
|
||||
static jmethodID midCaptureOpen;
|
||||
static jmethodID midCaptureReadShortBuffer;
|
||||
static jmethodID midCaptureReadByteBuffer;
|
||||
static jmethodID midCaptureClose;
|
||||
|
||||
/* controller manager */
|
||||
static jclass mControllerManagerClass;
|
||||
|
||||
/* method signatures */
|
||||
static jmethodID midPollInputDevices;
|
||||
static jmethodID midPollHapticDevices;
|
||||
static jmethodID midHapticRun;
|
||||
|
||||
/* static fields */
|
||||
static jfieldID fidSeparateMouseAndTouch;
|
||||
|
@ -245,7 +266,17 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
|
|||
return JNI_VERSION_1_4;
|
||||
}
|
||||
|
||||
/* Called before SDL_main() to initialize JNI bindings */
|
||||
void checkJNIReady()
|
||||
{
|
||||
if (!mActivityClass || !mAudioManagerClass || !mControllerManagerClass) {
|
||||
// We aren't fully initialized, let's just return.
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_SetMainReady();
|
||||
}
|
||||
|
||||
/* Activity initialization -- called before SDL_main() to initialize JNI bindings */
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass cls)
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeSetupJNI()");
|
||||
|
@ -256,28 +287,6 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass c
|
|||
|
||||
midGetNativeSurface = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"getNativeSurface","()Landroid/view/Surface;");
|
||||
midAudioOpen = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"audioOpen", "(IZZI)I");
|
||||
midAudioWriteShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"audioWriteShortBuffer", "([S)V");
|
||||
midAudioWriteByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"audioWriteByteBuffer", "([B)V");
|
||||
midAudioClose = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"audioClose", "()V");
|
||||
midCaptureOpen = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"captureOpen", "(IZZI)I");
|
||||
midCaptureReadShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"captureReadShortBuffer", "([SZ)I");
|
||||
midCaptureReadByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"captureReadByteBuffer", "([BZ)I");
|
||||
midCaptureClose = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"captureClose", "()V");
|
||||
midPollInputDevices = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"pollInputDevices", "()V");
|
||||
midPollHapticDevices = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"pollHapticDevices", "()V");
|
||||
midHapticRun = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"hapticRun", "(II)V");
|
||||
midSetActivityTitle = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"setActivityTitle","(Ljava/lang/String;)Z");
|
||||
midSetOrientation = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
|
@ -298,16 +307,14 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass c
|
|||
"clipboardGetText", "()Ljava/lang/String;");
|
||||
midClipboardHasText = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"clipboardHasText", "()Z");
|
||||
|
||||
bHasNewData = SDL_FALSE;
|
||||
midOpenAPKExpansionInputStream = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"openAPKExpansionInputStream", "(Ljava/lang/String;)Ljava/io/InputStream;");
|
||||
|
||||
if (!midGetNativeSurface ||
|
||||
!midAudioOpen || !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioClose ||
|
||||
!midCaptureOpen || !midCaptureReadShortBuffer || !midCaptureReadByteBuffer || !midCaptureClose ||
|
||||
!midPollInputDevices || !midPollHapticDevices || !midHapticRun ||
|
||||
!midSetActivityTitle || !midSetOrientation || !midGetContext || !midInputGetInputDeviceIds ||
|
||||
!midSendMessage || !midShowTextInput || !midIsScreenKeyboardShown ||
|
||||
!midClipboardSetText || !midClipboardGetText || !midClipboardHasText) {
|
||||
!midClipboardSetText || !midClipboardGetText || !midClipboardHasText ||
|
||||
!midOpenAPKExpansionInputStream) {
|
||||
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLActivity.java?");
|
||||
}
|
||||
|
||||
|
@ -317,7 +324,64 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass c
|
|||
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java static fields, do you have the latest version of SDLActivity.java?");
|
||||
}
|
||||
|
||||
SDL_SetMainReady();
|
||||
checkJNIReady();
|
||||
}
|
||||
|
||||
/* Audio initialization -- called before SDL_main() to initialize JNI bindings */
|
||||
JNIEXPORT void JNICALL SDL_JAVA_AUDIO_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass cls)
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "AUDIO nativeSetupJNI()");
|
||||
|
||||
Android_JNI_SetupThread();
|
||||
|
||||
mAudioManagerClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
|
||||
|
||||
midAudioOpen = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
||||
"audioOpen", "(IZZI)I");
|
||||
midAudioWriteShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
||||
"audioWriteShortBuffer", "([S)V");
|
||||
midAudioWriteByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
||||
"audioWriteByteBuffer", "([B)V");
|
||||
midAudioClose = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
||||
"audioClose", "()V");
|
||||
midCaptureOpen = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
||||
"captureOpen", "(IZZI)I");
|
||||
midCaptureReadShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
||||
"captureReadShortBuffer", "([SZ)I");
|
||||
midCaptureReadByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
||||
"captureReadByteBuffer", "([BZ)I");
|
||||
midCaptureClose = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
||||
"captureClose", "()V");
|
||||
|
||||
if (!midAudioOpen || !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioClose ||
|
||||
!midCaptureOpen || !midCaptureReadShortBuffer || !midCaptureReadByteBuffer || !midCaptureClose) {
|
||||
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLAudioManager.java?");
|
||||
}
|
||||
|
||||
checkJNIReady();
|
||||
}
|
||||
|
||||
/* Controller initialization -- called before SDL_main() to initialize JNI bindings */
|
||||
JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass cls)
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "CONTROLLER nativeSetupJNI()");
|
||||
|
||||
Android_JNI_SetupThread();
|
||||
|
||||
mControllerManagerClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
|
||||
|
||||
midPollInputDevices = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
|
||||
"pollInputDevices", "()V");
|
||||
midPollHapticDevices = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
|
||||
"pollHapticDevices", "()V");
|
||||
midHapticRun = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
|
||||
"hapticRun", "(II)V");
|
||||
|
||||
if (!midPollInputDevices || !midPollHapticDevices || !midHapticRun) {
|
||||
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLControllerManager.java?");
|
||||
}
|
||||
|
||||
checkJNIReady();
|
||||
}
|
||||
|
||||
/* SDL main function prototype */
|
||||
|
@ -421,7 +485,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeResize)(
|
|||
}
|
||||
|
||||
/* Paddown */
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(onNativePadDown)(
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jint keycode)
|
||||
{
|
||||
|
@ -429,7 +493,7 @@ JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(onNativePadDown)(
|
|||
}
|
||||
|
||||
/* Padup */
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(onNativePadUp)(
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jint keycode)
|
||||
{
|
||||
|
@ -437,7 +501,7 @@ JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(onNativePadUp)(
|
|||
}
|
||||
|
||||
/* Joy */
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeJoy)(
|
||||
JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoy)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jint axis, jfloat value)
|
||||
{
|
||||
|
@ -445,7 +509,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeJoy)(
|
|||
}
|
||||
|
||||
/* POV Hat */
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeHat)(
|
||||
JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jint hat_id, jint x, jint y)
|
||||
{
|
||||
|
@ -453,7 +517,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeHat)(
|
|||
}
|
||||
|
||||
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeAddJoystick)(
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jstring device_name, jstring device_desc, jint is_accelerometer,
|
||||
jint nbuttons, jint naxes, jint nhats, jint nballs)
|
||||
|
@ -470,14 +534,14 @@ JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeAddJoystick)(
|
|||
return retval;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeRemoveJoystick)(
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick)(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id)
|
||||
{
|
||||
return Android_RemoveJoystick(device_id);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeAddHaptic)(
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic)(
|
||||
JNIEnv* env, jclass jcls, jint device_id, jstring device_name)
|
||||
{
|
||||
int retval;
|
||||
|
@ -490,7 +554,7 @@ JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeAddHaptic)(
|
|||
return retval;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeRemoveHaptic)(
|
||||
JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic)(
|
||||
JNIEnv* env, jclass jcls, jint device_id)
|
||||
{
|
||||
return Android_RemoveHaptic(device_id);
|
||||
|
@ -882,7 +946,7 @@ int Android_JNI_OpenAudioDevice(int iscapture, int sampleRate, int is16Bit, int
|
|||
if (iscapture) {
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device for capture");
|
||||
captureBuffer16Bit = is16Bit;
|
||||
if ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
|
||||
if ((*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
|
||||
/* Error during audio initialization */
|
||||
__android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: error on AudioRecord initialization!");
|
||||
return 0;
|
||||
|
@ -890,7 +954,7 @@ int Android_JNI_OpenAudioDevice(int iscapture, int sampleRate, int is16Bit, int
|
|||
} else {
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device for output");
|
||||
audioBuffer16Bit = is16Bit;
|
||||
if ((*env)->CallStaticIntMethod(env, mActivityClass, midAudioOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
|
||||
if ((*env)->CallStaticIntMethod(env, mAudioManagerClass, midAudioOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
|
||||
/* Error during audio initialization */
|
||||
__android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: error on AudioTrack initialization!");
|
||||
return 0;
|
||||
|
@ -958,10 +1022,10 @@ void Android_JNI_WriteAudioBuffer(void)
|
|||
|
||||
if (audioBuffer16Bit) {
|
||||
(*mAudioEnv)->ReleaseShortArrayElements(mAudioEnv, (jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT);
|
||||
(*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mActivityClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
|
||||
(*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mAudioManagerClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
|
||||
} else {
|
||||
(*mAudioEnv)->ReleaseByteArrayElements(mAudioEnv, (jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT);
|
||||
(*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mActivityClass, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
|
||||
(*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mAudioManagerClass, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
|
||||
}
|
||||
|
||||
/* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */
|
||||
|
@ -975,7 +1039,7 @@ int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen)
|
|||
|
||||
if (captureBuffer16Bit) {
|
||||
SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == (buflen / 2));
|
||||
br = (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_TRUE);
|
||||
br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_TRUE);
|
||||
if (br > 0) {
|
||||
jshort *ptr = (*env)->GetShortArrayElements(env, (jshortArray)captureBuffer, &isCopy);
|
||||
br *= 2;
|
||||
|
@ -984,7 +1048,7 @@ int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen)
|
|||
}
|
||||
} else {
|
||||
SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == buflen);
|
||||
br = (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_TRUE);
|
||||
br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_TRUE);
|
||||
if (br > 0) {
|
||||
jbyte *ptr = (*env)->GetByteArrayElements(env, (jbyteArray)captureBuffer, &isCopy);
|
||||
SDL_memcpy(buffer, ptr, br);
|
||||
|
@ -1008,9 +1072,9 @@ void Android_JNI_FlushCapturedAudio(void)
|
|||
}
|
||||
#else
|
||||
if (captureBuffer16Bit) {
|
||||
(*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE);
|
||||
(*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE);
|
||||
} else {
|
||||
(*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE);
|
||||
(*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -1020,13 +1084,13 @@ void Android_JNI_CloseAudioDevice(const int iscapture)
|
|||
JNIEnv *env = Android_JNI_GetEnv();
|
||||
|
||||
if (iscapture) {
|
||||
(*env)->CallStaticVoidMethod(env, mActivityClass, midCaptureClose);
|
||||
(*env)->CallStaticVoidMethod(env, mAudioManagerClass, midCaptureClose);
|
||||
if (captureBuffer) {
|
||||
(*env)->DeleteGlobalRef(env, captureBuffer);
|
||||
captureBuffer = NULL;
|
||||
}
|
||||
} else {
|
||||
(*env)->CallStaticVoidMethod(env, mActivityClass, midAudioClose);
|
||||
(*env)->CallStaticVoidMethod(env, mAudioManagerClass, midAudioClose);
|
||||
if (audioBuffer) {
|
||||
(*env)->DeleteGlobalRef(env, audioBuffer);
|
||||
audioBuffer = NULL;
|
||||
|
@ -1160,13 +1224,7 @@ fallback:
|
|||
inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString, 1 /* ACCESS_RANDOM */);
|
||||
if (Android_JNI_ExceptionOccurred(SDL_FALSE)) {
|
||||
/* Try fallback to APK expansion files */
|
||||
mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
|
||||
"openAPKExpansionInputStream", "(Ljava/lang/String;)Ljava/io/InputStream;");
|
||||
if (!mid) {
|
||||
SDL_SetError("No openAPKExpansionInputStream() in Java class");
|
||||
goto failure; /* Java class is missing the required method */
|
||||
}
|
||||
inputStream = (*mEnv)->CallObjectMethod(mEnv, context, mid, fileNameJString);
|
||||
inputStream = (*mEnv)->CallStaticObjectMethod(mEnv, mActivityClass, midOpenAPKExpansionInputStream, fileNameJString);
|
||||
|
||||
/* Exception is checked first because it always needs to be cleared.
|
||||
* If no exception occurred then the last SDL error message is kept.
|
||||
|
@ -1673,19 +1731,19 @@ void Android_JNI_SetSeparateMouseAndTouch(SDL_bool new_value)
|
|||
void Android_JNI_PollInputDevices(void)
|
||||
{
|
||||
JNIEnv *env = Android_JNI_GetEnv();
|
||||
(*env)->CallStaticVoidMethod(env, mActivityClass, midPollInputDevices);
|
||||
(*env)->CallStaticVoidMethod(env, mControllerManagerClass, midPollInputDevices);
|
||||
}
|
||||
|
||||
void Android_JNI_PollHapticDevices(void)
|
||||
{
|
||||
JNIEnv *env = Android_JNI_GetEnv();
|
||||
(*env)->CallStaticVoidMethod(env, mActivityClass, midPollHapticDevices);
|
||||
(*env)->CallStaticVoidMethod(env, mControllerManagerClass, midPollHapticDevices);
|
||||
}
|
||||
|
||||
void Android_JNI_HapticRun(int device_id, int length)
|
||||
{
|
||||
JNIEnv *env = Android_JNI_GetEnv();
|
||||
(*env)->CallStaticVoidMethod(env, mActivityClass, midHapticRun, device_id, length);
|
||||
(*env)->CallStaticVoidMethod(env, mControllerManagerClass, midHapticRun, device_id, length);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1862,6 +1920,11 @@ const char * SDL_AndroidGetInternalStoragePath(void)
|
|||
|
||||
/* context = SDLActivity.getContext(); */
|
||||
context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
|
||||
if (!context) {
|
||||
SDL_SetError("Couldn't get Android context!");
|
||||
LocalReferenceHolder_Cleanup(&refs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* fileObj = context.getFilesDir(); */
|
||||
mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
|
||||
|
|
Loading…
Reference in New Issue