We're starting our usual monthly DC Perl Mongers meeting a bit early this Tuesday (September 7th) to have a little pizza and celebrate Rakudo-Star! Arrive at 6:30pm at the Starbucks at 18th and K Street NW (call me, Brock, if you miss us and need to be let in, number on the website) if you want food. But feel free to wander in any time thereafter, we usually stay as late as 10:00pm. We'll swoop down and look for people at the normal 7:30pm time too
Other activities:
Please put your name on http://dc.pm.org/Rakudo-Star_Party (or email the mailing list, which can be found at http://dc.pm.org/) so we know how much food to get.
If you have any questions, email the list or me directly -- awwaiid@gmail.com will do
About Rakudo Star: "Rakudo Star" is a useful and usable distribution of Perl 6. Current releases are aimed at "early adopters" of Perl 6. We can tell you ALL about it when you arrive
I just wrote a reCAPTCHA Extension for Oddmuse. I started out with the current version of my QuestionAsker Extension, threw in just a touch of Captcha::reCAPTCHA, and voi-la! Easy as pie.
If you are ever in the Captcha business, definitely check out Captcha::reCAPTCHA. It was extremely straightforward.
I very much enjoy writing Oddmuse modules. Oddmuse itself is this 4000-line beastie in a single file. Extensions, at least the interesting ones, build on the core by replacing internal functions with custom versions. So to add this captcha technology, for example, I overwrite the doEdit function with one of my own, calling the old doEdit function and then manipulating the generated HTML.
It's your standard sick and wonderful form of Aspect-Oriented aka Self-Modifying programming that makes me happy.
You can see the result over on the Continuity Wiki, just edit a page. Feel free to add some useful content while you're at it
Paul Graham wrote up some thoughts about the Arc release and some of the philosophy behind Arc. As I read along, I couldn't help but remark on the similarities with Perl.
First was his discussion about using lists as the basis for data structures. In Perl we have both lists and hashes, but the idea is the same, namely, flexible changeable structures that are easily evolved to cover the problem space. This way of building a program seems to work out rather well, at least to start with (to find the problem space and prove that it is even manageable, for example).
Check this paragraph from the essay out:
Arc tries to be a language that's dirty in the right ways. It tries not to forbid things, for example. Anywhere I found myself asking "should I allow people to...?" I tried always to say yes. This is not the sort of language that tries to save programmers from themselves.
Now replace "Arc" with "Perl".
So... anyone started the Arc-on-Parrot implementation yet?
In my house there is a central media-server holding our collective digital music collection. When at home we mount the server over NFS, which works wonderfully. I copy music over to my laptop for coffee-shop work, but always wanted something a bit more transparent. Enter Fuse.pm.
What I've built is a caching filesystem specifically designed for this situation, and I named it MobileFS. When I listen to a song it is cached locally. Then if I later try to listen to the song but the NFS is unavailable the cached version is used. To construct this, I took Fuse.pm's example dummy tool as my initial code. The example mounts one directory on another, providing all of the basic filesystem manipulations (such as open, read, write, and various stat commands). It was very straightforward to insert code that additionally caches all the files that are opened, and if a file being read disappears then to fall back to the cache. In a lot of ways I actually designed this for my wife to use, so transparency of operation was important.
I had to solve a couple problems. The first was that the song I was listening to would skip a bit at the beginning when the copy-to-cache started. This was fixed by calling out to rsync with bandwidth limit instead of plain 'cp'. The second problem was that many mp3 players (xmms for example) read a chunk at the beginning and the end of the file to get the ID3 information and song length. So instead of immediately caching a file when it is opened, I instead delay until a block in the file a little ways in is read. About 15 seconds in on my 192bps songs.
This is also not too difficult. In the open function I look for mp3/ogg files, and then do:
$read_action->{$bare_file} = sub {
my ($file,$bufsize,$off) = @_;
if($off > 500000 && $off < 1000000) {
print STDERR "Read at offset $off triggering action...\n";
cache_file($bare_file);
delete $read_action->{$bare_file};
}
};
Where $read_action is a hashref to hold callbacks like this per-file, and the filename is $bare_file. You can see that I have some constant offsets in there, I got those through experimentation with my own music, and it is a somewhat relative measure depending on the bitrate of the file. Notice also that once we trigger the callback it deletes itself, stopping it from being triggered multiple times. In the read function I then do:
if($read_action->{$bare_file}) {
$read_action->{$bare_file}->($bare_file, $bufsize, $off);
}
One thing is missing, and I haven't coded it yet, which is that mp3/ogg files that are opened but never read in the given offset range leave their callbacks around filling up memory. Interestingly, as far as I can tell there is no 'close' function in FUSE, otherwise that would be a great place. I can't just delete the callback on the next file open in case more than one file is being accessed through this filesystem. Perhaps I'll add in some sort of timestamp and then just kill the old ones after some time.
In any case... it works! It was impressively easy to adapt the Fuse.pm example, as I said. I have now unmounted and remounted my NFS while in the middle of a cached song, and it transparently switches from the real source, to the cache, and back. Loading songs into the XMMS playlist doesn't trigger them being cached, but playing them does. Now I just need to code up a cron job that goes through and clears out unused things in the cache, perhaps based on a fixed cache size.
Future features? Well, one that comes immediately to mind is that, when I'm in the coffee shop and try to play a song that isn't cached, I could actually have a GUI popup asking me if I'd like to queue this song for (possibly slow) HTTP retrieval. Or I could just do it without asking. Another thing would be to pre-cache files, for a directory containing an entire album of songs, for example. Got any other ideas?
You can see the project page for MobileFS at http://thelackthereof.org/MobileFS. If you play with it let me know