#!/usr/bin/perl -w # # Tooling with XMMS # # toys: lyrics! # http://www.lyrics007.com/Sugababes%20Lyrics/Hole%20In%20The%20Head%20Lyrics.html # use Xmms; use Xmms::Remote; use Getopt::Long; use MP3::Info; use File::Basename; use File::Find; use POSIX; use WWW::Mechanize; use Data::Dumper; my $mode = "what"; my $start = 0; my $syncdir; $|= 1; GetOptions( "mode=s" => \$mode, "start!" => \$start, "syncdir=s" => \$syncdir ) or die "usage: $0 --mode=whatever"; my $remote = Xmms::Remote->new; if ( !$remote->is_running and !$start ) { die "XMMS isn't running, or I can't contact it!"; } if ( !$remote->is_running ) { my $pid = fork(); if ( !$pid ) { setsid(); exec( "/usr/bin/xmms" ); } else { while ( !$remote->is_running ) { sleep 1; } } } my $pos = $remote->get_playlist_pos; if ( $mode eq "kill" ) { $remote->playlist_delete( $pos ); } elsif ( $mode eq "what" ) { if ( !$remote->is_playing or $remote->is_paused ) { print STDERR "XMMS is stopped\n"; exit; } my $file = $remote->get_playlist_file( $pos ); exit unless $file; # XXX ugleeee if ( $file =~ /^http/ ) { # go ask last.fm's remote control if ( $file =~ /last\.fm/ ) { $^W = 0; # sigh my ( $session ) = $file =~ m/.*Session=([0-9a-f]+)/; my $agent = WWW::Mechanize->new( env_proxy => 1, autocheck => 1 ); my $res = $agent->get( "http://www.last.fm/player/radio/np.php?session=$session" ); if ( $res->is_success ) { my ( $artist, $album, $track ) = ( "", "", "" ); my @bits = split( /[\r\n]+/, $res->content ); for my $bit ( @bits ) { if ( $bit =~ /^artist=(.*)$/ ) { $artist = $1; } elsif ( $bit =~ /^album=(.*)$/ ) { $album = $1; } elsif ( $bit =~ /^track=(.*)$/ ) { $track = $1; } } if ( $artist and $album and $track ) { print "$artist\t$album\t$track\n"; exit; } # else fall through } } # http://klortho:8000/admin?mode=sources # see if we can get a listing from the web server # print STDERR "Trying for ${file}admin?mode=sources\n"; # my $agent = WWW::Mechanize->new( env_proxy => 1, autocheck => 1 ); # my $res = $agent->get( $file . "admin?mode=sources" ); # if ( $res->is_success ) { # print STDERR Dumper( $res ); # } # crude, and harsh, and a bit lumpy $file = $remote->get_playlist_title( $pos ); if ( $file =~ /(.*)\ - (.*) \(Gronk\)/) { print "$1\t(streaming)\t$2\n"; exit; } } my $tag = get_mp3tag( $file ); my ( $artist, $album, $title ); if (defined( $tag )) { $artist = $tag->{ARTIST}; $album = $tag->{ALBUM}; $title = $tag->{TITLE}; # damn you people and your API-changing ways... it seems # MP3::Info doesn't merge the v1/v2 data any more. Bad # developer, no cookie. if ( ref $artist ) { $artist = $artist->[-1]; } if ( ref $album ) { $album = $album->[-1]; } if ( ref $title ) { $title = $title->[-1]; } } else { my ( @bits ) = split( '/', $file ); $title = pop @bits; $album = pop @bits; $artist = pop @bits; } $artist ||= "Unknown Artist"; $album ||= "Unknown Album"; $title ||= basename( $file ); $title =~ s/\.mp3$//i; # WTF? NULLs as well? Give me a BREAK! $artist =~ s/\x0//g; $album =~ s/\x0//g; $title =~ s/\x0//g; $artist =~ s/_/ /g; $album =~ s/_/ /g; $title =~ s/_/ /g; print "$artist\t$album\t$title\n"; } elsif ( $mode eq "rename" ) { my $oldname = shift; my $newname = shift; return unless $remote->get_playlist_length; my $found = 0; for my $ppos ( 0 .. $remote->get_playlist_length - 1 ) { my $current = $remote->get_playlist_file( $ppos ); $current =~ s@//@/@g; # no, really $current =~ s@/./@/@g; if ( $current eq $oldname ) { print " xmms-frob is replacing $ppos ($current) with $newname\n"; $remote->playlist_delete( $ppos ); $remote->playlist_add( [ $newname ] ); $found++; } } print "Didn't find $oldname in playlist\n" unless $found; } elsif ( $mode eq "rm" ) { my $oldname = shift; $oldname = getcwd() . "/$oldname" unless $oldname =~ m@^/@; for my $ppos ( 0 .. $remote->get_playlist_length - 1 ) { my $current = $remote->get_playlist_file( $ppos ); next unless $current; $current =~ s@//@/@g; # no, really $current =~ s@/./@/@g; if ( $current eq $oldname ) { $remote->playlist_delete( $ppos ); print "nuked $oldname from $ppos\n"; } } } elsif ( $mode eq "cleanup" ) { my %files; my $ppos = 0; while ( $ppos < $remote->get_playlist_length ) { my $current = $remote->get_playlist_file( $ppos ); next unless $current; $current =~ s@//@/@g; # no, really $current =~ s@/./@/@g; if ( defined($files{$current})) { print "deleted dupe $current at $ppos\n"; $remote->playlist_delete( $ppos ); } else { if ( ! -r $current ) { print "deleted non-file $current at $ppos\n"; $remote->playlist_delete( $ppos ); } else { $files{$current} = 1; $ppos++; } } } } elsif ( $mode eq "sync" ) { if ( !defined( $syncdir )) { die "You need to tell me what to sync with!"; } find( sub { my $file = $File::Find::name; return unless -f $file; # see if we already have the file for my $ppos ( 0 .. $remote->get_playlist_length - 1 ) { my $current = $remote->get_playlist_file( $ppos ); next unless $current; $current =~ s@//@/@g; # no, really $current =~ s@/./@/@g; if ( $file eq $current ) { print "matched $file\n"; return; } } print "You don't appear to have $file\n"; $remote->playlist_add( [ $file ] ); }, $syncdir ); }