One remote for the TV, the amp, MythTV and the PS3, over HDMI-CEC
Under the telly there’s a MythTV box, a PS3, an amp and, of course, the TV itself. That makes three remotes for one sofa: the TV’s, just to turn it on and off; the amp’s, for the volume; and the TV tuner card’s, for getting around MythTV.
The tuner card’s remote is the one that does the real work. The card lives in the MythTV PC, with an infrared receiver dangling from it on the end of a cable. My LIRC config for it started life as the stock one for the Hauppauge Nova-T-500’s silver-and-black “snowboard” remote. LIRC, the Linux infrared remote daemon, turns its button presses into MythTV key presses. What it can’t do is reach any of the other boxes.
HDMI can, though. Tucked away in the HDMI spec is CEC (Consumer Electronics Control), a slow little bus that lets everything plugged into the TV send each other commands: “turn on”, “switch to me”, “volume up”, “the user just pressed left”. Most manufacturers give it a silly brand name and then implement about half of it. Pulse-Eight’s open-source libcec lets a PC join in, with the help of their USB-CEC adapter. It sits in the HDMI cable between the PC and the TV, passing the picture straight through and slipping the PC onto the bus.
So the plan was simple: keep using the MythTV remote for everything, and have the PC translate the buttons it can’t handle itself into CEC commands for everyone else.
The bridge
My changes live in a fork, pthimon/libcec, in src/lircclient-qt. It started life in March 2012 as a hacked-up copy of libcec’s own cec-client test program, with its interactive prompt ripped out and a LIRC loop put in its place. On the bus it announces itself as a recording device called “MythCEC”.
LIRC does most of the thinking. My .lircrc maps a handful of buttons to made-up names like CEC_POWER and CEC_VOLUP, and the bridge acts on them:
- Power asks the TV whether it’s in standby. If it is, it wakes the TV and makes MythTV the active source. If not, it broadcasts “standby” and everything goes to bed at once.
- Volume up, down and mute go to the amp over CEC.
- Go (the button in the middle) flips the TV between MythTV and the PS3.
That last one involves a little white lie. The bridge sends the “set stream path” message as if it came from the TV, and everything on the bus takes the TV’s word for it. The politer libcec call is still in the code, commented out, which tells its own story.
Driving the PS3 with a MythTV remote
LIRC has a handy feature called modes. A block in .lircrc can be wrapped in begin ps3 … end ps3, and the program can switch modes at run time. So when the bridge switches the TV to the PS3, it also switches LIRC into ps3 mode. From then on, the arrows, OK and back buttons stop going to MythTV. Instead they’re sent over CEC as key presses addressed to the PS3, which happily obeys. That wasn’t really a surprise: Sony makes TVs and amps too, and my amp is a Sony, so the PS3 was always likely to speak fluent CEC.
A few buttons get new jobs. Guide becomes triangle, Radio brings up the PS3’s home menu, and Menu holds the PS button down for a second, since that’s how you get the PS3’s quit menu. It’s implemented, gloriously, as “press, sleep(1), release”.
Pressing Go again switches everything back to MythTV and puts LIRC back into myth mode.
Showing the volume on screen
The amp has no idea the TV has a screen, so turning the volume up gave no feedback at all. Fortunately the amp announces its new volume on the bus every time it changes. MythTV, meanwhile, has a network control socket on port 6546 that accepts commands like play volume 42%, which pops up its own volume bar. The bridge just listens for one and types the other. Mute shows up as 0%, because the amp reports it as a flag on the top bit rather than a number.
The Qt rewrite
The latest version is a rewrite on Qt’s event loop, which lets three things happen at once without a tangle of threads:
- LIRC is watched with a
QSocketNotifier, so key presses arrive as ordinary Qt signals. - MythTV gets a proper
QTcpSocketthat reconnects by itself when mythfrontend restarts. The old version connected once at start-up, so if mythfrontend restarted, the volume display was gone until the bridge was restarted too. - A tiny volume server listens on TCP port 24245. Send it
U,D,M,NorVand it turns the amp up, down, mutes, unmutes, or tells you the current volume. Anyone connected also gets told whenever the volume changes, which is useful for making a remote app for my Nokia N900.
The volume server checks the TV is on before doing anything, and just replies Off if it isn’t.
One warning if you fancy trying it: the bridge’s HDMI physical address is hard-coded (0x1100) to suit where my box is plugged in, so you’ll want to change that.
Where it’s got to
One remote now does the lot: power for everything, volume on the amp with an on-screen display, and a button that swaps between MythTV and the PS3 and takes the arrow keys with it. It works a treat, and the other two remotes have nothing left to do.
The code is in the fork. It’s very much built around my particular boxes, but it’s a decent starting point if you want your MythTV remote to boss the rest of the cabinet about.