/usr/local/CPAN/Xmpcr/Audio/Xmpcr/Network.pm
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# Audio::Xmpcr::Network
# Copyright Paul Bournival 2003
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
package Audio::Xmpcr::Network;
$VERSION="1.02";
use strict;
use IO::Socket::INET;
sub new {
my($class,$host,$port,$locker)=@_;
$port ||= 32463;
my $self={};
$self->{s}=new IO::Socket::INET(PeerAddr => "$host:$port")
or die "Can't contact xmdaemon: $!!\n";
bless $self,$class;
$self->_doop("appname $locker") if $locker;
$self->{queuedEvents}=[];
$self;
}
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# turn on/off power
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
sub power {
my($self,$status)=@_;
die "Xmpcr::power: incorrect parameters" if ! $status;
my @ret=$self->_doop($status);
scalar(@ret)==0 ? undef : $ret[0];
}
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# turn on/off mute
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
sub mute {
my($self,$status)=@_;
die "Xmpcr::mute: incorrect parameters" if ! $status;
my @ret=$self->_doop("mute $status");
scalar(@ret)==0 ? undef : $ret[0];
}
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# change channel
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
sub setchannel {
my($self,$chan)=@_;
die "Xmpcr::setchannel: incorrect parameters" if ! $chan;
my @ret=$self->_doop("channel $chan");
scalar(@ret)==0 ? undef : $ret[0];
}
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# force the lock
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
sub forcelock {
my($self)=@_;
my @ret=$self->_doop("forcelock");
scalar(@ret)==0 ? undef : $ret[0];
}
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# list 1 or all channels
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
sub list {
my($self,$chan)=@_;
my @list=$self->_doop("list" . ($chan ? " $chan" : ""));
my @ret;
for my $line (@list) {
push(@ret,$self->_hashifySongEntry($line));
}
$chan ? $ret[0] : @ret;
}
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# splits a tab-delimited entry into a hash
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
sub _hashifySongEntry {
my($self,$line)=@_;
my(@e)=split("\t",$line);
{
NUM => $e[0] || 0,
NAME => $e[1] || "",
CAT => $e[2] || "",
SONG => $e[3] || "",
ARTIST => $e[4] || "",
};
}
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# obtain general radio status
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
sub status {
my($self)=@_;
my %ret;
map {
my($k,$v)=split("\t",$_);
$ret{$k}=$v;
} $self->_doop("status");
%ret;
}
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# event support (i.e., song changing)
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
sub events {
my($self,$status)=@_;
die "Xmpcr::mute: incorrect parameters" if ! $status;
my @ret=$self->_doop("events $status");
scalar(@ret)==0 ? undef : $ret[0];
}
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# find out which channels have changed songs
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
sub processEvents {
my($self)=@_;
my($rin,$buf)="";
my @events=@{ $self->{queuedEvents} };
$self->{queuedEvents}=[];
vec($rin,fileno($self->{s}),1)=1;
if (select($rin,undef,undef,.05)) {
sysread($self->{s},$buf,16000);
if ($buf) {
map {
s/^\+\t//;
push(@events,$_);
} split("\n",$buf);
}
}
map {
$_=$self->_hashifySongEntry($_);
} @events;
@events;
}
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# return the server socket FD for select() calls
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
sub eventFd {
my($self)=@_;
return fileno($self->{s});
}
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# a general send/receive method.
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
sub _doop {
my($self,$cmd)=@_;
my($ret,@ret)=("");
syswrite($self->{s},$cmd . "\n") if $cmd;
my($rin,$rout)="";
vec($rin,fileno($self->{s}),1)=1;
while(1) {
my $buf;
sysread($self->{s},$buf,1024);
$ret .= $buf;
last if ! $buf or $ret =~ /Ready\n$/;
}
for my $line (split("\n",$ret)) {
if ($line =~ /^\+/) {
push(@{ $self->{queuedEvents} },$line) ;
} elsif ($line eq "Ready") {
} else {
push(@ret,$line);
}
}
@ret;
}
1;