I was bored today and the internet was broken so rather than going outside or exercising or something like that I tried to figure out how to remotely control XMMS. It was an interesting project that touched on a couple different areas of system configuration useful otherwise, so I figured I'd record the process.

I've got a Madrake box that has speakers, but which sits across the lab from the RedHat 9 server where I do my work. I want to be able to change songs and pause it when someone comes in without getting up.

There is a useful program under Mandrake called xmms-shell that lets me do the normal forward and back that I can do using the xmms program directly, but also select specific entries in the playlist and load playlists and different things.

It is a neat program and I wondered how it worked, so I ran strace xmms-shell to see. When I do a jump 10 I see a trace like this:

brk(0x807e000)                          = 0x807e000
socket(PF_UNIX, SOCK_STREAM, 0)         = 3
getuid32()                              = 503
geteuid32()                             = 503
setuid32(0x1f7)                         = 0
setreuid32(0x1f7, 0x1f7)                = 0
connect(3, {sin_family=AF_UNIX, path="/tmp/xmms_will.0"}, 110) = 0
write(3, "\1\0\t\0\0\0\0\0", 8)         = 8
read(3, "\1\0\0\0\4\0\0\0", 8)          = 8
read(3, "c\0\0\0", 4)                   = 4
read(3, "\1\0\0\0\0\0\0\0", 8)          = 8
close(3)                                = 0
socket(PF_UNIX, SOCK_STREAM, 0)         = 3
getuid32()                              = 503
geteuid32()                             = 503
setuid32(0x1f7)                         = 0
setreuid32(0x1f7, 0x1f7)                = 0
connect(3, {sin_family=AF_UNIX, path="/tmp/xmms_will.0"}, 110) = 0
write(3, "\1\0\10\0\4\0\0\0", 8)        = 8
write(3, "\t\0\0\0", 4)                 = 4
read(3, "\1\0\0\0\0\0\0\0", 8)          = 8
close(3)                                = 0
write(1, "Jumped to position 10 in the pla"..., 39Jumped to position 10 in the playlist.) = 39

It turns out that the important lines are these two:

write(3, "\1\0\10\0\4\0\0\0", 8)        = 8
write(3, "\t\0\0\0", 4)                 = 4

The following perl code will cause xmms to jump to a song:

#!/usr/bin/perl
use strict;
use Socket;

my $path = "/tmp/xmms_will.0";

my $num = shift || die "enter num";

socket(XMMS, PF_UNIX, SOCK_STREAM, 0) or die "socket: $!";
connect(XMMS, sockaddr_un($path)) or die "open: $path: $!";
syswrite(XMMS, "\1\0\10\0\4");
syswrite(XMMS, pack("C4", $num - 1));
close(XMMS);

I could go through and reverse engineer the codes for each command and write little scripts like the one above. This would be time consuming though and if the program changed versions the codes could well change.

Another option is to use the xmms-shell program which can take scripts on the command line like xmms-shell -e "jump 23". I like this idea more since it is more likely to last over time. The one drawback is xmms-shell isn't widley distributed and so it wouldn't work on other systems.

I think the idea I like the best is doing it programatically. XMMS includes functions that can be seen with nm /usr/lib/libxmms.a | grep remote. Calling those functions without writing a C program is a bit of a pain though. I think I want to do the interface through a scripting language...

Unfortunately the computer I am working on has no development tools at all installed, so even though I there is a XMMS interface module for perl, when I do perl -MCPAN -e 'install xmms' it fails because there is no C compiler and none of the header files for perl.

Because my goal was to do as few modifications as possible to the box I will stich with xmms-shell.

The setup that I want is to have my numeric keypad work in bash like it does for winamp. That is:

7
seek backward 5 seconds
not possible with xmms-shell
8
increase volume 5%
upvoulme
9
seek forward 5 seconds
not possible with xmms-shell
4
next song
next (only possible to do next song in order; no shuffle)
5
play
play
6
previous song
next (only possible to do previous song in order; no shuffle)
1
2
decrease volume 5%
downvolume
3