IrEye - Infrared Remote Control

Command Interface



IrEye implements a command interface that allows everyone to easy develop new user commands in Java. With the help of the Java Native Interface it is also simple to use C++ routines for system-dependent operations.
Although most operations in windows can be done with simulated key-strokes, it is better to have specialized commands, that always work, even when the destination window is in the background. Take WinAmp for example: it is cool to control WinAmp with the remote control while writing emails.

Please email me if you develop new commands! Maybe you'd like to release them with IrEye.



IrEye commands are classes that extend ireye.irEyeCommand. By adding a new command to a command list in irReceiver-functions a new instance of this command is created and serialized (saved) with the remote control. When an irReceiver-function is executed, it calls the run() method of that command instance, which should be overridden. When a command is selected in the command list, its configuration() method is called to show the returned Component in the lower frame. If the command has instances, that should be changeable by the user, the configuration() method should also be overridden. At least the toString() method should be overridden as shown below to give the command a proper name.

Container classes
These IrEye commands are inner classes of the outer container class, which extends ireye.irEyeCommandClass. This container class consists of a static part and an instance part. IrEye creates only one instance of the container class. This instance is serialized on exit and deserialized on start of IrEye to save all non-static members. The configuration() method should be overridden to return a configuration panel with components that manipulate these non-static members. When the is deserialized or created, the init() method is called, which should be overridden and at least set a static pointer to itself, so that the commands can access the saved variables. The toString() method should also be overridden to name the container class. The static part contains the commands, a static pointer to the instance and static variables that allow communication between commands.

Naming and location
When IrEye starts, it makes a list of subdirs in the "...\ireye\commands\" directory and then tries to find following classes: "ireye.commands.>dirName<.>dirName<". For this reason the container class has to be in the package "ireye.commands.>containerClassName<" and be located in "...\ireye\commands\>containerClassName<\" ("..." is the path to IrEye). So to install new commands it is only necessary to copy the container directory to "...\ireye\commands\". Native libraries can also be located in the container directory. The loadeLibrary method loads a library relative to the "...\ireye\commands\" directory (see example).



package ireye.commands.winamp;

the command class package must have the format:
import ireye.*;

it is necessary to import ireye.*.
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;


public class winamp extends irEyeCommandClass {

it is important that the class has the same name as the ending of the package and that it extends ireye.irEyeCommandClass.

public static final String commandClassName = "NullSoft WinAmp";

define a String constant for the command class name as it should appear in the IrEye window.

private static winamp winamp = null;

winamp is the static pointer to the instance of the class winamp, which is set in the init() method.

private static native void send_WM_COMMAND(int command);


static { loadLibrary("winamp\\winamp_lib.dll"); }

public static class forward extends irEyeCommand { the first command: commands must be public static

public void run() {

run(...) overridden

do {




} while (syncDelay(winamp.seekSpeed));

syncDelay(...) see irEyeCommandClass

} // run()


public String toString() { return commandName(commandClassName, "Fast-forward 5 seconds"); }

toString() overridden
} // forward

public static class play_Location extends irEyeCommand { the second command

private StringBuffer location = new StringBuffer();

instance members are serialized with the command

public void run() {


runWinamp("\"" + location.toString() + "\"");

runWinamp(...) uses winamp.winampPath

} // run()


public String toString() { return commandName(commandClassName, "Play location"); }


public Component configuration() {

configuration() overridden to return a Component that is shown in the configuration frame an manipulate location

return (new JScrollPane(new locationConfiguration(location)));


} // configuration()

} // play_location


private static class locationConfiguration extends JPanel {

private classes are not commands

private static StringBuffer path;


public locationConfiguration(StringBuffer path) {


this.path = path;


choosePathPanel pathPanel = new choosePathPanel(path, "choose location");






} // locationConfiguration()

} // locationConfiguration  

// ********** instance part **********


private int seekSpeed = 100;

instance members that will be saved

StringBuffer winampPath = new StringBuffer("C:\\Programme\\Winamp\\winamp.exe");


public void init() { winamp.winamp = this; }

init() is called on start and has to set the static pointer to this instance

public String toString() { return commandClassName; }


public Component configuration() { return (new JScrollPane( new WinAmp_configuration()) ); }


private class WinAmp_configuration extends JPanel {

a panel that manipulate seekSpeed and winampPath

public WinAmp_configuration() {

this panel is shown on a click in the command pool







} // WinAmp_configuration()

} // WinAmp_configuration  


Class ireye.irEyeCommand

public synchronized void run()

Is called when an irReceiverFunction is executed. Should be overridden to provide functionality.

public Component configuration()

Is called to get a Component for the configuration frame. Should be overridden to return a Component that manipulates the command's instance members.

public String toString()

Should be overridden in the following way: public String toString() { return commandName("container name", "command name"); }


Class ireye.irEyeCommandClass


public static boolean signalStillArriving()

Returns true, if the button is still pressed.

public static void delay(int milliseconds)

Waits an amount of milliseconds.

public static void syncDelay()

Waits until the pressed button of the remote control is released.

public static boolean syncDelay(int timeOut)

Waits until the pressed button is released or the time is out.
returns: true - when the time is out; false - when the button was released

public static String commandName(String commandClassName, String commandName)

Returns the correct command name in dependent on the situation.

public static void loadLibrary(String path)

Loads a native code library from the path relative to the ireye.commands path.

public static void dataModified()

Notifies the current irReceiverFunction that the command configuration has been modified.

public static void printStatus(String text)

Prints the text in the IrEye statusbar.

public static void runProgram(String programPath, String parameter)

Just runs an executable from the program path with the specified parameter. Only to make the code simpler.

public static void scheduleTimerTask(TimerTask task, long delay)

Schedules a java.util.TimerTask in the irEye timer. It is not necessary to create a separate timer thread for simple tasks.




No questions till now...


It is really difficult to write an understandable documentation of something complex that you have in mind. It is my first attempt to describe this issue. So if you are interested but don't understand the text or have further questions please ask me! I'll try to answer and to improve this documentation. And when you are new to JAVA maybe I can help you.


Copyright (c) 2001 Artur Wiebe