1#!/usr/bin/perl -w 2 3use 5.006; 4use strict; 5 6=head1 NAME 7 8scrobbler-helper - submit a track to AudioScrobbler 9 10=head1 SYNOPSIS 11 12 scrobbler-helper [-nv] [-e encoding] [-f configfile] -P progname 13 -V progver title artist album year comment genre length 14 15=head1 DESCRIPTION 16 17The B<scrobbler-helper> utility uses the C<Audio::Scrobbler> module to 18submit a single track's information to Last.fm's AudioScrobbler - 19http://www.audioscrobbler.com/. It requires the program (plug-in) name 20and version to be specified on the command line, and also requires all 21seven track attributes, although some of them may be omitted by supplying 22empty strings. 23 24The following command-line options are recognized: 25 26=over 4 27 28=item -e encoding 29 30Specify the character encoding of the track info, if it is neither UTF-8 31nor the one specified via B<default_encoding> in the configuration file. 32 33=item -f configfile 34 35Specify a different configuration file, not ~/.scrobbler-helper.conf. 36 37=item -n 38 39Do not actually perform the handshake and submission 40(sets the C<Audio::Scrobbler> B<"fake"> option). 41 42=item -P progname 43 44Specify the name of the AudioScrobbler plug-in submitting the data. 45This option is B<mandatory>! 46 47=item -v 48 49Verbose operation - display diagnostic messages to the standard output 50(sets the C<Audio::Scrobbler> B<"verbose"> option). 51 52=item -V progver 53 54Specify the version of the AudioScrobbler plug-in submitting the data. 55This option is B<mandatory>! 56 57=back 58 59Besides the command line, the B<scrobbler-helper> utility also retrieves 60information from a per-user configuration file, usually 61~/.scrobbler-helper.conf; it is a INI-style file, which must contain a 62secion named B<"global">. The following variables are recognized, with 63B<username> and B<password> being mandatory: 64 65=over 4 66 67=item * default_encoding 68 69The encoding to assume for the track info, if none is supplied with 70the B<-e> command-line option. If neither B<-e> is given on the command 71line nor B<default_encoding> specified in the configuration file, the 72B<scrobbler-helper> utility assumes UTF-8. 73 74=item * fix_track_name 75 76A boolean flag specifying whether to do some trivial fixes on the song 77name before submitting it. Currently, this only removes a "DD. " 78sequence at the start of the name, where 'D' is a digit. 79 80The values C<on>, C<true>, C<yes>, and C<1> are considered to be true. 81 82=item * password 83 84The password for the AudioScrobbler account. 85 86=item * username 87 88The username for the AudioScrobbler account. 89 90=back 91 92 [global] 93 username=jrandomlistener 94 password=mylittlesecret 95 # Optional (the default is UTF-8) 96 default_encoding=windows-1251 97 # Optional (the default is "no") 98 fix_track_name=yes 99 100=cut 101 102use Config::IniFiles; 103use Encode; 104use Getopt::Std; 105 106use Audio::Scrobbler; 107 108sub is_true($); 109 110my %infovars = ( 111 'cmdopts' => [ qw/P V/ ], 112 'cmdline' => [ qw/title artist album year comment genre length/ ], 113 'global' => [ qw/username password/ ], 114 'global_nc' => [ qw/default_encoding fix_track_name/ ], 115); 116my $verbose = 0; 117 118MAIN: 119{ 120 my %info; 121 my (%opts, %cfg) = (); 122 my ($configfname) = "$ENV{HOME}/.scrobbler-helper.conf"; 123 my ($scrob); 124 125 getopts('nve:f:P:V:', \%opts) or die "Parsing options: $!\n"; 126 $configfname = $opts{'f'} if $opts{'f'}; 127 $verbose = 1 if $opts{'v'}; 128 $info{'verbose'} = $verbose; 129 $info{'fake'} = 1 if $opts{'n'}; 130 131 @info{qw/progname progver encoding/} = @opts{@{$infovars{'cmdopts'}}}; 132 if (!($info{'progname'} && $info{'progver'})) { 133 die "Must specify program name (-P) and version (-V)!\n"; 134 } 135 136 if (@ARGV != @{$infovars{'cmdline'}}) { 137 die 'Need '.@{$infovars{'cmdline'}}.' args: '. 138 join(', ', @{$infovars{'cmdline'}}).".\n"; 139 } 140 @info{@{$infovars{'cmdline'}}} = @ARGV; 141 map { s/^\s+//; s/\s+$//; } @info{@{$infovars{'cmdline'}}}; 142 143 if (!tie %cfg, 'Config::IniFiles', 144 (-file => $configfname, -allowcontinue => 1)) { 145 my $err = join "\n", "Could not read $configfname: $!", 146 @Config::IniFiles::errors; 147 die "$err\n"; 148 } 149 150 @info{@{$infovars{'global'}}, @{$infovars{'global_nc'}}} = 151 @{$cfg{'global'}}{@{$infovars{'global'}}, 152 @{$infovars{'global_nc'}}}; 153 for (@{$infovars{'global'}}) { 154 die 'Missing variables in the config file, need at least '. 155 join(', ', @{$infovars{'global'}}).".\n" 156 unless defined($info{$_}); 157 } 158 159 # Recode the track info into UTF-8 160 if (defined($info{'default_encoding'}) && 161 (!defined($info{'encoding'}) || $info{'encoding'} eq '')) { 162 $info{'encoding'} = $info{'default_encoding'}; 163 } 164 if (defined($info{'encoding'}) && $info{'encoding'} !~ /^utf-?8$/i) { 165 print "RDBG recoding track info from $info{encoding} to UTF8\n" 166 if $verbose; 167 foreach (@{$infovars{'cmdline'}}) { 168 $info{$_} = decode($info{'encoding'}, $info{$_}); 169 } 170 } 171 172 # Fix up the track name if requested 173 if (defined($info{'fix_track_name'}) && 174 is_true($info{'fix_track_name'})) { 175 $info{'title'} =~ s/^\d\d?\. //; 176 print "RDBG fixed up the track name to $info{title}\n" 177 if $verbose; 178 } 179 180 # Rock'n'roll! 181 $scrob = new Audio::Scrobbler('cfg' => \%info) or 182 die "Could not create an Audio::Scrobbler object\n"; 183 $scrob->handshake() or 184 die "Scrobbler: ".$scrob->err()."\n"; 185 print "RDBG handshake successful, it seems\n" if $verbose; 186 $scrob->submit(\%info) or 187 die "Scrobbler submit: ".$scrob->err()."\n"; 188 print "RDBG submision successful, it seems\n" if $verbose; 189} 190 191sub is_true($) 192{ 193 my $s = lc $_[0]; 194 195 return ($s eq '1' || $s eq 'on' || $s =~ /^[ty]/); 196} 197 198=head1 TODO 199 200=over 4 201 202=item * 203 204Command-line options, so people don't have to submit everything... 205 206=item * 207 208Storing and caching of unsuccessful submissions for later retrying. 209 210=back 211 212=head1 SEE ALSO 213 214B<Audio::Scrobbler> 215 216=over 4 217 218=item * http://www.last.fm/ 219 220=item * http://www.audioscrobbler.com/ 221 222=item * http://www.audioscrobbler.net/ 223 224=back 225 226The home site of the C<Audio::Scrobbler> module is 227http://devel.ringlet.net/audio/Audio-Scrobbler/ 228 229=head1 AUTHOR 230 231Peter Pentchev, E<lt>roam@ringlet.netE<gt> 232 233=head1 COPYRIGHT AND LICENSE 234 235Copyright (C) 2005, 2006 by Peter Pentchev. 236 237This library is free software; you can redistribute it and/or modify 238it under the same terms as Perl itself, either Perl version 5.8.7 or, 239at your option, any later version of Perl 5 you may have available. 240 241$Id: scrobbler-helper 88 2006-01-02 09:16:32Z roam $ 242 243=cut 244 245