[project @ 5831]
[audio-mpd.git] / lib / Audio / MPD.pm
blobc38ef91923d9204b6568591470ddbf50149daf12
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.16.2';
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 @list = $mpd->_cooked_command_strip_first_field( $command );
182 # Lots of Audio::MPD methods are using _send_command() and then parse the
183 # output to remove the first field (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 list of strings.
187 sub _cooked_command_strip_first_field {
188 my ($self, $command) = @_;
190 my @list =
191 map { ( split(/:\s+/, $_, 2) )[1] }
192 $self->_send_command($command);
193 return @list;
198 # Public methods
200 # -- MPD interaction: general commands
203 # $mpd->ping;
205 # Sends a ping command to the mpd server.
207 sub ping {
208 my ($self) = @_;
209 $self->_send_command( "ping\n" );
214 # my $version = $mpd->version;
216 # Return version of MPD server's connected.
218 # sub version {} # implemented as an accessor.
223 # $mpd->kill;
225 # Send a message to the MPD server telling it to shut down.
227 sub kill {
228 my ($self) = @_;
229 $self->_send_command("kill\n");
234 # $mpd->password( [$password] )
236 # Change password used to communicate with MPD server to $password.
237 # Empty string is assumed if $password is not supplied.
239 sub password {
240 my ($self, $passwd) = @_;
241 $passwd ||= '';
242 $self->_password($passwd);
243 $self->ping; # ping sends a command, and thus the password is sent
248 # $mpd->updatedb( [$path] );
250 # Force mpd to recan its collection. If $path (relative to MPD's music
251 # directory) is supplied, MPD will only scan it - otherwise, MPD will rescan
252 # its whole collection.
254 sub updatedb {
255 my ($self, $path) = @_;
256 $path ||= '';
257 $self->_send_command("update $path\n");
262 # my @handlers = $mpd->urlhandlers;
264 # Return an array of supported URL schemes.
266 sub urlhandlers {
267 my ($self) = @_;
268 return $self->_cooked_command_strip_first_field("urlhandlers\n");
272 # -- MPD interaction: handling volume & output
275 # $mpd->volume( [+][-]$volume );
277 # Sets the audio output volume percentage to absolute $volume.
278 # If $volume is prefixed by '+' or '-' then the volume is changed relatively
279 # by that value.
281 sub volume {
282 my ($self, $volume) = @_;
284 if ($volume =~ /^(-|\+)(\d+)/ ) {
285 my $current = $self->status->volume;
286 $volume = $1 eq '+' ? $current + $2 : $current - $2;
288 $self->_send_command("setvol $volume\n");
293 # $mpd->output_enable( $output );
295 # Enable the specified audio output. $output is the ID of the audio output.
297 sub output_enable {
298 my ($self, $output) = @_;
299 $self->_send_command("enableoutput $output\n");
304 # $mpd->output_disable( $output );
306 # Disable the specified audio output. $output is the ID of the audio output.
308 sub output_disable {
309 my ($self, $output) = @_;
310 $self->_send_command("disableoutput $output\n");
315 # -- MPD interaction: retrieving info from current state
318 # $mpd->stats;
320 # Return a hashref with the number of artists, albums, songs in the database,
321 # as well as mpd uptime, the playtime of the playlist / the database and the
322 # last update of the database.
324 sub stats {
325 my ($self) = @_;
326 my %kv =
327 map { my ($k,$v) = split(/:\s+/, $_, 2); ($k => $v) }
328 $self->_send_command( "stats\n" );
329 return \%kv;
334 # my $status = $mpd->status;
336 # Return an Audio::MPD::Status object with various information on current
337 # MPD server settings. Check the embedded pod for more information on the
338 # available accessors.
340 sub status {
341 my ($self) = @_;
342 my @output = $self->_send_command( "status\n" );
343 my $status = Audio::MPD::Status->new( @output );
344 return $status;
349 # my $song = $mpd->current;
351 # Return an C<Audio::MPD::Item::Song> representing the song currently playing.
353 sub current {
354 my ($self) = @_;
355 my ($item) = $self->_cooked_command_as_items("currentsong\n");
356 return $item;
361 # my $song = $mpd->song( [$song] )
363 # Return an C<Audio::MPD::Item::Song> representing the song number C<$song>.
364 # If C<$song> is not supplied, returns the current song.
366 sub song {
367 my ($self, $song) = @_;
368 return $self->current unless defined $song;
369 my ($item) = $self->_cooked_command_as_items("playlistinfo $song\n");
370 return $item;
375 # my $song = $mpd->songid( [$songid] )
377 # Return an C<Audio::MPD::Item::Song> representing the song with id C<$songid>.
378 # If C<$songid> is not supplied, returns the current song.
380 sub songid {
381 my ($self, $songid) = @_;
382 return $self->current unless defined $songid;
383 my ($item) = $self->_cooked_command_as_items("playlistid $songid\n");
384 return $item;
388 # -- MPD interaction: altering settings
391 # $mpd->repeat( [$repeat] );
393 # Set the repeat mode to $repeat (1 or 0). If $repeat is not specified then
394 # the repeat mode is toggled.
396 sub repeat {
397 my ($self, $mode) = @_;
399 $mode = not $self->status->repeat
400 unless defined $mode; # toggle if no param
401 $mode = $mode ? 1 : 0; # force integer
402 $self->_send_command("repeat $mode\n");
407 # $mpd->random( [$random] );
409 # Set the random mode to $random (1 or 0). If $random is not specified then
410 # the random mode is toggled.
412 sub random {
413 my ($self, $mode) = @_;
415 $mode = not $self->status->random
416 unless defined $mode; # toggle if no param
417 $mode = $mode ? 1 : 0; # force integer
418 $self->_send_command("random $mode\n");
423 # $mpd->fade( [$seconds] );
425 # Enable crossfading and set the duration of crossfade between songs. If
426 # $seconds is not specified or $seconds is 0, then crossfading is disabled.
428 sub fade {
429 my ($self, $value) = @_;
430 $value ||= 0;
431 $self->_send_command("crossfade $value\n");
435 # -- MPD interaction: controlling playback
438 # $mpd->play( [$song] );
440 # Begin playing playlist at song number $song. If no argument supplied,
441 # resume playing.
443 sub play {
444 my ($self, $number) = @_;
445 $number = '' unless defined $number;
446 $self->_send_command("play $number\n");
450 # $mpd->playid( [$songid] );
452 # Begin playing playlist at song ID $songid. If no argument supplied,
453 # resume playing.
455 sub playid {
456 my ($self, $number) = @_;
457 $number ||= '';
458 $self->_send_command("playid $number\n");
463 # $mpd->pause( [$sate] );
465 # Pause playback. If $state is 0 then the current track is unpaused, if
466 # $state is 1 then the current track is paused.
468 # Note that if $state is not given, pause state will be toggled.
470 sub pause {
471 my ($self, $state) = @_;
472 $state ||= ''; # default is to toggle
473 $self->_send_command("pause $state\n");
478 # $mpd->stop;
480 # Stop playback.
482 sub stop {
483 my ($self) = @_;
484 $self->_send_command("stop\n");
489 # $mpd->next;
491 # Play next song in playlist.
493 sub next {
494 my ($self) = @_;
495 $self->_send_command("next\n");
499 # $mpd->prev;
501 # Play previous song in playlist.
503 sub prev {
504 my($self) = shift;
505 $self->_send_command("previous\n");
510 # $mpd->seek( $time, [$song]);
512 # Seek to $time seconds in song number $song. If $song number is not specified
513 # then the perl module will try and seek to $time in the current song.
515 sub seek {
516 my ($self, $time, $song) = @_;
517 $time ||= 0; $time = int $time;
518 $song = $self->status->song if not defined $song; # seek in current song
519 $self->_send_command( "seek $song $time\n" );
524 # $mpd->seekid( $time, $songid );
526 # Seek to $time seconds in song ID $songid. If $song number is not specified
527 # then the perl module will try and seek to $time in the current song.
529 sub seekid {
530 my ($self, $time, $song) = @_;
531 $time ||= 0; $time = int $time;
532 $song = $self->status->songid if not defined $song; # seek in current song
533 $self->_send_command( "seekid $song $time\n" );
539 ###############################################################
540 # CUSTOM METHODS #
541 #-------------------------------------------------------------#
542 # This section contains all methods not directly accessing #
543 # MPD, but may be useful for most people using the module. #
544 ###############################################################
547 sub get_time_format {
548 my ($self) = shift;
550 # Get the time from MPD; example: 49:395 (seconds so far:total seconds)
551 my ($sofar, $total) = split /:/, $self->status->time;
552 return sprintf "%d:%02d/%d:%02d",
553 ($sofar / 60), # minutes so far
554 ($sofar % 60), # seconds - minutes so far
555 ($total / 60), # minutes total
556 ($total % 60);# seconds - minutes total
559 sub get_time_info {
560 my ($self) = @_;
562 # Get the time from MPD; example: 49:395 (seconds so far:total seconds)
563 my ($sofar, $total) = split /:/, $self->status->time;
564 my $left = $total - $sofar;
566 # Store seconds for everything
567 my $rv = {};
568 $rv->{seconds_so_far} = $sofar;
569 $rv->{seconds_total} = $total;
570 $rv->{seconds_left} = $left;
572 # Store the percentage; use one decimal point
573 $rv->{percentage} =
574 $rv->{seconds_total}
575 ? 100*$rv->{seconds_so_far}/$rv->{seconds_total}
576 : 0;
577 $rv->{percentage} = sprintf "%.1f",$rv->{percentage};
580 # Parse the time so far
581 my $min_so_far = ($sofar / 60);
582 my $sec_so_far = ($sofar % 60);
584 $rv->{time_so_far} = sprintf("%d:%02d", $min_so_far, $sec_so_far);
585 $rv->{minutes_so_far} = sprintf("%00d", $min_so_far);
586 $rv->{seconds_so_far} = sprintf("%00d", $sec_so_far);
589 # Parse the total time
590 my $min_tot = ($total / 60);
591 my $sec_tot = ($total % 60);
593 $rv->{time_total} = sprintf("%d:%02d", $min_tot, $sec_tot);
594 $rv->{minutes} = $min_tot;
595 $rv->{seconds} = $sec_tot;
597 # Parse the time left
598 my $min_left = ($left / 60);
599 my $sec_left = ($left % 60);
600 $rv->{time_left} = sprintf("-%d:%02d", $min_left, $sec_left);
602 return $rv;
610 __END__
612 =pod
614 =head1 NAME
616 Audio::MPD - Class for talking to MPD (Music Player Daemon) servers
619 =head1 SYNOPSIS
621 use Audio::MPD;
623 my $mpd = Audio::MPD->new();
624 $mpd->play();
625 sleep 10;
626 $mpd->next();
629 =head1 DESCRIPTION
631 Audio::MPD gives a clear object-oriented interface for talking to and
632 controlling MPD (Music Player Daemon) servers. A connection to the MPD
633 server is established as soon as a new Audio::MPD object is created.
634 Commands are then sent to the server as the class's methods are called.
637 =head1 METHODS
639 =head2 Constructor
641 =over 4
643 =item new( [$host] [, $port] [, $password] )
645 This is the constructor for Audio::MPD. One can specify a $hostname, a
646 $port, and a $password.
648 If none is specified then defaults to environment vars MPD_HOST, MPD_PORT
649 and MPD_PASSWORD. If those aren't set, defaults to 'localhost', 6600 and ''.
651 =back
654 =head2 Controlling the server
656 =over 4
658 =item $mpd->ping()
660 Sends a ping command to the mpd server.
663 =item $mpd->version()
665 Return the version number for the server we are connected to.
668 =item $mpd->kill()
670 Send a message to the MPD server telling it to shut down.
673 =item $mpd->password( [$password] )
675 Change password used to communicate with MPD server to $password.
676 Empty string is assumed if $password is not supplied.
679 =item $mpd->updatedb( [$path] )
681 Force mpd to recan its collection. If $path (relative to MPD's music directory)
682 is supplied, MPD will only scan it - otherwise, MPD will rescan its whole
683 collection.
686 =item $mpd->urlhandlers()
688 Return an array of supported URL schemes.
691 =back
694 =head2 Handling volume & output
696 =over 4
698 =item $mpd->volume( [+][-]$volume )
700 Sets the audio output volume percentage to absolute $volume.
701 If $volume is prefixed by '+' or '-' then the volume is changed relatively
702 by that value.
705 =item $mpd->output_enable( $output )
707 Enable the specified audio output. $output is the ID of the audio output.
710 =item $mpd->output_disable( $output )
712 Disable the specified audio output. $output is the ID of the audio output.
714 =back
717 =head2 Retrieving info from current state
719 =over 4
721 =item $mpd->stats()
723 Return a hashref with the number of artists, albums, songs in the database,
724 as well as mpd uptime, the playtime of the playlist / the database and the
725 last update of the database
728 =item $mpd->status()
730 Return an C<Audio::MPD::Status> object with various information on current
731 MPD server settings. Check the embedded pod for more information on the
732 available accessors.
735 =item $mpd->current( )
737 Return an C<Audio::MPD::Item::Song> representing the song currently playing.
740 =item $mpd->song( [$song] )
742 Return an C<Audio::MPD::Item::Song> representing the song number C<$song>. If
743 C<$song> is not supplied, returns the current song.
746 =item $mpd->songid( [$songid] )
748 Return an C<Audio::MPD::Item::Song> representing the song with id C<$songid>.
749 If C<$songid> is not supplied, returns the current song.
751 =back
754 =head2 Altering MPD settings
756 =over 4
758 =item $mpd->repeat( [$repeat] )
760 Set the repeat mode to $repeat (1 or 0). If $repeat is not specified then
761 the repeat mode is toggled.
764 =item $mpd->random( [$random] )
766 Set the random mode to $random (1 or 0). If $random is not specified then
767 the random mode is toggled.
770 =item $mpd->fade( [$seconds] )
772 Enable crossfading and set the duration of crossfade between songs.
773 If $seconds is not specified or $seconds is 0, then crossfading is disabled.
775 =back
778 =head2 Controlling playback
780 =over 4
782 =item $mpd->play( [$song] )
784 Begin playing playlist at song number $song. If no argument supplied,
785 resume playing.
788 =item $mpd->playid( [$songid] )
790 Begin playing playlist at song ID $songid. If no argument supplied,
791 resume playing.
794 =item $mpd->pause( [$state] )
796 Pause playback. If C<$state> is 0 then the current track is unpaused,
797 if $state is 1 then the current track is paused.
799 Note that if C<$state> is not given, pause state will be toggled.
802 =item $mpd->stop()
804 Stop playback.
807 =item $mpd->next()
809 Play next song in playlist.
812 =item $mpd->prev()
814 Play previous song in playlist.
817 =item $mpd->seek( $time, [$song])
819 Seek to $time seconds in song number $song. If $song number is not specified
820 then the perl module will try and seek to $time in the current song.
823 =item $mpd->seekid( $time, $songid )
825 Seek to $time seconds in song ID $songid. If $song number is not specified
826 then the perl module will try and seek to $time in the current song.
828 =back
831 =head2 Retrieving information from current playlist
833 =over 4
835 =item $mpd->get_time_format( )
837 Returns the current position and duration of the current song.
838 String is formatted at "M:SS/M:SS", with current time first and total time
839 after.
842 =item $mpd->get_time_info( )
844 Return current timing information in various different formats
845 contained in a hashref with the following keys:
847 =over 4
849 =item minutes_so_far
851 =item seconds_so_far
853 =item time_so_far
855 =item minutes
857 =item seconds
859 =item percentage
861 =item time_total
863 =item seconds_total
865 =item seconds_left
867 =item time_left
869 =back
871 =back
874 =head2 Searching the collection
876 To search the collection, use the C<collection()> accessor, returning the
877 associated C<Audio::MPD::Collection> object. You will then be able to call:
879 $mpd->collection->random_song();
881 See C<Audio::MPD::Collection> documentation for more details on available
882 methods.
885 =head2 Handling the playlist
887 To update the playlist, use the C<playlist()> accessor, returning the
888 associated C<Audio::MPD::Playlist> object. You will then be able to call:
890 $mpd->playlist->clear;
892 See C<Audio::MPD::Playlist> documentation for more details on available
893 methods.
896 =head1 SEE ALSO
898 You can find more information on the mpd project on its homepage at
899 L<http://www.musicpd.org>, or its wiki L<http://mpd.wikia.com>.
901 Regarding this Perl module, you can report bugs on CPAN via
902 L<http://rt.cpan.org/Public/Bug/Report.html?Queue=Audio-MPD>.
904 Audio::MPD development takes place on <audio-mpd@googlegroups.com>: feel free
905 to join us. (use L<http://groups.google.com/group/audio-mpd> to sign in). Our
906 subversion repository is located at L<https://svn.musicpd.org>.
910 =head1 AUTHORS
912 Jerome Quelin <jquelin@cpan.org>
914 Original code by Tue Abrahamsen <tue.abrahamsen@gmail.com>, documented by
915 Nicholas J. Humfrey <njh@aelius.com>.
919 =head1 COPYRIGHT AND LICENSE
921 Copyright (c) 2005 Tue Abrahamsen <tue.abrahamsen@gmail.com>
923 Copyright (c) 2006 Nicholas J. Humfrey <njh@aelius.com>
925 Copyright (c) 2007 Jerome Quelin <jquelin@cpan.org>
928 This program is free software; you can redistribute it and/or modify
929 it under the terms of the GNU General Public License as published by
930 the Free Software Foundation; either version 2 of the License, or
931 (at your option) any later version.
933 This program is distributed in the hope that it will be useful,
934 but WITHOUT ANY WARRANTY; without even the implied warranty of
935 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
936 GNU General Public License for more details.
938 =cut