mirror of https://github.com/encounter/SDL.git
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.
This commit is contained in:
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