Thursday, May 7, 2015

Controlling VLC via Python and some AHK

I've got an Arduino with an LCD. Previously I developed a Python application which connected via serial and showed songs playing and let me change the track and volume through the magic of CMUS. CMUS is a wonderful music program, for *NIX systems. If you are trapped in a Windows environment you might use VLC. With CMUS you can connect via "cmus-remote" and query the tracks accessing the necessary information. With VLC no such feature is available. I was able to get my display information by looking at the window titles using a modification of the post on StackOverflow:

http://stackoverflow.com/questions/14653168/get-hwnd-of-each-window-python

I've put it in a function and modified it slightly from the post.

def getWindowsTitles():
    EnumWindows = ctypes.windll.user32.EnumWindows
    EnumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))
    GetWindowText = ctypes.windll.user32.GetWindowTextW
    GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
    IsWindowVisible = ctypes.windll.user32.IsWindowVisible
   
    titles = []
    def foreach_window(hwnd, lParam):
        if IsWindowVisible(hwnd):
            length = GetWindowTextLength(hwnd)
            buff = ctypes.create_unicode_buffer(length + 1)
            GetWindowText(hwnd, buff, length + 1)
            titles.append(buff.value)
        return True
    EnumWindows(EnumWindowsProc(foreach_window), 0)
    return titles

This works fine for reading the Artist and Song if one is playing, but that doesn't let us change the track.

I tried several things to send input to VLC, but to no avail. Several input libraries wouldn't work, and I finally tried AutoHotKey. The Python Package which hooks in didn't seem to work with the current DLL, so I just made exes from the AHK scripts:

Example Next Track:

SetTitleMatchMode, RegEx
IfWinExist .*VLC media player
    WinActivate

Sleep 1000
Send {Alt down}{l}
Sleep 100
Send {x}
Send {Alt up}
return



There are probably better ways of getting it work, but for now I'm content with this implementation.