Things I'll Forget In A Month Tech scratchpad and musings

7Dec/110

P2Proto: a Java RPC library for P2P applications built on protocol buffers

Yet another coding project I've been working on - this one is an RPC library for Java applications using protocol buffers. This started a few years back when I had a peer-to-peer app using Java RMI that needed to handle a large volume (hundreds) of simultaneous connections and calls, and the app was getting crushed under the load. Another problem was that RMI doesn't really have asynchronous method calls, which was creating an additional performance bottleneck due to the massive numbers of thread required.

To deal with these issues, I switched to using Google's Protocol Buffers, which are compact and efficient, but don't have any decent built-in RPC capabilities. Thus, I set about rolling my own RPC library for protocol buffers. I used it a number of times for distributed programs over the years, and each time improved it somewhat as the project dictated. For my most recent project, I felt that it finally reached a state that could be classified as a usable library, so I added some decent documentation and cleaned everything up to release.

The library itself handles a number of functions not provided by protocol buffers themselves:

  • Delimiting and extracting protocol buffer messages from a persistent network stream.
  • Setting up two-way message channels over which to exchange protocol buffer messages.
  • Associating query and response messages, independent of message arrival order (i.e., there's no need to manually determine which query message a response corresponds to).
  • Convenient handlers for the various types of RPC errors that can occur (local send errors, remote processing errors, and communication timeout errors).

This is all done without any synchronization (except for when multiple threads are using a single connection) or busy waiting, so the library overhead should be low. Protocol buffer messages themselves are extremely compact, so the amount of network data overhead should also be minimal.

As usual, here are the download links: the main project page, the complete library source, the library jarfile only, and finally, the online Javadoc, which includes some code samples using the library.

Filed under: Projects No Comments
21Nov/114

JSava: a Java bytecode interpreter in JavaScript

Here's another cool project I've been working on - it's an interpreter for Java bytecodes (i.e., like the JVM). What's more interesting about it, however, is that it's written in JavaScript. Furthermore, it runs on top of Mozilla Rhino, which means it's actually C code (the JVM) which runs Java code (Rhino) which runs JavaScript code (the interpreter, JSava) which runs Java code (a user program). The double-interpreter thing does take a hit on speed, but the point isn't to beat the JVM for speed - it's to just accomplish something cool in a quirky language like JavaScript.

This may seem like deja vu to Slashdot readers, which is what prompted me to post this. I think JSava is particularly interesting, however, because it can handle many fairly advanced features of the JVM and is capable of executing much (most?) of the JDK standard library. Some feature highlights include:

  • All 200 JVM opcodes are implemented.
  • All native Java types are supported, including 64-bit Longs, which are not natively supported by JavaScript. This is because JavaScript represents everything as 64-bit floating point numbers, which cannot store the full range of 64-bit integer values.
  • Full support for the Java threading model, including multithreading, synchronization between threads, and monitors (wait() and notify()). However, note that multithreading does not imply parallelism, which is at the moment effectively impossible in JavaScript - JSava provides threading support by timeslicing a single actual thread of execution.
  • JSava is complete enough to execute most major JDK library classes, such as java.util.HashMap and java.util.Random. Even some more exotic classes are mostly functional, such as java.util.concurrent.ExecutorService and company.
  • Substantial support for the Reflection API. This may seem like a weird thing to support, but reflection is heavily used in the JDK library classes, so supporting it is critical in enabling complete functionality.
  • All the usual Java goodness: exceptions, inheritance, interfaces, runtime error checking, etc... basically all the language features we know and love.
  • Native method handling capabilities for handing off to JavaScript implementations (e.g., System.arraycopy(), Thread.start() and lots of JDK support methods).
  • Rudimentary I/O support, accomplished through a lot of low-level trickery involving intercepting file descriptors and mapping them to native Java streams. JavaScript itself has effectively zero I/O support, but the only time Java is invoked to handle I/O is in the lowest level native methods (e.g., 'write these bytes to this file handle'). Everything above that (such as I/O buffering) is handled inside the interpreter.

The JDK class files which JSava was developed with are taken from the Mac OS X 10.6 JDK (Java SE 6). The interpreter may work on Linux, but probably won't on Windows without a little bit of tweaking, particularly for I/O (it's on my todo list).

