In this thread I asked wheter anyone had achieved something like copying the currently played song in mpd to a USB-Stick. Now I think I have succeeded. This is a refined version that checks for available filespace and deletes the oldest file on the device. Always deleting the oldest one might not be the best thing but it certainly gives you new songs. Even though this might delete your favourite song at some point.
I have to find a way to make the source file available for download.
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
use File::Copy;
# Declaration of a few variables
my $musicdir = "/media/mp3/";
my $mountpoint = "/media/stick/";
my $sound_ok = $musicdir.'sounds/button16.wav';
my $sound_size = $musicdir.'sounds/subdive.wav';
my $sound_mount = $musicdir.'sounds/pfiff.wav';
# Die if device is not added
#die unless ($ENV{ACTION} =~ /add/);
if ($ENV{ACTION} =~ /remove/) { die };
# Device has to be mounted otherwise we don't get the freespace
system("mount", $mountpoint) == 0
or die system("aplay", "-q", "-d", "2", $sound_mount);
# Determine how much space in bytes is available
sub space {
my $space = `df $mountpoint`;
chop $space;
$space =~ /(\d+\s*)(\d+\s*)(\d+)\s*/mg;
my $free = $3 * 1024;
return $free;
}
sub oldest {
my %data;
my @sorted;
my @content = `ls -1 $mountpoint`;
for (@content) {
chop $_;
$data{$_} = (stat($mountpoint.$_))[9];
@sorted = sort { $data{$a} cmp $data{$b} } keys %data;
}
return shift(@sorted);
}
die("MPD.pm not found!\n") unless -f "/usr/local/bin/MPD.pm";
require("/usr/local/bin/MPD.pm");
my $mpd = MPD->new();
my %currentsong = $mpd->get_current_song_info;
my $file = $musicdir.$currentsong{file};
my $filesize = (stat($file))[7];
for (my $freespace = space(); $filesize > $freespace; $freespace = space()) {
system("aplay", "-q", $sound_size);
unlink($mountpoint.oldest()) == 1
or die "Fehler: ";
}
copy($file, "/media/stick") or die "Copy failed: $!";
system("umount", $mountpoint);
system("aplay", "-q", $sound_ok);
The Perl Module MPD.pm is needed. It can be downloaded on the mpd download page (at the bottom). I think it can now be found on CPAN as well.
This script copys the currently playing song to /media/stick. For this to work automaticaly you have to do quite a few things more though. Install udev, create a udev-rule and adjust your /etc/dev.d. This proved to be pretty complicated for me…
Installing udev under debian was very simple once I new that I needed it:
apt-get install udev
creating the udev rule proved quit complicated because I assumed a few things that were wrong. The following links should tell you all you need to know:
http://www.linuxjournal.com/article/7316
http://www.reactivated.net/writing_udev_rules.html
http://kernel.org/pub/linux/utils/kernel/hotplug/RFC-dev.d
The second link is very usefull when you need to gain information about your USB-Device. The last one solves the mystery of how to execute a certain script after the device node has been set up. I always tried with the PROGRAM=”script.pl” option in the udev rule. That is wrong!
I had to make a directoy under /etc/dev.d/ which I called stick. So it looks like this:
/etc/dev.d/stick
[~] ls -l /etc/dev.d/stick/
insgesamt 0
lrwxrwxrwx 1 root 29 2005-09-12 22:08 copy.dev -> /usr/local/bin/copycurrent.pl
In there you can either put the scripts to be run when the stick is attached or you create symlinks. Another option is to write a bash script which then executes your scripts. Decide for yourself.
TODO:
- for now the oldest file in the device is deleted
- better error erporting
Update to v0.3 of copycurrent:
copycurrent v0.3/