File Coverage

blib/lib/Audio/MPD.pm
Criterion Covered Total %
statement 47 188 25.0
branch 0 58 0.0
condition 0 24 0.0
subroutine 16 52 30.7
pod 24 25 96.0
total 87 347 25.0


line stmt bran cond sub pod time code
1             #
2             # This file is part of Audio-MPD
3             #
4             # This software is copyright (c) 2007 by Jerome Quelin.
5             #
6             # This is free software; you can redistribute it and/or modify it under
7             # the same terms as the Perl 5 programming language system itself.
8             #
9 9     9   4137 use 5.008;
  9         21  
10 9     9   31 use warnings;
  9         9  
  9         168  
11 9     9   27 use strict;
  9         6  
  9         387  
12              
13             package Audio::MPD;
14             # ABSTRACT: class to talk to MPD (Music Player Daemon) servers
15             $Audio::MPD::VERSION = '2.004';
16 9     9   3692 use Audio::MPD::Common::Item;
  9         4774915  
  9         407  
17 9     9   5099 use Audio::MPD::Common::Stats;
  9         319156  
  9         374  
18 9     9   5385 use Audio::MPD::Common::Status;
  9         1463845  
  9         423  
19 9     9   5564 use Audio::MPD::Common::Output;
  9         94769  
  9         341  
20 9     9   6204 use Encode;
  9         70827  
  9         694  
21 9     9   4733 use IO::Socket::IP;
  9         260893  
  9         57  
22 9     9   4219 use Moose;
  9         14  
  9         76  
23 9     9   45920 use MooseX::Has::Sugar;
  9         13  
  9         103  
24 9     9   6118 use MooseX::SemiAffordanceAccessor;
  9         49967  
  9         29  
25              
26 9     9   163922 use Audio::MPD::Collection;
  9         32  
  9         589  
27 9     9   5323 use Audio::MPD::Playlist;
  9         20  
  9         314  
28 9     9   4505 use Audio::MPD::Types;
  9         20  
  9         17688  
