Controlling VLC via RC (“Remote Control”) interface using a UNIX domain socket (and no programming)

Sorry for the long title: I’ve had to dig through too many generic posts while fighting my way through this adventure. As always, once you know the solution, it’s really simple (just like discovering America). Well, this post will give me a warm and fuzzy feeling that my (mostly wasted) time and effort can make this world a happier place…

If you do not know what VLC is… go grab a copy, it’s free. It is, literally, the last media player you will ever need. It plays anything and everything, without any complex configuration, without hiccups (Ok, once in five years I do run into a problem file), and without pain. There is a version of VLC for every platform (Mac, PC, Unix, Linux, whatever). It can perform some very sophisticated tasks, like streamng video over the networks and driving webcams, and it has been used as an audio/video engine by numerous applications. I bet you’ve used it already without even knowing it. Oh, and it’s not even “version 1.0” yet – those guys are really serious about reaching perfection.

VLC is extremely user-friendly and mostly elf-explanatory. The nasty side-effect of that is that its documentation is… terse. Once you go digging in the obscure… there be dragons. But enough bitching.

My problem was simple:

VLC controls behave differently from Tivo controls in their handling of playback speed.

In VLC if you want to go faster, you click an icon or use a shortcut, and it goes faster. You click again – it goes even faster. And so on. Want to slow it down? Click another icon and it takes you to the next lower speed level.  So you would go through the sequence of FASTER-FASTER-FASTER-SLOWER-SLOWER-SLOWER and end up at normal speed. If you press PAUSE while goig fast, and then press PLAY, you will be going fast again. Very consistent, but…

Tivo does not have multiple “faster” speeds, but it does have a “reset-to-normal” function incorporated with the PLAY function. You go FAST, then you press PLAY and you are at normal speed again! A minor difference, but I control both my Tivo and my computer with one remote (Harmony), and my hand refuses to learn to distinguish between the devices. So when things work differently (no matter how internally consistent) it drives me nuts.

Unfortunately, there is no “reset to normal” menu item or hotkey shortcut.

The solution: use RC interface over UNIX domain socket.

Beside GUI and Hotkey interfaces, VLC has a bunch of other control options including a built-in Web server, mouse gestures, and several “remote control” interfaces (rumor has it there is even a LIRC infra-red driver on Linux).

These interfaces were not created equal: they support different sets of commands and some are a real headache to use.

RC (“Remote Control”) interface actually does not talk to any physical remote. It is basically very similar to a telnet session (there is even a talk among the developers about merging the two) only you can run it via a TCP socket or a UNIX domain socket (details follow).

Configuration Note: the following has been on a Mac running OS X (Leopard). Mac OS X is a UNIX (BSD) at heart (albeit a wird one). It is possible that on a Windows system you will have to choose a different path.

Disclaimer: This worked for me. It may not work for you. It may render you illegaly blind, and your computer permanently aberrant. I did not advise you to do anything. Look before you jump!

Note: you can start VLC without any GUI and control it exclusively via RC interface (see VLC Wiki and documentation). That was not my ambition, so I used the Graphical interface to configure RC.

Step 1: confirm that RC interface is working

Open a terminal window and invoke VLC with Remote Control interface (the path below is Mac-specific):

MyMac:~ user$ /Applications/VLC.app/Contents/MacOS/VLC -I rc

[00000001] main libvlc debug: VLC media player - version 0.9.8 Grishenko - (c) 1996-2008 the VideoLAN team
[00000001] main libvlc debug: libvlc was configured with ./configure  '--enable-release' '--enable-update-check' '--with-macosx-sdk=/Developer/SDKs/MacOSX10.4u.sdk' 'PKG_CONFIG_PATH=:/opt/local/lib/pkgconfig:/opt/local/lib/pkgconfig'
[00000001] main libvlc debug: translation test: code is "C"

Remote control interface initialized. Type `help' for help.

A-ha! It’s alive!Even better than “help” is “longhelp”. By the time you read this things may change, but still… here is the list of commands:

longhelp
+----[ Remote control commands ]
|
| add XYZ  . . . . . . . . . . . . add XYZ to playlist
| enqueue XYZ  . . . . . . . . . queue XYZ to playlist
| playlist . . . . .  show items currently in playlist
| play . . . . . . . . . . . . . . . . . . play stream
| stop . . . . . . . . . . . . . . . . . . stop stream
| next . . . . . . . . . . . . . .  next playlist item
| prev . . . . . . . . . . . .  previous playlist item
| goto . . . . . . . . . . . . . .  goto item at index
| repeat [on|off] . . . .  toggle playlist item repeat
| loop [on|off] . . . . . . . . . toggle playlist loop
| random [on|off] . . . . . . .  toggle random jumping
| clear . . . . . . . . . . . . . . clear the playlist
| status . . . . . . . . . . . current playlist status
| title [X]  . . . . . . set/get title in current item
| title_n  . . . . . . . .  next title in current item
| title_p  . . . . . .  previous title in current item
| chapter [X]  . . . . set/get chapter in current item
| chapter_n  . . . . . .  next chapter in current item
| chapter_p  . . . .  previous chapter in current item
|
| seek X . . . seek in seconds, for instance `seek 12'
| pause  . . . . . . . . . . . . . . . .  toggle pause
| fastforward  . . . . . . . .  .  set to maximum rate
| rewind  . . . . . . . . . . . .  set to minimum rate
| faster . . . . . . . . . .  faster playing of stream
| slower . . . . . . . . . .  slower playing of stream
| normal . . . . . . . . . .  normal playing of stream
| f [on|off] . . . . . . . . . . . . toggle fullscreen
| info . . . . .  information about the current stream
| stats  . . . . . . . .  show statistical information
| get_time . . seconds elapsed since stream's beginning
| is_playing . . . .  1 if a stream plays, 0 otherwise
| get_title . . . . .  the title of the current stream
| get_length . . . .  the length of the current stream
|
| volume [X] . . . . . . . . . .  set/get audio volume
| volup [X]  . . . . . . .  raise audio volume X steps
| voldown [X]  . . . . . .  lower audio volume X steps
| adev [X] . . . . . . . . . . .  set/get audio device
| achan [X]. . . . . . . . . .  set/get audio channels
| atrack [X] . . . . . . . . . . . set/get audio track
| vtrack [X] . . . . . . . . . . . set/get video track
| vratio [X]  . . . . . . . set/get video aspect ratio
| vcrop [X]  . . . . . . . . . . .  set/get video crop
| vzoom [X]  . . . . . . . . . . .  set/get video zoom
| snapshot . . . . . . . . . . . . take video snapshot
| strack [X] . . . . . . . . . set/get subtitles track
| key [hotkey name] . . . . . .  simulate hotkey press
| menu . . [on|off|up|down|left|right|select] use menu
|
| @name marq-marquee  STRING  . . overlay STRING in video
| @name marq-x X . . . . . . . . . . . .offset from left
| @name marq-y Y . . . . . . . . . . . . offset from top
| @name marq-position #. . .  .relative position control
| @name marq-color # . . . . . . . . . . font color, RGB
| @name marq-opacity # . . . . . . . . . . . . . opacity
| @name marq-timeout T. . . . . . . . . . timeout, in ms
| @name marq-size # . . . . . . . . font size, in pixels
|
| @name logo-file STRING . . .the overlay file path/name
| @name logo-x X . . . . . . . . . . . .offset from left
| @name logo-y Y . . . . . . . . . . . . offset from top
| @name logo-position #. . . . . . . . relative position
| @name logo-transparency #. . . . . . . . .transparency
|
| @name mosaic-alpha # . . . . . . . . . . . . . . alpha
| @name mosaic-height #. . . . . . . . . . . . . .height
| @name mosaic-width # . . . . . . . . . . . . . . width
| @name mosaic-xoffset # . . . .top left corner position
| @name mosaic-yoffset # . . . .top left corner position
| @name mosaic-offsets x,y(,x,y)*. . . . list of offsets
| @name mosaic-align 0..2,4..6,8..10. . .mosaic alignment
| @name mosaic-vborder # . . . . . . . . vertical border
| @name mosaic-hborder # . . . . . . . horizontal border
| @name mosaic-position {0=auto,1=fixed} . . . .position
| @name mosaic-rows #. . . . . . . . . . .number of rows
| @name mosaic-cols #. . . . . . . . . . .number of cols
| @name mosaic-order id(,id)* . . . . order of pictures
| @name mosaic-keep-aspect-ratio {0,1} . . .aspect ratio
|
| help . . . . . . . . . . . . . . . this help message
| longhelp . . . . . . . . . . . a longer help message
| logout . . . . . . .  exit (if in socket connection)
| quit . . . . . . . . . . . . . . . . . . .  quit vlc
|
+----[ end of help ]

