[project @ 5851]
[audio-mpd.git] / lib / Audio / MPD.pm
blob765150736caaa2c1e86f425af0345572c74b7f94
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
18 package Audio::MPD;
20 use warnings;
21 use strict;
23 use Audio::MPD::Collection;
24 use Audio::MPD::Item;
25 use Audio::MPD::Playlist;
26 use Audio::MPD::Status;
27 use Encode;
28 use IO::Socket;
31 use base qw[ Class::Accessor::Fast ];
32 __PACKAGE__->mk_accessors(
33 qw[ _host _password _port
34 collection playlist version ] );
37 our $VERSION = '0.17.0';
40 #--
41 # Constructor
44 # my $mpd = Audio::MPD->new( [$hostname], [$port], [$password] )
46 # This is the constructor for Audio::MPD. One can specify a $hostname, a
47 # $port, and a $password.
48 # If none is specified then defaults to environment vars MPD_HOST, MPD_PORT
49 # and MPD_PASSWORD. If those aren't set, defaults to 'localhost', 6600 and ''.
51 sub new {
52 my $class = shift;
53 my ($host, $port, $password) = @_;
55 # use mpd defaults.
56 $host = $ENV{MPD_HOST} || 'localhost' unless defined $host;
57 $port = $ENV{MPD_PORT} || '6600' unless defined $port;
58 $password = $ENV{MPD_PASSWORD} || '' unless defined $password;
60 # create & bless the object.
61 my $self = {
62 _host => $host,
63 _port => $port,
64 _password => $password,
66 bless $self, $class;
68 # create the helper objects and store them.
69 $self->collection( Audio::MPD::Collection->new($self) );
70 $self->playlist ( Audio::MPD::Playlist->new($self) );
72 # try to issue a ping to test connection - this can die.
73 $self->ping;
75 return $self;
79 #--
80 # Private methods
84 # my @result = $mpd->_send_command( $command );
86 # This method is central to the module. It is responsible for interacting with
87 # mpd by sending the $command and reading output - that will be returned as an
88 # array of chomped lines (status line will not be returned).
90 # Note that currently, this method will connect to mpd before sending any
91 # command, and will disconnect after the command has been issued. This scheme
92 # is far from optimal, but allows us not to care about timeout disconnections.
94 # /!\ Note that we're using high-level, blocking sockets. This means that if
95 # the mpd server is slow, or hangs for whatever reason, or even crash abruptly,
96 # the program will be hung forever in this sub. The POE::Component::Client::MPD
97 # module is way safer - you're advised to use it instead of Audio::MPD.
99 # This method can die on several conditions:
100 # - if the server cannot be reached,
101 # - if it's not an mpd server,
102 # - if the password is incorrect,
103 # - or if the command is an invalid mpd command.
104 # In the latter case, the mpd error message will be returned.
106 sub _send_command {
107 my ($self, $command) = @_;
109 # try to connect to mpd.
110 my $socket = IO::Socket::INET->new(
111 PeerAddr => $self->_host,
112 PeerPort => $self->_port
114 or die "Could not create socket: $!\n";
115 my $line;
117 # parse version information.
118 $line = $socket->getline;
119 chomp $line;
120 die "Not a mpd server - welcome string was: [$line]\n"
121 if $line !~ /^OK MPD (.+)$/;
122 $self->version($1);
124 # send password.
125 if ( $self->_password ) {
126 $socket->print( 'password ' . encode('utf-8', $self->_password) . "\n" );
127 $line = $socket->getline;
128 die $line if $line =~ s/^ACK //;
131 # ok, now we're connected - let's issue the command.
132 $socket->print( encode('utf-8', $command) );
133 my @output;
134 while (defined ( $line = $socket->getline ) ) {
135 chomp $line;
136 die $line if $line =~ s/^ACK //; # oops - error.
137 last if $line =~ /^OK/; # end of output.
138 push @output, decode('utf-8', $line);
141 # close the socket.
142 $socket->close;
144 return @output;
149 # my @items = $mpd->_cooked_command_as_items( $command );
151 # Lots of Audio::MPD methods are using _send_command() and then parse the
152 # output as a collection of Audio::MPD::Item. This method is meant to
153 # factorize this code, and will parse the raw output of _send_command() in
154 # a cooked list of items.
156 sub _cooked_command_as_items {
157 my ($self, $command) = @_;
159 my @lines = $self->_send_command($command);
160 my (@items, %param);
162 # parse lines in reverse order since "file:" or "directory:" lines
163 # come first. therefore, let's first store every other parameter,
164 # and the last line will trigger the object creation.
165 # of course, since we want to preserve the playlist order, this means
166 # that we're going to unshift the objects instead of push.
167 foreach my $line (reverse @lines) {
168 my ($k,$v) = split /:\s+/, $line, 2;
169 $param{$k} = $v;
170 next unless $k eq 'file' || $k eq 'directory'; # last param of item
171 unshift @items, Audio::MPD::Item->new(%param);
172 %param = ();
175 return @items;
180 # my %hash = $mpd->_cooked_command_as_kv( $command );
182 # Lots of Audio::MPD methods are using _send_command() and then parse the
183 # output to get a list of key / value (with the colon ":" acting as separator).
184 # This method is meant to factorize this code, and will parse the raw output
185 # of _send_command() in a cooked hash.
187 sub _cooked_command_as_kv {
188 my ($self, $command) = @_;
189 my %hash =
190 map { split(/:\s+/, $_, 2) }
191 $self->_send_command($command);
192 return %hash;
196 # my @list = $mpd->_cooked_command_strip_first_field( $command );
198 # Lots of Audio::MPD methods are using _send_command() and then parse the
199 # output to remove the first field (with the colon ":" acting as separator).
200 # This method is meant to factorize this code, and will parse the raw output
201 # of _send_command() in a cooked list of strings.
203 sub _cooked_command_strip_first_field {
204 my ($self, $command) = @_;
206 my @list =
207 map { ( split(/:\s+/, $_, 2) )[1] }
208 $self->_send_command($command);
209 return @list;
214 # Public methods
216 # -- MPD interaction: general commands
219 # $mpd->ping;
221 # Sends a ping command to the mpd server.
223 sub ping {
224 my ($self) = @_;
225 $self->_send_command( "ping\n" );
230 # my $version = $mpd->version;
232 # Return version of MPD server's connected.
234 # sub version {} # implemented as an accessor.
239 # $mpd->kill;
241 # Send a message to the MPD server telling it to shut down.
243 sub kill {
244 my ($self) = @_;
245 $self->_send_command("kill\n");
250 # $mpd->password( [$password] )
252 # Change password used to communicate with MPD server to $password.
253 # Empty string is assumed if $password is not supplied.
255 sub password {
256 my ($self, $passwd) = @_;
257 $passwd ||= '';
258 $self->_password($passwd);
259 $self->ping; # ping sends a command, and thus the password is sent
264 # $mpd->updatedb( [$path] );
266 # Force mpd to recan its collection. If $path (relative to MPD's music
267 # directory) is supplied, MPD will only scan it - otherwise, MPD will rescan
268 # its whole collection.
270 sub updatedb {
271 my ($self, $path) = @_;
272 $path ||= '';
273 $self->_send_command("update $path\n");
278 # my @handlers = $mpd->urlhandlers;
280 # Return an array of supported URL schemes.
282 sub urlhandlers {
283 my ($self) = @_;
284 return $self->_cooked_command_strip_first_field("urlhandlers\n");
288 # -- MPD interaction: handling volume & output
291 # $mpd->volume( [+][-]$volume );
293 # Sets the audio output volume percentage to absolute $volume.
294 # If $volume is prefixed by '+' or '-' then the volume is changed relatively
295 # by that value.
297 sub volume {
298 my ($self, $volume) = @_;
300 if ($volume =~ /^(-|\+)(\d+)/ ) {
301 my $current = $self->status->volume;
302 $volume = $1 eq '+' ? $current + $2 : $current - $2;
304 $self->_send_command("setvol $volume\n");
309 # $mpd->output_enable( $output );
311 # Enable the specified audio output. $output is the ID of the audio output.
313 sub output_enable {
314 my ($self, $output) = @_;
315 $self->_send_command("enableoutput $output\n");
320 # $mpd->output_disable( $output );
322 # Disable the specified audio output. $output is the ID of the audio output.
324 sub output_disable {
325 my ($self, $output) = @_;
326 $self->_send_command("disableoutput $output\n");
331 # -- MPD interaction: retrieving info from current state
334 # $mpd->stats;
336 # Return a hashref with the number of artists, albums, songs in the database,
337 # as well as mpd uptime, the playtime of the playlist / the database and the
338 # last update of the database.
340 sub stats {
341 my ($self) = @_;
342 my %kv = $self->_cooked_command_as_kv( "stats\n" );
343 return \%kv;
348 # my $status = $mpd->status;
350 # Return an Audio::MPD::Status object with various information on current
351 # MPD server settings. Check the embedded pod for more information on the
352 # available accessors.
354 sub status {
355 my ($self) = @_;
356 my %kv = $self->_cooked_command_as_kv( "status\n" );
357 my $status = Audio::MPD::Status->new( %kv );
358 return $status;
363 # my $song = $mpd->current;
365 # Return an C<Audio::MPD::Item::Song> representing the song currently playing.
367 sub current {
368 my ($self) = @_;
369 my ($item) = $self->_cooked_command_as_items("currentsong\n");
370 return $item;
375 # my $song = $mpd->song( [$song] )
377 # Return an C<Audio::MPD::Item::Song> representing the song number C<$song>.
378 # If C<$song> is not supplied, returns the current song.
380 sub song {
381 my ($self, $song) = @_;
382 return $self->current unless defined $song;
383 my ($item) = $self->_cooked_command_as_items("playlistinfo $song\n");
384 return $item;
389 # my $song = $mpd->songid( [$songid] )
391 # Return an C<Audio::MPD::Item::Song> representing the song with id C<$songid>.
392 # If C<$songid> is not supplied, returns the current song.
394 sub songid {
395 my ($self, $songid) = @_;
396 return $self->current unless defined $songid;
397 my ($item) = $self->_cooked_command_as_items("playlistid $songid\n");
398 return $item;
402 # -- MPD interaction: altering settings
405 # $mpd->repeat( [$repeat] );
407 # Set the repeat mode to $repeat (1 or 0). If $repeat is not specified then
408 # the repeat mode is toggled.
410 sub repeat {
411 my ($self, $mode) = @_;
413 $mode = not $self->status->repeat
414 unless defined $mode; # toggle if no param
415 $mode = $mode ? 1 : 0; # force integer
416 $self->_send_command("repeat $mode\n");
421 # $mpd->random( [$random] );
423 # Set the random mode to $random (1 or 0). If $random is not specified then
424 # the random mode is toggled.
426 sub random {
427 my ($self, $mode) = @_;
429 $mode = not $self->status->random
430 unless defined $mode; # toggle if no param
431 $mode = $mode ? 1 : 0; # force integer
432 $self->_send_command("random $mode\n");
437 # $mpd->fade( [$seconds] );
439 # Enable crossfading and set the duration of crossfade between songs. If
440 # $seconds is not specified or $seconds is 0, then crossfading is disabled.
442 sub fade {
443 my ($self, $value) = @_;
444 $value ||= 0;
445 $self->_send_command("crossfade $value\n");
449 # -- MPD interaction: controlling playback
452 # $mpd->play( [$song] );
454 # Begin playing playlist at song number $song. If no argument supplied,
455 # resume playing.
457 sub play {
458 my ($self, $number) = @_;
459 $number = '' unless defined $number;
460 $self->_send_command("play $number\n");
464 # $mpd->playid( [$songid] );
466 # Begin playing playlist at song ID $songid. If no argument supplied,
467 # resume playing.
469 sub playid {
470 my ($self, $number) = @_;
471 $number ||= '';
472 $self->_send_command("playid $number\n");
477 # $mpd->pause( [$sate] );
479 # Pause playback. If $state is 0 then the current track is unpaused, if
480 # $state is 1 then the current track is paused.
482 # Note that if $state is not given, pause state will be toggled.
484 sub pause {
485 my ($self, $state) = @_;
486 $state ||= ''; # default is to toggle
487 $self->_send_command("pause $state\n");
492 # $mpd->stop;
494 # Stop playback.
496 sub stop {
497 my ($self) = @_;
498 $self->_send_command("stop\n");
503 # $mpd->next;
505 # Play next song in playlist.
507 sub next {
508 my ($self) = @_;
509 $self->_send_command("next\n");
513 # $mpd->prev;
515 # Play previous song in playlist.
517 sub prev {
518 my($self) = shift;
519 $self->_send_command("previous\n");
524 # $mpd->seek( $time, [$song]);
526 # Seek to $time seconds in song number $song. If $song number is not specified
527 # then the perl module will try and seek to $time in the current song.
529 sub seek {
530 my ($self, $time, $song) = @_;
531 $time ||= 0; $time = int $time;
532 $song = $self->status->song if not defined $song; # seek in current song
533 $self->_send_command( "seek $song $time\n" );
538 # $mpd->seekid( $time, $songid );
540 # Seek to $time seconds in song ID $songid. If $song number is not specified
541 # then the perl module will try and seek to $time in the current song.
543 sub seekid {
544 my ($self, $time, $song) = @_;
545 $time ||= 0; $time = int $time;
546 $song = $self->status->songid if not defined $song; # seek in current song
547 $self->_send_command( "seekid $song $time\n" );
553 ###############################################################
554 # CUSTOM METHODS #
555 #-------------------------------------------------------------#
556 # This section contains all methods not directly accessing #
557 # MPD, but may be useful for most people using the module. #
558 ###############################################################
561 sub get_time_format {
562 my ($self) = shift;
564 # Get the time from MPD; example: 49:395 (seconds so far:total seconds)
565 my ($sofar, $total) = split /:/, $self->status->time;
566 return sprintf "%d:%02d/%d:%02d",
567 ($sofar / 60), # minutes so far
568 ($sofar % 60), # seconds - minutes so far
569 ($total / 60), # minutes total
570 ($total % 60);# seconds - minutes total
573 sub get_time_info {
574 my ($self) = @_;
576 # Get the time from MPD; example: 49:395 (seconds so far:total seconds)
577 my ($sofar, $total) = split /:/, $self->status->time;
578 my $left = $total - $sofar;
580 # Store seconds for everything
581 my $rv = {};
582 $rv->{seconds_so_far} = $sofar;
583 $rv->{seconds_total} = $total;
584 $rv->{seconds_left} = $left;
586 # Store the percentage; use one decimal point
587 $rv->{percentage} =
588 $rv->{seconds_total}
589 ? 100*$rv->{seconds_so_far}/$rv->{seconds_total}
590 : 0;
591 $rv->{percentage} = sprintf "%.1f",$rv->{percentage};
594 # Parse the time so far
595 my $min_so_far = ($sofar / 60);
596 my $sec_so_far = ($sofar % 60);
598 $rv->{time_so_far} = sprintf("%d:%02d", $min_so_far, $sec_so_far);
599 $rv->{minutes_so_far} = sprintf("%00d", $min_so_far);
600 $rv->{seconds_so_far} = sprintf("%00d", $sec_so_far);
603 # Parse the total time
604 my $min_tot = ($total / 60);
605 my $sec_tot = ($total % 60);
607 $rv->{time_total} = sprintf("%d:%02d", $min_tot, $sec_tot);
608 $rv->{minutes} = $min_tot;
609 $rv->{seconds} = $sec_tot;
611 # Parse the time left
612 my $min_left = ($left / 60);
613 my $sec_left = ($left % 60);
614 $rv->{time_left} = sprintf("-%d:%02d", $min_left, $sec_left);
616 return $rv;
624 __END__
626 =pod
628 =head1 NAME
630 Audio::MPD - class to talk to MPD (Music Player Daemon) servers
633 =head1 SYNOPSIS
635 use Audio::MPD;
637 my $mpd = Audio::MPD->new();
638 $mpd->play();
639 sleep 10;
640 $mpd->next();
643 =head1 DESCRIPTION
645 Audio::MPD gives a clear object-oriented interface for talking to and
646 controlling MPD (Music Player Daemon) servers. A connection to the MPD
647 server is established as soon as a new Audio::MPD object is created.
648 Commands are then sent to the server as the class's methods are called.
651 =head1 METHODS
653 =head2 Constructor
655 =over 4
657 =item new( [$host] [, $port] [, $password] )
659 This is the constructor for Audio::MPD. One can specify a $hostname, a
660 $port, and a $password.
662 If none is specified then defaults to environment vars MPD_HOST, MPD_PORT
663 and MPD_PASSWORD. If those aren't set, defaults to 'localhost', 6600 and ''.
665 =back
668 =head2 Controlling the server
670 =over 4
672 =item $mpd->ping()
674 Sends a ping command to the mpd server.
677 =item $mpd->version()
679 Return the version number for the server we are connected to.
682 =item $mpd->kill()
684 Send a message to the MPD server telling it to shut down.
687 =item $mpd->password( [$password] )
689 Change password used to communicate with MPD server to $password.
690 Empty string is assumed if $password is not supplied.
693 =item $mpd->updatedb( [$path] )
695 Force mpd to recan its collection. If $path (relative to MPD's music directory)
696 is supplied, MPD will only scan it - otherwise, MPD will rescan its whole
697 collection.
700 =item $mpd->urlhandlers()
702 Return an array of supported URL schemes.
705 =back
708 =head2 Handling volume & output
710 =over 4
712 =item $mpd->volume( [+][-]$volume )
714 Sets the audio output volume percentage to absolute $volume.
715 If $volume is prefixed by '+' or '-' then the volume is changed relatively
716 by that value.
719 =item $mpd->output_enable( $output )
721 Enable the specified audio output. $output is the ID of the audio output.
724 =item $mpd->output_disable( $output )
726 Disable the specified audio output. $output is the ID of the audio output.
728 =back
731 =head2 Retrieving info from current state
733 =over 4
735 =item $mpd->stats()
737 Return a hashref with the number of artists, albums, songs in the database,
738 as well as mpd uptime, the playtime of the playlist / the database and the
739 last update of the database
742 =item $mpd->status()
744 Return an C<Audio::MPD::Status> object with various information on current
745 MPD server settings. Check the embedded pod for more information on the
746 available accessors.
749 =item $mpd->current( )
751 Return an C<Audio::MPD::Item::Song> representing the song currently playing.
754 =item $mpd->song( [$song] )
756 Return an C<Audio::MPD::Item::Song> representing the song number C<$song>. If
757 C<$song> is not supplied, returns the current song.
760 =item $mpd->songid( [$songid] )
762 Return an C<Audio::MPD::Item::Song> representing the song with id C<$songid>.
763 If C<$songid> is not supplied, returns the current song.
765 =back
768 =head2 Altering MPD settings
770 =over 4
772 =item $mpd->repeat( [$repeat] )
774 Set the repeat mode to $repeat (1 or 0). If $repeat is not specified then
775 the repeat mode is toggled.
778 =item $mpd->random( [$random] )
780 Set the random mode to $random (1 or 0). If $random is not specified then
781 the random mode is toggled.
784 =item $mpd->fade( [$seconds] )
786 Enable crossfading and set the duration of crossfade between songs.
787 If $seconds is not specified or $seconds is 0, then crossfading is disabled.
789 =back
792 =head2 Controlling playback
794 =over 4
796 =item $mpd->play( [$song] )
798 Begin playing playlist at song number $song. If no argument supplied,
799 resume playing.
802 =item $mpd->playid( [$songid] )
804 Begin playing playlist at song ID $songid. If no argument supplied,
805 resume playing.
808 =item $mpd->pause( [$state] )
810 Pause playback. If C<$state> is 0 then the current track is unpaused,
811 if $state is 1 then the current track is paused.
813 Note that if C<$state> is not given, pause state will be toggled.
816 =item $mpd->stop()
818 Stop playback.
821 =item $mpd->next()
823 Play next song in playlist.
826 =item $mpd->prev()
828 Play previous song in playlist.
831 =item $mpd->seek( $time, [$song])
833 Seek to $time seconds in song number $song. If $song number is not specified
834 then the perl module will try and seek to $time in the current song.
837 =item $mpd->seekid( $time, $songid )
839 Seek to $time seconds in song ID $songid. If $song number is not specified
840 then the perl module will try and seek to $time in the current song.
842 =back
845 =head2 Retrieving information from current playlist
847 =over 4
849 =item $mpd->get_time_format( )
851 Returns the current position and duration of the current song.
852 String is formatted at "M:SS/M:SS", with current time first and total time
853 after.
856 =item $mpd->get_time_info( )
858 Return current timing information in various different formats
859 contained in a hashref with the following keys:
861 =over 4
863 =item minutes_so_far
865 =item seconds_so_far
867 =item time_so_far
869 =item minutes
871 =item seconds
873 =item percentage
875 =item time_total
877 =item seconds_total
879 =item seconds_left
881 =item time_left
883 =back
885 =back
888 =head2 Searching the collection
890 To search the collection, use the C<collection()> accessor, returning the
891 associated C<Audio::MPD::Collection> object. You will then be able to call:
893 $mpd->collection->random_song();
895 See C<Audio::MPD::Collection> documentation for more details on available
896 methods.
899 =head2 Handling the playlist
901 To update the playlist, use the C<playlist()> accessor, returning the
902 associated C<Audio::MPD::Playlist> object. You will then be able to call:
904 $mpd->playlist->clear;
906 See C<Audio::MPD::Playlist> documentation for more details on available
907 methods.
910 =head1 SEE ALSO
912 You can find more information on the mpd project on its homepage at
913 L<http://www.musicpd.org>, or its wiki L<http://mpd.wikia.com>.
915 Regarding this Perl module, you can report bugs on CPAN via
916 L<http://rt.cpan.org/Public/Bug/Report.html?Queue=Audio-MPD>.
918 Audio::MPD development takes place on <audio-mpd@googlegroups.com>: feel free
919 to join us. (use L<http://groups.google.com/group/audio-mpd> to sign in). Our
920 subversion repository is located at L<https://svn.musicpd.org>.
924 =head1 AUTHORS
926 Jerome Quelin <jquelin@cpan.org>
928 Original code by Tue Abrahamsen <tue.abrahamsen@gmail.com>, documented by
929 Nicholas J. Humfrey <njh@aelius.com>.
933 =head1 COPYRIGHT AND LICENSE
935 Copyright (c) 2005 Tue Abrahamsen <tue.abrahamsen@gmail.com>
937 Copyright (c) 2006 Nicholas J. Humfrey <njh@aelius.com>
939 Copyright (c) 2007 Jerome Quelin <jquelin@cpan.org>
942 This program is free software; you can redistribute it and/or modify
943 it under the terms of the GNU General Public License as published by
944 the Free Software Foundation; either version 2 of the License, or
945 (at your option) any later version.
947 This program is distributed in the hope that it will be useful,
948 but WITHOUT ANY WARRANTY; without even the implied warranty of
949 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
950 GNU General Public License for more details.
952 =cut