#!/usr/bin/perl
#
# xmms2-psipeptune -- updates Psi tune file with data from XMMS2
# Copyright (c)2008 Kacper Gutowski mwgamera at gmail dot com
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
use strict;
use Audio::XMMSClient;
# your $PSIDATADIR/tune here
use constant TUNEPATH => $ENV{HOME}.'/.psi/tune';
# connect to demon
my $xc = Audio::XMMSClient->new('xmms2-psipeptune');
$xc->connect or die $xc->get_last_error;
# data
my $status = eval { $xc->playback_status->wait->value };
my $cid = eval { $xc->playback_current_id->wait->value };
my %info = eval { %{$xc->medialib_get_info($cid)->wait->value} };
# publish initial values
save();
# catch termination to clear tune file
$xc->disconnect_callback_set( sub {
$cid = $status = -1; undef %info;
save(); print STDERR"Abnormal termination.\n";
exit 1;
});
eval { $xc->broadcast_quit->notifier_set( sub {
$cid = $status = -1; undef %info;
save(); print STDERR"Server quit.\n";
exit 0;
}); 1 } or die $xc->get_last_error;
# catch signals
$SIG{INT} = $SIG{TERM} =
sub { $cid = $status = -1; undef %info; save(); exit 0; };
# setup event handlers
eval { $xc->broadcast_medialib_entry_changed->notifier_set( sub {
if ($cid == (my$r=shift->value)) {
my %i = getinfo();
my %ti = %info; %info = %i;
save() if inse(%ti) ne inse(%i);
}
}); 1 } or die $xc->get_last_error;
eval { $xc->broadcast_playback_status->notifier_set( sub {
my$r=shift->value;
my $ts = $status; $status = $r;
save() if $ts != $r && $r != 2;
}); 1 } or die $xc->get_last_error;
eval { $xc->broadcast_playback_current_id->notifier_set( sub {
my $r=shift->value;
my $tc = $cid; $cid = $r;
%info = getinfo();
save() if $tc != $r;
}); 1 } or die $xc->get_last_error;
# main loop
$xc->loop;
exit;
# get info hash of current (ID=$cid) position
sub getinfo { return eval{%{$xc->medialib_get_info($cid)->wait->value}} }
# synchronise data with file
sub save {
if ($status!=1) {
print STDERR"Stopped.\n" if $status<1;
truncate TUNEPATH, 0;
return 0;
}
# diagnostic
print STDERR"Publishing #$cid $info{artist} - $info{title} ".
($info{duration}?sprintf("[%d:%02d]",
int($info{duration}/60000),
int($info{duration}/1000)%60):'')."\n";
# publish ( http://psi-im.org/wiki/Publish_Tune )
open F,'>'.TUNEPATH or die $!;
print F "$info{title}\n";
print F "$info{artist}\n";
print F "$info{album}\n";
print F "$info{tracknr}\n";
print F int($info{duration}/1000)."\n";
close F or die $!;
return 0;
}
# serialise info hash for comparison
sub inse {
(%_) = @_;
return "$_{id}\1$_{tracknr}\1$_{title}\1"
."$_{artist}\1$_{duration}\1$_{url}\1";
}
__END__