#!/usr/bin/perl # yargla - Yet Another Rapid Glue Last.fm App v0.02 # Glues together Audio::MPD and Audio::Scrobbler # Reads current playing track from MPD daemon # and submits it to your last.fm profile # put yargla somewhere in your $PATH, chmod +x it # install Audio::MPD, Audio::Scrobbler and Config::Tiny (and Readonly) # with cpan -i or your distrib/os packages # p5-Audio-MPD, p5-Audio-Scrobbler and p5-Config-Tiny are in OpenBSD ports # i wrote this script because mpdscribble kept segfaulting on my boxes, # scmpc has mad dependencies, and i like perl - the glue of the internet. # the mandatory licence for each little piece of code - ISC licenced # # Copyright (c) 2008 Jasper Lievisse Adriaanse # Copyright (c) 2007 Landry Breuil # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # # TODO: daemonize on -d, log into file # cache tracks and submit by batchs # # sample config file: # ; MPD-host variables # [mpd] # host = localhost # port = 6600 # ; Last.FM user variables # [lastfm] # user = foo # password = secret # use Audio::MPD; use Audio::Scrobbler; use Config::Tiny; use Getopt::Long; use strict; use vars qw($VERSION); $VERSION = "0.02"; sub usage; # parse cmdline options my ($as_user, $as_pass, $mpd_host, $mpd_port) = ('', '', 'localhost', 6600); my ($help, $verbose, $config, $config_fh); GetOptions('verbose' => \$verbose, 'help' => \$help, 'file:s' => \$config, 'user:s' => \$as_user, 'password:s' => \$as_pass, 'mpd:s' => \$mpd_host, 'nport:i' => \$mpd_port); if ($as_user eq '' || $as_pass eq '' || $help) { usage() if (!defined($config)); } # parse the configuration file unless (!defined($config)) { if (! -e $config) { print "Configuration file $config not found.\n"; usage(); } $config_fh = Config::Tiny->read("$config"); } $mpd_host = $config_fh->{mpd}->{host}; $mpd_port = $config_fh->{mpd}->{port}; $as_user = $config_fh->{lastfm}->{user}; $as_pass = $config_fh->{lastfm}->{password}; # validate the configuration values if ((!defined($mpd_host)) or ($mpd_host eq '')) { die "No valid host found in $config\n"; } elsif ((!defined($mpd_port)) or ($mpd_port eq '')) { die "No valid port found in $config\n"; } elsif ((!defined($as_user)) or ($as_user eq '')) { die "No valid user found in $config\n"; } elsif ((!defined($as_pass)) or ($as_pass eq '')) { die "No valid password found in $config\n"; } # initialize handlers on both sides print "Connecting to MPD on $mpd_host:$mpd_port\n"; my $mpd = Audio::MPD->new($mpd_host, $mpd_port) || die "Failed to connect to MPD"; my $as = Audio::Scrobbler->new( cfg => { verbose => $verbose, progname => 'mdc', # use mpdscribble id atm progver => '0.2.12', username => $as_user, password => $as_pass} ); $as->handshake() || die "Failed to handshake() with Last.fm"; my $status = $mpd->status(); while(1) { my $curid = $status->songid(); my $cursong = $mpd->current(); my ($artist,$title,$album,$length) = ($cursong->artist,$cursong->title,$cursong->album,$cursong->time); my @t = localtime(); my $datestr = sprintf('%04d-%02d-%02d %02d:%02d:%02d', $t[5] + 1900, $t[4] + 1, @t[3, 2, 1, 0]); print "[$datestr] submitting $artist - $album - $title\n"; my $r = $as->submit( {title => "$title", artist => "$artist", album => "$album", 'length' => "$length"}); if (!$r) { print "error:".$as->err.", trying to re-handshake and re-submit in 5s...\n"; sleep 5; $as->handshake(); $as->submit( {title => "$title", artist => "$artist", album => "$album", 'length' => "$length"}); } while ($curid == $status->songid) { if ($status->state eq "play") { sleep 10; } else { sleep 60; } $status = $mpd->status(); } } sub usage { print "$0 v. $VERSION\n"; print "usage: $0 -v|--verbose -h|--help -f|--file [config] \n-u|--user [Last.fm user] -p|--password [Last.fm password] -m|--mpd [MPD host]\n-n|--nport [MPD port]\n\n"; print "-u and -p are mandatory, unless -f is specified\n"; print "-m and -n defaults to localhost:6600\n"; print "-h shows usage\n\n"; print "values provided in the file provided with -f, overrule command line flags\n"; exit; } # (c) 2007 - G.C.U.