In my quest to get the Wii remote working on XBMC, I've tried every possible API I was able to find and tried them all out.
Initially I thought I could get away with using window messages, sending WM_KEYDOWN, WM_CHAR and WM_KEYUP and VK_ENTER which worked until you started watching videos. For some reason, on-screen display (OSD) would stack up all input in a queue and replay them once you leave the OSD.
So I looked into more "official" control APIs. The HTTP-API was first on the list, but also deprecated no point building something upon that.
I also tried the HTTP-API replacement called JSONRPC. Although I got it working, that API felt like it was more complicated than it should have been. By the way, don't include the trailing backslash unless you like 404's.
The input methods would work fine for navigating menus, but when it came to controlling the video playback I had to use different commands. Seriously!?
This is what I felt like doing after wasting my time with that...
Here's some simple JSONRPC code that worked, just for the sake of it.
JavaScriptSerializer jss = new JavaScriptSerializer();
Object obj = new { jsonrpc = "2.0", method = "Input.Left" };
String data = jss.Serialize(obj);
WebClient client = new WebClient();
string text = client.DownloadString("http://localhost:8080/jsonrpc?request=" + Uri.EscapeDataString(data));
Now remember, this is just to send a simple request. You're not processing any data from it yet!
So came my last hope, EventServer. Well to say least, it worked but was also poorly documented. There was so much guess-work when it came to the input arguments, but when you've finally figured it out all the little puzzle pieces, it comes together very nicely!
Enabling EventServer on XBMC
First you've gotta have this enabled. Otherwise there'll be no event server to connect to.
- Go to System > Services > Remote control
- Enable "Allow programs on this system to control XBMC" (lol yeah, it's badly named)
XBMC EventServer libraries and sample code
Now for the fun part, choosing your poison. These EventServer client libraries were written between 2-5 years ago (at time of writing this blog post)
These libraries really save you a lot of time, so get the library for your language of choice. There are also example clients available which are worth taking a look at.
Coding
For the purpose of this tutorial I'll chose C#, a language I absolutely hate with a passion. Why the hell would I do that!? Because Wiimotelib is written in C#...
Anyways... copy "EventClient.cs" from the C# library into your project. Import the namespace.
using XBMC;
Now to set up the client. This is assuming you're running this code on the same machine that XBMC is running with the default event server port of 9777.
EventClient eventClient;
eventClient = new EventClient();
eventClient.Connect("localhost", 9777);
eventClient.SendHelo("Wii remote");
SendHelo() (another badly named function) will display a notification on your screen saying a new device has connected. Let's test out the connection shall we?
eventClient.SendNotification(
"Yo VIP",
"Vanilla ice ice baby"
);
This should display a nice little notification on your screen. If it doesn't, you're missing a vital step somewhere.
Action commands
We'll start off with something simple. To control parts of XBMC functionality, you can just send specialised action commands.
eventClient.SendAction("mute");
eventClient.SendAction("nextsubtitle");
For a full list of supported actions, look at ButtonTranslator.cpp and search for "ActionMapping actions[]".
To implement some basic navigation, I tried out "left" and "right" but they didn't seem to work so I had to resort to button commands.
Button commands
This is where the magic happens. The following code will send a "enter" command to XBMC.
eventClient.SendButton(
"enter",
"KB",
XBMC.ButtonFlagsType.BTN_DOWN | ButtonFlagsType.BTN_NO_REPEAT
);
Simple enough, sends an "Enter" button command ("enter") to XBMC in the form of a keyboard ("KB") device map. This ensures that we're using the keyboard.xml keyboard mapping.
If you're wondering what keymaps are, check em out because you've already got a whole heap of mappings with your XBMC install (see "1. Location of keymaps")
Now you might also be wondering where I found these magic string values like "enter", or the deviceMap "KB". Even more confusing was the sample client code which uses deviceMap "XG".
Well I had to dig through a fair bit of XBMC source for that and it took up much of my time! For sanity sake, you can find some useful values for device maps in EventClient.cs to use in SendButton().
- "KB" - Standard keyboard map
- "XG" - Xbox Gamepad
- "R1" - Xbox Remote
- "R2" - Xbox Universal Remote
- "LI:devicename" - valid LIRC device map where 'devicename' is the actual name of the LIRC device
- "JS<num>:joyname" - valid Joystick device map where 'joyname' is the name specified in the keymap. JS only supports button code and not button name currently (ie. "JS0:WiiRemote")
Given the choices I went with keyboard, which makes life much easier. OK, so now what button do you want to send?
Check out ButtonTranslator.cpp in the XBMC source. It's the "best/neatest" way to see what buttons are supported by the given mapping.
Depending on the device map you're using, search for either:
- CButtonTranslator::TranslateKeyboardString
- CButtonTranslator::TranslateGamepadString
- CButtonTranslator::TranslateRemoteString
For Joystick (JS) button presses, you're better off just gleaming the values from the keymap XML files. The <global> config should give you a fair idea of what the button IDs are.
Cleaning up
Now now, don't forget to clean up after yourself once you're done having fun. Remember to disconnect your client properly.
if (eventClient != null) {
eventClient.SendBye();
eventClient.Disconnect();
}
There are so many dead ends on a wiki page, and it seems that I've already run into most of them for you. Hopefully this tutorial provides more than enough information so it makes life easier for you.
Sources