PageRenderTime 79ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/src/org/xbmc/eventclient/EventClient.java

https://github.com/antoniosejas/android-xbmcremote
Java | 412 lines | 203 code | 41 blank | 168 comment | 31 complexity | f0accaefa5fff28528841f57c118d24d MD5 | raw file
  1. package org.xbmc.eventclient;
  2. import java.io.FileInputStream;
  3. import java.io.IOException;
  4. import java.net.InetAddress;
  5. import org.xbmc.api.data.IEventClient;
  6. import android.util.Log;
  7. /**
  8. * XBMC Event Client Class
  9. *
  10. * Implements an XBMC-Client. This class can be used to implement your own
  11. * application which should act as a Input device for XBMC. Also starts a
  12. * Ping-Thread, which tells the XBMC EventServer that the client is alive.
  13. * Therefore if you close your application you SHOULD call stopClient()!
  14. *
  15. * 03.09.2009 freezy changed class name and member variables
  16. *
  17. * @author Stefan Agner
  18. */
  19. public class EventClient implements IEventClient {
  20. private final String mDeviceName;
  21. private boolean mHasIcon = false;
  22. private PingThread mPingThread;
  23. private byte mIconType = Packet.ICON_NONE;
  24. private byte[] mIconData;
  25. private InetAddress mHostAddress;
  26. private int mHostPort;
  27. private static final String TAG = "EventClient";
  28. /**
  29. * Creates an empty instance but doesn't start it.
  30. */
  31. public EventClient(String deviceName) {
  32. Log.i(TAG, "EventClient(" + deviceName + ")");
  33. mDeviceName = deviceName;
  34. }
  35. /**
  36. * Starts a XBMC EventClient without an icon.
  37. *
  38. * @param hostAddress Address of the Host running XBMC
  39. * @param hostPort Port of the Host running XBMC (default 9777)
  40. * @param deviceName Name of the Device
  41. * @throws IOException
  42. */
  43. public EventClient(InetAddress hostAddress, int hostPort, String deviceName) {
  44. Log.i(TAG, "EventClient(" + hostAddress + ", " + hostPort + ", " + deviceName + ")");
  45. mDeviceName = deviceName;
  46. startClient(hostAddress, hostPort);
  47. }
  48. /**
  49. * Starts a XBMC EventClient.
  50. *
  51. * @param hostAddress Address of the Host running XBMC
  52. * @param hostPort Port of the Host running XBMC (default 9777)
  53. * @param deviceName Name of the Device
  54. * @param iconFile Path to the Iconfile (PNG, JPEG or GIF)
  55. * @throws IOException
  56. */
  57. public EventClient(InetAddress hostAddress, int hostPort, String deviceName, String iconFile) {
  58. Log.i(TAG, "EventClient(" + hostAddress + ", " + hostPort + ", " + deviceName + ", " + iconFile + ")");
  59. mDeviceName = deviceName;
  60. setIcon(iconFile);
  61. startClient(hostAddress, hostPort);
  62. }
  63. /**
  64. * Starts a XBMC EventClient.
  65. *
  66. * @param hostAddress Address of the Host running XBMC
  67. * @param hostPort Port of the Host running XBMC (default 9777)
  68. * @param deviceName Name of the Device
  69. * @param iconType Type of the icon file (see Packet.ICON_PNG,
  70. * Packet.ICON_JPEG or Packet.ICON_GIF)
  71. * @param iconData The icon itself as a Byte-Array
  72. * @throws IOException
  73. */
  74. public EventClient(InetAddress hostAddress, int hostPort, String deviceName, byte iconType, byte[] iconData) {
  75. Log.i(TAG, "EventClient(" + hostAddress + ", " + hostPort + ", " + deviceName + ", " + iconType + ", " + iconData + ")");
  76. mDeviceName = deviceName;
  77. setIcon(iconType, iconData);
  78. startClient(hostAddress, hostPort);
  79. }
  80. public void setHost(InetAddress addr, int port) {
  81. if (addr != null) {
  82. Log.e(TAG, "Setting mHostAddress = " + addr.getHostAddress());
  83. if (mHostAddress == null) {
  84. startClient(addr, port);
  85. } else {
  86. mHostAddress = addr;
  87. mHostPort = port;
  88. mPingThread.setHost(addr, port);
  89. }
  90. } else {
  91. Log.e(TAG, "Setting null host!");
  92. try {
  93. throw new Exception("Setting null host.");
  94. } catch (Exception e) {
  95. e.printStackTrace();
  96. }
  97. mHostAddress = null;
  98. }
  99. }
  100. /**
  101. * Sets the icon using a path name to a image file (png, jpg or gif).
  102. * @param iconPath Path to icon
  103. */
  104. public void setIcon(String iconPath) {
  105. byte iconType = Packet.ICON_PNG;
  106. // Assume png as icon type
  107. if (iconPath.toLowerCase().endsWith(".jpeg"))
  108. iconType = Packet.ICON_JPEG;
  109. if (iconPath.toLowerCase().endsWith(".jpg"))
  110. iconType = Packet.ICON_JPEG;
  111. if (iconPath.toLowerCase().endsWith(".gif"))
  112. iconType = Packet.ICON_GIF;
  113. // Read the icon file to the byte array...
  114. FileInputStream iconFileStream;
  115. byte[] iconData;
  116. try {
  117. iconFileStream = new FileInputStream(iconPath);
  118. iconData = new byte[iconFileStream.available()];
  119. iconFileStream.read(iconData);
  120. } catch (IOException e) {
  121. mHasIcon = false;
  122. return;
  123. }
  124. mHasIcon = true;
  125. setIcon(iconType, iconData);
  126. }
  127. /**
  128. * Sets the icon from raw data
  129. * @param iconType Type of the icon file (see Packet.ICON_PNG, Packet.ICON_JPEG or Packet.ICON_GIF)
  130. * @param iconData The icon itself as a Byte-Array
  131. */
  132. public void setIcon(byte iconType, byte[] iconData) {
  133. mIconType = iconType;
  134. mIconData = iconData;
  135. }
  136. /**
  137. * Starts a XBMC EventClient.
  138. *
  139. * @param hostAddress Address of the Host running XBMC
  140. * @param hostPort Port of the Host running XBMC (default 9777)
  141. * @throws IOException
  142. */
  143. private void startClient(InetAddress hostAddress, int hostPort) {
  144. Log.i(TAG, "Starting new EventClient at " + hostAddress + ":" + hostPort);
  145. // Save host address and port
  146. mHostAddress = hostAddress;
  147. mHostPort = hostPort;
  148. // Send Hello Packet...
  149. PacketHELO p;
  150. if (mHasIcon)
  151. p = new PacketHELO(mDeviceName, mIconType, mIconData);
  152. else
  153. p = new PacketHELO(mDeviceName);
  154. try {
  155. p.send(hostAddress, hostPort);
  156. // Start Thread (for Ping packets...)
  157. mPingThread = new PingThread(hostAddress, hostPort, 20000);
  158. mPingThread.start();
  159. } catch (IOException e) {
  160. }
  161. }
  162. /**
  163. * Stops the XBMC EventClient (especially the Ping-Thread)
  164. *
  165. * @throws IOException
  166. */
  167. public void stopClient() throws IOException {
  168. final InetAddress addr = mHostAddress;
  169. if (addr != null) {
  170. // Stop Ping-Thread...
  171. mPingThread.giveup();
  172. mPingThread.interrupt();
  173. PacketBYE p = new PacketBYE();
  174. p.send(mHostAddress, mHostPort);
  175. }
  176. }
  177. /**
  178. * Displays a notification window in XBMC.
  179. *
  180. * @param title Message title
  181. * @param message The actual message
  182. */
  183. public void sendNotification(String title, String message) throws IOException {
  184. final InetAddress addr = mHostAddress;
  185. if (addr != null) {
  186. PacketNOTIFICATION p;
  187. if (mHasIcon)
  188. p = new PacketNOTIFICATION(title, message, mIconType, mIconData);
  189. else
  190. p = new PacketNOTIFICATION(title, message);
  191. p.send(addr, mHostPort);
  192. }
  193. }
  194. public void sendNotification(String title, String message, byte icontype, byte[] icondata) throws IOException {
  195. final InetAddress addr = mHostAddress;
  196. if (addr != null) {
  197. PacketNOTIFICATION p = new PacketNOTIFICATION(title, message, icontype, icondata);
  198. p.send(addr, mHostPort);
  199. }
  200. }
  201. /**
  202. * Sends a Button event
  203. *
  204. * @param code Raw button code (default: 0)
  205. * @param repeat This key press should repeat until released (default: 1)
  206. * Note that queued pressed cannot repeat.
  207. * @param down If this is 1, it implies a press event, 0 implies a
  208. * release event. (default: 1)
  209. * @param queue A queued key press means that the button event is executed
  210. * just once after which the next key press is processed. It
  211. * can be used for macros. Currently there is no support for
  212. * time delays between queued presses. (default: 0)
  213. * @param amount Unimplemented for now; in the future it will be used for
  214. * specifying magnitude of analog key press events
  215. * @param axis
  216. */
  217. public void sendButton(short code, boolean repeat, boolean down, boolean queue, short amount, byte axis) throws IOException {
  218. final InetAddress addr = mHostAddress;
  219. if (addr != null) {
  220. PacketBUTTON p = new PacketBUTTON(code, repeat, down, queue, amount, axis);
  221. p.send(addr, mHostPort);
  222. }
  223. }
  224. /**
  225. * Sends a Button event
  226. *
  227. * @param map_name
  228. * A combination of map_name and button_name refers to a mapping
  229. * in the user's Keymap.xml or Lircmap.xml. map_name can be one
  230. * of the following:
  231. * <ul>
  232. * <li><code>KB</code> - Standard keyboard map (<code>&lt;keyboard&gt;</code> section)</li>
  233. * <li><code>XG</code> - Xbox gamepad map (<code>&lt;gamepad&gt;</code> section)</li>
  234. * <li><code>R1</code> - Xbox remote map (<code>&lt;remote&gt;</code> section)</li>
  235. * <li><code>R2</code> - Xbox universal remote map (<code>&lt;universalremote&gt;</code>
  236. * section)</li>
  237. * <li><code>LI:devicename</code> - LIRC remote map where <code>devicename</code> is
  238. * the actual device's name</li>
  239. * </ul>
  240. * @param button_name
  241. * A button name defined in the map specified in map_name. For
  242. * example, if map_name is "KB" refering to the <keyboard>
  243. * section in Keymap.xml then, valid button_names include
  244. * "printscreen", "minus", "x", etc.
  245. * @param repeat
  246. * This key press should repeat until released (default: 1) Note
  247. * that queued pressed cannot repeat.
  248. * @param down
  249. * If this is 1, it implies a press event, 0 implies a release
  250. * event. (default: 1)
  251. * @param queue
  252. * A queued key press means that the button event is executed
  253. * just once after which the next key press is processed. It can
  254. * be used for macros. Currently there is no support for time
  255. * delays between queued presses. (default: 0)
  256. * @param amount
  257. * Unimplemented for now; in the future it will be used for
  258. * specifying magnitude of analog key press events
  259. * @param axis
  260. */
  261. public void sendButton(String map_name, String button_name, boolean repeat, boolean down, boolean queue, short amount, byte axis) throws IOException {
  262. final InetAddress addr = mHostAddress;
  263. if (addr != null) {
  264. Log.i(TAG, "sendButton(" + map_name + ", \"" + button_name + "\", " + (repeat ? "rep, " : "nonrep, ") + (down ? "down)" : "up)"));
  265. PacketBUTTON p = new PacketBUTTON(map_name, button_name, repeat, down, queue, amount, axis);
  266. p.send(addr, mHostPort);
  267. } else {
  268. Log.e(TAG, "sendButton failed due to unset host address!");
  269. }
  270. }
  271. /**
  272. * Sets the mouse position in XBMC
  273. *
  274. * @param x Horizontal position ranging from 0 to 65535
  275. * @param y Vertical position ranging from 0 to 65535
  276. */
  277. public void sendMouse(int x, int y) throws IOException {
  278. final InetAddress addr = mHostAddress;
  279. if (addr != null) {
  280. PacketMOUSE p = new PacketMOUSE(x, y);
  281. p.send(addr, mHostPort);
  282. }
  283. }
  284. /**
  285. * Sends a ping to the XBMC EventServer
  286. *
  287. * @throws IOException
  288. */
  289. public void ping() throws IOException {
  290. final InetAddress addr = mHostAddress;
  291. if (addr != null) {
  292. PacketPING p = new PacketPING();
  293. p.send(addr, mHostPort);
  294. }
  295. }
  296. /**
  297. * Tells XBMC to log the message to xbmc.log with the loglevel as specified.
  298. *
  299. * @param loglevel
  300. * The log level, follows XBMC standard.
  301. * <ul>
  302. * <li>0 = DEBUG</li>
  303. * <li>1 = INFO</li>
  304. * <li>2 = NOTICE</li>
  305. * <li>3 = WARNING</li>
  306. * <li>4 = ERROR</li>
  307. * <li>5 = SEVERE</li>
  308. * </ul>
  309. * @param logmessage
  310. * The message to log
  311. */
  312. public void sendLog(byte loglevel, String logmessage) throws IOException {
  313. final InetAddress addr = mHostAddress;
  314. if (addr != null) {
  315. PacketLOG p = new PacketLOG(loglevel, logmessage);
  316. p.send(addr, mHostPort);
  317. }
  318. }
  319. /**
  320. * Tells XBMC to do the action specified, based on the type it knows were it
  321. * needs to be sent.
  322. *
  323. * @param actionmessage Actionmessage (as in scripting/skinning)
  324. */
  325. public void sendAction(String actionmessage) throws IOException {
  326. final InetAddress addr = mHostAddress;
  327. if (addr != null) {
  328. PacketACTION p = new PacketACTION(actionmessage);
  329. p.send(addr, mHostPort);
  330. }
  331. }
  332. /**
  333. * Implements a PingThread which tells XBMC EventServer that the Client is
  334. * alive (this should be done at least every 60 seconds!
  335. *
  336. * @author Stefan Agner
  337. */
  338. private static class PingThread extends Thread {
  339. private InetAddress mHostAddress;
  340. private int mHostPort;
  341. private int mSleepTime;
  342. private boolean mGiveup = false;
  343. public PingThread(InetAddress hostAddress, int hostPort, int sleepTime) {
  344. super("XBMC EventClient Ping-Thread");
  345. mHostAddress = hostAddress;
  346. mHostPort = hostPort;
  347. mSleepTime = sleepTime;
  348. }
  349. public void giveup() {
  350. mGiveup = true;
  351. }
  352. public void setHost(InetAddress addr, int port) {
  353. mHostAddress = addr;
  354. mHostPort = port;
  355. }
  356. public void run() {
  357. while (!mGiveup) {
  358. try {
  359. PacketPING p = new PacketPING();
  360. p.send(mHostAddress, mHostPort);
  361. } catch (IOException e) {
  362. e.printStackTrace();
  363. }
  364. try {
  365. Thread.sleep(mSleepTime);
  366. } catch (InterruptedException e) {
  367. }
  368. }
  369. }
  370. }
  371. }