diff options
author | jeffpk <[email protected]> | 2003-06-06 21:04:07 +0000 |
---|---|---|
committer | jeffpk <[email protected]> | 2003-06-06 21:04:07 +0000 |
commit | 454233e113a22a149fe45624ce3e405474ded053 (patch) | |
tree | 173b3916eff745d921bc22fc858f4bddcc966bde /plugins/DX8 | |
parent | 4275dabe7f7cf2e427626550cb54f5e8ba104e44 (diff) |
Initial check-in of the Java Games Initiative's game controller discovery and input library.
git-svn-id: file:///home/sven/projects/JOGL/git-svn/svn-server-sync/jinput/trunk@3 e343933a-64c8-49c5-92b1-88f2ce3e89e8
Diffstat (limited to 'plugins/DX8')
-rw-r--r-- | plugins/DX8/README.txt | 46 | ||||
-rw-r--r-- | plugins/DX8/build.xml | 103 | ||||
-rw-r--r-- | plugins/DX8/src/java/net/java/games/input/DirectInputAxis.java | 211 | ||||
-rw-r--r-- | plugins/DX8/src/java/net/java/games/input/DirectInputDevice.java | 207 | ||||
-rw-r--r-- | plugins/DX8/src/java/net/java/games/input/DirectInputEnvironmentPlugin.java | 183 | ||||
-rw-r--r-- | plugins/DX8/src/java/net/java/games/input/DirectInputKeyboard.java | 208 | ||||
-rw-r--r-- | plugins/DX8/src/java/net/java/games/input/DirectInputMouse.java | 311 | ||||
-rw-r--r-- | plugins/DX8/src/native/input.cpp | 888 |
8 files changed, 2157 insertions, 0 deletions
diff --git a/plugins/DX8/README.txt b/plugins/DX8/README.txt new file mode 100644 index 0000000..12cd468 --- /dev/null +++ b/plugins/DX8/README.txt @@ -0,0 +1,46 @@ +This file modified last on 06/06/2003 by Jeff Kesselman + +This is the source tree for the core input API. + +Directory Organization: + +The root contains a master ANT build.xml. +After a successful build you will have the following sub directories: + -- apidocs Where the javadocs get built to + -- lib Where dependant libraries are kept. + -- bin Where the plugin dll and jar files ar built to. + -- src The source files. + + +Build instructions: + +To clean: ant clean +To build: ant all (or just ant) +To build docs: ant javadoc +To test: + This build will install the plug-in into the coreAPI's test + directories. + Use the tests in the coreAPI build.xml to test. + +Release Info: + Initial Release: This release contains an implementation of the input + API designed by Mike Martak of Sun and Thomas (?) of Sony CEA for + the WIn32 platform. All the code in src/input is cross platform. The + Win32 code is segregated to the DirectX plugin (src/DXplugin) which + depends on DirectInput from DX7 (or later). + + 05/09/2003: A number of bugs and problems with the DXPlugin are fixed in this + release. This release also brings the code up to date using the DI8 + interface. This thus is the first release that requries Peter Puck's + DX8 bindings to compile with MinGW. + + 05/09/2003 (second update): + This version adds a new standard value type to the API. + Axis.POV holds standard definitions for values for POV (hat) switches + -- Axis.POV.CENTER and Axis.POV.OFF are synonmous and are + the center position. + -- Axis.POV.UP, Axis.POV.DOWN, Axis.POV.LEFT and Axis.POV.RIGHT + should be self explainatory. + Any hat that claims to be "normalized" will return these values. (It is + recommended that all hats be normalized by the systemn specific plugins.) + diff --git a/plugins/DX8/build.xml b/plugins/DX8/build.xml new file mode 100644 index 0000000..32001e1 --- /dev/null +++ b/plugins/DX8/build.xml @@ -0,0 +1,103 @@ +<?xml version="1.0"?> + +<!-- Written to assume that classpath is rooted in the current directory. --> +<!-- So this should be OK if you make this script in the root of a filesystem. --> +<!-- If not, you may prefer to adjust the basedir, or move some directories around. --> +<!-- The idea is that both Ant and NetBeans have to know what the package root is --> +<!-- for the classes in your application. --> +<project name="Direct Input Plugin" basedir="." default="all"> + + <!-- Don't worry if you don't know the Ant syntax completely or need help on some tasks! --> + <!-- The standard Ant documentation is bundled. See Help | Help Sets | Ant 1.4.1 Manual. --> + + <target name="init"> + <!-- You can set up any variables you want used throughout the script here. --> + <property name="hello" value="world"/> + <mkdir dir="classes"/> + <mkdir dir="bin"/> + <!-- To use e.g. Jikes, uncomment this line. --> + <!-- (Or make the same change in Tools | Options | Ant Settings | Properties.) --> + <!-- <property name="build.compiler" value="jikes"/> --> + <!-- You might like to set up some overridable paths, etc.: --> + <!-- <property name="mylib" value="../lib/mylib.jar"/> --> + </target> + + <target name="compile" depends="init"> + <!-- Both srcdir and destdir should be package roots. --> + <!-- They could be different of course; in that case NetBeans can also be set --> + <!-- up to compile to a different filesystem in the same way; see Compiler Types: --> + <javac srcdir="src/java" destdir="classes" debug="true" deprecation="true" source="1.4"> + <!-- To add something to the classpath: --> + <classpath> + <pathelement location="lib/controller.jar"/> + <pathelement location="lib/jutils.jar"/> + </classpath> + <!-- To exclude some files: --> + <!-- + <exclude name="com/foo/SomeFile.java"/> + <exclude name="com/foo/somepackage/"/> + --> + </javac> + <exec dir="." executable="gcc" os="Windows 2000"> + <arg line=" -D_STRICT_ANSI -D_JNI_IMPLEMENTATION_"/> + <arg line=" -I'${java.home}/../include' -I'${java.home}/../include/win32' -Ic:/dx9/include"/> + <arg line=" -o bin/dxinput.dll src/native/input.cpp -Wl,--export-all-symbols"/> + <arg line=" -shared -Wl,--kill-at -ldxguid -ldinput -ldinput8"/> + </exec> + <copy file="bin/dxinput.dll" todir="../../coreAPI/src/tests/controller" /> + </target> + + <target name="jar" depends="init,compile"> + <!-- To make a standalone app: --> + <!-- 1. Create a myapp.mf manifest somewhere. --> + <!-- 2. Put in it: --> + <!-- Manifest-Version: 1.0 --> + <!-- Main-Class: com.foo.Main --> + <!-- 3. Pass to <jar>: manifest="myapp.mf" --> + <jar jarfile="bin/dxinput.jar" compress="true" basedir="classes"> + <exclude name="**/*.java"/> + <exclude name="**/*.form"/> + <exclude name="dxinput.mf"/> + <exclude name="dxinput.jar"/> + <exclude name="apidoc"/> + </jar> + <copy file="bin/dxinput.jar" todir="../../coreAPI/src/tests/controller" /> + </target> + + <target name="all" depends="compile,jar" description="Build everything."> + <echo message="Application built. Hello ${hello}!"/> + </target> + + <target name="test" depends="init,all" description="Try running it."> + <echo message="Test by running test on the build.xml for input"/> + </target> + + <target name="javadoc" depends="init" description="Javadoc for my API."> + <mkdir dir="apidocs"/> + <javadoc packagenames="net.*" + destdir="apidocs" + additionalparam="-source 1.4"> + <sourcepath> + <pathelement location="src/java"/> + </sourcepath> + <classpath> + <pathelement location="lib/controller.jar"/> + <pathelement location="lib/jutils.jar"/> + </classpath> + </javadoc> + </target> + + <target name="clean" depends="init" description="Clean all build products."> + <delete> + <fileset dir="classes"> + <include name="**/*.class"/> + </fileset> + </delete> + <delete file="bin/dxinput.jar" failonerror="no"/> + <delete file="bin/dxinput.dll" failonerror="no"/> + <delete file="../../coreAPI/src/tests/controller/dxinput.jar" failonerror="no" /> + <delete file="../../coreAPI/src/test/controller/dxinput.dll" failonerror="no"/> + <delete dir="../../docs/input/win32/apidoc" failonerror="no"/> + </target> + +</project> diff --git a/plugins/DX8/src/java/net/java/games/input/DirectInputAxis.java b/plugins/DX8/src/java/net/java/games/input/DirectInputAxis.java new file mode 100644 index 0000000..58df37d --- /dev/null +++ b/plugins/DX8/src/java/net/java/games/input/DirectInputAxis.java @@ -0,0 +1,211 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import net.java.games.input.AbstractAxis; +import net.java.games.input.Axis; + +/** + * + * @author martak + * @version + */ +class DirectInputAxis extends AbstractAxis { + + /** + * DIDFT_ constants and macros defined in dinput.h + */ + private static final int DIDFT_ALL = 0x00000000; + private static final int DIDFT_RELAXIS = 0x00000001; + private static final int DIDFT_ABSAXIS = 0x00000002; + private static final int DIDFT_AXIS = 0x00000003; + private static final int DIDFT_PSHBUTTON = 0x00000004; + private static final int DIDFT_TGLBUTTON = 0x00000008; + private static final int DIDFT_BUTTON = 0x0000000C; + private static final int DIDFT_POV = 0x00000010; + private static final int DIDFT_COLLECTION = 0x00000040; + private static final int DIDFT_NODATA = 0x00000080; + private static final int DIDFT_ANYINSTANCE = 0x00FFFF00; + private static final int DIDFT_INSTANCEMASK = DIDFT_ANYINSTANCE; + private static final int DIDFT_FFACTUATOR = 0x01000000; + private static final int DIDFT_FFEFFECTTRIGGER = 0x02000000; + private static final int DIDFT_OUTPUT = 0x10000000; + private static final int DIDFT_NOCOLLECTION = 0x00FFFF00; + private static int DIDFT_MAKEINSTANCE(int n) { + return ((n&0xffff) << 8); + } + private static int DIDFT_GETTYPE(int n) { + return (n&0xFF); + } + private static int DIDFT_GETINSTANCE(int n) { + return ((n >> 8)&0xffff); + } + private static int DIDFT_ENUMCOLLECTION(int n) { + return ((n&0xFFFF) << 8); + } + + private DirectInputDevice device; + /** + * DIJOYSTATE structure defined in dinput.h: + * + * <pre> + * typedef struct DIJOYSTATE { + * LONG lX; + * LONG lY; + * LONG lZ; + * LONG lRx; + * LONG lRy; + * LONG lRz; + * LONG rglSlider[2]; + * DWORD rgdwPOV[4]; + * BYTE rgbButtons[32]; + * } DIJOYSTATE, *LPDIJOYSTATE; + * + * 80 bytes total + * </pre> + */ + private int offset; + private int type; + private int instance; + private int bitmask = 0xffffffff; + private int bitshift = 0; + + private DirectInputAxis(DirectInputDevice device, Axis.Identifier id, + int didft, String name) { + super(name, id); + this.device = device; + this.type = DIDFT_GETTYPE(didft); + this.instance = DIDFT_GETINSTANCE(didft); + if (id == Axis.Identifier.X) { + offset = 0; + } else if (id == Axis.Identifier.Y) { + offset = 1; + } else if (id == Axis.Identifier.Z) { + offset = 2; + } else if (id == Axis.Identifier.RX) { + offset = 3; + } else if (id == Axis.Identifier.RY) { + offset = 4; + } else if (id == Axis.Identifier.RZ) { + offset = 5; + } else if (id == Axis.Identifier.SLIDER) { + //System.out.println("Slider on "+name+" instance = "+instance); + offset = 6 + (instance>>2); + } else if (id == Axis.Identifier.POV) { + //System.out.println("POV on "+name+" instance = "+instance); + offset = 8 + instance; + } else if (id == Axis.Identifier.BUTTON) { + //System.out.println("Button on "+name+" instance = "+instance); + offset = 12 + (instance/4); + bitshift = (instance%4)*8; + bitmask=0xff; + } + } + + /** Returns the data from the last time the control has been polled. + * If this axis is a button, the value returned will be either 0.0f or 1.0f. + * If this axis is normalized, the value returned will be between -1.0f and + * 1.0f. + * @return A float between -1.0 and 1.0 + */ + public float getPollData() { + int data = ((device.data[offset] >> bitshift)&bitmask); + if ((type&DIDFT_BUTTON) != 0 ) { + return (float)((data&0x80)>>7); + } else if ((type&DIDFT_AXIS)!=0){ // all axes are set for -32768 to 32738 + return ((float)data)/32768; + } else if ((type&DIDFT_POV)!=0) { + if (data == -1) { + return Axis.POV.OFF; + } else if (data == 0.0) { + return Axis.POV.UP; + } else if (data == 9000) { + return Axis.POV.RIGHT; + } else if (data == 18000) { + return Axis.POV.DOWN; + } else if (data == 27000) { + return Axis.POV.LEFT; + } else { + System.err.print("Unexpected value for DX8 HAT: "+data); + return Axis.POV.OFF; + } + } else { // return raw value + return (float)data; + } + + } + + /** Returns <code>true</code> if data returned from <code>poll</code> + * is relative to the last call, or <code>false</code> if data + * is absolute. + * @return true if data has chnaged since last poll, else false + */ + public boolean isRelative() { + return (type & DIDFT_RELAXIS) != 0; + } + + /** Returns whether or not the axis is analog, or false if it is digital. + * @return true if analog, false if digital + */ + public boolean isAnalog() { + return (type & DIDFT_AXIS) != 0; + } + + /** Returns whether or not data polled from this axis is normalized + * between the values of -1.0f and 1.0f. + * @return true if data is normalized, false if not. + */ + public boolean isNormalized() { + return (type & (DIDFT_BUTTON|DIDFT_AXIS|DIDFT_POV)) != 0; + } + + /** Creates a new DirectInputAxis (factory method). + * This is a function used internally during set up + * @return The new DirectInputAxis object. + * @param device The device to attach this axis to. + * + * @param didft The identifier for the axis as provided by DX8. + * @param name A name to give the new axis. + * @param id The identifier for the device + */ + public static DirectInputAxis createAxis(DirectInputDevice device, + Axis.Identifier id, int didft, String name) { + return new DirectInputAxis(device, id, didft, name); + } +} diff --git a/plugins/DX8/src/java/net/java/games/input/DirectInputDevice.java b/plugins/DX8/src/java/net/java/games/input/DirectInputDevice.java new file mode 100644 index 0000000..f31c66e --- /dev/null +++ b/plugins/DX8/src/java/net/java/games/input/DirectInputDevice.java @@ -0,0 +1,207 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import net.java.games.input.AbstractController; +import net.java.games.input.Axis; +import net.java.games.input.Controller; +import java.util.ArrayList; +import java.util.Iterator; + +/** + * + * @author martak + * @version + */ +class DirectInputDevice extends AbstractController { + + /** + * DIDEVTYPE_ constants from dinput.h header file + ** JPK NOTE: This changed in DI8. In general this + * is fragile anda way shoudl be found to tie these mroe directly + * to the header files. + */ + /* Mike's <=DX7 types + private static final int DIDEVTYPEJOYSTICK_UNKNOWN = 1; + private static final int DIDEVTYPEJOYSTICK_TRADITIONAL = 2; + private static final int DIDEVTYPEJOYSTICK_FLIGHTSTICK = 3; + private static final int DIDEVTYPEJOYSTICK_GAMEPAD = 4; + private static final int DIDEVTYPEJOYSTICK_RUDDER = 5; + private static final int DIDEVTYPEJOYSTICK_WHEEL = 6; + private static final int DIDEVTYPEJOYSTICK_HEADTRACKER = 7; + */ + + /** + * Pointer to the IDirectInputDevice for this device + */ + private long lpDevice; + + /** + * Type of device + */ + private Type type; + + /** + * Do we need to poll data? + */ + private boolean polled = true; + /** + * Data when polling, as per the DIJOYSTATE structure in dinput.h; + * @see DirectInputAxis for a breakdown of this structure + */ + int[] data = new int[32]; + + /** + * Private constructor + * @param lpDevice A pointer to the IDirectInputDevice for the device. + * @param subtype The subtype of device, as defined in the DIDEVTYPE + * constants above + * @param productName The product name for the device + * @param instanceName The name of the device + */ + private DirectInputDevice(long lpDevice, int subtype, String productName, + String instanceName,boolean polled) { + super(productName + " " + instanceName); + this.lpDevice = lpDevice; + this.polled = polled; + System.out.println("Creating "+productName+" polling = "+polled); + switch(subtype) { + /* + case DIDEVTYPEJOYSTICK_GAMEPAD: + type = Type.GAMEPAD; break; + case DIDEVTYPEJOYSTICK_RUDDER: + type = Type.RUDDER; break; + case DIDEVTYPEJOYSTICK_WHEEL: + type = Type.WHEEL; break; + case DIDEVTYPEJOYSTICK_HEADTRACKER: + type = Type.HEADTRACKER; break; + case DIDEVTYPEJOYSTICK_TRADITIONAL: // fall through + case DIDEVTYPEJOYSTICK_FLIGHTSTICK: // fall through + */ + default: + type = Type.STICK; break; + } + axes = initDirectInputAxes(); + } + + /** + * Used instead of overriding initAxes because it needs the + * pointer to the IDirectInputDevice + */ + private Axis[] initDirectInputAxes() { + ArrayList list = new ArrayList(); + enumObjects(lpDevice, list); + Axis[] ret = new Axis[list.size()]; + Iterator it = list.iterator(); + int i = 0; + while (it.hasNext()) { + ret[i] = (Axis)it.next(); + i++; + } + return ret; + } + + /** + * Callback called by enumObjects to add a new axis into the list + * @param list This in which to add the new axis + * @param id The identifier for the axis, based on GUID + * @param didft The combination of DIDFT_ flags that make up the type and + * instance number of the axis. + * @param name The name to call the axis. + */ + private void addAxis(ArrayList list, Axis.Identifier id, int didft, + String name) { + list.add(DirectInputAxis.createAxis(this, id, didft, name)); + } + + /** Polls axes for data. Returns false if the controller is no longer valid. + * Polling reflects the current state of the device when polled, and is + * unbuffered. + * @return False if the co troller is no longer valid, else true. + */ + public boolean poll() { + return pollNative(lpDevice, data, polled); + } + + /** Returns the type of Controller. + * @return The type of the controller. + */ + public Type getType() { + return type; + } + + /** Returns the zero-based port number for this Controller. + * @return The port number. + */ + public int getPortNumber() { + // REMIND : We may be able to parse this from the name string + return 0; + } + + /** + * Polls the device; native method. The data from the poll is stored in + * the data array. + */ + private native boolean pollNative(long lpDevice, int[] data, + boolean polled); + + /** + * Enumerates the axes on the device + */ + private native boolean enumObjects(long lpDevice, ArrayList list); + + /** Creates a new DirectInputDevice (factory method) + * This is a function used internally during set up + * @param polled Whether this device's driver should actually be + * polled during a call to Poll or whether it is an + * interrupt driven device that should ignore poll + * requests. + * @param lpDevice A pointer to the IDirectInputDevice for the device. + * @param subtype The subtype of device, as defined in the DIDEVTYPE + * constants above + * @param productName The product name for the device + * @param instanceName The name of the device + * @return The new DirectInputDevice object + */ + public static DirectInputDevice createDevice(long lpDevice, int subtype, + String productName, String instanceName, boolean polled) { + return new DirectInputDevice(lpDevice, subtype, productName, + instanceName,polled); + } +} // class DirectInputDevice diff --git a/plugins/DX8/src/java/net/java/games/input/DirectInputEnvironmentPlugin.java b/plugins/DX8/src/java/net/java/games/input/DirectInputEnvironmentPlugin.java new file mode 100644 index 0000000..a406b09 --- /dev/null +++ b/plugins/DX8/src/java/net/java/games/input/DirectInputEnvironmentPlugin.java @@ -0,0 +1,183 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.security.AccessController; +import java.util.ArrayList; +import java.util.Iterator; +import net.java.games.input.Controller; +import net.java.games.input.ControllerEnvironment; +//import sun.security.action.LoadLibraryAction; +import net.java.games.util.plugins.Plugin; + +/** DirectInput implementation of controller environment + * @author martak + * @version 1.0 + */ +public class DirectInputEnvironmentPlugin extends ControllerEnvironment + implements Plugin +{ + + static { + /** Mikes old code, causes it to be laoded by wrong loader + java.security.AccessController.doPrivileged( + new LoadLibraryAction("jinput")); + */ + System.loadLibrary("dxinput"); + } + + /** + * DIDEVTYPE_ constants from dinput.h header file + * JPK NOTE: changed in DX8 so had to be changed. This is + * fragile, we should find a way to set them from + * the C side sowe can stay up to date with header + */ + /** DX7 and earlier + private static final int DIDEVTYPE_DEVICE = 1; + private static final int DIDEVTYPE_MOUSE = 2; + private static final int DIDEVTYPE_KEYBOARD = 3; + private static final int DIDEVTYPE_JOYSTICK = 4; + private static final int DIDEVTYPE_HID = 0x00010000; + private static int GET_DIDEVICE_TYPE(int dwDevType) { + return (int)((byte)dwDevType); + } + private static int GET_DIDEVICE_SUBTYPE(int dwDevType) { + return (int)((byte)((((short)dwDevType) >> 8) & 0xFF)); + } + **/ + /* DX8 and 9 */ + private static final int DI8DEVTYPE_DEVICE = 0x11; + private static final int DI8DEVTYPE_MOUSE = 0x12; + private static final int DI8DEVTYPE_KEYBOARD = 0x13; + private static final int DI8DEVTYPE_JOYSTICK = 0x14; + private static final int DI8DEVTYPE_GAMEPAD = 0x15; + private static final int DI8DEVTYPE_DRIVING = 0x16; + private static final int DI8DEVTYPE_FLIGHT = 0x17; + private static final int DI8DEVTYPE_1STPERSON = 0x18; + private static final int DI8DEVTYPE_DEVICECTRL = 0x19; + private static final int DI8DEVTYPE_SCREENPOINTER = 0x1A; + private static final int DI8DEVTYPE_REMOTE = 0x1B; + private static final int DI8DEVTYPE_SUPPLEMENTAL = 0x1C; + + private static int GET_DIDEVICE_TYPE(int dwDevType) { + return (dwDevType&0xFF); + } + private static int GET_DIDEVICE_SUBTYPE(int dwDevType) { + return (int)((byte)((((short)dwDevType) >> 8) & 0xFF)); + } + + // Pointer to DirectInput instance + private long lpDirectInput; + // Permanent array of controllers + private Controller[] controllers; + + /** Creates new DirectInputEnvironment */ + public DirectInputEnvironmentPlugin() { + lpDirectInput = directInputCreate(); + enumControllers(); + } + + /** Returns a list of all controllers available to this environment, + * or an empty array if there are no controllers in this environment. + * @return An array of controllers that may be empty. + */ + public Controller[] getControllers() { + return controllers; + } + + private void enumControllers() { + // If direct input fails, create an empty array + if (lpDirectInput == 0) { + controllers = new Controller[] {}; + return; + } + // Create temporary controller array + ArrayList tempDevices = new ArrayList(); + // Eumerate devices + enumDevices(lpDirectInput, tempDevices); + // Set up permanent controller array + controllers = new Controller[tempDevices.size()]; + Iterator it = tempDevices.iterator(); + int i = 0; + while (it.hasNext()) { + controllers[i] = (Controller)it.next(); + i++; + } + } + + /** + * Creates a new device, adding it to the list supplied. + * @param lpDevice A pointer to the IDirectInputDevice for the device. + * @param type The type of device to create, as defined by the constants + * in dinput.h (see DI8DEVTYPE constants above). + * @param productName The product name for the device + * @param instanceName The name of the device + */ + private void addDevice(ArrayList list, long lpDevice, + int type, String productName, String instanceName, boolean polled) { + Controller c; + int category = GET_DIDEVICE_TYPE(type); + int subtype = GET_DIDEVICE_SUBTYPE(type); + //System.out.println("Category = "+category); + if (category == DI8DEVTYPE_MOUSE) { + c = DirectInputMouse.createMouse(lpDevice, subtype, productName, + instanceName); + } else if (category == DI8DEVTYPE_KEYBOARD) { + c = DirectInputKeyboard.createKeyboard(lpDevice, subtype, + productName, instanceName); + } else { + assert category == DI8DEVTYPE_JOYSTICK; + c = DirectInputDevice.createDevice(lpDevice, subtype, productName, + instanceName,polled); + } + if (c != null) { + list.add(c); + } + } + + /** + * Returns the direct input instance, or 0 if failed to initialize + */ + private native long directInputCreate(); + + /** + * Enumerates all devices, calling createDevice for each one + */ + private native boolean enumDevices(long lpDirectInput, ArrayList list); +} // class DirectInputEnvironment diff --git a/plugins/DX8/src/java/net/java/games/input/DirectInputKeyboard.java b/plugins/DX8/src/java/net/java/games/input/DirectInputKeyboard.java new file mode 100644 index 0000000..6faf163 --- /dev/null +++ b/plugins/DX8/src/java/net/java/games/input/DirectInputKeyboard.java @@ -0,0 +1,208 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import net.java.games.input.AbstractAxis; +import net.java.games.input.Axis; +import net.java.games.input.StandardKeyboard; + +/** + * DirectInput keyboard implementation. + * @author martak + * @version + */ +class DirectInputKeyboard extends StandardKeyboard { + + /** + * DIDEVTYPE_ constants from dinput.h header file + */ + private static final int DIDEVTYPEKEYBOARD_UNKNOWN = 0; + private static final int DIDEVTYPEKEYBOARD_PCXT = 1; + private static final int DIDEVTYPEKEYBOARD_OLIVETTI = 2; + private static final int DIDEVTYPEKEYBOARD_PCAT = 3; + private static final int DIDEVTYPEKEYBOARD_PCENH = 4; + private static final int DIDEVTYPEKEYBOARD_NOKIA1050 = 5; + private static final int DIDEVTYPEKEYBOARD_NOKIA9140 = 6; + private static final int DIDEVTYPEKEYBOARD_NEC98 = 7; + private static final int DIDEVTYPEKEYBOARD_NEC98LAPTOP = 8; + private static final int DIDEVTYPEKEYBOARD_NEC98106 = 9; + private static final int DIDEVTYPEKEYBOARD_JAPAN106 = 10; + private static final int DIDEVTYPEKEYBOARD_JAPANAX = 11; + private static final int DIDEVTYPEKEYBOARD_J3100 = 12; + + /** + * Key index crosstable; maps indices into the data array to virtual keys + * in the key array in StandardKeyboard. + * For example, the key F11 is at index 84 in the array of keys in + * StandardKeyboard, yet it is data element 87 (0x57) in our data array. + * <p> + * To access the data element of a particular key (F11), we use the + * crosstable as follows: + * <p><code> + * KeyID f11 = StandardKey.KeyID.F11; + * int keyIndex = f11.getKeyIndex(); // returns 84 + * int crossIndex = CROSSTABLE[keyIndex]; // returns 0x57 (87) + * </code> + * To find a key given the data element index (87), we do a simple search + * through the crosstable starting at that index (index 87/0x57 = 0x65) and + * looking backwards until we find our key itself, or a lower number + * (meaning the key was not found). We can only take advantage of this + * algorithm only because on Windows, our crosstable is in increasing order. + */ + private final static int[] CROSSTABLE = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, // _9 + 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, // Y + 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, // D + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, // BACKSLASH + 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, // RSHIFT + 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, // F7 + 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, // NUMPAD5 + 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x57, 0x58, 0x64, 0x65, // F14 + 0x66, 0x70, 0x79, 0x7B, 0x7D, 0x8D, 0x90, 0x91, 0x92, 0x93, 0x94, // KANJI + 0x95, 0x96, 0x97, 0x9C, 0x9D, 0xB3, 0xB5, 0xB7, 0xB8, 0xC5, 0xC7, // HOME + 0xC8, 0xC9, 0xCB, 0xCD, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xDB, 0xDC, // RWIN + 0xDD, 0xDE, 0xDF // SLEEP + }; + + /** + * Pointer to the IDirectInputDevice for this device + */ + private long lpDevice; + + /** + * Subtype of keyboard, defined by DIDEVTYPE constants + */ + private int subtype; + + /** + * Polling key data + */ + private byte[] keyData = new byte[256]; + + /** + * Private constructor + * @param lpDevice A pointer to the IDirectInputDevice for the device. + * @param subtype The subtype of keyboard, as defined in the DIDEVTYPE + * constants above + * @param productName The product name for the device + * @param instanceName The name of the device + */ + private DirectInputKeyboard(long lpDevice, int subtype, String productName, + String instanceName) { + super(productName + " (" + instanceName + ")"); + this.lpDevice = lpDevice; + this.subtype = subtype; + } + + /** + * Callback to rename a given key by index, name + * @param index the index in the data array + * @param name the name of the key + */ + private void renameKey(int index, String name) { + int keyIndex = index; + if (keyIndex > CROSSTABLE.length) { + keyIndex = CROSSTABLE.length - 1; + } + for (; CROSSTABLE[keyIndex] > index; keyIndex--) + ; + if (CROSSTABLE[keyIndex] == index) { + Axis[] axes = getAxes(); + AbstractAxis key = (AbstractAxis)axes[index]; + if (name != null && name.length() > 0) { + //System.out.println("Renaming key " + key.getName() + + // " to " + name + " index=" + + // index + " keyIndex=" + keyIndex + " CROSSTAB=" + + // CROSSTABLE[keyIndex]); + key.setName(name); + } + } else { + //System.out.println("Key not found " + name + " index=" + index + + // " keyIndex=" + keyIndex + " CROSSTAB=" + + // CROSSTABLE[keyIndex]); + } + } + + /** Polls axes for data. Returns false if the controller is no longer valid. + * Polling reflects the current state of the device when polled. + * @return False if the KB is no longer valid, true otherwise. + */ + public boolean poll() { + return pollNative(lpDevice, keyData); + } + + /** Returns whether or not the given key has been pressed since the last + * call to poll. + * @param key The key whose state to check. + * @return true if this key has changed state since last read of its state, false otherwise. + */ + protected boolean isKeyPressed(Key key) { + KeyID id = (KeyID)key.getIdentifier(); + int keyIndex = id.getKeyIndex(); + int crossIndex = CROSSTABLE[keyIndex]; + return ((keyData[crossIndex] & 0x80) != 0); + } + + /** + * Polls the device; native method + */ + private native boolean pollNative(long lpDevice, byte[] keyData); + + /** + * Renames the keys with the name provided by DirectInput + */ + private native boolean renameKeys(long lpDevice); + + /** Creates a new DirectInputKeyboard (factory method) + * This is a function used internally during set up. + * @param lpDevice A pointer to the IDirectInputDevice for the device. + * @param subtype The subtype of keyboard, as defined in the DIDEVTYPE + * constants above + * @param productName The product name for the keyboard + * @param instanceName The name of the keyboard + * @return The new DirectInputKeyboard object. + */ + public static DirectInputKeyboard createKeyboard(long lpDevice, + int subtype, String productName, String instanceName) { + DirectInputKeyboard ret = new DirectInputKeyboard(lpDevice, subtype, + productName, instanceName); + ret.renameKeys(lpDevice); + return ret; + } +} // class DirectInputKeyboard diff --git a/plugins/DX8/src/java/net/java/games/input/DirectInputMouse.java b/plugins/DX8/src/java/net/java/games/input/DirectInputMouse.java new file mode 100644 index 0000000..f706250 --- /dev/null +++ b/plugins/DX8/src/java/net/java/games/input/DirectInputMouse.java @@ -0,0 +1,311 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import net.java.games.input.AbstractAxis; +import net.java.games.input.Axis; +import net.java.games.input.Mouse; + +/** + * DirectInput mouse implementation. + * @author martak + * @version + */ +class DirectInputMouse extends Mouse { + + /** + * DIDEVTYPE_ constants from dinput.h header file + */ + private static final int DIDEVTYPEMOUSE_UNKNOWN = 1; + private static final int DIDEVTYPEMOUSE_TRADITIONAL = 2; + private static final int DIDEVTYPEMOUSE_FINGERSTICK = 3; + private static final int DIDEVTYPEMOUSE_TOUCHPAD = 4; + private static final int DIDEVTYPEMOUSE_TRACKBALL = 5; + + /** + * Pointer to the IDirectInputDevice for this device + */ + private long lpDevice; + + /** + * Type of mouse + */ + private Type type; + + /** + * Mouse data + */ + private byte[] mouseData = new byte[16]; + + /** + * Private constructor + * @param lpDevice A pointer to the IDirectInputDevice for the device. + * @param subtype The subtype of mouse, as defined in the DIDEVTYPE + * constants above + * @param productName The product name for the device + * @param instanceName The name of the device + */ + private DirectInputMouse(long lpDevice, int subtype, String productName, + String instanceName) { + super(productName + " " + instanceName); + buttons = new ButtonsImpl(); + ball = new BallImpl(); + this.lpDevice = lpDevice; + switch(subtype) { + case DIDEVTYPEMOUSE_FINGERSTICK: + type = Type.FINGERSTICK; break; + case DIDEVTYPEMOUSE_TOUCHPAD: + type = Type.TRACKPAD; break; + case DIDEVTYPEMOUSE_TRACKBALL: + type = Type.TRACKBALL; break; + case DIDEVTYPEMOUSE_TRADITIONAL: // fall through + case DIDEVTYPEMOUSE_UNKNOWN: // fall through + default: + type = Type.MOUSE; break; + } + renameAxes(lpDevice); + } + + /** + * Callback to rename a given axis by type, name + */ + private void renameAxis(Axis.Identifier id, String name) { + AbstractAxis axis; + if (id instanceof ButtonID) { + axis = (AbstractAxis)getButtons().getAxis(id); + } else { + axis = (AbstractAxis)getBall().getAxis(id); + } + axis.setName(name); + //System.out.println("Renaming " + name); + } + + /** Polls axes for data. Returns false if the controller is no longer valid. + * Polling reflects the current state of the device when polled. + * @return false if the mosue is no lonegr valid, true otherwise. + */ + public boolean poll() { + return pollNative(lpDevice, mouseData); + } + + /** Returns the type of the Controller. + * @return The device type of the controller (logically this + * shoudl be some form of "mouse" .) + */ + public Type getType() { + return type; + } + + /** Creates a new DirectInputMouse (factory method) + * This is a function used internally during set up. + * @param lpDevice A pointer to the IDirectInputDevice for the device. + * @param subtype The subtype of mouse, as defined in the DIDEVTYPE + * constants above + * @param productName The product name for the keyboard + * @param instanceName The name of the keyboard + * @return The new DirectInputMouse object. + */ + public static DirectInputMouse createMouse(long lpDevice, int subtype, + String productName, String instanceName) { + return new DirectInputMouse(lpDevice, subtype, productName, + instanceName); + } + + /** + * Implementation class representing the mouse ball + */ + class BallImpl extends Ball { + + /** + * Public constructor + */ + public BallImpl() { + super(DirectInputMouse.this.getName() + " ball"); + x = new BallAxis(Axis.Identifier.X); + y = new BallAxis(Axis.Identifier.Y); + wheel = new BallAxis(Axis.Identifier.SLIDER); + } + } // class DirectInputMouse.BallImpl + + /** + * Implementation class representing the mouse buttons + */ + class ButtonsImpl extends Buttons { + + /** + * Public constructor + */ + public ButtonsImpl() { + super(DirectInputMouse.this.getName() + " buttons"); + left = new ButtonImpl(ButtonID.LEFT); + right = new ButtonImpl(ButtonID.RIGHT); + middle = new ButtonImpl(ButtonID.MIDDLE); + } + } // class DirectInputMouse.ButtonsImpl + + /** + * Polls the device; native method + */ + private native boolean pollNative(long lpDevice, byte[] mouseData); + + /** + * Renames the axes with the name provided by DirectInput + */ + private native boolean renameAxes(long lpDevice); + + /** + * Mouse button axis implementation + */ + class ButtonImpl extends Button { + + /** + * Index into the mouseData array + */ + private final int index; + + /** Public constructor + * @param id An ID of a button to create an obejct to represent. + * + */ + public ButtonImpl(ButtonID id) { + super(id.getName(), id); + if (id == ButtonID.LEFT) { + index = 12; + } else if (id == ButtonID.RIGHT) { + index = 13; + } else if (id == ButtonID.MIDDLE) { + index = 14; + } else { + throw new RuntimeException("Unknown button"); + } + } + + /** Returns the data from the last time the control has been polled. + * If this axis is a button, the value returned will be either 0.0f or 1.0f. + * If this axis is normalized, the value returned will be between -1.0f and + * 1.0f. + * @return state of controller. (Note: DX8 mice actually + * queue state so what is returned is the next state, + * not necessarily the most current one.) + */ + public float getPollData() { + // Mouse button + byte data = mouseData[index]; + if ((data & 0x80) != 0) { + return 1.0f; + } else { + return 0.0f; + } + } + + /** Returns <code>true</code> if data returned from <code>poll</code> + * is relative to the last call, or <code>false</code> if data + * is absolute. + * @return true if data is relative, otherwise false. + */ + public boolean isRelative() { + return false; + } + } // class DirectInputMouse.ButtonImpl + + /** + * Mouse ball axis implementation + */ + class BallAxis extends AbstractAxis { + + /** + * Starting index into the mouseData array + */ + private final int index; + + /** Public constructor + * @param id An ID for a mouse axis to create an object to represent. + */ + public BallAxis(Identifier id) { + super(id.getName(), id); + if (id == Identifier.X) { + index = 0; + } else if (id == Identifier.Y) { + index = 4; + } else if (id == Identifier.SLIDER) { + index = 8; + } else { + throw new RuntimeException("Unknown mouse axis"); + } + } + + /** Returns the data from the last time the control has been polled. + * If this axis is a button, the value returned will be either 0.0f or 1.0f. + * If this axis is normalized, the value returned will be between -1.0f and + * 1.0f. + * @return data. (Note that mice queue state in DX8 so what + * is returned is the next stae in the queue, not + * necessarily the most current one.) + */ + public float getPollData() { + int data = ((int)mouseData[index] << 12) | + ((int)mouseData[index + 1] << 8) | + ((int)mouseData[index + 2] << 4) | + ((int)mouseData[index + 3]); + if (data == -1) { + return -1.0f; + } else if (data >= 1) { + return 1.0f; + } else { + return 0.0f; + } + } + + /** Returns <code>true</code> if data returned from <code>poll</code> + * is relative to the last call, or <code>false</code> if data + * is absolute. + * @return true if relative, otherwise false. + */ + public boolean isRelative() { + return true; + } + + /** Returns whether or not the axis is analog, or false if it is digital. + * @return true if analog, false if digital + */ + public boolean isAnalog() { + return true; + } + } // class DirectInputMouse.MouseBallAxis +} // class DirectInputMouse diff --git a/plugins/DX8/src/native/input.cpp b/plugins/DX8/src/native/input.cpp new file mode 100644 index 0000000..ccfda2f --- /dev/null +++ b/plugins/DX8/src/native/input.cpp @@ -0,0 +1,888 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +#ifndef WIN32 + #error This is a Windows-only file +#endif + +// hard define as DX7 +//#define DIRECTINPUT_VERSION 0x0800 +#include <windows.h> +#include <jni.h> +#include <dinput.h> + + +/* + ****************************************************************************** + * Global variables + ****************************************************************************** + */ +jclass CLASS_AxisIdentifier = NULL; +jclass CLASS_ButtonIdentifier = NULL; +jclass CLASS_DirectInputEnvironmentPlugin = NULL; +jclass CLASS_DirectInputDevice = NULL; +jclass CLASS_DirectInputKeyboard = NULL; +jclass CLASS_DirectInputMouse = NULL; +jmethodID MID_AddDevice = NULL; +jmethodID MID_AddAxis = NULL; +jmethodID MID_RenameKey = NULL; +jmethodID MID_RenameAxis = NULL; +jfieldID FID_X = NULL; +jfieldID FID_Y = NULL; +jfieldID FID_Z = NULL; +jfieldID FID_RX = NULL; +jfieldID FID_RY = NULL; +jfieldID FID_RZ = NULL; +jfieldID FID_Slider = NULL; +jfieldID FID_Button = NULL; +jfieldID FID_POV = NULL; +jfieldID FID_Left = NULL; +jfieldID FID_Right = NULL; +jfieldID FID_Middle = NULL; + +const char* FD_AxisIdentifier = "Lnet/java/games/input/Axis$Identifier;"; +const char* FD_ButtonIdentifier = "Lnet/java/games/input/Mouse$ButtonID;"; +// Dummy input window. This is needed because DirectX evidently needs a window +// to do anything, such as setting the cooperative level for a device. +const TCHAR* DUMMY_WINDOW_NAME = "InputControllerWindow"; +HWND hwndDummy = NULL; +// Buffer size +const DWORD BUFFER_SIZE = 16; + +// Class for handing device data to the callback for EnumDevices +class DeviceParamData { +public: + DeviceParamData(LPDIRECTINPUT8 lpdi, JNIEnv* e, jobject o, jobject l) : + lpDirectInput(lpdi), env(e), obj(o), list(l) + { + } + LPDIRECTINPUT8 lpDirectInput; + JNIEnv* env; + jobject obj; + jobject list; +}; + +// Class for handing device data to the callback for EnumObjects +class ObjectParamData { +public: + ObjectParamData(LPDIRECTINPUTDEVICE8 lpDev, JNIEnv* e, jobject o, + jobject l) : + lpDevice(lpDev), env(e), obj(o), list(l) + { + } + LPDIRECTINPUTDEVICE8 lpDevice; + JNIEnv* env; + jobject obj; + jobject list; +}; + +void PrintOutput(TCHAR* tszMessage) { + printf("%s\n", tszMessage); +} + +void PrintDIError(TCHAR* tszOutput, HRESULT res) { + TCHAR tszMessage[256]; +#define CHECK_RESULT(r) case r: \ +sprintf(tszMessage, "%s : %s", tszOutput, #r); \ +break; + switch (res) { + CHECK_RESULT(DI_OK) + CHECK_RESULT(DI_NOTATTACHED) + CHECK_RESULT(DI_POLLEDDEVICE) + CHECK_RESULT(DI_DOWNLOADSKIPPED) + CHECK_RESULT(DI_EFFECTRESTARTED) + CHECK_RESULT(DI_TRUNCATED) + CHECK_RESULT(DI_TRUNCATEDANDRESTARTED) + CHECK_RESULT(DIERR_OLDDIRECTINPUTVERSION) + CHECK_RESULT(DIERR_BETADIRECTINPUTVERSION) + CHECK_RESULT(DIERR_BADDRIVERVER) + CHECK_RESULT(DIERR_DEVICENOTREG) + CHECK_RESULT(DIERR_NOTFOUND) + //CHECK_RESULT(DIERR_OBJECTNOTFOUND) + CHECK_RESULT(DIERR_INVALIDPARAM) + CHECK_RESULT(DIERR_NOINTERFACE) + CHECK_RESULT(DIERR_GENERIC) + CHECK_RESULT(DIERR_OUTOFMEMORY) + CHECK_RESULT(DIERR_UNSUPPORTED) + CHECK_RESULT(DIERR_NOTINITIALIZED) + CHECK_RESULT(DIERR_ALREADYINITIALIZED) + CHECK_RESULT(DIERR_NOAGGREGATION) + CHECK_RESULT(DIERR_OTHERAPPHASPRIO) + CHECK_RESULT(DIERR_INPUTLOST) + CHECK_RESULT(DIERR_ACQUIRED) + CHECK_RESULT(DIERR_NOTACQUIRED) + //CHECK_RESULT(DIERR_READONLY) + //CHECK_RESULT(DIERR_HANDLEEXISTS) + CHECK_RESULT(DIERR_INSUFFICIENTPRIVS) + CHECK_RESULT(DIERR_DEVICEFULL) + CHECK_RESULT(DIERR_MOREDATA) + CHECK_RESULT(DIERR_NOTDOWNLOADED) + CHECK_RESULT(DIERR_HASEFFECTS) + CHECK_RESULT(DIERR_NOTEXCLUSIVEACQUIRED) + CHECK_RESULT(DIERR_INCOMPLETEEFFECT) + CHECK_RESULT(DIERR_NOTBUFFERED) + CHECK_RESULT(DIERR_EFFECTPLAYING) + CHECK_RESULT(DIERR_UNPLUGGED) + CHECK_RESULT(DIERR_REPORTFULL) + default: sprintf(tszMessage, "Unknown"); break; + } + PrintOutput(tszMessage); +} + +/* + ****************************************************************************** + * DirectInputEnvironmentPlugin + ****************************************************************************** + */ + +/* + * Initialize all class, method, and field IDs + */ +BOOL InitIDs(JNIEnv* env) { + CLASS_AxisIdentifier = + env->FindClass("net/java/games/input/Axis$Identifier"); + if (CLASS_AxisIdentifier == NULL) { + return FALSE; + } + FID_X = env->GetStaticFieldID(CLASS_AxisIdentifier, "X", + FD_AxisIdentifier); + if (FID_X == NULL) { + return FALSE; + } + FID_Y = env->GetStaticFieldID(CLASS_AxisIdentifier, "Y", + FD_AxisIdentifier); + if (FID_Y == NULL) { + return FALSE; + } + FID_Z = env->GetStaticFieldID(CLASS_AxisIdentifier, "Z", + FD_AxisIdentifier); + if (FID_Z == NULL) { + return FALSE; + } + FID_RX = env->GetStaticFieldID(CLASS_AxisIdentifier, "RX", + FD_AxisIdentifier); + if (FID_RX == NULL) { + return FALSE; + } + FID_RY = env->GetStaticFieldID(CLASS_AxisIdentifier, "RY", + FD_AxisIdentifier); + if (FID_RY == NULL) { + return FALSE; + } + FID_RZ = env->GetStaticFieldID(CLASS_AxisIdentifier, "RZ", + FD_AxisIdentifier); + if (FID_RZ == NULL) { + return FALSE; + } + FID_Slider = env->GetStaticFieldID(CLASS_AxisIdentifier, "SLIDER", + FD_AxisIdentifier); + if (FID_Slider == NULL) { + return FALSE; + } + FID_Button = env->GetStaticFieldID(CLASS_AxisIdentifier, "BUTTON", + FD_AxisIdentifier); + if (FID_Button == NULL) { + return FALSE; + } + FID_POV = env->GetStaticFieldID(CLASS_AxisIdentifier, "POV", + FD_AxisIdentifier); + if (FID_POV == NULL) { + return FALSE; + } + CLASS_ButtonIdentifier = + env->FindClass("net/java/games/input/Mouse$ButtonID"); + if (CLASS_ButtonIdentifier == NULL) { + return FALSE; + } + FID_Left = env->GetStaticFieldID(CLASS_ButtonIdentifier, "LEFT", + FD_ButtonIdentifier); + if (FID_Left == NULL) { + return FALSE; + } + FID_Right = env->GetStaticFieldID(CLASS_ButtonIdentifier, "RIGHT", + FD_ButtonIdentifier); + if (FID_Right == NULL) { + return FALSE; + } + FID_Middle = env->GetStaticFieldID(CLASS_ButtonIdentifier, "MIDDLE", + FD_ButtonIdentifier); + if (FID_Middle == NULL) { + return FALSE; + } + CLASS_DirectInputEnvironmentPlugin = + env->FindClass("net/java/games/input/DirectInputEnvironmentPlugin"); + if (CLASS_DirectInputEnvironmentPlugin == NULL) { + return FALSE; + } + MID_AddDevice = env->GetMethodID(CLASS_DirectInputEnvironmentPlugin, "addDevice", + "(Ljava/util/ArrayList;JILjava/lang/String;Ljava/lang/String;Z)V"); + if (MID_AddDevice == NULL) { + return FALSE; + } + CLASS_DirectInputDevice = + env->FindClass("net/java/games/input/DirectInputDevice"); + if (CLASS_DirectInputDevice == NULL) { + return FALSE; + } + MID_AddAxis = env->GetMethodID(CLASS_DirectInputDevice, "addAxis", + "(Ljava/util/ArrayList;Lnet/java/games/input/Axis$Identifier;ILjava/lang/String;)V"); + if (MID_AddAxis == NULL) { + return FALSE; + } + CLASS_DirectInputKeyboard = + env->FindClass("net/java/games/input/DirectInputKeyboard"); + if (CLASS_DirectInputKeyboard == NULL) { + return FALSE; + } + MID_RenameKey = env->GetMethodID(CLASS_DirectInputKeyboard, "renameKey", + "(ILjava/lang/String;)V"); + if (MID_RenameKey == NULL) { + return FALSE; + } + CLASS_DirectInputMouse = + env->FindClass("net/java/games/input/DirectInputMouse"); + if (CLASS_DirectInputMouse == NULL) { + return FALSE; + } + MID_RenameAxis = env->GetMethodID(CLASS_DirectInputMouse, "renameAxis", + "(Lnet/java/games/input/Axis$Identifier;Ljava/lang/String;)V"); + if (MID_RenameAxis == NULL) { + return FALSE; + } + return TRUE; +} + +/* + * WndProc for our dummy input window + */ +LRESULT CALLBACK DummyWndProc( + HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + return DefWindowProc(hWnd, message, wParam, lParam); +} + +/* + * Register the dummy input window class + */ +BOOL RegisterDummyWindow(HINSTANCE hInstance) +{ + WNDCLASSEX wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = (WNDPROC)DummyWndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = NULL; + wcex.hCursor = NULL; + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = (LPCSTR)NULL; + wcex.lpszClassName = DUMMY_WINDOW_NAME; + wcex.hIconSm = NULL; + return RegisterClassEx(&wcex); +} + +/* + * Class: org_java_games_input_DirectInputEnvironmentPlugin + * Method: directInputCreate + * Signature: ()J + */ +extern "C" JNIEXPORT jlong JNICALL +Java_net_java_games_input_DirectInputEnvironmentPlugin_directInputCreate + (JNIEnv* env, jobject obj) +{ + // Get our module handle + HINSTANCE hInst = GetModuleHandle(NULL); + + // Register the dummy input window + if (!RegisterDummyWindow(hInst)) { + return (jlong)0; + } + + // Create the dummy input window + hwndDummy = CreateWindow(DUMMY_WINDOW_NAME, NULL, + WS_POPUP | WS_ICONIC, + 0, 0, 0, 0, NULL, NULL, hInst, NULL); + if (hwndDummy == NULL) + { + return (jlong)0; + } + + // Create the IDirectInput object + DWORD dwVersion = DIRECTINPUT_VERSION; + LPDIRECTINPUT8 lpDirectInput = NULL; + HRESULT res; + if (FAILED(res = DirectInput8Create(hInst, DIRECTINPUT_VERSION, + IID_IDirectInput8,(VOID **)&lpDirectInput, NULL))){ + PrintDIError("DirectInputCreate", res); + return (jlong)0; + } + + // Initialize method, class, and field IDs + if (!InitIDs(env)) { + lpDirectInput->Release(); + return (jlong)0; + } + + return (jlong)(long)lpDirectInput; +} + +/* + * Enumeration callback for devices + * + * returns DIENUM_CONTINUE or DIENUM_STOP + */ + +/** mikes old enum callback +BOOL CALLBACK EnumDeviceCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) +{ + DeviceParamData* pData = (DeviceParamData*)pvRef; + LPDIRECTINPUT8 lpDirectInput = pData->lpDirectInput; + JNIEnv* env = pData->env; + jobject obj = pData->obj; + jobject list = pData->list; + LPDIRECTINPUTDEVICE8 lpDevice = NULL; + LPUNKNOWN pUnknown = NULL; + + // Create the device object + HRESULT res = lpDirectInput->CreateDevice(lpddi->guidInstance, &lpDevice, + pUnknown); + if (res != DI_OK) { + PrintDIError("CreateDevice", res); + return DIENUM_STOP; + } + + LPDIRECTINPUTDEVICE8 lpDevice2 = NULL; + // Get the IDirectDrawDevice8 interface from the object + res = lpDevice->QueryInterface(IID_IDirectInputDevice8, + (void**)&lpDevice2); + if (res != DI_OK) { + PrintDIError("QueryInterface DID2", res); + lpDevice->Release(); + return DIENUM_STOP; + } + + // Set the data format + DWORD category = GET_DIDEVICE_TYPE(lpddi->dwDevType); + LPCDIDATAFORMAT lpDataFormat = &c_dfDIJoystick; + if (category == DI8DEVTYPE_MOUSE) { + lpDataFormat = &c_dfDIMouse; + } else if (category == DI8DEVTYPE_KEYBOARD) { + lpDataFormat = &c_dfDIKeyboard; + } + res = lpDevice2->SetDataFormat(lpDataFormat); + if (res != DI_OK) { + PrintDIError("SetDataFormat", res); + lpDevice2->Release(); + lpDevice->Release(); + return DIENUM_STOP; + } + + // If we are the mouse, we have to buffer the data + if (category == DI8DEVTYPE_MOUSE) { + DIPROPDWORD dipropdw; + dipropdw.diph.dwSize = sizeof(DIPROPDWORD); + dipropdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); + dipropdw.diph.dwObj = 0; + dipropdw.diph.dwHow = DIPH_DEVICE; + dipropdw.dwData = BUFFER_SIZE; + res = lpDevice2->SetProperty(DIPROP_BUFFERSIZE, &dipropdw.diph); + if (res != DI_OK) { + PrintDIError("SetProperty", res); + lpDevice2->Release(); + lpDevice->Release(); + return DIENUM_STOP; + } + } + + // Set the cooperative level + res = lpDevice2->SetCooperativeLevel(hwndDummy, + DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); + if (res != DI_OK) { + PrintDIError("SetCooperativeLevel", res); + lpDevice2->Release(); + lpDevice->Release(); + return DIENUM_STOP; + } + + // Acquire the device + res = lpDevice2->Acquire(); + if (res != DI_OK && res != S_FALSE) { + PrintDIError("Acquire", res); + lpDevice2->Release(); + lpDevice->Release(); + return DIENUM_STOP; + } + + // Set the variables for the Java callback + jint type = (jint)lpddi->dwDevType; + jstring productName = env->NewStringUTF(lpddi->tszProductName); + if (productName == NULL) { + lpDevice2->Release(); + lpDevice->Release(); + return DIENUM_STOP; + } + jstring instanceName = env->NewStringUTF(lpddi->tszInstanceName); + if (instanceName == NULL) { + lpDevice2->Release(); + lpDevice->Release(); + return DIENUM_STOP; + } + + // Add the device into the list + env->CallVoidMethod(obj, MID_AddDevice, list, (jlong)(long)lpDevice2, type, + productName, instanceName); + return DIENUM_CONTINUE; +} +*/ +/** jeff's new enum callback */ +BOOL CALLBACK EnumDeviceCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) +{ + DeviceParamData* pData = (DeviceParamData*)pvRef; + LPDIRECTINPUT8 lpDirectInput = pData->lpDirectInput; + JNIEnv* env = pData->env; + jobject obj = pData->obj; + jobject list = pData->list; + LPDIRECTINPUTDEVICE8 lpDevice = NULL; + LPUNKNOWN pUnknown = NULL; + HRESULT res; + + // Create the device object + if (FAILED(res = lpDirectInput->CreateDevice(lpddi->guidInstance, &lpDevice, + pUnknown))){ + PrintDIError("CreateDevice", res); + return DIENUM_STOP; + } + + /* + LPDIRECTINPUTDEVICE8 lpDevice2 = NULL; + // Get the IDirectDrawDevice8 interface from the object + res = lpDevice->QueryInterface(IID_IDirectInputDevice8, + (void**)&lpDevice2); + if (res != DI_OK) { + PrintDIError("QueryInterface DID2", res); + lpDevice->Release(); + return DIENUM_STOP; + } + */ + + // Set the data format + LPCDIDATAFORMAT lpDataFormat; + DWORD category = GET_DIDEVICE_TYPE(lpddi->dwDevType)&0xFF; + switch (category){ + case DI8DEVTYPE_KEYBOARD: + //printf("found Keyboard\n"); + lpDataFormat = &c_dfDIKeyboard; + break; + case DI8DEVTYPE_MOUSE: + //printf("found mouse\n"); + lpDataFormat = &c_dfDIMouse; + // set up buffering + DIPROPDWORD dipropdw; + dipropdw.diph.dwSize = sizeof(DIPROPDWORD); + dipropdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); + dipropdw.diph.dwObj = 0; + dipropdw.diph.dwHow = DIPH_DEVICE; + dipropdw.dwData = BUFFER_SIZE; + if (FAILED( + res = lpDevice->SetProperty(DIPROP_BUFFERSIZE, + &dipropdw.diph))) { + PrintDIError("SetProperty", res); + lpDevice->Release(); + return DIENUM_STOP; + } + break; + case DI8DEVTYPE_JOYSTICK: + default: + //printf("found stick\n"); + lpDataFormat = &c_dfDIJoystick; + break; + } + + if (FAILED(res = lpDevice->SetDataFormat(lpDataFormat))){ + PrintDIError("SetDataFormat", res); + lpDevice->Release(); + return DIENUM_STOP; + } + + // Set the cooperative level + if(FAILED(res = lpDevice->SetCooperativeLevel(hwndDummy, + DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))){ + PrintDIError("SetCooperativeLevel", res); + lpDevice->Release(); + return DIENUM_STOP; + } + + // get polling + DIDEVCAPS didc; + // Allocate space for all the device's objects (axes, buttons, POVS) + ZeroMemory( &didc, sizeof(DIDEVCAPS) ); + didc.dwSize = sizeof(DIDEVCAPS); + if (FAILED(res=lpDevice->GetCapabilities(&didc))){ + PrintDIError("Get Device Capabilities", res); + lpDevice->Release(); + return DIENUM_STOP; + } + jboolean polled = JNI_FALSE; + if ((didc.dwFlags)&DIDC_POLLEDDATAFORMAT) { + polled = JNI_TRUE; + } + + // Acquire the device + if(FAILED(res = lpDevice->Acquire())){ + PrintDIError("Acquire", res); + lpDevice->Release(); + return DIENUM_STOP; + } + + // Set the variables for the Java callback + jint type = (jint)lpddi->dwDevType&0xffff; + //printf("type == %x\n",type); + jstring productName = env->NewStringUTF(lpddi->tszProductName); + if (productName == NULL) { + lpDevice->Release(); + return DIENUM_STOP; + } + jstring instanceName = env->NewStringUTF(lpddi->tszInstanceName); + if (instanceName == NULL) { + lpDevice->Release(); + return DIENUM_STOP; + } + + // Add the device into the list + env->CallVoidMethod(obj, MID_AddDevice, list, (jlong)(long)lpDevice, type, + productName, instanceName,(jboolean)polled); + return DIENUM_CONTINUE; +} + +/* + * Class: org_java_games_input_DirectInputEnvironmentPlugin + * Method: enumDevices + * Signature: (JLjava/util/ArrayList;)Z + */ +extern "C" JNIEXPORT jboolean JNICALL +Java_net_java_games_input_DirectInputEnvironmentPlugin_enumDevices + (JNIEnv* env, jobject obj, jlong lDirectInput, jobject list) +{ + LPDIRECTINPUT8 lpDirectInput = (LPDIRECTINPUT8)(long)lDirectInput; + DWORD dwDevType = DI8DEVCLASS_ALL; + DeviceParamData data(lpDirectInput, env, obj, list); + LPVOID pvRef = (LPVOID)&data; + DWORD dwFlags = DIEDFL_ATTACHEDONLY; + HRESULT res; + if(FAILED(res=lpDirectInput->EnumDevices(dwDevType, + EnumDeviceCallback, pvRef, dwFlags))){ + PrintDIError("EnumDevices", res); + return JNI_FALSE; + } + return JNI_TRUE; +} + +/* + ****************************************************************************** + * DirectInputDevice + ****************************************************************************** + */ + +/* + * Class: org_java_games_input_DirectInputDevice + * Method: pollNative + * Signature: (J[B)Z + */ +extern "C" JNIEXPORT jboolean JNICALL +Java_net_java_games_input_DirectInputDevice_pollNative + (JNIEnv* env, jobject obj, jlong lDevice, jintArray baData, + jboolean pollme) +{ + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(long)lDevice; + // Reacquire the device + HRESULT res = lpDevice->Acquire(); + if (res != DI_OK && res != S_FALSE) { + PrintDIError("Acquire", res); + return JNI_FALSE; + } + // Poll the device + if (pollme == JNI_TRUE) { + res = lpDevice->Poll(); + if (res != DI_OK) { + PrintDIError("Poll", res); + return JNI_FALSE; + } + } + // Get the device state (data) + DIJOYSTATE data; + res = lpDevice->GetDeviceState(sizeof(data), &data); + if (res != DI_OK) { + PrintDIError("GetDeviceState", res); + return JNI_FALSE; + } + // Copy the data into the byte array + env->SetIntArrayRegion(baData, 0, (jsize)(sizeof(data)/4), (jint*)&data); + return JNI_TRUE; +} + +/* + * Enumeration callback for device objects + * + * returns DIENUM_CONTINUE or DIENUM_STOP + */ +BOOL CALLBACK EnumObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, + LPVOID pvRef) +{ + ObjectParamData* pData = (ObjectParamData*)pvRef; + LPDIRECTINPUTDEVICE8 lpDevice = pData->lpDevice; + JNIEnv* env = pData->env; + jobject obj = pData->obj; + jobject list = pData->list; + jobject identifier = NULL; + HRESULT res; + if (lpddoi->guidType == GUID_XAxis) { + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_X); + } else if (lpddoi->guidType == GUID_YAxis) { + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_Y); + } else if (lpddoi->guidType == GUID_ZAxis) { + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_Z); + } else if (lpddoi->guidType == GUID_RxAxis) { + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_RX); + } else if (lpddoi->guidType == GUID_RyAxis) { + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_RY); + } else if (lpddoi->guidType == GUID_RzAxis) { + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_RZ); + } else if (lpddoi->guidType == GUID_Slider) { + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_Slider); + } else if (lpddoi->guidType == GUID_Button) { + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_Button); + } else if (lpddoi->guidType == GUID_POV) { + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_POV); + } else { + // Do not add this axis into the list, since we don't know what it is + return DIENUM_CONTINUE; + } + if (identifier == NULL) { + return DIENUM_STOP; + } + if (DIDFT_GETTYPE(lpddoi->dwType)&DIDFT_AXIS){ + // set axis range + DIPROPRANGE joy_axis_range; + joy_axis_range.lMin = -32768; + joy_axis_range.lMax = 32768; + joy_axis_range.diph.dwSize=sizeof(DIPROPRANGE); + joy_axis_range.diph.dwHeaderSize=sizeof(DIPROPHEADER); + joy_axis_range.diph.dwHow = DIPH_BYID; + joy_axis_range.diph.dwObj=lpddoi->dwType; + if (FAILED( + res=lpDevice->SetProperty(DIPROP_RANGE,&joy_axis_range.diph))){ + PrintDIError("SetProperty", res); + } + } + jint didft = (jint)lpddoi->dwType; + jstring name = env->NewStringUTF(lpddoi->tszName); + // Add the axis into our list + env->CallVoidMethod(obj, MID_AddAxis, list, identifier, didft, + name); + return DIENUM_CONTINUE; +} + +/* + * Class: org_java_games_input_DirectInputDevice + * Method: enumObjects + * Signature: (JLjava/util/ArrayList;)Z + */ +extern "C" JNIEXPORT jboolean JNICALL +Java_net_java_games_input_DirectInputDevice_enumObjects + (JNIEnv* env, jobject obj, jlong lDevice, jobject list) +{ + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(long)lDevice; + ObjectParamData data(lpDevice, env, obj, list); + LPVOID pvRef = (LPVOID)&data; + DWORD dwFlags = DIDFT_ALL; + // Enum objects + HRESULT res = lpDevice->EnumObjects(EnumObjectsCallback, pvRef, dwFlags); + if (res != DI_OK) { + PrintDIError("EnumObjects", res); + return JNI_FALSE; + } + return JNI_TRUE; +} + +/* + ****************************************************************************** + * DirectInputKeyboard + ****************************************************************************** + */ + +/* + * Class: org_java_games_input_DirectInputKeyboard + * Method: pollNative + * Signature: (J[B)Z + */ +extern "C" JNIEXPORT jboolean JNICALL +Java_net_java_games_input_DirectInputKeyboard_pollNative + (JNIEnv* env, jobject obj, jlong lDevice, jbyteArray baData) +{ + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(long)lDevice; + // Reacquire the device + HRESULT res = lpDevice->Acquire(); + if (res != DI_OK && res != S_FALSE) { + PrintDIError("Acquire", res); + return JNI_FALSE; + } + // Get the device state (data) + char data[256]; + res = lpDevice->GetDeviceState(sizeof(data), data); + if (res != DI_OK) { + PrintDIError("GetDeviceState", res); + return JNI_FALSE; + } + env->SetByteArrayRegion(baData, 0, (jsize)sizeof(data), (jbyte*)&data); + return JNI_TRUE; +} + +/* + * Enumeration callback to rename keyboard keys + * + * returns DIENUM_CONTINUE or DIENUM_STOP + */ +BOOL CALLBACK RenameKeysCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, + LPVOID pvRef) +{ + ObjectParamData* pData = (ObjectParamData*)pvRef; + //LPDIRECTINPUTDEVICE8 lpDevice = pData->lpDevice; + JNIEnv* env = pData->env; + jobject obj = pData->obj; + jint index = (jint)lpddoi->dwOfs; + jstring name = env->NewStringUTF(lpddoi->tszName); + env->CallVoidMethod(obj, MID_RenameKey, index, name); + return DIENUM_CONTINUE; +} + +/* + * Class: org_java_games_input_DirectInputKeyboard + * Method: renameKeys + * Signature: (J)Z + */ +extern "C" JNIEXPORT jboolean JNICALL +Java_net_java_games_input_DirectInputKeyboard_renameKeys + (JNIEnv* env, jobject obj, jlong lDevice) +{ + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(long)lDevice; + ObjectParamData data(lpDevice, env, obj, NULL); + LPVOID pvRef = (LPVOID)&data; + DWORD dwFlags = DIDFT_ALL; + // Enum objects + HRESULT res = lpDevice->EnumObjects(RenameKeysCallback, pvRef, dwFlags); + if (res != DI_OK) { + PrintDIError("EnumObjects", res); + return JNI_FALSE; + } + return JNI_TRUE; +} + +/* + ****************************************************************************** + * DirectInputMouse + ****************************************************************************** + */ + +/* + * Class: org_java_games_input_DirectInputMouse + * Method: pollNative + * Signature: (J[B)Z + */ +extern "C" JNIEXPORT jboolean JNICALL +Java_net_java_games_input_DirectInputMouse_pollNative + (JNIEnv* env, jobject obj, jlong lDevice, jbyteArray baData) +{ + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(long)lDevice; + // Reacquire the device + HRESULT res = lpDevice->Acquire(); + if (res != DI_OK && res != S_FALSE) { + PrintDIError("Acquire", res); + return JNI_FALSE; + } + // Get the data + DIMOUSESTATE data; + res = lpDevice->GetDeviceState(sizeof(data), &data); + if (res != DI_OK) { + PrintDIError("GetDeviceState", res); + return JNI_FALSE; + } + // Set the data in our array + env->SetByteArrayRegion(baData, 0, (jsize)sizeof(data), (jbyte*)&data); + return JNI_TRUE; +} + +/* + * Enumeration callback to rename mouse axes + * + * returns DIENUM_CONTINUE or DIENUM_STOP + */ +BOOL CALLBACK RenameAxesCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, + LPVOID pvRef) +{ + ObjectParamData* pData = (ObjectParamData*)pvRef; + //LPDIRECTINPUTDEVICE8 lpDevice = pData->lpDevice; + JNIEnv* env = pData->env; + jobject obj = pData->obj; + jobject identifier; + switch (lpddoi->dwOfs) { + case DIMOFS_X: + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, + FID_X); + break; + case DIMOFS_Y: + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, + FID_Y); + break; + case DIMOFS_Z: + identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, + FID_Slider); + break; + case DIMOFS_BUTTON0: + identifier = env->GetStaticObjectField(CLASS_ButtonIdentifier, + FID_Left); + break; + case DIMOFS_BUTTON1: + identifier = env->GetStaticObjectField(CLASS_ButtonIdentifier, + FID_Right); + break; + case DIMOFS_BUTTON2: + identifier = env->GetStaticObjectField(CLASS_ButtonIdentifier, + FID_Middle); + break; + case DIMOFS_BUTTON3: + default: + return DIENUM_CONTINUE; // Not an axis we know + } + jstring name = env->NewStringUTF(lpddoi->tszName); + env->CallVoidMethod(obj, MID_RenameAxis, identifier, name); + return DIENUM_CONTINUE; +} + +/* + * Class: org_java_games_input_DirectInputMouse + * Method: renameAxes + * Signature: (J)Z + */ +extern "C" JNIEXPORT jboolean JNICALL +Java_net_java_games_input_DirectInputMouse_renameAxes + (JNIEnv* env, jobject obj, jlong lDevice) +{ + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(long)lDevice; + ObjectParamData data(lpDevice, env, obj, NULL); + LPVOID pvRef = (LPVOID)&data; + DWORD dwFlags = DIDFT_ALL; + // Enum objects + HRESULT res = lpDevice->EnumObjects(RenameAxesCallback, pvRef, dwFlags); + if (res != DI_OK) { + PrintDIError("EnumObjects", res); + return JNI_FALSE; + } + return JNI_TRUE; +} + + |