Thursday, February 19, 2009

Switching audio output device on HTPC via Harmony remote

In my HTPC setup, I have two audio output devices connected; The first is my plasma TV via HDMI and the second is my home theater sound system via optical S/PDIF connection. Now normally, I will pipe the audio from the PC via my TV speakers for TV and general purpose use (such as Skype conferencing, watching youTube videos, some games etc). On the occasions where I'm listening to my music collection or watching movies, I will want to switch over to my 6.1 home theater sound system.

Unfortunately, there is no OOTB feature provided in Windows, VMC or the IR receiver software (SoundTech iMon) to allow me to switch the audio outputs via the remote. Hence I will have to use the mouse to enter the dreaded Windows interface, call up the audio devices control panel applet and change it manually. Typically, a five minutes process not including the need to walk up to my HTPC since I don't have a wireless mouse handy. Bummer!

Fortunately, you can maintain your couch potato laziness (and maximise your investment in the expensive Harmony remote!) by using a combination of AutoHotKey (a Windows scripting engine) and custom commands in iMon.

Here's how it works:
  1. An AutoHotKey script will be running on the PC at all times waiting for certain keyboard shortcut to be triggered. In my case, CTRL+F5 to trigger HDMI output and CTRL+F6 to trigger S/PDIF.
  2. Map two unused remote keys via the iMon custom command feature to CTRL+F5 and CTRL+F6 respectively. In my case, star (*) key to trigger CTRL+F5 and sharp (#) key to trigger CTRL+F6.
  3. In summary, when you hit the (*) or (#) keys on the Harmony (or MCE for that matter) remote, the iMon software will capture it and send the respective CTRL+F5 or CTRL+F6 keyboard shortcut in Windows. The AutoHotKey script will pick it up and execute the main sequence to open the audio device control panel applet, select the right audio output device and close (my script actually does more than that like sanity checks and reopening VMC if it is open at the time the script is called).

And here's how to get it working on your setup:
  1. Download and install AutoHotKey.
  2. Download and extract the two necessary addon scripts (COM standard library and Vista Audio Control Functions) to the \Lib folder (create if its not already present) of AutoHotKey's program folder. These two addon scripts are needed to enable AutoHotKey to talk to the Vista audio device APIs.
  3. Now create a text file with name "Audio device switch helper.ahk" and copy the following text into it:
    ; CTRL+F5 = Change audio device to Digital Output
    ^F5::
    ; check if HDMI output is already set
    COM_Init()
    device := VA_GetDevice()
    device_name := VA_GetDeviceName(device)
    COM_Release(device)
    COM_Term()

    vmcOpen := "nothing"

    if InStr(device_name, "Digital")
    {
    ;already set, so lets pop a message and return
    if WinActive("ahk_class eHome Render Window")
    {
    vmcOpen := "VMC Open"
    WinMinimize
    }
    SplashTextOn, 250, , Digital audio output already selected
    Sleep, 1500
    SplashTextOff
    ; TrayTip, ,Digital audio output already selected, 10,1
    if InStr(vmcOpen, "VMC Open")
    {
    WinMaximize, ahk_class eHome Render Window
    }
    return
    }

    if WinActive("ahk_class eHome Render Window")
    {
    vmcOpen := "VMC Open"
    ; Close application with Alt-F4
    WinClose
    ;Send !{F4}
    }

    Run, mmsys.cpl
    WinWait,Sound
    ControlSend,SysListView321,{Down 2}
    Sleep, 200
    ControlClick,&Set Default
    ControlClick,OK

    if InStr(vmcOpen, "VMC Open")
    {
    Run, C:\Windows\ehome\ehshell.exe, , max
    }
    return

    ; CTRL+F6 = Change audio device to HDMI Output
    ^F6::
    ; check if HDMI output is already set
    COM_Init()
    device := VA_GetDevice()
    device_name := VA_GetDeviceName(device)
    COM_Release(device)
    COM_Term()

    vmcOpen := "nothing"

    if InStr(device_name, "HDMI")
    {
    ;already set, so lets pop a message and return
    if WinActive("ahk_class eHome Render Window")
    {
    vmcOpen := "VMC Open"
    WinMinimize
    }
    SplashTextOn, 250, , HDMI audio output already selected
    Sleep, 1500
    SplashTextOff
    ; TrayTip, ,HDMI audio output already selected, 10,1
    if InStr(vmcOpen, "VMC Open")
    {
    WinMaximize, ahk_class eHome Render Window
    }
    return
    }


    ; check if VMC is open, if yes, close it
    if WinActive("ahk_class eHome Render Window")
    {
    vmcOpen := "VMC Open"
    ; Close application with Alt-F4
    WinClose
    ;Send !{F4}
    }

    Run, mmsys.cpl
    WinWait,Sound
    ControlSend,SysListView321,{Down 3}
    Sleep, 400
    ControlClick,&Set Default
    ;Sleep, 1000
    ControlClick,OK

    ;if vmc was open previously, we open it again
    if InStr(vmcOpen, "VMC Open")
    {
    Run, C:\Windows\ehome\ehshell.exe, , max
    }
    return
  4. Notice that in the above code, there are two lines with text in red. You will need to change them according to the order your devices are listed in the audio device control panel applet! So for example, in my case, my HDMI audio device is the first item in the list while the S/PDIF audio device is listed fourth. So to switch between them, the script will need to move up three items to select HDMI (assuming the current selection is at S/PDIF) and move down three items to select S/PDIF (assuming that the current selection is at HDMI).
  5. Save the script and test it (double click on the file to launch).
  6. Once you have it working, open up iMon manager and select "Custom Command" on the left.
  7. Click on the "Add" button, give the new function a name (e.g. "Select HDMI Audio"), configure the shortcut CTRL+F5, followed by selecting the remote key STAR.
  8. Click on the "Add" button again, give the new function a name (e.g. "Select S/PDIF Audio"), configure the shortcut CTRL+F6, followed by selecting the remote key SHARP.
  9. Now select "Program Command" followed by selecting "XPMediaCenter" as the program and finally, remove the (*) and (#) keys from the mapping. You need to do this to allow the custom command to work when VMC is the active application.
  10. Click on "OK"
  11. At this point, you should be able to start using the (*) and (#) keys on the remote to switch between the two audio outputs.
  12. To enable this feature to survive a reboot, add a shortcut to this script in the "Startup" folder of all users.
For those with a Harmony remote, you can add these keys into the startup sequence of your activities so that you don't even need to manually click the (*) or (#) buttons! e.g. in my case, when I start the "Watch Movie" or the "Listen to Music" activities, at the end of the startup sequence, a (#) key will be sent to ensure that the S/PDIF audio output is selected.

Ahhh.... a true couch potato's blessing indeed!

No comments: