Created
August 18, 2012 17:37
-
-
Save Tolriq/3388636 to your computer and use it in GitHub Desktop.
EventClient
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.leetzone.android.yatselibs.client.xbmceden; | |
import java.io.FileInputStream; | |
import java.io.IOException; | |
import java.net.InetAddress; | |
import java.util.Stack; | |
import org.leetzone.android.utils.Logger; | |
import org.leetzone.android.yatselibs.client.xbmceden.eventclient.Packet; | |
import org.leetzone.android.yatselibs.client.xbmceden.eventclient.PacketACTION; | |
import org.leetzone.android.yatselibs.client.xbmceden.eventclient.PacketBUTTON; | |
import org.leetzone.android.yatselibs.client.xbmceden.eventclient.PacketLOG; | |
import org.leetzone.android.yatselibs.client.xbmceden.eventclient.PacketMOUSE; | |
import org.leetzone.android.yatselibs.client.xbmceden.eventclient.PacketNOTIFICATION; | |
import org.leetzone.android.yatselibs.client.xbmceden.eventclient.PacketPING; | |
/** | |
* XBMC Event Client Class | |
* | |
* Implements an XBMC-Client. This class can be used to implement your own | |
* application which should act as a Input device for XBMC. Also starts a | |
* Ping-Thread, which tells the XBMC EventServer that the client is alive. | |
* Therefore if you close your application you SHOULD call stopClient()! | |
* | |
* 03.09.2009 freezy changed class name and member variables | |
* | |
* @author Stefan Agner | |
*/ | |
public class EventClient { | |
private final static String TAG = "Xbmc-EventClient"; | |
private boolean mHasIcon = false; | |
private byte mIconType = Packet.ICON_NONE; | |
private byte[] mIconData; | |
// private InetAddress mHostAddress; | |
private String mHostName; | |
private int mHostPort; | |
private final PacketQueue mPacketQueue = new PacketQueue(); | |
private final Thread mPacketSenderThread = new Thread(new packetSenderManager()); | |
public void Stop() { | |
try { | |
synchronized (mPacketQueue.packetRefs) { | |
mPacketQueue.packetRefs.clear(); | |
} | |
mPacketSenderThread.interrupt(); | |
} catch (Exception e) { | |
} | |
} | |
private void SendPacket(Packet p, String host, int port) { | |
PacketData packetdata = new PacketData(); | |
packetdata.packet = p; | |
packetdata.host = host; | |
packetdata.port = port; | |
synchronized (mPacketQueue.packetRefs) { | |
mPacketQueue.packetRefs.push(packetdata); | |
mPacketQueue.packetRefs.notifyAll(); | |
} | |
// Start thread if it's not started yet | |
if (mPacketSenderThread.getState() == Thread.State.NEW) | |
mPacketSenderThread.start(); | |
} | |
/** | |
* Starts a XBMC EventClient without an icon. | |
* | |
* @param hostAddress | |
* Address of the Host running XBMC | |
* @param hostPort | |
* Port of the Host running XBMC (default 9777) | |
* @param deviceName | |
* Name of the Device | |
* @throws IOException | |
*/ | |
public EventClient(String hostName, int hostPort) { | |
Logger.Verbose(TAG, "EventClient(" + hostName + ", " + hostPort + ")"); | |
setHost(hostName, hostPort); | |
} | |
/** | |
* Starts a XBMC EventClient. | |
* | |
* @param hostAddress | |
* Address of the Host running XBMC | |
* @param hostPort | |
* Port of the Host running XBMC (default 9777) | |
* @param deviceName | |
* Name of the Device | |
* @param iconFile | |
* Path to the Iconfile (PNG, JPEG or GIF) | |
* @throws IOException | |
*/ | |
public EventClient(String hostName, int hostPort, String iconFile) { | |
Logger.Verbose(TAG, "EventClient(" + hostName + ", " + hostPort + ", " + ", " + iconFile | |
+ ")"); | |
setIcon(iconFile); | |
setHost(hostName, hostPort); | |
} | |
/** | |
* Starts a XBMC EventClient. | |
* | |
* @param hostAddress | |
* Address of the Host running XBMC | |
* @param hostPort | |
* Port of the Host running XBMC (default 9777) | |
* @param deviceName | |
* Name of the Device | |
* @param iconType | |
* Type of the icon file (see Packet.ICON_PNG, Packet.ICON_JPEG | |
* or Packet.ICON_GIF) | |
* @param iconData | |
* The icon itself as a Byte-Array | |
* @throws IOException | |
*/ | |
public EventClient(String hostName, int hostPort, byte iconType, byte[] iconData) { | |
Logger.Verbose(TAG, "EventClient(" + hostName + ", " + hostPort + ", " + iconType + ", " | |
+ iconData + ")"); | |
setIcon(iconType, iconData); | |
setHost(hostName, hostPort); | |
} | |
public void setHost(String host, int port) { | |
if (host != null) { | |
Logger.Verbose(TAG, "Setting mHostName = " + host); | |
mHostName = host; | |
mHostPort = port; | |
} else { | |
Logger.Error(TAG, "Setting null host!"); | |
mHostName = null; | |
} | |
} | |
/** | |
* Sets the icon using a path name to a image file (png, jpg or gif). | |
* | |
* @param iconPath | |
* Path to icon | |
*/ | |
public void setIcon(String iconPath) { | |
byte iconType = Packet.ICON_PNG; | |
// Assume png as icon type | |
if (iconPath.toLowerCase().endsWith(".jpeg")) | |
iconType = Packet.ICON_JPEG; | |
if (iconPath.toLowerCase().endsWith(".jpg")) | |
iconType = Packet.ICON_JPEG; | |
if (iconPath.toLowerCase().endsWith(".gif")) | |
iconType = Packet.ICON_GIF; | |
// Read the icon file to the byte array... | |
FileInputStream iconFileStream; | |
byte[] iconData; | |
try { | |
iconFileStream = new FileInputStream(iconPath); | |
iconData = new byte[iconFileStream.available()]; | |
iconFileStream.read(iconData); | |
iconFileStream.close(); | |
} catch (IOException e) { | |
mHasIcon = false; | |
return; | |
} | |
mHasIcon = true; | |
setIcon(iconType, iconData); | |
} | |
/** | |
* Sets the icon from raw data | |
* | |
* @param iconType | |
* Type of the icon file (see Packet.ICON_PNG, Packet.ICON_JPEG | |
* or Packet.ICON_GIF) | |
* @param iconData | |
* The icon itself as a Byte-Array | |
*/ | |
public void setIcon(byte iconType, byte[] iconData) { | |
mIconType = iconType; | |
mIconData = iconData; | |
} | |
/** | |
* Displays a notification window in XBMC. | |
* | |
* @param title | |
* Message title | |
* @param message | |
* The actual message | |
*/ | |
public void sendNotification(String title, String message) { | |
PacketNOTIFICATION p; | |
if (mHasIcon) | |
p = new PacketNOTIFICATION(title, message, mIconType, mIconData); | |
else | |
p = new PacketNOTIFICATION(title, message); | |
SendPacket(p, mHostName, mHostPort); | |
} | |
public void sendNotification(String title, String message, byte icontype, byte[] icondata) { | |
PacketNOTIFICATION p = new PacketNOTIFICATION(title, message, icontype, icondata); | |
SendPacket(p, mHostName, mHostPort); | |
} | |
/** | |
* Sends a Button event | |
* | |
* @param code | |
* Raw button code (default: 0) | |
* @param repeat | |
* This key press should repeat until released (default: 1) Note | |
* that queued pressed cannot repeat. | |
* @param down | |
* If this is 1, it implies a press event, 0 implies a release | |
* event. (default: 1) | |
* @param queue | |
* A queued key press means that the button event is executed | |
* just once after which the next key press is processed. It can | |
* be used for macros. Currently there is no support for time | |
* delays between queued presses. (default: 0) | |
* @param amount | |
* Unimplemented for now; in the future it will be used for | |
* specifying magnitude of analog key press events | |
* @param axis | |
*/ | |
public void sendButton(short code, boolean repeat, boolean down, boolean queue, short amount, | |
byte axis) { | |
Logger.Verbose(TAG, "sendButton(" + code + ", " + (repeat ? "rep, " : "nonrep, ") | |
+ (down ? "down)" : "up)")); | |
PacketBUTTON p = new PacketBUTTON(code, repeat, down, queue, amount, axis); | |
SendPacket(p, mHostName, mHostPort); | |
} | |
public void sendvKey(short code) { | |
Logger.Verbose(TAG, "sendvKey(" + code + ")"); | |
PacketBUTTON p = new PacketBUTTON(code); | |
SendPacket(p, mHostName, mHostPort); | |
} | |
/** | |
* Sends a Button event | |
* | |
* @param map_name | |
* A combination of map_name and button_name refers to a mapping | |
* in the user's Keymap.xml or Lircmap.xml. map_name can be one | |
* of the following: | |
* <ul> | |
* <li><code>KB</code> - Standard keyboard map ( | |
* <code><keyboard></code> section)</li> | |
* <li><code>XG</code> - Xbox gamepad map ( | |
* <code><gamepad></code> section)</li> | |
* <li><code>R1</code> - Xbox remote map ( | |
* <code><remote></code> section)</li> | |
* <li><code>R2</code> - Xbox universal remote map ( | |
* <code><universalremote></code> section)</li> | |
* <li><code>LI:devicename</code> - LIRC remote map where | |
* <code>devicename</code> is the actual device's name</li> | |
* </ul> | |
* @param button_name | |
* A button name defined in the map specified in map_name. For | |
* example, if map_name is "KB" refering to the <keyboard> | |
* section in Keymap.xml then, valid button_names include | |
* "printscreen", "minus", "x", etc. | |
* @param repeat | |
* This key press should repeat until released (default: 1) Note | |
* that queued pressed cannot repeat. | |
* @param down | |
* If this is 1, it implies a press event, 0 implies a release | |
* event. (default: 1) | |
* @param queue | |
* A queued key press means that the button event is executed | |
* just once after which the next key press is processed. It can | |
* be used for macros. Currently there is no support for time | |
* delays between queued presses. (default: 0) | |
* @param amount | |
* Unimplemented for now; in the future it will be used for | |
* specifying magnitude of analog key press events | |
* @param axis | |
*/ | |
public void sendButton(String map_name, String button_name, boolean repeat, boolean down, | |
boolean queue, short amount, byte axis) { | |
Logger.Verbose(TAG, "sendButton(" + map_name + ", \"" + button_name + "\", " | |
+ (repeat ? "rep, " : "nonrep, ") + (down ? "down)" : "up)")); | |
ping(); | |
PacketBUTTON p = new PacketBUTTON(map_name, button_name, repeat, down, queue, amount, axis); | |
SendPacket(p, mHostName, mHostPort); | |
} | |
/** | |
* Sets the mouse position in XBMC | |
* | |
* @param x | |
* Horizontal position ranging from 0 to 65535 | |
* @param y | |
* Vertical position ranging from 0 to 65535 | |
*/ | |
public void sendMouse(int x, int y) { | |
PacketMOUSE p = new PacketMOUSE(x, y); | |
SendPacket(p, mHostName, mHostPort); | |
} | |
/** | |
* Sends a ping to the XBMC EventServer | |
* | |
* @throws IOException | |
*/ | |
public void ping() { | |
PacketPING p = new PacketPING(); | |
SendPacket(p, mHostName, mHostPort); | |
} | |
/** | |
* Tells XBMC to log the message to xbmc.log with the loglevel as specified. | |
* | |
* @param loglevel | |
* The log level, follows XBMC standard. | |
* <ul> | |
* <li>0 = DEBUG</li> | |
* <li>1 = INFO</li> | |
* <li>2 = NOTICE</li> | |
* <li>3 = WARNING</li> | |
* <li>4 = ERROR</li> | |
* <li>5 = SEVERE</li> | |
* </ul> | |
* @param logmessage | |
* The message to log | |
*/ | |
public void sendLog(byte loglevel, String logmessage) { | |
PacketLOG p = new PacketLOG(loglevel, logmessage); | |
SendPacket(p, mHostName, mHostPort); | |
} | |
/** | |
* Tells XBMC to do the action specified, based on the type it knows were it | |
* needs to be sent. | |
* | |
* @param actionmessage | |
* Actionmessage (as in scripting/skinning) | |
*/ | |
public void sendAction(String actionmessage) { | |
PacketACTION p = new PacketACTION(actionmessage); | |
SendPacket(p, mHostName, mHostPort); | |
} | |
private class PacketQueue { | |
private Stack<PacketData> packetRefs = new Stack<PacketData>(); | |
} | |
private class PacketData { | |
Packet packet; | |
String host; | |
int port; | |
} | |
private class packetSenderManager implements Runnable { | |
@Override | |
public void run() { | |
try { | |
while (true) { | |
if (mPacketQueue.packetRefs.size() == 0) { | |
synchronized (mPacketQueue.packetRefs) { | |
mPacketQueue.packetRefs.wait(); | |
} | |
} | |
if (mPacketQueue.packetRefs.size() != 0) { | |
PacketData packetdata; | |
synchronized (mPacketQueue.packetRefs) { | |
packetdata = mPacketQueue.packetRefs.pop(); | |
} | |
InetAddress addr; | |
try { | |
addr = InetAddress.getByName(packetdata.host); | |
} catch (Exception e) { | |
Logger.Warning(TAG, "Error sending packet host not set or resolved"); | |
continue; | |
} | |
packetdata.packet.send(addr, packetdata.port); | |
} | |
if (Thread.interrupted()) | |
break; | |
} | |
} catch (InterruptedException e) { | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment