Version: 1:2
vlc: VideoLAN VLC Media Player Control in Racket
1 Introduction
This
vlc package permit Racket programs to start and control a
VideoLAN VLC media player, for playing video and audio.
VLC itself is a separate computer program, and must be installed
separately.
This package uses the
VLC RC interface over TCP. The Racket host OS process’s address space is isolated
from potential memory-handling defects in the various native code libraries
involved in media playing.
For a simple example of using this package, imagine that you are
studying how to improve a corporate training video, and you have a theory that
the video would be more efficacious, were minimum-wage new hires not bored to
catatonia by the CEO’s rambling 10-minute introduction. Fortunately, you have
human subjects available, since the new hires all use a Racket-based training
system that can be modified quickly to add scientific experiments, showing the
CEO’s intro to some subjects but not to others. Unfortunately, you can’t just
edit the training video to make an alternate version without the CEO’s intro,
since the CEO is an aspiring Hollywood actor, who negotiated “points” on DVD
sales. Fortunately, you can use VLC and this Racket vlc package, to launch the pertinent DVD chapter and seek past the
initial 10 minutes of Valium:
(start-vlc "dvd:///dev/dvd#1:2") |
(wait-for-vlc-active-playing) |
(vlc-seek 594) |
In addition to highly contrived examples like that, this package is
being used as part of a Racket-based home theatre system being developed.
This package is currently developed using VLC 2.0.3, on Debian
GNU/Linux, and has been observed to also work on Mac OS X. MS Windows is not
currently supported (since, on MS Windows, VLC 2.0.3 does not support the RC
interface, and instead uses something called oldrc).
2 Processes & Connections
A connection to a VLC process is represented by the vlc object. This connection can be to a process that is started by
the start-vlc procedure, or an existing VLC process (possibly on a host
elsewhere on the network).
(vlc? x) → boolean?
|
x : any/c |
Predicate for whether or not x is a vlc object.
(current-vlc) → (or/c vlc? #f)
|
(current-vlc vlc) → void? |
vlc : (or/c vlc? #f) |
Parameter for the vlc to use as the default for most procedures in this package
when the optional #:vlc argument is not supplied to the procedure.
(connect-to-vlc | | #:port port | | | | | | [ | #:hostname hostname | | | | | | | #:connecting-timeout connecting-timeout | | | | | | | #:set-current-vlc? set-current-vlc?]) | | → | | vlc? |
|
| port | | : | | (and/c exact-nonnegative-integer? | (integer-in 1 65535)) |
|
|
hostname : string? = "localhost" |
connecting-timeout : (and/c real? (not/c negative?)) = 5.0 |
set-current-vlc? : boolean? = #t |
Connect to the RC interface on an existing process, at TCP hostname and port, and return a vlc object. If set-current-vlc? is true, which is the default, then the current-vlc parameter is also set.
connecting-timeout is a guideline of the maximum number of seconds total that
should be spend attempting to get a TCP connection to the VLC process and then
exchange certain initial protocol. It is not a hard limit, however. Note that
multiple attempts at the TCP connection may be tried within that limit, for
situations such as waiting for a VLC process to start up.
(start-vlc | [ | #:port port | | | | | | | #:hostname hostname | | | | | | | #:connecting-timeout connecting-timeout | | | | | | | #:logger logger | | | | | | | #:logger-level logger-level | | | | | | | #:set-current-vlc? set-current-vlc? | | | | | | | #:command command | | | | | | | extra-args ...]) | | → | | vlc? |
|
| port | | : | | (or/c #f | (and/c exact-nonnegative-integer? | (integer-in 1 65535))) |
| | = | | #f |
|
hostname : string? = "localhost" |
| connecting-timeout | | : | | (or/c #f (and/c real? (not/c negative?))) | | | | = | | 60.0 |
|
logger : (or/c #f logger?) = (current-logger) |
| logger-level | | : | | (or/c 'fatal 'error 'warning 'info 'debug) | | | | = | | 'info |
|
set-current-vlc? : boolean? = #t |
command : (or/c #f path-string?) = #f |
extra-args : (listof (or/c string? path?)) = '() |
Start a VLC process on the same machine on which this Racket
program is running, with RC enabled, and connect to it. A vlc object is returned. If set-current-vlc? is true, which is the default, then the current-vlc parameter is also set.
command is a string or path object for the complete path to the VLC executable; or, if the default of #f, then this package attempts to find the VLC executable.
This package supplies some command-line arguments to VLC, to set
up the RC interface. Additional command-line arguments can be supplied as
strings and/or path objects to the extra-args argument of this procedure.
(start-vlc "--snapshot-path=/home/me/film-class/review-screenshots" |
"dvd:///dev/dvd") |
If logger is #f, then stdout and stderr output is consumed and ignored. Otherwise, such output is
redirected to the logger, with the log level specified by logger-level.
If port is #f, which is the default, then this package attempts to select a
TCP port in the ephemeral range for VLC to use for RC; otherwise, port is the port number to use.
hostname is the string hostname (or the IP address as a string) on which
VLC should listen on the TCP port for RC. By default, this is "localhost", which is what you normally want with start-vlc rather than connect-to-vlc. In the unlikely event that you wish for the RC port of this
VLC process to also be accessible from other hosts, you may supply the hostname
or IP address for a non-localhost interface.
connecting-timeout is as documented for connect-to-vlc.
The VLC process is started under the current custodian. If you are calling start-vlc from a short-lived thread with its own custodian that you
shutdown as the thread exits, such as for an HTTP request that triggers
starting of VLC, you might want to do something like:
(parameterize ((current-custodian <long-lived-custodian>)) |
(start-vlc)) |
3 URLs
URLs may be provided to VLC commands in any of a few different
formats. See documentation for vlc-url?.
(vlc-url? x) → boolean?
|
x : any/c |
Predicate for whether or not x can (likely) be used as a URL argument to procedures like vlc-add and vlc-enqueue. Specifically, URLs can be represented as one of the following:
String starting with a URL scheme, such as "http://example.com/foo.mp4". Note that this string must contain a %-escaped URL, with no spaces or other problematic characters.
url object, such as is produced by (string->url "http://example.com/bar/foo.mp4").
String not starting with a URL scheme, such as "/home/billybob/tractors.mp4", which is a file path.
path object, such as is produced by (string->path "/home/scotty/sheep.wav").
Byte string of a complete URL in UTF-8 encoding, including %-escaping. This is passed verbatim in the RC protocol.
Note that URLs provided to commands are processed by the VLC
program, which might be on a different computer than the Racket program that is
sending commands. URLs that may be accessed from one computer can’t
necessarily be accessed by another.
(to-vlc-rc-url-bytes x) → bytes?
|
x : (or/c string? path? url? bytes?) |
Accepts a VLC URL as described in the documentation for vlc-url? and yields a byte string representation. Note that, if x is a byte string, then it is returned verbatim. This procedure
will not be called directly by most programs using this package.
4 Commands
This section lists the various command procedures. Generally, each
procedure corresponds to a VLC RC command. For example, vlc-add corresponds to the RC add command. For the most part, these procedures are defined to “do
whatever the RC command does.” The RC command itself might not be
well-documented. So, for example, if, in the version of VLC being used, the add command results in the the specified URL both being prepended to
the playlist and being played, then that’s what the vlc-add command will do.
Note that some of these commands have asynchronous effects, due to
the design of VLC or of the VLC RC protocol. For example, the vlc-play procedure can return before VLC is actually playing the media.
4.1 Playlist
(vlc-clear [#:vlc vlc]) → void?
|
vlc : vlc? = (current-vlc) |
Clear all items from the playlist.
(vlc-add thing [#:vlc vlc]) → void?
|
thing : vlc-url? |
vlc : vlc? = (current-vlc) |
Adds the URL thing to the playlist. This command seems to also cause VLC to start
playing the item.
(vlc-enqueue thing [#:vlc vlc]) → void?
|
thing : vlc-url? |
vlc : vlc? = (current-vlc) |
Enqueues the URL thing in the playlist.
(vlc-next [#:vlc vlc]) → void?
|
vlc : vlc? = (current-vlc) |
Start playing the next item in the playlist.
(vlc-prev [#:vlc vlc]) → void?
|
vlc : vlc? = (current-vlc) |
Start playing the previous item in the playlist.
4.2 Repeat / Loop / Random
(vlc-repeat on? [#:vlc vlc]) → void?
|
on? : boolean |
vlc : vlc? = (current-vlc) |
Set whether VLC should repeat playing the current stream continuously.
(vlc-loop on? [#:vlc vlc]) → void?
|
on? : boolean |
vlc : vlc? = (current-vlc) |
Set whether VLC should repeat playing the playlist continuously.
(vlc-random on? [#:vlc vlc]) → void?
|
on? : boolean |
vlc : vlc? = (current-vlc) |
Set whether VLC should select streams from the playlist randomly,
rather than in order.
4.3 Title and Chapter
(vlc-title-n [#:vlc vlc]) → void?
|
vlc : vlc? = (current-vlc) |
Switch to the next title of the current stream.
(vlc-title-p [#:vlc vlc]) → void?
|
vlc : vlc? = (current-vlc) |
Switch to the previous title of the current stream.
(vlc-chapter-n [#:vlc vlc]) → void?
|
vlc : vlc? = (current-vlc) |
Switch to the next chapter of the current stream.
(vlc-chapter-p [#:vlc vlc]) → void?
|
vlc : vlc? = (current-vlc) |
Switch to the previous chapter of the current stream.
4.4 Play, Pause, and Stop
(vlc-play [#:vlc vlc]) → void?
|
vlc : vlc? = (current-vlc) |
Play the next stream, if not already playing one.
(vlc-pause [#:vlc vlc]) → void?
|
vlc : vlc? = (current-vlc) |
Toggle the playing pause state.
(vlc-stop [#:vlc vlc]) → void?
|
vlc : vlc? = (current-vlc) |
Stop playing the current stream, if playing or paused.
(vlc-is-playing [#:vlc vlc]) → number?
|
vlc : vlc? = (current-vlc) |
Yields a boolean value for whether or not a stream is
playing.
4.5 Rate
(vlc-fastforward [#:vlc vlc]) → void?
|
vlc : vlc? = (current-vlc) |
Set rate of playing to maximum.
(vlc-rewind [#:vlc vlc]) → void?
|
vlc : vlc? = (current-vlc) |
Set rate of playing to maximum reverse.
(vlc-faster [#:vlc vlc]) → void?
|
vlc : vlc? = (current-vlc) |
Increase the rate of playing of the current stream.
(vlc-slower [#:vlc vlc]) → void?
|
vlc : vlc? = (current-vlc) |
Lower the rate of playing of the current stream.
(vlc-normal [#:vlc vlc]) → void?
|
vlc : vlc? = (current-vlc) |
Play the current stream, and at normal speed.
(vlc-frame [#:vlc vlc]) → void?
|
vlc : vlc? = (current-vlc) |
Set current stream playing to frame-by-frame, or advance one
frame.
(vlc-rate rate [#:vlc vlc]) → void?
|
rate : real? |
vlc : vlc? = (current-vlc) |
Set playing rate to rate.
4.6 Absolute Position
(vlc-get-time [#:vlc vlc]) → number?
|
vlc : vlc? = (current-vlc) |
Get the time position of the current stream, in seconds.
(vlc-get-length [#:vlc vlc]) → number?
|
vlc : vlc? = (current-vlc) |
Get the length of the current stream, in seconds.
(vlc-seek seconds [#:vlc vlc]) → void?
|
seconds : exact-nonnegative-integer? |
vlc : vlc? = (current-vlc) |
Seek playing to position seconds.
4.7 Audio, Video, and Subtitle Tracks
(vlc-atrack [#:vlc vlc])
|
| → | | integer? | (listof (cons/c string? (listof (cons/c string? integer?)))) |
|
|
vlc : vlc? = (current-vlc) |
(vlc-atrack num [#:vlc vlc]) → void? |
num : integer? |
vlc : vlc? = (current-vlc) |
If num is not provided, yields information about current and available audio
tracks for the current stream.
If num is provided, switches the audio to that track.
(vlc-vtrack [#:vlc vlc])
|
| → | | integer? | (listof (cons/c string? (listof (cons/c string? integer?)))) |
|
|
vlc : vlc? = (current-vlc) |
(vlc-vtrack num [#:vlc vlc]) → void? |
num : integer? |
vlc : vlc? = (current-vlc) |
If num is not provided, yields information about current and available video
tracks for the current stream.
If num is provided, switches the audio to that track.
(vlc-strack [#:vlc vlc])
|
| → | | integer? | (listof (cons/c string? (listof (cons/c string? integer?)))) |
|
|
vlc : vlc? = (current-vlc) |
(vlc-strack num [#:vlc vlc]) → void? |
num : integer? |
vlc : vlc? = (current-vlc) |
If num is not provided, yields information about current and available
subtitles and captions tracks for the current stream. For example, for one
DVD:
-1 |
'(("spu-es" |
("Disable" . -1) |
("Track 1 - [Français]" . 14) |
("Track 2 - [Español]" . 15) |
("Closed captions 1" . 17) |
("Closed captions 2" . 18) |
("Closed captions 3" . 19) |
("Closed captions 4" . 20))) |
If num is provided, switches the subtitles/captions to that track.
4.8 Audio Options
4.9 Video Options
(vlc-fullscreen on? [#:vlc vlc]) → void?
|
on? : boolean? |
vlc : vlc? = (current-vlc) |
Set whether VLC is in fullscreen mode.
4.10 Misc. Info
(vlc-get-title [#:vlc vlc]) → string?
|
vlc : vlc? = (current-vlc) |
Get the title of the current stream. For example, a particular
DVD, might give behavior like:
> (vlc-get-title) |
"WEST_WING_S7_D3" |
Warning: Season 7 is not the best season for West Wing.
(vlc-status [#:vlc vlc]) → (list-of (cons/c bytes? bytes?))
|
vlc : vlc? = (current-vlc) |
Yields an alist of some information about current status. The car of each pair of the alist is a byte string of one of the
following attribute names, and the cdr is a byte string of the attribute value:
#"new input" – URL of the current playlist item.
#"audio volume" – number representing the audio volume.
#"state" – play state; possibly including the following values: #"playing", #"paused", #"stopped".
Which attributes are included depends on VLC.
5 Snapshots
(vlc-snapshot [#:vlc vlc]) → void?
|
vlc : vlc? = (current-vlc) |
Write a snapshot still image of the current video display to a
file. See VLC documentation for command line arguments for controlling where
and how these files are written, such as –snapshot-path.
6 Exiting
(vlc-shutdown [#:vlc vlc]) → void?
|
vlc : vlc? = (current-vlc) |
Terminate the VLC process in an orderly fashion.
7 Other Operations
In addition to the procedures that correspond to VLC RC commands,
there are some additional procedures that are built atop RC commands.
(wait-for-vlc-active-playing | [ | #:delay delay | | | | | | | #:vlc vlc]) | | → | | void? |
|
delay : (and/c real? (not/c negative?)) = 0.1 |
vlc : vlc? = (current-vlc) |
Wait for VLC to be actively playing, by which we mean that the
stream has actually started playing, not just the RC status command indicating state: playing, when, say, the DVD hasn’t actually started playing. This seems
to be important for some other operations to take effect, such as seeking in
some cases.
Note that this procedure is currently protocol-intensive with the
RC interface. delay is the number of seconds to pause in between repeatedly sending
some RC messages. By default, it is 0.1, meaning one tenth of a second.
8 Known Issues
Finish implementing RC commands.
Need to verify that RC uses UTF-8, and consistently.
Should try to verify existence of objects before being added to
the playlist, since otherwise VLC can keep trying them continuously and
flooding with repeated error messages.
The protocol parsing is pretty good, but could still be improved.
In particular, for some messages, it would be better to make the message end
detection sensitive to the syntax of the message. Before doing that, verify
that RC uses UTF-8 consistently.
Add a exn:fail:vlc exception, for ease of handling errors from the protocol, such as
error-message output from RC commands. Currently, these are raised as exn:fail.
Make vlc-status return strings instead of byte strings, after making sure UTF-8 is consistent.
9 History
PLaneT 1:2 — 2012-09-27
PLaneT 1:1 — 2012-09-27
When start-vlc can’t find VLC in the executable search path, it will
then try a few “known suspect” paths, including the standard one for Mac OS
X. (Thanks to Greg Hendershott for reporting.)
Documentation for start-vlc regarding custodians has been corrected. (Thanks to
Greg Hendershott for reporting.)
Updated documentation to say that this package has been
reported to work on Mac OS X and Microsoft Windows XP.
PLaneT 1:0 — 2012-09-22
10 Legal
Copyright 2012 Neil Van Dyke. This program is Free Software; you
can redistribute it and/or modify it under the terms of the GNU Lesser General
Public License as published by the Free Software Foundation; either version 3
of the License, or (at your option) any later version. This program is
distributed in the hope that it will be useful, but without any warranty;
without even the implied warranty of merchantability or fitness for a
particular purpose. See http://www.gnu.org/licenses/ for details. For other
licenses and consulting, please contact the author.
VideoLAN, VLC, and VLC media player are trademarks of VideoLAN.