As usual, I've also created a new program page for the project. The main download link (or Dropbox mirror) provides the entire JSava runtime environment, including Rhino and JDK library classes (3.3M). If you have Java installed, running the interpreter is as easy as executing one command (no building required!). If you only want to look at the source code and not actually run the interpreter, you can also download the source only (54K).

There were a lot of engineering tricks that went into JSava and I may write about some of them in the future. However, JSava is still very much a work in progress and I plan to extend it to handle even more than it already does.

Filed under: Hacks, JSava, Projects 4 Comments
10Nov/113

plmtools-imeter

Update (8/7/2012): plmtools-imeter now lives over at my university: check it out!

I've packaged up a new release of the modified plmtools package for talking to the iMeter. I think the code has diverged from the base plmtools enough to warrant a rebranding, so I'm (uncreatively) naming the fork 'plmtools-imeter'. I've posted a page for the project over on the main site.

Improvements from the previous release include support for both Revision 1.1 and 1.15 iMeters (thanks to Erik Wile for his detective work regarding that issue) and a variety of other smaller improvements.

A bit over a week ago I presented my research group's recent work on building monitoring using home automation devices at the BuildSys 2011 workshop in Seattle. Our paper on this work ('Exploiting Home Automation Protocols for Load Monitoring in Smart Buildings') was facilitated in part by the plmtools-imeter package.

25Apr/1110

plmtools for the iMeter Solo and/or the GuruPlug

Update (11/10/2011): I've posted an updated version of the code that fixes the issue with the new 1.15 iMeters: see my more recent post.

Update (9/26/2011): Smarthome has come out with a new revision of the iMeter that breaks this utility -- the meter firmware seems to have changed, and the new one does not provide all the information of the old. To see if you have the old meter (that does work), look for a sticker on the back side of the iMeter. If you see a "V1.1", then you have the old one (good). If you see a "Rev. 1.15", then you have the new one (bad). I'm working on figuring out the 1.15 protocol to get this utility working again with the new ones.


