diff --git a/java/src/com/dt/iTunesController/ITPlaylist.java b/java/src/com/dt/iTunesController/ITPlaylist.java index d45dbee..4f38f3b 100644 --- a/java/src/com/dt/iTunesController/ITPlaylist.java +++ b/java/src/com/dt/iTunesController/ITPlaylist.java @@ -117,6 +117,14 @@ public class ITPlaylist extends ITObject { Dispatch.put(object, "SongRepeat", repeatMode.ordinal()); } + /** + * Cycle repeat modes. + */ + public void cycleSongRepeat() { + int repeat = Dispatch.get(object, "SongRepeat").getInt(); + Dispatch.put(object, "SongRepeat", (repeat + 1) % 3); + } + /** * Returns the playback repeat mode. * @return Returns the playback repeat mode. diff --git a/java/src/com/dt/iTunesController/iTunes.java b/java/src/com/dt/iTunesController/iTunes.java index 24e9e2c..06e5502 100644 --- a/java/src/com/dt/iTunesController/iTunes.java +++ b/java/src/com/dt/iTunesController/iTunes.java @@ -499,4 +499,8 @@ public class iTunes { Dispatch window = iTunes.getProperty("BrowserWindow").toDispatch(); return new ITBrowserWindow(window); } + + public void cycleSongRepeat() { + getCurrentPlaylist().cycleSongRepeat(); + } } diff --git a/java/src/pm/Main.java b/java/src/pm/Main.java index e806e37..42b59e7 100644 --- a/java/src/pm/Main.java +++ b/java/src/pm/Main.java @@ -24,6 +24,7 @@ import pm.exception.application.ApplicationExitException; import pm.exception.application.ApplicationInitialiseException; import pm.exception.device.DeviceExitException; import pm.exception.device.DeviceInitialiseException; +import pm.macro.Active; import pm.value.Action; public class Main extends EventListener { @@ -50,10 +51,37 @@ public class Main extends EventListener { add(new JIntellitypeDevice()); //add(new PlayerDevice()); //add(new RumblepadDevice()); - //add(new WiimoteDevice()); + add(new WiimoteDevice()); //add(new GUIDevice()); //add(new TextDevice()); //add(new LanTextDevice()); + startDevices(); + + //add(new ExampleApplication()); + //add(new WMPApplication()); + //add(new GomPlayerApplication()); + //add(new WinampApplication()); + add(new iTunesApplication()); + startApplications(); + } + + protected void startApplications() { + ArrayList removeList = new ArrayList(); + for (Application application : applicationCycle) { + try { + application.initialise(); + application.start(); + } catch (ApplicationInitialiseException e) { + removeList.add(application); + } + } + for (Application application : removeList) { + remove(application); + } + } + + protected void startDevices() { + ArrayList removeList = new ArrayList(); for (Device device : deviceList) { try { device.initialise(); @@ -63,20 +91,9 @@ public class Main extends EventListener { remove(device); } } - - add(new ExampleApplication()); - //add(new WMPApplication()); - //add(new GomPlayerApplication()); - //add(new WinampApplication()); - //add(new iTunesApplication()); - for (Application application : applicationCycle) { - try { - application.initialise(); - application.start(); - } catch (ApplicationInitialiseException e) { - remove(application); - } - } + for (Device device : removeList) { + remove(device); + } } public void exit() { diff --git a/java/src/pm/application/itunes/iTunesApplication.java b/java/src/pm/application/itunes/iTunesApplication.java index 1415923..51e3529 100644 --- a/java/src/pm/application/itunes/iTunesApplication.java +++ b/java/src/pm/application/itunes/iTunesApplication.java @@ -5,6 +5,7 @@ import pm.exception.application.ApplicationExitException; import pm.value.Action; import com.dt.iTunesController.ITCOMDisabledReason; +import com.dt.iTunesController.ITPlaylistRepeatMode; import com.dt.iTunesController.ITTrack; import com.dt.iTunesController.iTunes; import com.dt.iTunesController.iTunesEventsInterface; @@ -65,6 +66,11 @@ public class iTunesApplication extends Application implements iTunesEventsInterf break; case SHUFFLE: iTunes.toggleShuffle(); + //iTunes.fastForward(); + break; + case REPEAT: + iTunes.cycleSongRepeat(); + //iTunes.resume(); break; } } diff --git a/java/src/pm/application/windows/WindowsApplication.java b/java/src/pm/application/windows/WindowsApplication.java index 4014e05..c4bf76e 100644 --- a/java/src/pm/application/windows/WindowsApplication.java +++ b/java/src/pm/application/windows/WindowsApplication.java @@ -1,50 +1,30 @@ package pm.application.windows; import java.io.IOException; +import java.util.Map; import pm.Application; import pm.exception.application.ApplicationExitException; import pm.exception.application.ApplicationInitialiseException; -import pm.exception.application.windows.SendCommandException; -import pm.exception.application.windows.SendKeyException; import pm.util.Native; import pm.util.Windows; import pm.value.Command; import pm.value.Key; import pm.value.Type; -import com.eaio.nativecall.IntCall; -import com.eaio.nativecall.NativeCall; - abstract public class WindowsApplication extends Application { protected final static int TERMINATE_SLEEP = 500; protected final static int START_SLEEP = 500; protected final static String REGISTRY = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths"; - protected final static int WM_COMMAND = 0x0111; - protected final static int WM_APPCOMMAND = 0x0319; - protected String program; protected String title; protected String name; - protected String target; protected Process process; protected int handle; - protected IntCall sendMessage; - protected IntCall postMessage; - protected IntCall mapVirtualKey; - - static { - try { - NativeCall.init(); - } catch (Exception e) { - e.printStackTrace(); - } - } - public WindowsApplication(String program, String title, String name) { this.program = program; this.title = title; @@ -53,20 +33,18 @@ abstract public class WindowsApplication extends Application { } public void initialise() throws ApplicationInitialiseException { - sendMessage = new IntCall("user32", "SendMessageA"); - postMessage = new IntCall("user32", "PostMessageA"); - mapVirtualKey = new IntCall("user32", "MapVirtualKeyA"); - handle = Windows.findWindow(name, null); if (handle < 1) { String key = String.format("%s\\%s", REGISTRY, program); String path = Native.getValue(key); try { String command = String.format("\"%s\"", path); + command = Native.replaceVariables(command); process = Runtime.getRuntime().exec(command); sleep(START_SLEEP); handle = Windows.findWindow(name, null); - } catch (IOException e) {} + System.out.println(handle); + } catch (IOException e) {e.printStackTrace();} } if (handle < 1) { throw new ApplicationInitialiseException(); @@ -80,36 +58,28 @@ abstract public class WindowsApplication extends Application { super.exit(); } - protected void command(Command command) throws SendCommandException { - int result = sendMessage.executeCall(new Object[] { - handle, WM_APPCOMMAND, handle, command.getCode() << 16}); - if (result < 1 || sendMessage.getLastError() != null) { - throw new SendCommandException(); - } + protected void command(Command command) { + Windows.sendMessage(handle, Windows.WM_APPCOMMAND, handle, command.getCode() << 16); } - protected void command(int command) throws SendCommandException { - int result = sendMessage.executeCall(new Object[] { - handle, WM_COMMAND, command}); - if (result < 1 || sendMessage.getLastError() != null) { - throw new SendCommandException(); - } + protected void command(int command) { + Windows.sendMessage(handle, Windows.WM_COMMAND, command, 0); } - protected void key(Type key, int code) throws SendKeyException { - int scanCode = mapVirtualKey.executeCall(new Object[] {code, 0}); - int result = postMessage.executeCall(new Object[] { - handle, key.getCode(), code, 1 | (scanCode << 16)}); - if (result < 1 || postMessage.getLastError() != null) { - throw new SendKeyException(); - } + protected void user(int code) { + Windows.sendMessage(handle, Windows.WM_USER + code, 0, 0); } - protected void key(Type key, char character) throws SendKeyException { + protected void key(Type key, int code) { + int scanCode = Windows.mapVirtualKey(code, Windows.MAPVK_VK_TO_VSC); + Windows.postMessage(handle, key.getCode(), code, 1 | (scanCode << 16)); + } + + protected void key(Type key, char character) { key(key, (int) Character.toUpperCase(character)); } - protected void key(Type key, Key virtualKey) throws SendKeyException { + protected void key(Type key, Key virtualKey) { key(key, virtualKey.getCode()); } } diff --git a/java/src/pm/application/windows/gomplayer/GomPlayerApplication.java b/java/src/pm/application/windows/gomplayer/GomPlayerApplication.java index 331a8a8..10fa2e4 100644 --- a/java/src/pm/application/windows/gomplayer/GomPlayerApplication.java +++ b/java/src/pm/application/windows/gomplayer/GomPlayerApplication.java @@ -1,12 +1,7 @@ package pm.application.windows.gomplayer; import pm.application.windows.WindowsApplication; -import pm.exception.application.windows.SendCommandException; -import pm.exception.application.windows.SendKeyException; import pm.value.Action; -import pm.value.Command; -import pm.value.Key; -import pm.value.Type; public class GomPlayerApplication extends WindowsApplication { protected final static String PROGRAM = "GOM.exe"; @@ -18,35 +13,26 @@ public class GomPlayerApplication extends WindowsApplication { } public void action(Action action) { - System.out.println(handle); System.out.println("GomPlayerApplication: " + action); - try { - switch (action) { - case PLAY: - command(0x800C); - break; - case NEXT: - command(Command.MEDIA_NEXTTRACK); - break; - case PREVIOUS: - command(Command.MEDIA_PREVIOUSTRACK); - break; - case FORWARD: - command(Command.MEDIA_FAST_FORWARD); - break; - case REWIND: - command(Command.MEDIA_REWIND); - break; - case MUTE: - key(Type.DOWN, 'm'); - break; - case VOLUME_UP: - key(Type.DOWN, Key.UP); - break; - case VOLUME_DOWN: - key(Type.DOWN, Key.DOWN); - break; - } - } catch (SendCommandException e) {} catch (SendKeyException e) {} + switch (action) { + case PLAY: + command(0x800C); + break; + case FORWARD: + command(0x8009); + break; + case REWIND: + command(0x8008); + break; + case MUTE: + command(0x8016); + break; + case VOLUME_UP: + command(0x8014); + break; + case VOLUME_DOWN: + command(0x8013); + break; + } } } diff --git a/java/src/pm/application/windows/wmp/WMPApplication.java b/java/src/pm/application/windows/wmp/WMPApplication.java index c218885..6854082 100644 --- a/java/src/pm/application/windows/wmp/WMPApplication.java +++ b/java/src/pm/application/windows/wmp/WMPApplication.java @@ -1,8 +1,6 @@ package pm.application.windows.wmp; import pm.application.windows.WindowsApplication; -import pm.exception.application.ApplicationInitialiseException; -import pm.exception.application.windows.SendCommandException; import pm.value.Action; import pm.value.Command; @@ -17,15 +15,38 @@ public class WMPApplication extends WindowsApplication { public void action(Action action) { System.out.println("WMPApplication: " + action); - try { - switch (action) { - case PLAY: - command(Command.MEDIA_PLAY_PAUSE); - break; - case TEST: - command(Command.VOLUME_MUTE); - break; - } - } catch (SendCommandException e) {} + System.out.println(handle); + switch (action) { + case PLAY: + command(18808); + break; + case NEXT: + command(18811); + break; + case PREVIOUS: + command(18810); + break; + case FORWARD: + command(18813); + break; + case REWIND: + command(18814); + break; + case MUTE: + command(18817); + break; + case VOLUME_UP: + command(18815); + break; + case VOLUME_DOWN: + command(18816); + break; + case SHUFFLE: + command(18842); + break; + case REPEAT: + command(18843); + break; + } } } diff --git a/java/src/pm/device/wiimote/WiimoteDevice.java b/java/src/pm/device/wiimote/WiimoteDevice.java index ad479bc..9ad648f 100644 --- a/java/src/pm/device/wiimote/WiimoteDevice.java +++ b/java/src/pm/device/wiimote/WiimoteDevice.java @@ -11,6 +11,7 @@ import pm.event.Task; import pm.event.task.Continuous; import pm.event.task.Dynamic; import pm.exception.button.UnknownButtonException; +import pm.exception.device.DeviceExitException; import pm.exception.device.DeviceInitialiseException; import pm.macro.state.Hold; import pm.macro.state.Press; @@ -48,7 +49,7 @@ public class WiimoteDevice extends Device implements GestureListener { public void initialise() throws DeviceInitialiseException { wiimote = wiimoteService.getDevice(this); wiimote.activateMotionSensing(); - add( + /*add( new Hold(WiimoteButton.A), new Task(Action.TRAIN), new Task(Action.STOP)); @@ -61,7 +62,7 @@ public class WiimoteDevice extends Device implements GestureListener { add( new Hold(WiimoteButton.HOME), new Task(Action.RECOGNIZE), - new Task(Action.STOP)); + new Task(Action.STOP));*/ add( new Press(WiimoteButton.A), new Task(Action.PLAY, Target.APPLICATION)); @@ -73,7 +74,7 @@ public class WiimoteDevice extends Device implements GestureListener { new Task(Action.SHUFFLE, Target.APPLICATION)); add( new Press(WiimoteButton.TWO), - new Task(Action.NEXT, Target.MAIN)); + new Task(Action.REPEAT, Target.APPLICATION)); add( new Press(WiimoteButton.UP), new Task(Action.NEXT, Target.APPLICATION)); @@ -92,9 +93,13 @@ public class WiimoteDevice extends Device implements GestureListener { add( new Hold(WiimoteButton.PLUS), new Continuous(Action.VOLUME_UP, Target.APPLICATION, 100)); + add( + new Press(WiimoteButton.HOME), + new Task(Action.NEXT, Target.MAIN)); } - public void exit() { + public void exit() throws DeviceExitException { + super.exit(); wiimote.deactivateMotionSensing(); wiimoteService.exit(); } diff --git a/java/src/pm/event/EventListener.java b/java/src/pm/event/EventListener.java index 94db51c..9c216ca 100644 --- a/java/src/pm/event/EventListener.java +++ b/java/src/pm/event/EventListener.java @@ -16,6 +16,7 @@ public abstract class EventListener extends Listener implements Runnable { } public final void run() { + System.out.println(this); while (run) { if (eventQueue.isEmpty()) { sleep(); diff --git a/java/src/pm/event/EventManager.java b/java/src/pm/event/EventManager.java index beffdc3..ad85adb 100644 --- a/java/src/pm/event/EventManager.java +++ b/java/src/pm/event/EventManager.java @@ -39,7 +39,9 @@ public class EventManager { self.add(task); break; case APPLICATION: - applicationCycle.current().add(task); + if (applicationCycle.size() > 0) { + applicationCycle.current().add(task); + } break; default: for (EventListener eventListener : taskListenerList) { diff --git a/java/src/pm/exception/application/windows/SendCommandException.java b/java/src/pm/exception/util/SendCommandException.java similarity index 55% rename from java/src/pm/exception/application/windows/SendCommandException.java rename to java/src/pm/exception/util/SendCommandException.java index 09a316e..194f889 100644 --- a/java/src/pm/exception/application/windows/SendCommandException.java +++ b/java/src/pm/exception/util/SendCommandException.java @@ -1,4 +1,6 @@ -package pm.exception.application.windows; +package pm.exception.util; + +import pm.exception.application.windows.WindowsApplicationException; public class SendCommandException extends WindowsApplicationException { protected static final long serialVersionUID = 1L; diff --git a/java/src/pm/exception/application/windows/SendKeyException.java b/java/src/pm/exception/util/SendKeyException.java similarity index 54% rename from java/src/pm/exception/application/windows/SendKeyException.java rename to java/src/pm/exception/util/SendKeyException.java index 62be3ac..e705c9d 100644 --- a/java/src/pm/exception/application/windows/SendKeyException.java +++ b/java/src/pm/exception/util/SendKeyException.java @@ -1,4 +1,6 @@ -package pm.exception.application.windows; +package pm.exception.util; + +import pm.exception.application.windows.WindowsApplicationException; public class SendKeyException extends WindowsApplicationException { protected static final long serialVersionUID = 1L; diff --git a/java/src/pm/macro/Active.java b/java/src/pm/macro/Active.java index 6c23712..c29931b 100644 --- a/java/src/pm/macro/Active.java +++ b/java/src/pm/macro/Active.java @@ -4,16 +4,23 @@ package pm.macro; public class Active { protected Sequence sequence; protected int step; + //protected long start; + //protected long duration; public Active(Sequence sequence) { this.sequence = sequence; step = -1; + //start = System.nanoTime(); } public Sequence getSequence() { return sequence; } + /*public long getDuration() { + return duration; + }*/ + public boolean next(State state) { State next = sequence.get(++step); return next == null ? false : state.equals(next); @@ -21,5 +28,10 @@ public class Active { public boolean last() { return step == sequence.count() - 1; + /*boolean last = step == sequence.count() - 1; + if (last) { + duration = System.nanoTime() - start; + } + return last;*/ } } diff --git a/java/src/pm/util/Native.java b/java/src/pm/util/Native.java index 004e5ed..93f3d75 100644 --- a/java/src/pm/util/Native.java +++ b/java/src/pm/util/Native.java @@ -4,6 +4,7 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.InputMismatchException; +import java.util.Map; import java.util.NoSuchElementException; import java.util.Scanner; @@ -63,4 +64,12 @@ public class Native { } catch (IOException e) {} return null; } + + public static String replaceVariables(String string) { + Map env = System.getenv(); + for (String key : env.keySet()) { + string = string.replace(String.format("%%%s%%", key), env.get(key)); + } + return string; + } } diff --git a/java/src/pm/util/Windows.java b/java/src/pm/util/Windows.java index 5689a0c..fe4d8a7 100644 --- a/java/src/pm/util/Windows.java +++ b/java/src/pm/util/Windows.java @@ -1,18 +1,29 @@ package pm.util; import com.eaio.nativecall.IntCall; +import com.eaio.nativecall.NativeCall; public class Windows { + public static final int WM_COMMAND = 0x0111; + public static final int WM_APPCOMMAND = 0x0319; + public static final int MAPVK_VK_TO_VSC = 0; + public static final int WM_USER = 0x0400; + protected static IntCall findWindow; protected static IntCall sendMessage; protected static IntCall postMessage; protected static IntCall mapVirtualKey; static { - findWindow = new IntCall("user32", "FindWindowA"); - sendMessage = new IntCall("user32", "SendMessageA"); - postMessage = new IntCall("user32", "PostMessageA"); - mapVirtualKey = new IntCall("user32", "MapVirtualKeyA"); + try { + NativeCall.init(); + findWindow = new IntCall("user32", "FindWindowA"); + sendMessage = new IntCall("user32", "SendMessageA"); + postMessage = new IntCall("user32", "PostMessageA"); + mapVirtualKey = new IntCall("user32", "MapVirtualKeyA"); + } catch (Exception e) { + e.printStackTrace(); + } } public static int findWindow(String className, String windowName) { @@ -22,4 +33,12 @@ public class Windows { public static boolean postMessage(int handle, int message, int wParam, int lParam) { return postMessage.executeBooleanCall(new Object[] {handle, message, wParam, lParam}); } + + public static boolean sendMessage(int handle, int message, int wParam, int lParam) { + return sendMessage.executeBooleanCall(new Object[] {handle, message, wParam, lParam}); + } + + public static int mapVirtualKey(int code, int mapType) { + return mapVirtualKey.executeCall(new Object[] {code, 0}); + } }