aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/DX8
diff options
context:
space:
mode:
authorjeffpk <[email protected]>2003-06-06 21:04:07 +0000
committerjeffpk <[email protected]>2003-06-06 21:04:07 +0000
commit454233e113a22a149fe45624ce3e405474ded053 (patch)
tree173b3916eff745d921bc22fc858f4bddcc966bde /plugins/DX8
parent4275dabe7f7cf2e427626550cb54f5e8ba104e44 (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.txt46
-rw-r--r--plugins/DX8/build.xml103
-rw-r--r--plugins/DX8/src/java/net/java/games/input/DirectInputAxis.java211
-rw-r--r--plugins/DX8/src/java/net/java/games/input/DirectInputDevice.java207
-rw-r--r--plugins/DX8/src/java/net/java/games/input/DirectInputEnvironmentPlugin.java183
-rw-r--r--plugins/DX8/src/java/net/java/games/input/DirectInputKeyboard.java208
-rw-r--r--plugins/DX8/src/java/net/java/games/input/DirectInputMouse.java311
-rw-r--r--plugins/DX8/src/native/input.cpp888
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;
+}
+
+