29              
30              
31              
32             has conntype => ( ro, isa=>'CONNTYPE', default=>'once' );
33             has host => ( ro, lazy_build );
34             has password => ( rw, lazy_build, trigger=>sub { $_[0]->ping } );
35             has port => ( ro, lazy_build );
36              
37             has collection => ( ro, lazy_build, isa=>'Audio::MPD::Collection' );
38             has playlist => ( ro, lazy_build, isa=>'Audio::MPD::Playlist' );
39             has version => ( rw );
40              
41             has _socket => ( rw, isa=>'IO::Socket' );
42              
43              
44             #--
45             # initializer & lazy builders
46              
47              
48             sub BUILD {
49 0     0 0   my $self = shift;
50              
51             # create the connection if conntype is set to $REUSE
52 0 0         $self->_connect_to_mpd_server if $self->conntype eq 'reuse';
53              
54             # try to issue a ping to test connection - this can die.
55 0           $self->ping;
56             }
57              
58             #
59             # my ($passwd, $host, $port) = _parse_env_var();
60             #
61             # parse MPD_HOST environment variable, and extract its components. the
62             # canonical format of MPD_HOST is passwd@host:port.
63             #
64             sub _parse_env_var {
65 0 0   0     return (undef, undef, undef) unless defined $ENV{MPD_HOST};
66 0 0         return ($1, $2, $3) if $ENV{MPD_HOST} =~ /^([^@]+)\@([^:@]+):(\d+)$/; # passwd@host:port
67 0 0         return ($1, $2, undef) if $ENV{MPD_HOST} =~ /^([^@]+)\@([^:@]+)$/; # passwd@host
68 0 0         return (undef, $1, $2) if $ENV{MPD_HOST} =~ /^([^:@]+):(\d+)$/; # host:port
69 0           return (undef, $ENV{MPD_HOST}, undef);
70             }
71              
72 0   0 0     sub _build_host { return ( _parse_env_var() )[1] || 'localhost'; }
73 0   0 0     sub _build_port { return $ENV{MPD_PORT} || ( _parse_env_var() )[2] || 6600; }
74 0   0 0     sub _build_password { return $ENV{MPD_PASSWORD} || ( _parse_env_var() )[0] || ''; }
75              
76 0     0     sub _build_collection { Audio::MPD::Collection->new( _mpd => $_[0] ); }
77 0     0     sub _build_playlist { Audio::MPD::Playlist ->new( _mpd => $_[0] ); }
78              
79              
80             #--
81             # Private methods
82              
83              
84             #
85             # $mpd->_connect_to_mpd_server;
86             #
87             # This method connects to the mpd server. It can die on several conditions:
88             # - if the server cannot be reached,
89             # - if it's not an mpd server,
90             # - or if the password is incorrect,
91             #
92             sub _connect_to_mpd_server {
93 0     0     my ($self) = @_;
94              
95             # try to connect to mpd.
96 0           my $socket;
97              
98 0 0         if ($self->host =~ m{^/}) {
99 0 0         eval q{use IO::Socket::UNIX qw(); 1}
100             or die "Could not load IO::Socket::UNIX: $@\n";
101 0 0         $socket = IO::Socket::UNIX->new($self->host)
102             or die "Could not create socket: $!\n";
103             }
104             else {
105 0 0         $socket = IO::Socket::IP->new(
106             PeerAddr => $self->host,
107             PeerPort => $self->port,
108             )
109             or die "Could not create socket: $!\n";
110             }
111              
112             # parse version information.
113 0           my $line = $socket->getline;
114 0           chomp $line;
115 0 0         die "Not a mpd server - welcome string was: [$line]\n"
116             if $line !~ /^OK MPD (.+)$/;
117 0           $self->set_version($1);
118              
119             # send password.
120 0 0         if ( $self->password ) {
121 0           $socket->print( 'password ' . encode('utf-8', $self->password) . "\n" );
122 0           $line = $socket->getline;
123 0 0         die $line if $line =~ s/^ACK //;
124             }
125              
126             # save socket
127 0           $self->_set_socket($socket);
128             }
129              
130              
131             #
132             # my @result = $mpd->_send_command( $command );
133             #
134             # This method is central to the module. It is responsible for interacting with
135             # mpd by sending the $command and reading output - that will be returned as an
136             # array of chomped lines (status line will not be returned).
137             #
138             # This method can die on several conditions:
139             # - if the server cannot be reached,
140             # - if it's not an mpd server,
141             # - if the password is incorrect,
142             # - or if the command is an invalid mpd command.
143             # In the latter case, the mpd error message will be returned.
144             #
145             sub _send_command {
146 0     0     my ($self, $command) = @_;
147              
148 0 0         $self->_connect_to_mpd_server if $self->conntype eq 'once';
149 0           my $socket = $self->_socket;
150              
151             # ok, now we're connected - let's issue the command.
152 0           $socket->print( encode('utf-8', $command) );
153 0           my @output;
154 0           while (defined ( my $line = $socket->getline ) ) {
155 0           chomp $line;
156 0 0         die $line if $line =~ s/^ACK //; # oops - error.
157 0 0         last if $line =~ /^OK/; # end of output.
158 0           push @output, decode('utf-8', $line);
159             }
160              
161             # close the socket.
162 0 0         $socket->close if $self->conntype eq 'once';
163              
164 0           return @output;
165             }
166              
167              
168             #
169             # my @items = $mpd->_cooked_command_as_items( $command );
170             #
171             # Lots of Audio::MPD methods are using _send_command() and then parse the
172             # output as a collection of AMC::Item. This method is meant to factorize
173             # this code, and will parse the raw output of _send_command() in a cooked
174             # list of items.
175             #
176             sub _cooked_command_as_items {
177 0     0     my ($self, $command) = @_;
178              
179 0           my @lines = $self->_send_command($command);
180 0           my (@items, %param);
181              
182             # parse lines in reverse order since "file:" or "directory:" lines
183             # come first. therefore, let's first store every other parameter,
184             # and the last line will trigger the object creation.
185             # of course, since we want to preserve the playlist order, this means
186             # that we're going to unshift the objects instead of push.
187 0           foreach my $line (reverse @lines) {
188 0           my ($k,$v) = split /:\s/, $line, 2;
189 0           $param{$k} = $v;
190 0 0 0       next unless $k eq 'file' || $k eq 'directory' || $k eq 'playlist'; # last param of item
      0        
191 0           unshift @items, Audio::MPD::Common::Item->new(%param);
192 0           %param = ();
193             }
194              
195 0           return @items;
196             }
197              
198              
199             #
200             # my %hash = $mpd->_cooked_command_as_kv( $command );
201             #
202             # Lots of Audio::MPD methods are using _send_command() and then parse the
203             # output to get a list of key / value (with the colon ":" acting as separator).
204             # This method is meant to factorize this code, and will parse the raw output
205             # of _send_command() in a cooked hash.
206             #
207             sub _cooked_command_as_kv {
208 0     0     my ($self, $command) = @_;
209             my %hash =
210 0           map { split(/:\s/, $_, 2) }
  0            
211             $self->_send_command($command);
212 0           return %hash;
213             }
214              
215             #
216             # my @list = $mpd->_cooked_command_strip_first_field( $command );
217             #
218             # Lots of Audio::MPD methods are using _send_command() and then parse the
219             # output to remove the first field (with the colon ":" acting as separator).
220             # This method is meant to factorize this code, and will parse the raw output
221             # of _send_command() in a cooked list of strings.
222             #
223             sub _cooked_command_strip_first_field {
224 0     0     my ($self, $command) = @_;
225              
226             my @list =
227 0           map { ( split(/:\s+/, $_, 2) )[1] }
  0            
228             $self->_send_command($command);
229 0           return @list;
230             }
231              
232              
233             #--
234             # Public methods
235              
236             # -- MPD interaction: general commands
237              
238              
239             sub ping {
240 0     0 1   my ($self) = @_;
241 0           $self->_send_command( "ping\n" );
242             }
243              
244              
245              
246              
247             # sub version {} # implemented as an accessor.
248              
249              
250              
251              
252             sub kill {
253 0     0 1   my ($self) = @_;
254 0           $self->_send_command("kill\n");
255             }
256              
257              
258              
259              
260             # implemented by password trigger (from moose)
261              
262              
263              
264             sub updatedb {
265 0     0 1   my ($self, $path) = @_;
266 0   0       $path ||= '';
267 0           $self->_send_command("update $path\n");
268             }
269              
270              
271              
272             sub urlhandlers {
273 0     0 1   my ($self) = @_;
274 0           return $self->_cooked_command_strip_first_field("urlhandlers\n");
275             }
276              
277              
278             # -- MPD interaction: handling volume & output
279              
280              
281             sub volume {
282 0     0 1   my ($self, $volume) = @_;
283              
284 0 0         if ($volume =~ /^(-|\+)(\d+)/ ) {
285 0           my $current = $self->status->volume;
286 0 0         $volume = $1 eq '+' ? $current + $2 : $current - $2;
287             }
288 0           $self->_send_command("setvol $volume\n");
289             }
290              
291              
292              
293             sub outputs {
294 0     0 1   my ($self) = @_;
295              
296 0           my @lines = $self->_send_command("outputs\n");
297 0           my (@outputs, %param);
298              
299             # parse lines in reverse order since "id" lines come first
300 0           foreach my $line (reverse @lines) {
301 0           my ($k,$v) = split /:\s/, $line, 2;
302 0           $k =~ s/^output//;
303 0           $param{$k} = $v;
304 0 0         next unless $k eq 'id'; # last output param
305 0           unshift @outputs, Audio::MPD::Common::Output->new(%param);
306 0           %param = ();
307             }
308              
309 0           return @outputs;
310             }
311              
312              
313              
314             sub output_enable {
315 0     0 1   my ($self, $output) = @_;
316 0           $self->_send_command("enableoutput $output\n");
317             }
318              
319              
320              
321             sub output_disable {
322 0     0 1   my ($self, $output) = @_;
323 0           $self->_send_command("disableoutput $output\n");
324             }
325              
326              
327              
328             # -- MPD interaction: retrieving info from current state
329              
330              
331             sub stats {
332 0     0 1   my ($self) = @_;
333 0           my %kv = $self->_cooked_command_as_kv( "stats\n" );
334 0           return Audio::MPD::Common::Stats->new(\%kv);
335             }
336              
337              
338              
339             sub status {
340 0     0 1   my ($self) = @_;
341 0           my %kv = $self->_cooked_command_as_kv( "status\n" );
342 0           my $status = Audio::MPD::Common::Status->new( \%kv );
343 0           return $status;
344             }
345              
346              
347              
348             sub current {
349 0     0 1   my ($self) = @_;
350 0           my ($item) = $self->_cooked_command_as_items("currentsong\n");
351 0           return $item;
352             }
353              
354              
355              
356             sub song {
357 0     0 1   my ($self, $song) = @_;
358 0 0         return $self->current unless defined $song;
359 0           my ($item) = $self->_cooked_command_as_items("playlistinfo $song\n");
360 0           return $item;
361             }
362              
363              
364              
365             sub songid {
366 0     0 1   my ($self, $songid) = @_;
367 0 0         return $self->current unless defined $songid;
368 0           my ($item) = $self->_cooked_command_as_items("playlistid $songid\n");
369 0           return $item;
370             }
371              
372              
373             # -- MPD interaction: altering settings
374              
375              
376              
377             sub repeat {
378 0     0 1   my ($self, $mode) = @_;
379              
380 0 0         $mode = not $self->status->repeat
381             unless defined $mode; # toggle if no param
382 0 0         $mode = $mode ? 1 : 0; # force integer
383 0           $self->_send_command("repeat $mode\n");
384             }
385              
386              
387              
388             sub random {
389 0     0 1   my ($self, $mode) = @_;
390              
391 0 0         $mode = not $self->status->random
392             unless defined $mode; # toggle if no param
393 0 0         $mode = $mode ? 1 : 0; # force integer
394 0           $self->_send_command("random $mode\n");
395             }
396              
397              
398              
399             sub fade {
400 0     0 1   my ($self, $value) = @_;
401 0   0       $value ||= 0;
402 0           $self->_send_command("crossfade $value\n");
403             }
404              
405              
406             # -- MPD interaction: controlling playback
407              
408              
409             sub play {
410 0     0 1   my ($self, $number) = @_;
411 0 0         $number = '' unless defined $number;
412 0           $self->_send_command("play $number\n");
413             }
414              
415              
416              
417             sub playid {
418 0     0 1   my ($self, $number) = @_;
419 0   0       $number ||= '';
420 0           $self->_send_command("playid $number\n");
421             }
422              
423              
424              
425             sub pause {
426 0     0 1   my ($self, $state) = @_;
427 0   0       $state ||= ''; # default is to toggle
428 0           $self->_send_command("pause $state\n");
429             }
430              
431              
432              
433             sub stop {
434 0     0 1   my ($self) = @_;
435 0           $self->_send_command("stop\n");
436             }
437              
438              
439              
440             sub next {
441 0     0 1   my ($self) = @_;
442 0           $self->_send_command("next\n");
443             }
444              
445              
446              
447             sub prev {
448 0     0 1   my($self) = shift;
449 0           $self->_send_command("previous\n");
450             }
451              
452              
453              
454             sub seek {
455 0     0 1   my ($self, $time, $song) = @_;
456 0   0       $time ||= 0; $time = int $time;
  0            
457 0 0         $song = $self->status->song if not defined $song; # seek in current song
458 0           $self->_send_command( "seek $song $time\n" );
459             }
460              
461              
462              
463             sub seekid {
464 0     0 1   my ($self, $time, $song) = @_;
465 0   0       $time ||= 0; $time = int $time;
  0            
466 0 0         $song = $self->status->songid if not defined $song; # seek in current song
467 0           $self->_send_command( "seekid $song $time\n" );
468             }
469              
470              
471 9     9   71 no Moose;
  9         17  
  9         95  