If you are having trouble – make sure you got “fake TTY” option on (see the wiki or the next steps).

Also, keep in mind that the help is not always right – I failed to make PLAY command work (but pause acts as a play/ppause toggle, so I am happy enough).

Step 2: enable RC Interface.

Enable RC interface

Enable RC interface

Step 3: Configure RC interface

Configure RC Interface

Configure RC Interface

You can use TCP command input (type in something like “localhost 9999”) and telnet into thee system (port 9999 in this case). But telnet is hard to script and even harder to secure. So unless you actually need to control VLC remotely, a UNIX socket is a safer (and more efficient) choice.

For those not proficient in UNIX lore, a “domain socket” is sort of like  a pipe. In the system it is represented by a special kind of a file (well, virtually everything in UNIX is represented by a file of some sort, although you cnnot just write into a socket – you use special commands for that). Sockets are popular for inter-process communication, which is why few non-programmers ever run into them.

I do not believe that “.sock” extention is a must. It’s just kinda traditional.

You can put your socket anywhere, just make sure that VLC has proper access rights to the directory.

I do not get any results unless the “Fake TTY” box is ticked. No, I do not know why. (Do YOU kow? – Post a comment!)

Once you save the settings, every time you launch VLC a socket file will appear. When VLC closes, the socket is automatically destroyed. So just by watching the directory you can tell that the socket is up.  Well, now that it is up, let’s talk to it!

Step 4: talking to VLC through the socket.

Launch VLC by double-clicking on it (or you can launch it via the command line with all the proper keys, but I am taking the GUI route here). Open a video. Let it play.

Now open a terminal window and issue a command:

sh-3.2$ /bin/echo -n  "pause" | nc -U /Users/vlc.sock

Look! Your move just paused! Do it again! O-la-la! It’s playing again!

Make it go faster:

sh-3.2$ echo faster | nc -U /Users/vlc.sock
status change: ( new rate: 666 )
faster: returned 0 (no error)

Faster!

sh-3.2$ echo faster | nc -U /Users/vlc.sock
status change: ( new rate: 500 )
faster: returned 0 (no error)

See how the rate changed? The voices in the movie are really high and funny now.

And now the best part (as far as I am concerned):

sh-3.2$ /bin/echo -n  "normal" | nc -U /Users/vlc.sock

And it is back to normal speed.

Note: It would appear that “normal” command works more consistently if the video is NOT paused, although this may change from version to version.

What are all those commands?

All we did is we used “echo” to output the command text and then piped this output (see the “|” symbol) to “netcat” or “nc”.

Echo is built into every command shell I know. Mac terminal uses bash shell, but Applescript uses a different shell, with a slightly different version of echo. If you intend to issue the above commands via Applescript on a Mac, you need to either specify the location of echo, or be aware of the differences.

Nc (or netcat) is an amazingly versatile command line tool that can be used for anything from testing a connection to building a firewall. In this case we just tell it to take the input from echo and send it into a UNIX domain socket. That’s is. No more magic.

A few Mac-specific details

The funky configuration I concocted to control my mac via Harmony Remote (Mac Pro does not come with a remote control) does not let me issue shell commands directly, but is Ok with Applescript. So I just put together a simple script for each button (actually, for most buttons I just use hotkeys).

For the “go at normal speed” I attach the following to the PLAY button on my remote:

do shell script "echo normal | nc -U /Users/andrabr/vlc.sock"
do shell script "echo pause | nc -U /Users/andrabr/vlc.sock"
do shell script "echo normal | nc -U /Users/andrabr/vlc.sock"

The repeated “normal” command is due to my using ‘PLAY button as a play/pause toggle (and “normal” does not work reliably when the video is paused). For most other commands you just need to issue them once.

That’s it folks!

Go forth and make your VLC dance to the tune of your socket 😀

Did I miss anything? Can this be improved? Let me know!


About this entry