One of my current research projects involves instrumenting a house with a lot of Insteon home-automation devices and collecting data from them. I've been using the very useful Linux plmtools utilities to talk to the Insteon devices programmatically. However, the plmtools suite has a few shortcomings for my purposes: one, the current release doesn't compile or run on ARM-based machines (such as the GuruPlugs I'm using) and two, it has no functionality for talking to the new Insteon power meter, the iMeter Solo. The iMeter Solo basically works exactly like a Kill-A-Watt meter, except that since it's an Insteon device it's possible to interface with it.

I've dealt with both of the above problems. I've fixed the ARM-specific problems in the code so it runs great on the GuruPlug, and I've added functionality for querying the current wattage level from an iMeter Solo. I imagine there are others who would like to use plmtools on ARM-based machines, and as far as I know there are no existing tools that allow you to query the iMeter from within Linux. Now, you can query the current watt draw reported by the iMeter using a simple 'insteon mydevice meter' command.

Also note that the iMeter Solo is frequently advertised alongside a special 'HouseLinc'-enabled version of the PLM that's required to use the HouseLinc software that can talk to the iMeter. This is unnecessary for my solution, which works just fine on a regular PLM.

You can download the modified plmtools here. See the included README for details both on how the base plmtools utilities work as well as how the added meter functionality works.

22Feb/1121

Configuring the GuruPlug as a wireless client

Update (Nov. 2012): Several people have noted that the links to the GuruPlug kernel files have broken. I've mirrored them on the blog and changed the links below.

By default, the GuruPlug comes configured to act as an access point, which is probably not what most people want. Unfortunately, getting the plug to act as a reliable wifi client is nontrivial. Most existing tutorials on the topic are pretty in-depth - I'm going to give a quick and dirty method for getting wifi configured and working reliably. It's been working nonstop on my plug for several weeks with no dropouts, kernel panics, or the like.

Most of this howto is derived from info gleaned from the Plug Computer wiki, the Plug Computer forum, and tweaks I made myself.

We're going to install a custom 2.6.33.7 kernel. A prebuilt image and modules are provided on the Plug Computer wiki. A note about u-boot: I'm not sure if the included bootloader on the plugs can boot custom kernels, but if you opt to upgrade it, I recommend the version linked here. I'm not going to discuss the bootloader setup any further in this post.

Login to your plug as root, then download and install the kernel image:

wget http://blog.zortrium.net/files/uImage-2.6.33.7
cp uImage-2.6.33.7 /boot/uImage
chown root:root /boot/uImage

And now the kernel modules:

wget http://blog.zortrium.net/files/modules-2.6.33.7.tar.bz2
tar xvfj modules-2.6.33.7.tar.bz2
mv 2.6.33.7 /lib/modules/

Now we'll grab an archive of the wifi drivers and firmware, some custom wifi initialization scripts, and the wifi configuration file. We'll store all this stuff in /root.

wget http://blog.zortrium.net/files/wifi-files.tar.gz
tar xvzf wifi-files.tar.gz
mv wifi-files/* /root/

There are three main wifi files. The script that runs before Linux brings up the wireless interface is /root/wifi_pre.sh and executes some firmware voodoo to get client mode working properly. The script that runs after the interface is up is /root/wifi_post.sh and turns on a blue LED to give a visual indication that the wireless came up successfully. Finally, there's the wireless settings file /root/wifi.conf.

Open up wifi.conf and input your wireless settings. The file should be self-explanatory and basically fill-in-the-blanks for most setups, but you can read 'man wpa_supplicant.conf' for all the gory details and possible settings.

Now we need to configure Linux to cleanly bring up the wireless interface. Open up /etc/network/interfaces and input the following entry for the wireless interface mlan0:

auto mlan0
iface mlan0 inet dhcp
pre-up /root/wifi_pre.sh
post-up /root/wifi_post.sh
wpa-conf /root/wifi.conf

This will cause the plug to DHCP a wireless address -- you can also assign a static IP as you would for any other interface.

Finally, the default GuruPlug filesystem includes a bunch of garbage in /etc/rc.local. Remove any stuff pertaining to wireless (my rc.local has nothing in it at all).

And that's pretty much it. Assuming your plug is properly configured to boot from /boot/uImage, you should be able to restart and Linux will bring up the wireless at the same time it brings up the wired interface (if configured in /etc/network/interfaces). The blue LED will confirm that the wireless came up successfully.

Update (4/11): One problem I've encountered that may bite you later is that the uImage file is (re)generated by updates to the installed kernel package -- which is probably still installed on the plug, even though we overwrote the kernel image. This means that the next time you update your software and an update to the (unneeded) kernel package is pulled down, your custom uImage will be overwritten and the plug will be rendered unbootable the next time it starts. You should be able to avoid this problem by renaming the custom uImage to something else (like /boot/uImage-custom) and then changing the bootloader to boot from that rather than the standard /boot/uImage. Otherwise, when your image gets overwritten, you'll need to manually replace your custom uImage (easy enough if you're running off an SD card).

25Feb/103

Toggling audio devices in Mac OS X

I frequently switch between my external computer speakers and my headphones. Repeatedly plugging and unplugging my headphones started wearing out my headphone jack, so I hooked up an iMic to a USB port to give myself a second headphone jack. This allows switching between them in software through the Sound preference pane, which is more convenient, but still takes too long. So the next step is automating the switch. This thread on Mac OS X Hints has people discussing various ways to do it. The easiest GUI way to do the switch on Snow Leopard is just option-clicking the menu bar volume control and selecting the new output device (on Leopard, you can do effectively the same by installing SoundSource).

I'd like to avoid using the mouse at all, of course. Someone got the sources to SoundSource and created a little command-line app called audiodevice that can do the switch without a GUI. Making progress, but that still requires executing a custom command to switch from the headphones to speakers or vice versa. As a final step, I threw together a quick script that uses audiodevice to toggle between the two without any arguments:

#!/usr/bin/perl -w

use strict;

my $device1 = 'Headphones'; # my speakers, plugged into my computer's jack
my $device2 = 'iMic USB audio system'; # my headphones, plugged into my iMic's jack

foreach (`audiodevice`) {
  if (/output: (.*)/) {
    if ($1 eq $device1) {
      system("audiodevice output '$device2'");
      exit;
    } elsif ($1 eq $device2) {
      system("audiodevice output '$device1'");
      exit;
    } else {
      print "Unrecognized output device '$1'.\n";
      exit;
    }   
  }
}

print "Failed to find output device.\n";


I saved this script as audioswitch and added it to my LaunchBar index so I can call it from anywhere using only 4 or 5 keystrokes. Works exactly as I'd like, and you can modify it to toggle between any two devices by substituting the name of the devices (in the Output tab of the Sound preference pane) into the script.

UPDATE (3/11/10): I've fixed up the above script so that it automatically figures out what the two output devices are and switches between the two accordingly. This means that it'll work for switching between the iMic and either internal or external speakers. Also fixed a problem where system sounds would continue to play through the original device after switching and added a Growl notification with growlnotify.

#!/usr/bin/perl -w

use strict;

my $device1;
my $device2;

foreach (`audiodevice output list`) {
  chomp;
  if (defined $device1) {
    $device2 = $_; 
    last;
  } else {
    $device1 = $_; 
  }
}

foreach (`audiodevice`) {
  if (/output: (.*)/) {
    if ($1 eq $device1) {
      activate($device2);
      exit;
    } else {
      activate($device1);
      exit;
    }   
  }
}

print "Failed to find output device.\n";

sub activate {
  my $device = shift;
  system("audiodevice output '$device'");
  system("audiodevice system '$device'");
  system("growlnotify -n audioswitch -m 'switching to $device'");
}

Filed under: Hacks, Mac 3 Comments
22Feb/100

Remote controlling an iSight

One of the neat things to do with a remote Mac is to control the built-in iSight remotely to snap photos. There are several commercial applications to do this, but we're going for the low-tech approach: taking pictures via command line over SSH. The free app iSightCapture is designed to do this, but hasn't been updated in awhile and doesn't work as-is on anything after 10.4.9 (including 10.5 and 10.6) due to new security restrictions. I put together a little script that basically wraps iSightCapture so that it works as designed on an up-to-date system.

You'll need to have iSightCapture installed and in your $PATH -- you can either do that by manually installing the binary at the above link or via MacPorts with 'sudo port install isightcapture'. Then create a new file in /usr/local/bin (or wherever) and put in the following Perl snippet:

#!/usr/bin/perl -w

use strict;

foreach (split(/\n/, `ps aux | grep loginwindow`)) {
  if (/^\w+\s+(\d+).+?loginwindow\.app/) {
    my $sudo = ($> == 0) ? '' : 'sudo ';
    exec("$sudo launchctl bsexec $1 isightcapture @ARGV");
    exit;
  }
}

print "Failed to find loginwindow process.\n";

I called the new binary 'snap', so at the command-line, I just type 'snap image.jpg' instead of 'isightcapture image.jpg'. The only real difference from isightcapture is that you need sudo -- that's an intentional Mac OS X security restriction that can't be circumvented (and probably shouldn't) as far as I know. All the iSightCapture command-line options should work as-is, so just refer to its documentation for those. The wrapper script is definitely a hack that might break with a future OS update, but has worked flawlessly for me on several different machines running a variety of Mac OS X versions.

Filed under: Hacks, Mac No Comments
12Feb/1021

Planescape: Torment in Crossover

Update (July 2010): This method appears to have been broken by Crossover Games 9.0.0, and remains broken in the beta of Crossover Games 9.1.0, because switching the resolution with SwitchResX causes Crossover to freak out. It remains working flawlessly in Crossover Games 8.1.4, so stick to that version for now (I've filed a ticket with Codeweavers on this issue so hopefully it'll get fixed). Downgrading from 9.0.0 to 8.1.4 was as simple as replacing the application for me.


Ever since Macs made the switch to Intel processors and made it easily possible to run Windows applications, I've taken the opportunity to play some classic PC games that never made it to the Mac. One of these is Planescape: Torment, an RPG with a unique setting and great story (a feature sadly often lacking from more modern titles). I started playing it around a year and a half ago through Crossover Games, which in addition to not requiring a reboot, doesn't even need Windows. PS:T worked flawlessly in Crossover (both on my iMac and MacBook) until Apple issued the Mac OS X 10.5.6 update, which included new graphics drivers that completely broke the game -- I (and everyone else playing through Crossover) couldn't even get to the title screen without the game complaining about a bad resolution or color depth and crashing.

Seeing as I was only about a third of the way into the game when this happened, I tried pretty extensively to get the game running again. My Boot Camp installation (Vista at the time) ran the game but had weird graphical glitches on the spell effects as a result of modern graphics drivers, and I didn't really want to have to reboot anyways. VMware Fusion 3 running either Windows 7 or XP also runs the game but exhibits an extremely annoying cursor and animation flicker (I've encountered this flicker in other apps on Fusion 3 that worked great in Fusion 2, and it's one of the reasons I'm not very impressed with v.3 compared to v.2 -- but that's a rant for another time). I also tried in Parallels, which thankfully didn't have any of the aforementioned graphical glitches, but unfortunately also exhibited constant sound glitches including pops and crackles.

Last night I came across my CDs again, decided to take one more whack at it, and, to my suprise, managed to get the game running perfectly in an up-to-date Crossover Games (8.1.4) on a brand-new 27" iMac running Mac OS X 10.6.2. For anyone else frustrated by being unable to get this game running, here's how I did it:

First, we have to install the game and a whole bunch of community mods. These mods do a variety of nice things like making the game run in modern widescreen resolutions, fixing a pile of bugs not fixed by the official patch, and both adding and expanding game content. All good stuff that you should be installing anyways because it gives PS:T a lot of much-needed polish, but in this case, we'll also need them to get the game to run at all. To do the installation and modding, follow this very detailed PS:T installation guide, with a few caveats:

  • While installation of the base game works perfectly in Crossover, the mod installations didn't seem to work. I worked around this by performing only the base installation in Crossover, then firing up a Windows XP virtual machine in Fusion to do the full installation (base installation again, then all mod installations as described in the install guide). Once that was done, I copied the modded "Planescape - Torment" folder back to my Mac and replaced the unmodded folder that Crossover had installed in the Program Files folder. The .app file that Crossover installs still works fine for launching the replaced application. For performing the full PC installation, any VM or native installation should do (Fusion, Parallels, Boot Camp, a separate PC, etc).
  • When installing the widescreen mod, make sure you use the exact native resolution of the Mac that you'll be playing on, even if you think it's overkill for a game that was released at 640x480. In my case, that was 2560x1440 for my 27" iMac. This is where the larger text mod comes in handy -- I installed the 80% increase. I think if you don't install the native resolution, you won't be able to get the game to launch at all.
    I've discovered that the above is actually not true -- you can use any resolution as long as it's natively supported by your monitor. I've also found that running at very high resolutions like 2560x1440 causes some graphical jerkiness, particularly in text scrolling, which is distracting considering the extensive dialogs in the game. I settled on using 1600x900 on my 27" iMac, which is perfectly smooth and still looks great. On a 13" laptop, I'd recommend using the native 1280x800, which is perfectly smooth on an aluminum MacBook.

One you've gotten your modded installation set up in Crossover, there's one more obstacle to overcome -- you have to set your monitor to thousands of colors or Planescape will error out on launch. The problem here is that the Displays preference pane in Snow Leopard no longer lets you change the color depth from Millions. To fix this, we need to install the SwitchResX tool, which will let us change to thousands of colors. The option we want in this utility is a bit hidden -- first go to the Menus tab of the SwitchResX Preferences, then activate the Menu Extra by checking the box. This makes a SwitchResX menu appear in the Mac OS X top toolbar, which should allow you to select Thousands of Colors.

Almost there. To launch the game, switch to thousands of colors before launching Crossover Games. If Crossover is already open when you switch, it won't work. If you're not running Torment at your monitor's native resolution, you shouldn't need to switch that manually -- the game seems to be able to switch the resolution itself, just not the bit depth. After switching to thousands of colors and then launching Crossover, you should be able to start Torment from the programs menu, and (fingers crossed) assuming everything worked, Torment should launch to the intro videos successfully. If you don't have the physical CD in the drive, the game may demand CD 2 -- I worked around that by mounting a disk image of disc 2, which was accepted without complaint.

I've only tried actually playing the game for a few minutes since getting it running again, but it seems to be perfect -- runs smoothly and no apparent graphical or sound glitches. The one issue I have on my iMac is that the very bottom of the screen is clipped in-game. I suspect that's a result of the UI mods expecting a typical 16x10 resolution rather than the 16x9 resolution of the new iMacs, but I'll either find a workaround or just play on my 16x10 MacBook. After installing on my MacBook, I found that the screen clipping issue was still present -- it doesn't look to be a symptom of any particular resolution. Luckily, I played around a bit and found a very easy one-time fix. In Crossover Games, go to Configure -> Manage Bottles, then select the bottle that Torment's installed in (in my case, that's TORMENT_1). Select the Control Panel tab and launch winecfg. In the Wine configuration window, select the Graphics tab and deselect "Allow the window manager to decorate the windows" and "Allow the window manager to control the windows". That is, none of the four "Window Settings" boxes should be checked. After you've done that and hit Apply, go back to the Control Panel and reboot the bottle by launching the reboot item. Now launch Planescape...no clipping!

If you've gone to all the trouble of setting this up, you probably already know what a great game Planescape: Torment is, but regardless -- have fun!

Filed under: Games, Mac 21 Comments
8Feb/106

My Plug for the SheevaPlug

A month or two ago I picked up a Marvell SheevaPlug to use as a multipurpose home server. Previously, I'd been running all my network services (primarily this web site and an SSH server) on my iMac, but this had several downsides: I had to leave my iMac on all the time, and, more seriously, all my services went down every time I wanted to reboot into Windows. Being a lifelong Mac user, I didn't have an old PC lying around to dedicate as a full time Linux server, and my tiny apartment wouldn't accommodate a tower very well anyways. The SheevaPlug was an ideal alternative -- tiny, silent, very low power, and powerful enough for my home needs.

The plug comes with a 1.2 GHz single-core ARM processor, 512 MB of RAM, 512 MB of built-in flash (preloaded with an Ubuntu 9.04 installation), and a gigabit Ethernet port. The processor isn't going to compete with a typical dual or quad-core Intel processor, but it's got plenty of punch for a regular Linux installation and beats the heck out of a typical NAS box. The flash is something of a problem, since it's quite easy to fill up the 512 MB with applications and obviously you can't store any appreciable amount of media on it. Luckily, the plug also has a USB 2.0 port and an SD card slot. The board itself also has an eSATA connection, but the most common SheevaPlug model (manufactured by GlobalScale Technologies) doesn't have it exposed. Some newer manufacturers have started building in an eSATA port and some adventurous souls have successfully modded their plugs to expose the existing connection, but I don't trust myself that much with a soldering iron so I've stuck to USB for external hard drives. My plug and all peripherals only cost me about $200 total for the plug ($99, purchased here), a 500 gig hard drive ($50), an external USB enclosure ($30), and annoyingly steep shipping costs for the plug ($20). I'm not using the SD card slot at the moment, but a popular use for it is to put the kernel and OS on an SD card and just use a USB hard drive for media -- this is beneficial both because the bootloader is more reliable booting from an SD card than USB and also because it allows easily swapping out the OS on multiple cards.

The default Ubuntu installation is fully functional, which is nice because you can just connect the ethernet cable and SSH into the plug. Unfortunately, there are a few weird or broken things in the default install that make doing a clean install desirable. A bigger problem is that you can't upgrade the plug to Ubuntu 9.10 because 9.10 builds with an incompatible ARM instruction set, so as soon as support for 9.04 ends, you're out of luck. This is why a significant number of people have loaded other distros onto it (Debian and Gentoo being the two I've seen most mentioned). Being most familiar with Ubuntu, I went with Debian, which also has a great installation site courtesy of Martin Michlmayr. I installed everything on my USB hard drive and left the internal flash untouched as a backup. Booting the kernel off USB is a little flaky due to the buggy u-boot bootloader, but once the plug is booted it's rock solid for weeks on end.

I'm running a whole pile of services on my plug 24/7:

  • This web site: Apache 2, PHP 5, and MySQL 5, with WordPress for the blog.
  • The Transmission BitTorrent client, controlled via the slick web interface. Transmission is nice and efficient and rarely makes my plug sweat even when maxing out my cable connection.
  • mt-daapd for serving music to iTunes clients on my network, gradually switching over to forked-daapd for both music and video streaming to Front Row.
  • An NFS server sharing a dedicated media partition on the external hard drive -- I use this to share a single iPhoto library across my iMac and two laptops, and also house my music collection on it. I've set my iMac to manage my NFS music collection in iTunes directly, so whenever I import new music on my Mac, it gets copied over to the SheevaPlug automatically where it's picked up by forked-daapd and shared across the network. This also lets me easily sync my iPod on my Mac without maintaining two copies of my music library. I picked NFS for sharing vs AFP or Samba because (1) I don't have any Windows clients to worry about, and (2) NFS easily has the best performance. My LAN is only 100 mbit rather than gigabit, but the SheevaPlug easily maxes out my bandwidth (~11-12 MB/sec). I've read accounts that on a gigabit network, the plug can push around 30 MB/sec over NFS, though significantly less with Samba.

I'm constantly refining how I use my plug, but I've been very happy with how it's worked out, and I can now turn off or reboot my Mac into Windows at will without interrupting my site, torrents, or music streaming. Getting everything running just right definitely requires some careful research and trial and error, though -- don't expect to get everything working in one night (or one weekend, for that matter). Lastly, I should point you to the most useful general SheevaPlug resources on the web I found:

  • The aforementioned Debian on SheevaPlug site for getting a fresh Debian installation running
  • The ComputingPlugs wiki -- lots of good info for getting set up initially, though some of the kernel specific stuff (like patches) are out of date.
  • The OpenPlug wiki -- I referred to this a couple of times when I couldn't find things on the ComputingPlugs site, and finally,
  • The Plug Computer Forums -- forums for everything from the bootloader to software installations to hardware mods. Lots of good stuff and a place to ask questions if you're stuck.

Happy hacking!

Filed under: Plug Computers 6 Comments
31Jan/103

forked-daapd and libantlr3c on SheevaPlug

11/10 Update: As several people have pointed out, since this post was written, forked-daapd has been added to the standard Debian repositories. Thus, if you are running Debian Squeeze (or newer), installing it is now as simple as 'apt-get install forked-daapd' and none of the below is necessary.


I recently purchased a SheevaPlug to use as a home server in an environment of mostly Macs.  I'll post in more detail about my SheevaPlug setup later, but here I wanted to detail how I got forked-daapd running. I've got a Debian installation on my plug (previously Lenny, now upgraded to Squeeze) and while installing most things is as easy as 'apt-get install package', getting forked-daapd running turned out to be a major pain due to one of the dependency libraries, libantlr3c. I'm not aware of anyone else who installed libantlr3c on the SheevaPlug, so I'm posting how I got it to work here.

The forked-daapd package is very new and very under development, so there aren't any packages in the Debian repositories. Over at the Ubuntu forums, someone posted instructions on compiling forked-daapd on Ubuntu 9.10. Since Ubuntu and Debian are quite similar under the hood, I figured the same instructions should work on my plug, but problems occurred with getting the libantlr3c libraries to compile. After installing all the dependency libraries from the repositories, the configure script ran to completion, but the resulting make failed immediately. The first error was a bad compiler flag '-m32', which does nothing on an ARM machine like the plug anyways, so I just deleted it from the makefile, but then I started getting weird errors during the make like

/usr/lib/gcc/arm-linux-gnueabi/4.3.2/include/stddef.h:214: error: duplicate 'unsigned'
/usr/lib/gcc/arm-linux-gnueabi/4.3.2/include/stddef.h:214: error: two or more data types in declaration specifiers

It turns out that something went wrong in the configure script and it couldn't find a bunch of standard headers that were exactly where they ought to be in /usr/include, and thus the generated antlr3config.h was completely wrong. The only solution I found was hand-editing this file to have the correct values -- once I did that, I was able to manually compile and install the static library.

The forked-daapd instructions at the Ubuntu forums used antlr 3.1.3 -- I used 3.2 and didn't have any problems, but make sure you use the same version of the jar file and the C headers. The instructions below are what I used to install 3.2 (after dealing with dependencies by running the configure script and installing the next missing dependency until it succeeded):

Install antlr3 from the repos and grab and extract the C header sources:

sudo apt-get install antlr3
wget http://antlr.org/download/C/libantlr3c-3.2.tar.gz
tar xvfz libantlr3c-3.2.tar.gz

Grab my modified antlr3config.h, or modify the faulty one generated by ./configure to suit your system:

wget http://blog.zortrium.net/files/sheeva-antlr3config.h
mv sheeva-antlr3config.h libantlr3c-3.2/antlr3config.h

Now we manually compile and build a static library file. If your antlr3config.h is right and you have all the dependencies, the compilation should go off without a hitch.

cd libantlr3c-3.2/src
gcc -c -O2 -I.. -I../include *.c
ar cru libantlr3c.a *.o
ranlib libantlr3c.a

Now install the header files and library file into /usr/local:

sudo cp libantlr3c.a /usr/local/lib/
sudo cp ../antlr3config.h /usr/local/include/
sudo cp ../include/*.h /usr/local/include/

Now we have to fix the system-installed antlr to use the right jarfile:

wget http://www.antlr.org/download/antlr-3.2.jar
sudo mv antlr-3.2.jar /usr/share/java/
sudo vi /usr/bin/antlr

At the last step, just change the classpath line in /usr/bin/antlr (which is just a text file) to point to the new jarfile -- for instance, I changed mine to

export CLASSPATH=/usr/share/java/stringtemplate.jar:/usr/share/java/antlr-3.2.jar

Finally, after all of this, you're back in sync with the Ubuntu instructions and can proceed from the 'Configure and build forked-daapd' section. Forked-daapd itself has a bunch of other dependencies I had to install, but all were easily installed from the Debian repositories. The only snag I ran into was that the Lenny version of avahi-daemon is too old for forked-daapd -- this was one of the factors that prompted me to upgrade my plug to Squeeze, at which point I didn't have any other issues. Forked-daapd is now running great on my plug and streaming movies to my Mac clients over Front Row.

Filed under: Plug Computers 3 Comments