472             __PACKAGE__->meta->make_immutable;
473             1;
474              
475             __END__
476              
477             =pod
478              
479             =head1 NAME
480              
481             Audio::MPD - class to talk to MPD (Music Player Daemon) servers
482              
483             =head1 VERSION
484              
485             version 2.004
486              
487             =head1 SYNOPSIS
488              
489             use Audio::MPD;
490              
491             my $mpd = Audio::MPD->new;
492             $mpd->play;
493             sleep 10;
494             $mpd->next;
495              
496             =head1 DESCRIPTION
497              
498             L<Audio::MPD> gives a clear object-oriented interface for talking to and
499             controlling MPD (Music Player Daemon) servers. A connection to the MPD
500             server is established as soon as a new L<Audio::MPD> object is created.
501              
502             Since mpd is still in 0.x versions, L<Audio::MPD> sticks to latest mpd
503             (0.15 as time of writing) protocol & behaviour, and does B<not> try to
504             maintain backward compatibility.
505              
506             Note that the module will by default connect to mpd before sending any
507             command, and will disconnect after the command has been issued. This
508             scheme is far from optimal, but allows us not to care about timeout
509             disconnections. Because of that, the C<idle> command (new in mpd 0.14)
510             is B<not> (and will not) be supported in L<Audio::MPD>. This will be
511             implemented in L<POE::Component::Client::MPD>.
512              
513             B</!\> Note that L<Audio::MPD> is using high-level, blocking sockets.
514             This means that if the mpd server is slow, or hangs for whatever reason,
515             or even crash abruptly, the program will be hung forever in this sub.
516             The L<POE::Component::Client::MPD> module is way safer - you're advised
517             to use it instead of L<Audio::MPD>. Or you can try to set C<conntype> to
518             C<$REUSE> (see L<Audio::MPD> constructor for more details), but you
519             would be then on your own to deal with disconnections.
520              
521             =head2 Searching the collection
522              
523             To search the collection, use the C<collection()> accessor, returning the
524             associated L<Audio::MPD::Collection> object. You will then be able to call:
525              
526             $mpd->collection->all_songs;
527              
528             See L<Audio::MPD::Collection> documentation for more details on available
529             methods.
530              
531             =head2 Handling the playlist
532              
533             To update the playlist, use the C<playlist()> accessor, returning the
534             associated L<Audio::MPD::Playlist> object. You will then be able to call:
535              
536             $mpd->playlist->clear;
537              
538             See L<Audio::MPD::Playlist> documentation for more details on available
539             methods.
540              
541             =head1 ATTRIBUTES
542              
543             =head2 host
544              
545             The hostname where MPD is running. Defaults to environment var
546             C<MPD_HOST>, then to 'localhost'. Note that C<MPD_HOST> can be of
547             the form C<password@host:port> (each of C<password@> or C<:port> can
548             be omitted).
549              
550             =head2 port
551              
552             The port that MPD server listens to. Defaults to environment var
553             C<MPD_PORT>, then to parsed C<MPD_HOST> (cf above), then to 6600.
554              
555             =head2 password
556              
557             The password to access special MPD functions. Defaults to environment
558             var C<MPD_PASSWORD>, then to parsed C<MPD_HOST> (cf above), then to
559             empty string.
560              
561             =head2 conntype
562              
563             Change how the connection to mpd server is handled. It should be of a
564             C<CONNTYPE> type (cf L<Audio::MPD::Types>). Use either the C<reuse>
565             string to reuse the same connection or C<once> to open a new connection
566             per command (default).
567              
568             =head1 METHODS
569              
570             =head2 new
571              
572             my $mpd = Audio::MPD->new( \%opts );
573              
574             This is the constructor for L<Audio::MPD>. One can specify any of the
575             attributes (cf above).
576              
577             =head1 CONTROLLING THE SERVER
578              
579             =head2 ping
580              
581             $mpd->ping;
582              
583             Sends a ping command to the mpd server.
584              
585             =head2 version
586              
587             my $version = $mpd->version;
588              
589             Return mpd's version number as advertised during connection. Note that
590             mpd returns B<protocol> version when connected. This protocol version
591             can differ from the real mpd version. eg, mpd version 0.13.2 is
592             "speaking" and thus advertising version 0.13.0.
593              
594             =head2 kill
595              
596             $mpd->kill;
597              
598             Send a message to the MPD server telling it to shut down.
599              
600             =head2 set_password
601              
602             $mpd->set_password( [$password] );
603              
604             Change password used to communicate with MPD server to C<$password>.
605             Empty string is assumed if C<$password> is not supplied.
606              
607             =head2 updatedb
608              
609             $mpd->updatedb( [$path] );
610              
611             Force mpd to recan its collection. If C<$path> (relative to MPD's music
612             directory) is supplied, MPD will only scan it - otherwise, MPD will
613             rescan its whole collection.
614              
615             =head2 urlhandlers
616              
617             my @handlers = $mpd->urlhandlers;
618              
619             Return an array of supported URL schemes.
620              
621             =head1 HANDLING VOLUME & OUTPUT
622              
623             =head2 volume
624              
625             $mpd->volume( [+][-]$volume );
626              
627             Sets the audio output volume percentage to absolute C<$volume>. If
628             C<$volume> is prefixed by '+' or '-' then the volume is changed
629             relatively by that value.
630              
631             =head2 outputs
632              
633             my @outputs = $mpd->outputs( );
634              
635             Return a list of C<Audio::MPD::Common::Outputs> with all outputs
636             available within MPD.
637              
638             =head2 output_enable
639              
640             $mpd->output_enable( $output );
641              
642             Enable the specified audio output. C<$output> is the ID of the audio
643             output.
644              
645             =head2 output_disable
646              
647             $mpd->output_disable( $output );
648              
649             Disable the specified audio output. C<$output> is the ID of the audio
650             output.
651              
652             =head1 RETRIEVING INFO FROM CURRENT STATE
653              
654             =head2 stats
655              
656             my $stats = $mpd->stats;
657              
658             Return an L<Audio::MPD::Common::Stats> object with the current statistics
659             of MPD. See the associated pod for more information.
660              
661             =head2 status
662              
663             my $status = $mpd->status;
664              
665             Return an L<Audio::MPD::Common::Status> object with various information on
666             current MPD server settings. See the associated pod for more information.
667              
668             =head2 current
669              
670             my $song = $mpd->current;
671              
672             Return an L<Audio::MPD::Common::Item::Song> representing the song currently
673             playing.
674              
675             =head2 song
676              
677             my $song = $mpd->song( [$song] );
678              
679             Return an L<Audio::MPD::Common::Item::Song> representing the song number
680             C<$song>. If C<$song> is not supplied, returns the current song.
681              
682             =head2 songid
683              
684             my $song = $mpd->songid( [$songid] );
685              
686             Return an L<Audio::MPD::Common::Item::Song> representing the song with id
687             C<$songid>. If C<$songid> is not supplied, returns the current song.
688              
689             =head1 ALTERING MPD SETTINGS
690              
691             =head2 repeat
692              
693             $mpd->repeat( [$repeat] );
694              
695             Set the repeat mode to C<$repeat> (1 or 0). If C<$repeat> is not
696             specified then the repeat mode is toggled.
697              
698             =head2 random
699              
700             $mpd->random( [$random] );
701              
702             Set the random mode to C<$random> (1 or 0). If C<$random> is not
703             specified then the random mode is toggled.
704              
705             =head2 fade
706              
707             $mpd->fade( [$seconds] );
708              
709             Enable crossfading and set the duration of crossfade between songs. If
710             C<$seconds> is not specified or $seconds is 0, then crossfading is
711             disabled.
712              
713             =head1 CONTROLLING PLAYBACK
714              
715             =head2 play
716              
717             $mpd->play( [$song] );
718              
719             Begin playing playlist at song number C<$song>. If no argument supplied,
720             resume playing.
721              
722             =head2 playid
723              
724             $mpd->playid( [$songid] );
725              
726             Begin playing playlist at song ID C<$songid>. If no argument supplied,
727             resume playing.
728              
729             =head2 pause
730              
731             $mpd->pause( [$state] );
732              
733             Pause playback. If C<$state> is 0 then the current track is unpaused,
734             if C<$state> is 1 then the current track is paused.
735              
736             Note that if C<$state> is not given, pause state will be toggled.
737              
738             =head2 stop
739              
740             $mpd->stop;
741              
742             Stop playback.
743              
744             =head2 next
745              
746             $mpd->next;
747              
748             Play next song in playlist.
749              
750             =head2 prev
751              
752             $mpd->prev;
753              
754             Play previous song in playlist.
755              
756             =head2 seek
757              
758             $mpd->seek( $time, [$song]);
759              
760             Seek to C<$time> seconds in song number C<$song>. If C<$song> number is
761             not specified then the perl module will try and seek to C<$time> in the
762             current song.
763              
764             =head2 seekid
765              
766             $mpd->seekid( $time, $songid );
767              
768             Seek to C<$time> seconds in song ID C<$songid>. If C<$song> number is
769             not specified then the perl module will try and seek to C<$time> in the
770             current song.
771              
772             =for Pod::Coverage BUILD
773              
774             =head1 SEE ALSO
775              
776             You can find more information on the mpd project on its homepage at
777             L<http://www.musicpd.org>.wikia.com>.
778              
779             Original code (2005) by Tue Abrahamsen C<< <tue.abrahamsen@gmail.com> >>,
780             documented in 2006 by Nicholas J. Humfrey C<< <njh@aelius.com> >>.
781              
782             You can look for information on this module at:
783              
784             =over 4
785              
786             =item * Search CPAN
787              
788             L<http://metacpan.org/release/Audio-MPD>
789              
790             =item * See open / report bugs
791              
792             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Audio-MPD>
793              
794             =item * Mailing-list
795              
796             L<http://groups.google.com/group/audio-mpd>
797              
798             =item * Git repository
799              
800             L<http://github.com/jquelin/audio-mpd.git>
801              
802             =item * AnnoCPAN: Annotated CPAN documentation
803              
804             L<http://annocpan.org/dist/Audio-MPD>
805              
806             =item * CPAN Ratings
807              
808             L<http://cpanratings.perl.org/d/Audio-MPD>
809              
810             =back
811              
812             =head1 AUTHOR
813              
814             Jerome Quelin
815              
816             =head1 COPYRIGHT AND LICENSE
817              
818             This software is copyright (c) 2007 by Jerome Quelin.
819              
820             This is free software; you can redistribute it and/or modify it under
821             the same terms as the Perl 5 programming language system itself.
822              
823             =cut