666 lines
17 KiB
Java
666 lines
17 KiB
Java
/**
|
|
* This file is part of WiiuseJ.
|
|
*
|
|
* WiiuseJ is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* WiiuseJ is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with WiiuseJ. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
package wiiusej;
|
|
|
|
import java.util.concurrent.Semaphore;
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
|
import javax.swing.event.EventListenerList;
|
|
|
|
import wiiusej.values.Calibration;
|
|
import wiiusej.values.RawAcceleration;
|
|
import wiiusej.wiiusejevents.utils.EventsGatherer;
|
|
import wiiusej.wiiusejevents.utils.WiiUseApiListener;
|
|
import wiiusej.wiiusejevents.wiiuseapievents.WiiUseApiEvent;
|
|
|
|
/**
|
|
* Class that manages the use of Wiiuse API.
|
|
*
|
|
* @author guiguito
|
|
*/
|
|
public class WiiUseApiManager extends Thread {
|
|
|
|
private static WiiUseApiManager instance = new WiiUseApiManager();
|
|
|
|
private final EventListenerList listeners = new EventListenerList();
|
|
|
|
private Semaphore semaphore = new Semaphore(0);
|
|
|
|
private Wiimote[] wiimotes;
|
|
|
|
private WiiUseApi wiiuse = WiiUseApi.getInstance();
|
|
|
|
private int connected = -1;
|
|
|
|
private AtomicBoolean running = new AtomicBoolean(false);
|
|
|
|
private boolean leave = false;
|
|
|
|
public static int WIIUSE_STACK_UNKNOWN = 0;
|
|
public static int WIIUSE_STACK_MS = 1;
|
|
public static int WIIUSE_STACK_BLUESOLEIL = 2;
|
|
|
|
public static WiiUseApiManager getInstance() {
|
|
return instance;
|
|
}
|
|
|
|
/**
|
|
* Get wiimotes. Load library if necessary. Connect to wiimotes if
|
|
* necessary. Start polling if necessary. Return an array with the connected
|
|
* wiimotes.
|
|
*
|
|
* @param nb
|
|
* try to connect nb wiimotes.
|
|
* @param rumble
|
|
* make the connected wiimotes rumble.
|
|
*
|
|
* @return an array with connected wiimotes or NULL.
|
|
*/
|
|
public static Wiimote[] getWiimotes(int nb, boolean rumble) {
|
|
return getWiimotesPrivate(nb, rumble, false, WIIUSE_STACK_UNKNOWN);
|
|
}
|
|
|
|
/**
|
|
* Get wiimotes. Load library if necessary. Connect to wiimotes if
|
|
* necessary. Start polling if necessary. Return an array with the connected
|
|
* wiimotes.
|
|
*
|
|
* @param nb
|
|
* try to connect nb wiimotes.
|
|
* @param rumble
|
|
* make the connected wiimotes rumble.*
|
|
* @param stackType
|
|
* the stack type : WiiUseApiManager.WIIUSE_STACK_UNKNOWN or
|
|
* WiiUseApiManager.WIIUSE_STACK_MS or
|
|
* WiiUseApiManager.WIIUSE_STACK_BLUESOLEIL
|
|
*
|
|
* @return an array with connected wiimotes or NULL.
|
|
*/
|
|
public static Wiimote[] getWiimotes(int nb, boolean rumble, int stackType) {
|
|
return getWiimotesPrivate(nb, rumble, true, stackType);
|
|
}
|
|
|
|
/**
|
|
* Get wiimotes. Load library if necessary. Connect to wiimotes if
|
|
* necessary. Start polling if necessary. Return an array with the connected
|
|
* wiimotes.
|
|
*
|
|
* @param nb
|
|
* try to connect nb wiimotes.
|
|
* @param rumble
|
|
* make the connected wiimotes rumble.*
|
|
* @param forceStackType
|
|
* true if we want to force the stack type.
|
|
* @param stackType
|
|
* the stack type : WiiUseApiManager.WIIUSE_STACK_UNKNOWN or
|
|
* WiiUseApiManager.WIIUSE_STACK_MS or
|
|
* WiiUseApiManager.WIIUSE_STACK_BLUESOLEIL
|
|
*
|
|
* @return an array with connected wiimotes or NULL.
|
|
*/
|
|
private synchronized static Wiimote[] getWiimotesPrivate(int nb,
|
|
boolean rumble, boolean forceStackType, int stackType) {
|
|
WiiUseApiManager manager = getInstance();
|
|
|
|
if (manager.leave)
|
|
return null;// wiiusej definitively stopped
|
|
|
|
if (manager.connected <= 0 && !manager.running.get()) {
|
|
// connect wiimotes.
|
|
int nbWiimotes = manager.connectWiimotes(nb, rumble,
|
|
forceStackType, stackType);
|
|
manager.wiimotes = new Wiimote[nbWiimotes];
|
|
for (int i = 0; i < nbWiimotes; i++) {
|
|
Wiimote wim = new Wiimote(WiiUseApi.getInstance().getUnId(i),
|
|
manager);
|
|
manager.wiimotes[i] = wim;
|
|
manager.addWiiUseApiListener(wim);
|
|
}
|
|
// Set leds on wiimote
|
|
for (Wiimote wiimote : manager.wiimotes) {
|
|
int id = wiimote.getId();
|
|
if (id % 4 == 0) {
|
|
wiimote.setLeds(true, true, true, true);
|
|
} else if (id % 4 == 1) {
|
|
wiimote.setLeds(true, false, false, false);
|
|
} else if (id % 4 == 2) {
|
|
wiimote.setLeds(true, true, false, false);
|
|
} else if (id % 4 == 3) {
|
|
wiimote.setLeds(true, true, true, false);
|
|
}
|
|
}
|
|
// make the connected wiimotes rumble
|
|
if (rumble) {
|
|
for (Wiimote wiimote : manager.wiimotes) {
|
|
wiimote.activateRumble();
|
|
}
|
|
try {
|
|
sleep(500);
|
|
} catch (InterruptedException e) {
|
|
}
|
|
for (Wiimote wiimote : manager.wiimotes) {
|
|
wiimote.deactivateRumble();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (manager.connected == 0) {// no wiimote connected
|
|
// return empty array
|
|
return new Wiimote[0];
|
|
}
|
|
|
|
if (!manager.isAlive())// start wiiuseJ polling
|
|
manager.start();
|
|
|
|
manager.semaphore.release(1);
|
|
|
|
return manager.wiimotes;
|
|
}
|
|
|
|
/**
|
|
* Connect wiimote and get the number of wiimotes connected. Supposed to be
|
|
* used once.
|
|
*
|
|
* @param nb
|
|
* try to connect nb wiimotes
|
|
* @param rumble
|
|
* make the connected wiimotes rumble
|
|
* @param forceStackType
|
|
* true if we want to force the stack type.
|
|
* @param stackType
|
|
* the stack type : WiiUseApiManager.WIIUSE_STACK_UNKNOWN or
|
|
* WiiUseApiManager.WIIUSE_STACK_MS or
|
|
* WiiUseApiManager.WIIUSE_STACK_BLUESOLEIL
|
|
* @return 0 if nothing connected or the number of wiimotes connected.
|
|
*/
|
|
private int connectWiimotes(int nb, boolean rumble, boolean forceStackType,
|
|
int stackType) {
|
|
if (connected <= 0) {
|
|
int nbWiimotesFound;
|
|
wiiuse.init(nb);
|
|
// force bluetooth stack type ?
|
|
if (forceStackType)
|
|
setBlueToothstackType(stackType);
|
|
nbWiimotesFound = wiiuse.find(nb, 3);
|
|
connected = wiiuse.connect(nbWiimotesFound);
|
|
return connected;
|
|
} else {// library not loaded, no wiimotes connected
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Ask the thread to close a connection.
|
|
*
|
|
* @param id
|
|
* id of the wiimote to disconnect.
|
|
*/
|
|
protected void closeConnection(int id) {
|
|
int index = 0;
|
|
boolean found = false;
|
|
while (index < wiimotes.length && !found) {
|
|
if (wiimotes[index]!=null && wiimotes[index].getId() == id) {// we have a wiimote with this
|
|
// id
|
|
// remove the wiimote
|
|
removeWiiUseApiListener(wiimotes[index]);
|
|
wiimotes[index] = null;
|
|
connected--;
|
|
if (connected == 0) {// stop this thread if there is
|
|
// no more wiimotes connected.
|
|
// stop thread
|
|
running.set(false);
|
|
}
|
|
/* Close connection in wiiuse */
|
|
wiiuse.closeConnection(index);
|
|
}
|
|
index++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the number of wiimotes connected.
|
|
*
|
|
* @return the number of wiimotes connected.
|
|
*/
|
|
public static int getNbConnectedWiimotes() {
|
|
return getInstance().connected;
|
|
}
|
|
|
|
/**
|
|
* Stop thread and shutdown wiiuse Api.
|
|
*/
|
|
public static void shutdown() {
|
|
WiiUseApiManager manager = getInstance();
|
|
int pastConnected = manager.connected;
|
|
if (manager.connected > 0) {
|
|
for (Wiimote wim : manager.wiimotes) {
|
|
if (wim != null)
|
|
wim.disconnect();
|
|
}
|
|
}
|
|
manager.running.set(false);
|
|
if (pastConnected > 0) {
|
|
manager.wiiuse.cleanUp();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Stop wiiuseJ definitively for this program. It finishes Wiiusej thread
|
|
* and shutdown wiiuse API.
|
|
*/
|
|
public static void definitiveShutdown() {
|
|
getInstance().leave = true;
|
|
shutdown();
|
|
}
|
|
|
|
/**
|
|
* Activate the rumble for the wiimote with the given id.
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
*/
|
|
protected void activateRumble(int id) {
|
|
wiiuse.activateRumble(id);
|
|
}
|
|
|
|
/**
|
|
* Deactivate the rumble for the wiimote with the given id.
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
*/
|
|
protected void deactivateRumble(int id) {
|
|
wiiuse.deactivateRumble(id);
|
|
}
|
|
|
|
/**
|
|
* Activate IR Tracking for the wiimote with the given id.
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
*/
|
|
protected void activateIRTRacking(int id) {
|
|
wiiuse.activateIRTracking(id);
|
|
}
|
|
|
|
/**
|
|
* Deactivate IR Tracking for the wiimote with the given id.
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
*/
|
|
protected void deactivateIRTRacking(int id) {
|
|
wiiuse.deactivateIRTracking(id);
|
|
}
|
|
|
|
/**
|
|
* Activate motion sensing for the wiimote with the given id.
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
*/
|
|
protected void activateMotionSensing(int id) {
|
|
wiiuse.activateMotionSensing(id);
|
|
}
|
|
|
|
/**
|
|
* Deactivate motion sensing for the wiimoter with the given id.
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
*/
|
|
protected void deactivateMotionSensing(int id) {
|
|
wiiuse.deactivateMotionSensing(id);
|
|
}
|
|
|
|
/**
|
|
* Activate smoothing the wiimotes with the given id.
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
*/
|
|
protected void activateSmoothing(int id) {
|
|
wiiuse.activateSmoothing(id);
|
|
}
|
|
|
|
/**
|
|
* Deactivate smoothing the wiimotes with the given id.
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
*/
|
|
protected void deactivateSmoothing(int id) {
|
|
wiiuse.deactivateSmoothing(id);
|
|
}
|
|
|
|
/**
|
|
* Activate continuous for the wiimotes with the given id.
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
*/
|
|
protected void activateContinuous(int id) {
|
|
wiiuse.activateContinuous(id);
|
|
}
|
|
|
|
/**
|
|
* Deactivate continuous for the wiimotes with the given id.
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
*/
|
|
protected void deactivateContinuous(int id) {
|
|
wiiuse.deactivateContinuous(id);
|
|
}
|
|
|
|
/**
|
|
* Set leds for the wiimotes with the given id.
|
|
*
|
|
* @param id
|
|
* id of the wiimote
|
|
* @param l1
|
|
* status of led1. True : ON, False : OFF.
|
|
* @param l2
|
|
* status of led2. True : ON, False : OFF.
|
|
* @param l3
|
|
* status of led3. True : ON, False : OFF.
|
|
* @param l4
|
|
* status of led4. True : ON, False : OFF.
|
|
*/
|
|
protected void setLeds(int id, boolean l1, boolean l2, boolean l3,
|
|
boolean l4) {
|
|
wiiuse.setLeds(id, l1, l2, l3, l4);
|
|
}
|
|
|
|
/**
|
|
* Set the orientation threshold for the given id. (minimum angle between
|
|
* two events)
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
* @param th
|
|
* threshold in degrees.
|
|
*/
|
|
protected void setOrientationThreshold(int id, float th) {
|
|
wiiuse.setOrientThreshold(id, th);
|
|
}
|
|
|
|
/**
|
|
* Set the acceleration threshold for the given id. (minimum angle between
|
|
* two events)
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
* @param th
|
|
* threshold.
|
|
*/
|
|
protected void setAccelerationThreshold(int id, int th) {
|
|
wiiuse.setAccelThreshold(id, th);
|
|
}
|
|
|
|
/**
|
|
* Set alpha smoothing for the given id.
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
* @param th
|
|
* threshold.
|
|
*/
|
|
protected void setAlphaSmoothing(int id, float th) {
|
|
wiiuse.setAlphaSmoothing(id, th);
|
|
}
|
|
|
|
/**
|
|
* Try to resync with the wiimote by starting a new handshake.
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
*/
|
|
protected void reSync(int id) {
|
|
wiiuse.reSync(id);
|
|
}
|
|
|
|
/**
|
|
* Set screen aspect ratio to 4/3 for the given id.
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
*/
|
|
protected void setScreenAspectRatio43(int id) {
|
|
wiiuse.setScreenRatio43(id);
|
|
}
|
|
|
|
/**
|
|
* Set screen aspect ratio to 16/9 for the given id.
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
*/
|
|
protected void setScreenAspectRatio169(int id) {
|
|
wiiuse.setScreenRatio169(id);
|
|
}
|
|
|
|
/**
|
|
* Set the sensor bar to be above the screen.
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
*/
|
|
protected void setSensorBarAboveScreen(int id) {
|
|
wiiuse.setSensorBarAboveScreen(id);
|
|
}
|
|
|
|
/**
|
|
* Set the sensor bar to be below the screen.
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
*/
|
|
protected void setSensorBarBelowScreen(int id) {
|
|
wiiuse.setSensorBarBelowScreen(id);
|
|
}
|
|
|
|
/**
|
|
* Set virtual resolution. It is used to automatically compute the position
|
|
* of a cursor on this virtual screen using the sensor bar. These results
|
|
* come in the IREvent.
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
* @param x
|
|
* x resolution.
|
|
* @param y
|
|
* y resolution.
|
|
*/
|
|
protected void setVirtualResolution(int id, int x, int y) {
|
|
wiiuse.setVirtualScreenResolution(id, x, y);
|
|
}
|
|
|
|
/**
|
|
* Get Status for the wiimote for the given id.
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
*/
|
|
protected void getStatus(int id) {
|
|
wiiuse.getStatus(id);
|
|
}
|
|
|
|
/**
|
|
* Set the normal and expansion handshake timeouts.
|
|
*
|
|
* @param id
|
|
* the id of the wiimote concerned.
|
|
* @param normalTimeout
|
|
* The timeout in milliseconds for a normal read.
|
|
* @param expansionTimeout
|
|
* The timeout in millisecondsd to wait for an expansion
|
|
* handshake.
|
|
*/
|
|
protected void setTimeout(int id, short normalTimeout,
|
|
short expansionTimeout) {
|
|
wiiuse.setTimeout(id, normalTimeout, expansionTimeout);
|
|
}
|
|
|
|
/**
|
|
* Set the IR sensitivity.
|
|
*
|
|
* @param id
|
|
* the id of the wiimote concerned.
|
|
* @param level
|
|
* 1-5, same as Wii system sensitivity setting. If the level is <
|
|
* 1, then level will be set to 1. If the level is > 5, then
|
|
* level will be set to 5.
|
|
*/
|
|
protected void setIrSensitivity(int id, int level) {
|
|
wiiuse.setIrSensitivity(id, level);
|
|
}
|
|
|
|
/**
|
|
* Set the nunchuk orientation threshold for the given id. (minimum angle
|
|
* between two events)
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
* @param th
|
|
* threshold in degrees.
|
|
*/
|
|
protected void setNunchukOrientationThreshold(int id, float th) {
|
|
wiiuse.setNunchukOrientationThreshold(id, th);
|
|
}
|
|
|
|
/**
|
|
* Set the nunchuk acceleration threshold for the given id. (minimum angle
|
|
* between two events)
|
|
*
|
|
* @param id
|
|
* id of the wiimote.
|
|
* @param th
|
|
* threshold.
|
|
*/
|
|
protected void setNunchukAccelerationThreshold(int id, int th) {
|
|
wiiuse.setNunchukAccelerationThreshold(id, th);
|
|
}
|
|
|
|
/**
|
|
* Force the bluetooth stack type.(useful only for windows)
|
|
*
|
|
* @param type
|
|
* must be WIIUSE_STACK_UNKNOWN or WIIUSE_STACK_MS or
|
|
* WIIUSE_STACK_BLUESOLEIL.
|
|
*/
|
|
private void setBlueToothstackType(int type) {
|
|
wiiuse.windowsSetBluetoothStack(type);
|
|
}
|
|
|
|
@Override
|
|
public void run() {
|
|
|
|
while (!leave) {
|
|
try {
|
|
semaphore.acquire();
|
|
} catch (InterruptedException e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
if (connected > 0) {
|
|
running.set(true);
|
|
|
|
EventsGatherer gather = new EventsGatherer(connected);
|
|
|
|
// Start polling and tell the observers when there are Wiimote
|
|
// events
|
|
while (running.get() && connected > 0) {
|
|
|
|
/* Polling */
|
|
wiiuse.specialPoll(gather);
|
|
|
|
/* deal with events gathered in Wiiuse API */
|
|
for (WiiUseApiEvent evt : gather.getEvents()) {
|
|
if (evt.getWiimoteId() != -1) {// event filled
|
|
// there is an event notify observers
|
|
notifyWiiUseApiListener(evt);
|
|
if (evt.getEventType() == WiiUseApiEvent.DISCONNECTION_EVENT) {
|
|
// check if it was a disconnection
|
|
// in this case disconnect the wiimote
|
|
closeConnection(evt.getWiimoteId());
|
|
}
|
|
} else {
|
|
System.out
|
|
.println("There is an event with id == -1 ??? there is a problem !!! : "
|
|
+ evt);
|
|
}
|
|
}
|
|
gather.clearEvents();
|
|
}
|
|
}/* else {
|
|
if (connected <= 0) {
|
|
System.out.println("No wiimotes connected !");
|
|
}
|
|
}*/
|
|
}// end while true
|
|
}
|
|
|
|
/**
|
|
* Add WiiUseApiListener to the listeners list.
|
|
*
|
|
* @param listener
|
|
* a WiiUseApiListener
|
|
*/
|
|
protected void addWiiUseApiListener(WiiUseApiListener listener) {
|
|
listeners.add(WiiUseApiListener.class, listener);
|
|
}
|
|
|
|
/**
|
|
* Remove WiiUseApiListener from the listeners list.
|
|
*
|
|
* @param listener
|
|
* a WiiUseApiListener
|
|
*/
|
|
protected void removeWiiUseApiListener(WiiUseApiListener listener) {
|
|
listeners.remove(WiiUseApiListener.class, listener);
|
|
}
|
|
|
|
/**
|
|
* Get the list of WiiUseApiListeners.
|
|
*
|
|
* @return the list of WiiUseApiListeners.
|
|
*/
|
|
protected WiiUseApiListener[] getWiiUseApiListeners() {
|
|
return listeners.getListeners(WiiUseApiListener.class);
|
|
}
|
|
|
|
/**
|
|
* Notify WiiUseApiListeners that an event occured.
|
|
*
|
|
* @param evt
|
|
* GenericEvent occured
|
|
*/
|
|
private void notifyWiiUseApiListener(WiiUseApiEvent evt) {
|
|
for (WiiUseApiListener listener : getWiiUseApiListeners()) {
|
|
listener.onWiiUseApiEvent(evt);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called by the garbage collector at the end.
|
|
*/
|
|
protected void finalize() throws Throwable {
|
|
shutdown();
|
|
}
|
|
}
|