
In my living room, there's a TV, with a computer connected to it.
In that computer, there's a DVD-ROM player, a hard disk, and a card
with a TV output.
On that hard disk, there's
Debian with xine to view DVDs
When I originally put it there, I would pick up the keyboard to do
some user input. This works, but a keyboard is klunky. So, instead, I've
been working on jsxine, a little application that does not much more
than open a window, and tell xine to play a DVD there, but use the
joystick for UI[
1]. My 'joystick' is a
Logitech
Wingman Gamepad Extreme, which has a cable long enough for me to be able
to use it comfortably from the couch, so I can use it as a sort of
remote control.
The current version has quite some things hardcoded: button 0 is
'select', button 5 is 'eject', button 6 'previous chapter', button 7
'next chapter', and button 8 is 'start or stop playing'. The primary two
axes move around in the DVD menu; and other stuff is not yet
implemented. This layout, of course, makes a lot of sense on this
particular gamepad, but I doubt it does on other joystick devices. And
since I want this to eventually be useful for other people, too, I
recognized that I would need some way to configure things.
My initial stab at configuration would create a hash table of
available actions, read out a configuration file, and then find the
appropriate function pointer in the hash table. While this works, it has
one rather important downside: adding a configurable action would
requrie another item in the hash table; this would eventually make the
hash table horribly long. So I thought, why not use the configuration
value to ask the dynamic linker to get me a function pointer?
With a little help from
my
friends, that's exactly what I did. Proof-of-concept code:
#include <dlfcn.h>
#include <stdio.h>
int function()
printf("In function!\n");
int main(int argc, char**argv)
int (*funcptr)(void);
void* handle;
printf("foo\n");
handle = dlopen(NULL, RTLD_NOW);
funcptr = dlsym(handle, "function");
funcptr();
return 0;
Compile with
cc -ldl -rdynamic. Et voila, that gets you an
application which can do a lookup of function names at run time.
Long live C.
Of course, there's a bit of a danger in the above example. A
user could just write a config file that has things like 'open' and/or
'write' as arguments, or the like. One should make sure that it can be
obvious from the function name that it does indeed define an action; for
example, by giving them a common prefix, and prepending that prefix to
the function name before handing the name off to dlsym().
But other than that, this seems to work. It apparently also is
documented in the FreeBSD documentation on dlopen(), so maybe it's not
as much a hack as I thought...
Oh well.
Note that on GNU systems, you can also put a
#define
_GNU_SOURCE before the
#include <dlfcn.h>, you can
drop the
dlopen() call and go straight to dlsym(), with
RTLD_DEFAULT as the handle.
[1] Yes, I could have done a Xine
plugin. I didn't want to. This is as much a project to produce
something useful as it is a project to hack and have fun.