2 # This program is free software; you can redistribute it and/or modify
3 # it under the terms of the GNU General Public License as published by
4 # the Free Software Foundation; either version 2 of the License, or
5 # (at your option) any later version.
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
12 # You should have received a copy of the GNU General Public License
13 # along with this program; if not, write to the Free Software
14 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 use Audio
::MPD
::Status
;
27 use base qw
[ Class
::Accessor
::Fast
];
28 __PACKAGE__
->mk_accessors( qw
[ _host _password _port version
] );
31 our $VERSION = '0.13.4';
38 # my $mpd = Audio::MPD->new( [$hostname], [$port], [$password] )
40 # This is the constructor for Audio::MPD. One can specify a $hostname, a
41 # $port, and a $password.
42 # If none is specified then defaults to environment vars MPD_HOST, MPD_PORT
43 # and MPD_PASSWORD. If those aren't set, defaults to 'localhost', 6600 and ''.
47 my ($host, $port, $password) = @_;
50 $host = $ENV{MPD_HOST
} || 'localhost' unless defined $host;
51 $port = $ENV{MPD_PORT
} || '6600' unless defined $port;
52 $password = $ENV{MPD_PASSWORD
} || '' unless defined $password;
54 # create & bless the object.
58 _password
=> $password,
62 # try to issue a ping to test connection - this can die.
74 # my @result = $mpd->_send_command( $command );
76 # This method is central to the module. It is responsible for interacting with
77 # mpd by sending the $command and reading output - that will be returned as an
78 # array of chomped lines (status line will not be returned).
80 # Note that currently, this method will connect to mpd before sending any
81 # command, and will disconnect after the command has been issued. This scheme
82 # is far from optimal, but allows us not to care about timeout disconnections.
84 # /!\ Note that we're using high-level, blocking sockets. This means that if
85 # the mpd server is slow, or hangs for whatever reason, or even crash abruptly,
86 # the program will be hung forever in this sub. The POE::Component::Client::MPD
87 # module is way safer - you're advised to use it instead of Audio::MPD.
89 # This method can die on several conditions:
90 # - if the server cannot be reached,
91 # - if it's not an mpd server,
92 # - if the password is incorrect,
93 # - or if the command is an invalid mpd command.
94 # In the latter case, the mpd error message will be returned.
97 my ($self, $command) = @_;
99 # try to connect to mpd.
100 my $socket = IO
::Socket
::INET
->new(
101 PeerAddr
=> $self->_host,
102 PeerPort
=> $self->_port
104 or die "Could not create socket: $!\n";
107 # parse version information.
108 $line = $socket->getline;
110 die "Not a mpd server - welcome string was: [$line]\n"
111 if $line !~ /^OK MPD (.+)$/;
115 if ( $self->_password ) {
116 $socket->print( 'password ' . $self->_password . "\n" );
117 $line = $socket->getline;
118 die $line if $line =~ s/^ACK //;
121 # ok, now we're connected - let's issue the command.
122 $socket->print( $command );
124 while (defined ( $line = $socket->getline ) ) {
126 die $line if $line =~ s/^ACK //; # oops - error.
127 last if $line =~ /^OK/; # end of output.
142 # -- MPD interaction: general commands
147 # Sends a ping command to the mpd server.
151 $self->_send_command( "ping\n" );
156 # my $version = $mpd->version;
158 # Return version of MPD server's connected.
160 # sub version {} # implemented as an accessor.
167 # Send a message to the MPD server telling it to shut down.
171 $self->_send_command("kill\n");
176 # $mpd->password( [$password] )
178 # Change password used to communicate with MPD server to $password.
179 # Empty string is assumed if $password is not supplied.
182 my ($self, $passwd) = @_;
184 $self->_password($passwd);
185 $self->ping; # ping sends a command, and thus the password is sent
190 # $mpd->updatedb( [$path] );
192 # Force mpd to recan its collection. If $path (relative to MPD's music
193 # directory) is supplied, MPD will only scan it - otherwise, MPD will rescan
194 # its whole collection.
197 my ($self, $path) = @_;
199 $self->_send_command("update $path\n");
204 # -- MPD interaction: handling volume & output
207 # $mpd->volume( [+][-]$volume );
209 # Sets the audio output volume percentage to absolute $volume.
210 # If $volume is prefixed by '+' or '-' then the volume is changed relatively
214 my ($self, $volume) = @_;
216 if ($volume =~ /^(-|\+)(\d+)/ ) {
217 my $current = $self->status->volume;
218 $volume = $1 eq '+' ?
$current + $2 : $current - $2;
220 $self->_send_command("setvol $volume\n");
225 # $mpd->output_enable( $output );
227 # Enable the specified audio output. $output is the ID of the audio output.
230 my ($self, $output) = @_;
231 $self->_send_command("enableoutput $output\n");
236 # $mpd->output_disable( $output );
238 # Disable the specified audio output. $output is the ID of the audio output.
241 my ($self, $output) = @_;
242 $self->_send_command("disableoutput $output\n");
247 # -- MPD interaction: retrieving info
252 # Return a hashref with the number of artists, albums, songs in the database,
253 # as well as mpd uptime, the playtime of the playlist / the database and the
254 # last update of the database.
259 map { /^([^:]+):\s+(\S+)$/ ?
($1 => $2) : () }
260 $self->_send_command( "stats\n" );
266 # my $status = $mpd->status;
268 # Return a Audio::MPD::Status object with various information on current
269 # MPD server settings. Check the embedded pod for more information on the
270 # available accessors.
274 my @output = $self->_send_command( "status\n" );
275 my $status = Audio
::MPD
::Status
->new( @output );
280 sub get_urlhandlers
{
283 map { /^handler: (.+)$/ ?
$1 : () }
284 $self->_send_command("urlhandlers\n");
289 # -- MPD interaction: altering settings
293 # $mpd->repeat( [$repeat] );
295 # Set the repeat mode to $repeat (1 or 0). If $repeat is not specified then
296 # the repeat mode is toggled.
299 my ($self, $mode) = @_;
301 $mode ||= not $self->status->repeat; # toggle if no param
302 $mode = $mode ?
1 : 0; # force integer
303 $self->_send_command("repeat $mode\n");
307 my ($self, $mode) = @_;
309 $mode ||= not $self->status->random; # toggle if no param
310 $mode = $mode ?
1 : 0; # force integer
311 $self->_send_command("random $mode\n");
315 my ($self, $value) = @_;
317 $self->_send_command("crossfade $value\n");
321 # -- MPD interaction: controlling playback
324 my ($self, $number) = @_;
326 $self->_send_command("play $number\n");
330 my ($self, $number) = @_;
332 $self->_send_command("playid $number\n");
336 my ($self, $state) = @_;
337 $state ||= ''; # default is to toggle
338 $self->_send_command("pause $state\n");
343 $self->_send_command("stop\n");
348 $self->_send_command("next\n");
353 $self->_send_command("previous\n");
357 my ($self, $time, $song) = @_;
358 $time ||= 0; $time = int $time;
359 $song = $self->status->song || 0 if not defined $song; # seek in current song
360 $self->_send_command( "seek $song $time\n" );
364 my ($self, $time, $song) = @_;
365 $time ||= 0; $time = int $time;
366 $song ||= 0; $song = int $song;
367 $self->_send_command( "seekid $song $time\n" );
371 # -- MPD interaction: handling playlist
375 # $mpd->add( $path );
377 # Add the song identified by $path (relative to MPD's music directory) to
378 # the current playlist. No return value.
381 my ($self, $path) = @_;
383 $self->_send_command( qq[add
"$path"\n] );
388 # $mpd->delete( $song [, $song [...] ] );
390 # Remove song number $song from the current playlist. No return value.
393 my ($self, @songs) = @_;
395 "command_list_begin\n"
396 . join( '', map { "delete $_\n" } @songs )
397 . "command_list_end\n";
398 $self->_send_command( $command );
403 # $mpd->deleteid( $songid [, $songid [...] ]);
405 # Remove the specified $songid from the current playlist. No return value.
408 my ($self, @songs) = @_;
410 "command_list_begin\n"
411 . join( '', map { "deleteid $_\n" } @songs )
412 . "command_list_end\n";
413 $self->_send_command( $command );
420 # Remove all the songs from the current playlist. No return value.
424 $self->_send_command("clear\n");
431 # Remove all of the songs from the current playlist *except* the current one.
436 my $status = $self->status;
437 my $cur = $status->song;
438 my $len = $status->playlistlength - 1;
441 "command_list_begin\n"
442 . join( '', map { $_ != $cur ?
"delete $_\n" : '' } reverse 0..$len )
443 . "command_list_end\n";
444 $self->_send_command( $command );
450 my ($self, $from, $to) = @_;
451 $self->_send_command("swap $from $to\n");
455 my ($self, $from, $to) = @_;
456 $self->_send_command("swapid $from $to\n");
461 $self->_send_command("shuffle\n");
465 my ($self, $song, $pos) = @_;
466 $self->_send_command("move $song $pos\n");
470 my ($self, $song, $pos) = @_;
471 $self->_send_command("moveid $song $pos\n");
475 my ($self, $playlist) = @_;
476 return unless defined $playlist;
477 $self->_send_command( qq[load
"$playlist"\n] );
481 my ($self, $playlist) = @_;
482 return unless defined $playlist;
483 $self->_send_command( qq[save
"$playlist"\n] );
487 if(!$self->_process_feedback)
489 # Does the playlist already exist?
490 if(${$self->get_error}[0] eq '56' && $config{'OVERWRITE_PLAYLIST'})
492 $self->rm($playlist);
493 $self->save($playlist);
506 my ($self, $playlist) = @_;
507 return unless defined $playlist;
508 $self->_send_command( qq[rm
"$playlist"\n] );
513 # -- MPD interaction: searching collection
517 my ($self, $type, $string, $strict) = @_;
519 my $command = (!defined($strict) || $strict == 0 ?
'search' : 'find');
520 my @lines = $self->_send_command( qq[$command $type "$string"\n] );
524 foreach my $line (@lines) {
525 next unless $line =~ /^([^:]+):\s(.+)$/;
527 push @list, { %hash } if %hash;
532 push @list, { %hash }; # Remember the last entry
537 my ($self, $type, $artist) = @_;
538 my $command = "list $type " . $type eq 'album' ?
qq["$artist"] : '';
540 map { /^[^:]+:\s+(.*)$/ ?
$1 : () }
541 $self->_send_command( "$command\n" );
544 # recursively, but only dirs & files
546 my ($self, $path) = @_;
548 return $self->_send_command( qq[listall
"$path"\n] );
549 # FIXME: return item::songs / item::directory
552 # recursive, with all tags
554 my ($self, $path) = @_;
556 my @lines = $self->_send_command( qq[listallinfo
"$path"\n] );
560 foreach my $line (@lines) {
562 next unless $line =~ /^([^:]+):\s(.+)$/;
564 push @results, { %element } if %element;
569 push @results, { %element };
571 # FIXME: return item::songs / item::directory
574 # only in the current path, all tags
576 my ($self, $path) = @_;
579 my @lines = $self->_send_command( qq[lsinfo
"$path"\n] );
583 foreach my $line (@lines) {
585 next unless $line =~ /^([^:]+):\s(.+)$/;
586 if ($1 eq 'file' || $1 eq 'playlist' || $1 eq 'directory') {
587 push @results, { %element } if %element;
592 push @results, { %element };
594 # FIXME: return item::songs / item::directory
598 ###############################################################
600 #-------------------------------------------------------------#
601 # This section contains all methods not directly accessing #
602 # MPD, but may be useful for most people using the module. #
603 ###############################################################
606 my ($self, $song) = @_;
607 $song ||= $self->status->song;
609 map { /^([^:]+):\s(.+)$/ ?
($1=>$2) : () }
610 $self->_send_command("playlistinfo $song\n");
611 # FIXME: return item::songs / item::directory
614 sub get_current_song_info
{
617 map { /^([^:]+):\s(.+)$/ ?
($1=>$2) : () }
618 $self->_send_command("currentsong\n");
619 # FIXME: return item::songs / item::directory
622 sub get_song_info_from_id
{
623 my ($self, $song) = @_;
624 $song ||= $self->status->song;
626 map { /^([^:]+):\s(.+)$/ ?
($1=>$2) : () }
627 $self->_send_command("playlistid $song\n");
628 # FIXME: return item::songs / item::directory
632 my ($self, $type, $string) = @_;
633 my @results = $self->search($type, $string);
635 return unless @results;
638 "command_list_begin\n"
639 . join( '', map { qq[add
"$_->{file}"\n] } @results )
640 . "command_list_end\n";
641 $self->_send_command( $command );
649 my @lines = $self->_send_command("playlistinfo\n");
653 foreach my $line (@lines) {
654 next unless $line =~ /^([^:]+):\s(.+)$/;
656 push @list, { %hash } if %hash;
661 push @list, { %hash }; # Remember the last entry
667 my ($self, $song) = @_;
669 my %data = $self->get_song_info($song);
670 return $data{Artist
}.' - '.$data{Title
} if $data{Artist
} && $data{Title
};
671 return $data{Title
} if $data{Title
};
675 sub get_time_format
{
678 # Get the time from MPD; example: 49:395 (seconds so far:total seconds)
679 my ($sofar, $total) = split /:/, $self->status->time;
680 return sprintf "%d:%02d/%d:%02d",
681 ($sofar / 60), # minutes so far
682 ($sofar % 60), # seconds - minutes so far
683 ($total / 60), # minutes total
684 ($total % 60);# seconds - minutes total
690 # Get the time from MPD; example: 49:395 (seconds so far:total seconds)
691 my ($sofar, $total) = split /:/, $self->status->time;
692 my $left = $total - $sofar;
694 # Store seconds for everything
696 $rv->{seconds_so_far
} = $sofar;
697 $rv->{seconds_total
} = $total;
698 $rv->{seconds_left
} = $left;
700 # Store the percentage; use one decimal point
703 ?
100*$rv->{seconds_so_far
}/$rv->{seconds_total
}
705 $rv->{percentage
} = sprintf "%.1f",$rv->{percentage
};
708 # Parse the time so far
709 my $min_so_far = ($sofar / 60);
710 my $sec_so_far = ($sofar % 60);
712 $rv->{time_so_far
} = sprintf("%d:%02d", $min_so_far, $sec_so_far);
713 $rv->{minutes_so_far
} = sprintf("%00d", $min_so_far);
714 $rv->{seconds_so_far
} = sprintf("%00d", $sec_so_far);
717 # Parse the total time
718 my $min_tot = ($total / 60);
719 my $sec_tot = ($total % 60);
721 $rv->{time_total
} = sprintf("%d:%02d", $min_tot, $sec_tot);
722 $rv->{minutes
} = $min_tot;
723 $rv->{seconds
} = $sec_tot;
725 # Parse the time left
726 my $min_left = ($left / 60);
727 my $sec_left = ($left % 60);
728 $rv->{time_left
} = sprintf("-%d:%02d", $min_left, $sec_left);
734 sub playlist_changes
{
735 my ($self, $plid) = @_;
739 my @lines = $self->_send_command("plchanges $plid\n");
740 my $entry; # hash reference
741 foreach my $line (@lines) {
742 next unless $line =~ /^([^:]+):\s(.+)$/;
743 my ($key, $value) = ($1, $2);
744 # create a new hash for the start of each entry
745 $entry = {} if $key eq 'file';
746 # save a ref to the entry as soon as we know where it goes
747 $changes{$value} = $entry if $key eq 'Pos';
748 # save all attributes of the entry
749 $entry->{$key} = $value;
766 Audio::MPD - Class for talking to MPD (Music Player Daemon) servers
773 my $mpd = Audio::MPD->new();
781 Audio::MPD gives a clear object-oriented interface for talking to and
782 controlling MPD (Music Player Daemon) servers. A connection to the MPD
783 server is established as soon as a new Audio::MPD object is created.
784 Commands are then sent to the server as the class's methods are called.
793 =item new( [$host] [, $port] [, $password] )
795 This is the constructor for Audio::MPD. One can specify a $hostname, a
796 $port, and a $password.
798 If none is specified then defaults to environment vars MPD_HOST, MPD_PORT
799 and MPD_PASSWORD. If those aren't set, defaults to 'localhost', 6600 and ''.
804 =head2 Controlling the server
810 Sends a ping command to the mpd server.
813 =item $mpd->version()
815 Return the version number for the server we are connected to.
820 Send a message to the MPD server telling it to shut down.
823 =item $mpd->password( [$password] )
825 Change password used to communicate with MPD server to $password.
826 Empty string is assumed if $password is not supplied.
829 =item $mpd->updatedb( [$path] )
831 Force mpd to recan its collection. If $path (relative to MPD's music directory)
832 is supplied, MPD will only scan it - otherwise, MPD will rescan its whole
838 =head2 Handling volume & output
842 =item $mpd->volume( [+][-]$volume )
844 Sets the audio output volume percentage to absolute $volume.
845 If $volume is prefixed by '+' or '-' then the volume is changed relatively
849 =item $mpd->output_enable( $output )
851 Enable the specified audio output. $output is the ID of the audio output.
854 =item $mpd->output_disable( $output )
856 Disable the specified audio output. $output is the ID of the audio output.
861 =head2 Retrieving info
867 Return a hashref with the number of artists, albums, songs in the database,
868 as well as mpd uptime, the playtime of the playlist / the database and the
869 last update of the database
874 Return a C<Audio::MPD::Status> object with various information on current
875 MPD server settings. Check the embedded pod for more information on the
879 =item $mpd->get_urlhandlers()
881 Return an array of supported URL schemes.
887 =head2 Altering MPD settings
891 =item $mpd->repeat( [$repeat] )
893 Set the repeat mode to $repeat (1 or 0). If $repeat is not specified then
894 the repeat mode is toggled.
897 =item $mpd->random( [$random] )
899 Set the random mode to $random (1 or 0). If $random is not specified then
900 the random mode is toggled.
903 =item $mpd->fade( [$seconds] )
905 Enable crossfading and set the duration of crossfade between songs.
906 If $seconds is not specified or $seconds is 0, then crossfading is disabled.
911 =head2 Controlling playback
915 =item $mpd->play( [$number] )
917 Begin playing playlist at song number $number.
920 =item $mpd->playid( [$songid] )
922 Begin playing playlist at song ID $songid.
925 =item $mpd->pause( [$state] )
927 Pause playback. If C<$state> is 0 then the current track is unpaused,
928 if $state is 1 then the current track is paused.
930 Note that if C<$state> is not given, pause state will be toggled.
940 Play next song in playlist.
945 Play previous song in playlist.
948 =item $mpd->seek( $time, [$song])
950 Seek to $time seconds.
951 If $song number is not specified then the perl module will try and
952 seek to $time in the current song.
955 =item $mpd->seekid( $time, $songid )
957 Seek to $time seconds in song ID $songid.
962 =head2 Handling playlist
966 =item $mpd->add( $path )
968 Add the song identified by $path (relative to MPD's music directory) to the
969 current playlist. No return value.
972 =item $mpd->delete( $song )
974 Remove song number $song from the current playlist. No return value.
977 =item $mpd->deleteid( $songid )
979 Remove the specified $songid from the current playlist. No return value.
984 Remove all the songs from the current playlist. No return value.
989 Remove all of the songs from the current playlist *except* the
990 song currently playing.
993 =item $mpd->swap( $song1, $song2 )
995 Swap positions of song number $song1 and $song2 on the current playlist. No
999 =item $mpd->swapid( $songid1, $songid2 )
1001 Swap the postions of song ID $songid1 with song ID $songid2 on the current
1002 playlist. No return value.
1005 =item $mpd->move( $song, $newpos )
1007 Move song number $song to the position $newpos. No return value.
1010 =item $mpd->moveid( $songid, $newpos )
1012 Move song ID $songid to the position $newpos. No return value.
1015 =item $mpd->shuffle()
1017 Shuffle the current playlist. No return value.
1020 =item $mpd->load( $playlist )
1022 Load list of songs from specified $playlist file. No return value.
1025 =item $mpd->save( $playlist )
1027 Save the current playlist to a file called $playlist in MPD's playlist
1028 directory. No return value.
1031 =item $mpd->rm( $playlist )
1033 Delete playlist named $playlist from MPD's playlist directory. No return value.
1039 =head2 Searching the collection
1043 =item $mpd->search( $type, $string, [$strict] )
1045 Search through MPD's database of music for matching songs.
1047 $type is the field to search in: "title","artist","album", or "filename", and
1048 $string is the keyword(s) to seach for. If $strict is true then only exact
1049 matches are returned.
1051 Return an array of matching file paths.
1054 =item $mpd->searchadd( $type, $string )
1056 Perform the same action as $mpd->search(), but add any
1057 matching songs to the current playlist, instead of just returning
1058 information about them.
1061 =item $mpd->list( $type, [$artist] )
1063 Returns an array of all the "album" or "artist" in
1064 the music database (as chosen by $type). $artist is an
1065 optional parameter, which will only return albums by the
1066 specified $artist when $type is "album".
1069 =item $mpd->listall( [$path] )
1071 Return an array of all the songs in the music database.
1072 If $path is specified, then it only returns songs matching
1076 =item $mpd->listallinfo( [$path] )
1078 Returns an array of hashes containing all the paths and metadata about
1079 songs in the music database. If $path is specified, then it only
1080 returns songs matching the directory/path.
1083 =item $mpd->lsinfo( [$directory] )
1085 Returns an array of hashes containing all the paths and metadata about
1086 songs in the specified directory. If no directory is specified, then only
1087 the songs/directories in the root directory are listed.
1092 =head2 Retrieving information from current playlist
1096 =item $mpd->get_current_song_info( )
1098 Return a hash of metadata for the song currently playing.
1101 =item $mpd->playlist( )
1103 Return an arrayref containing a hashref of metadata for each of the
1104 songs in the current playlist.
1107 =item $mpd->playlist_changes( $plversion )
1109 Return a hash of hashref with all the differences in the playlist since
1110 playlist $plversion.
1113 =item $mpd->get_song_info( $song )
1115 Returns an a hash containing information about song number $song.
1118 =item $mpd->get_song_info_from_id( $songid )
1120 Returns an a hash containing information about song ID $songid.
1123 =item $mpd->get_title( [$song] )
1125 Return the 'title string' of song number $song. The 'title' is the artist and
1126 title of the song. If the artist isn't available, then just the title is
1127 returned. If there is no title available, then the filename is returned.
1129 If $song is not specified, then the 'title' of the current song is returned.
1132 =item $mpd->get_time_format( )
1134 Returns the current position and duration of the current song.
1135 String is formatted at "M:SS/M:SS", with current time first and total time
1139 =item $mpd->get_time_info( )
1141 Return current timing information in various different formats
1142 contained in a hashref with the following keys:
1146 =item minutes_so_far
1148 =item seconds_so_far
1173 You can find more information on the mpd project on its homepage at
1174 L<http://www.musicpd.org>, or its wiki L<http://mpd.wikia.com>.
1176 Regarding this Perl module, you can report bugs on CPAN via
1177 L<http://rt.cpan.org/Public/Bug/Report.html?Queue=Audio-MPD>.
1179 Audio::MPD development takes place on <audio-mpd@googlegroups.com>: feel free
1180 to join us. (use L<http://groups.google.com/group/audio-mpd> to sign in). Our
1181 subversion repository is located at L<https://svn.musicpd.org>.
1187 Jerome Quelin <jquelin@cpan.org>
1189 Original code by Tue Abrahamsen <tue.abrahamsen@gmail.com>, documented by
1190 Nicholas J. Humfrey <njh@aelius.com>.
1194 =head1 COPYRIGHT AND LICENSE
1196 Copyright (c) 2005 Tue Abrahamsen <tue.abrahamsen@gmail.com>
1198 Copyright (c) 2006 Nicholas J. Humfrey <njh@aelius.com>
1200 Copyright (c) 2007 Jerome Quelin <jquelin@cpan.org>
1203 This program is free software; you can redistribute it and/or modify
1204 it under the terms of the GNU General Public License as published by
1205 the Free Software Foundation; either version 2 of the License, or
1206 (at your option) any later version.
1208 This program is distributed in the hope that it will be useful,
1209 but WITHOUT ANY WARRANTY; without even the implied warranty of
1210 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1211 GNU General Public License for more details.