1 ############################################################################
3 # /mplay [title|filename|artist|album] <search arg>
4 # First arguments are optional, if left out, title is used.
6 # /madd [title|filename|artist|album] <search arg>
7 # /mremove [title|filename|artist|album] <search arg>
8 # /mload [title|filename|artist|album] <search arg>
9 # First arguments are optional, if left out, artist is used.
10 # If invoked without any arguments all files are added/removed to/from list.
12 # /madd will search for <search args> and add result to current playlist
13 # /mremove will search for <search args> and remove matches from current playlist
14 # /mload will search for <search args> and create a playlist with the found files.
15 # So if you want to listen to the artist FooBars you type /mload artist FooBars
18 # Prints Artist - Album - Title to active window
19 # Not that anyone will ever be interested in what song you are
20 # listening to, but what the heck.
28 # /mrandom [on/1|off/0]
29 # /mrepeat [on/1|off/0]
34 # Variables (settings) - set from irssi with /set
36 # mpd_show_state ON/OFF
41 # mpd_show_artist ON/OFF
42 # mpd_show_album ON/OFF
43 # mpd_show_title ON/OFF
44 # mpd_show_time ON/OFF
45 # mpd_show_percent ON/OFF
46 # mpd_show_volume ON/OFF
47 # mpd_show_mode ON/OFF
50 # mpd_autoreconnect ON/OFF
59 # 2.1.3 - Corrected Audio::MPD constructor arguments
60 # 2.1.2 - Added /mremove
61 # 2.1.1 - Added mpd_show_volume and mpd_show_mode.
62 # Changed position-format from ##.#% to ##%
64 # 2.1.0 - Rewritten for Audio::MPD 0.19.1
65 # Added mpd_show_artist, mpd_show_album
66 # 2.0.5 - Removed some redudant code.
67 # Below only works with Audio::MPD 0.12.4 patched with Audio-MPD-0.12.4-safeconnect.patch
68 # (http://0xa0.org/stuff/Audio-MPD-0.12.4-safeconnect.patch)
69 # Added setting: mpd_autoreconnect
71 # 2.0.4 - MPD seems to have moved back to Audio::MPD in 0.12.3 ...
72 # I'll leave it to the user to change these two lines of code
73 # back to MPD as in 2.0.3 if they happen to be using an older version
74 # of Audio::MPD (MPD).
75 # 2.0.3 - Audio::MPD seems to have moved to MPD, appropriate changes made.
77 # 2.0.1 - Fixed a bug in /mplay where no results were played unless the
78 # first match were a track in the playlist.
79 # 2.0.0 - Total rewrite. Now uses Audio::MPD. Most things remain the same.
80 # /mremove was removed since it was very ugly and I found no nice way
82 # mpd_show_artist was removed and is now a part of mpd_show_title.
83 # 1.3.4 - Just changed the hardcoded MPD_PORT and MPD_HOST to use the env-vars
85 # 1.3.3 - Removed $data="OK" from get_playlistinfo since it caused ogg/flac
86 # files titles to not be displayed, as pointed out by jat in #mpd.
87 # 1.3.2 - Added utf8 to iso-8859-15 convertion. No more รถ here!
88 # 1.3.1 - if no tag, display filename, as pointed out by t0ffel. Thanks.
89 # added /minfo and /mclear
90 # 1.3.0 - remade big parts of the script. Added a /mvolume
91 # 1.2.1 - changed my email address to the evilninja.org domain.
92 # 1.2 - added /mload, /mremove, /madd - thus breaking the no-playlist-thing. :)
93 # 1.1 - added /mstop, /mrepeat and /mrandom
94 ############################################################################
101 use Env
qw(MPD_PORT MPD_HOST);
103 use vars
qw($VERSION %IRSSI);
109 contact => 'bumbyn@gmail.com',
111 description => 'Irssi MPD control',
113 changed => '2007/12/28'
116 ############################################################################
120 $MPD{'port'} = $ENV{'MPD_PORT'}?$ENV{'MPD_PORT'}:"6600";
121 $MPD{'host'} = $ENV{'MPD_HOST'}?$ENV{'MPD_HOST'}:"localhost";
122 $MPD{'timeout'} = "5";
124 our $mpd = new Audio::MPD(hostname =>$MPD{'host'}, port => $MPD{'port'});
127 $STATE{'play'} = ' >';
128 $STATE{'pause'} = '||';
129 $STATE{'stop'} = '[]';
131 # to give impc a dedicated statusbar comment these two lines
132 #Irssi::command("statusbar window add mpdbar");
133 #Irssi::command("statusbar window enable mpdbar");
134 # and uncomment these
135 Irssi::command("statusbar dmpdbar placement top");
136 Irssi::command("statusbar dmpdbar position 0");
137 Irssi::command("statusbar dmpdbar enable");
138 Irssi::command("statusbar dmpdbar add mpdbar");
139 Irssi::command("statusbar dmpdbar visible active");
141 Irssi::settings_add_bool('misc', 'mpd_show_state', '1');
142 Irssi::settings_add_bool('misc', 'mpd_show_artist', '1');
143 Irssi::settings_add_bool('misc', 'mpd_show_album', '0');
144 Irssi::settings_add_bool('misc', 'mpd_show_title', '1');
145 Irssi::settings_add_bool('misc', 'mpd_show_time', '1');
146 Irssi::settings_add_bool('misc', 'mpd_show_percent', '1');
147 Irssi::settings_add_bool('misc', 'mpd_show_volume', '0');
148 Irssi::settings_add_bool('misc', 'mpd_show_mode', '0');
149 Irssi::settings_add_bool('misc', 'mpd_autoreconnect', '0');
150 ############################################################################
152 ############################################################################
153 # irssi-bound commands
156 my ($args, $server, $witem) = @_;
157 my @a = split(/ /, $args);
158 my $type = lc shift @a;
160 foreach my $element (@a){
166 eval { $mpd->play(0); };
168 $MPD{'state'}="Error: $@";
169 Irssi::statusbar_items_redraw('mpdbar');
175 if($name eq ""){$name=$type}
177 $MPD{'state'}="Searching...";
178 Irssi::statusbar_items_redraw('mpdbar');
182 eval { @plylist = $mpd->playlist->as_items; };
185 $MPD{'state'}="Error: $@";
186 Irssi::statusbar_items_redraw('mpdbar');
191 while( (my $track = shift @plylist) && not defined $tracknr) {
192 if($track->{$type} =~ /$name/i) {
193 eval { $mpd->play($track->{'pos'}); };
195 $MPD{'state'}="Error: $@";
196 Irssi::statusbar_items_redraw('mpdbar');
204 my ($args, $server, $witem) = @_;
205 my @a = split(/ /, $args);
206 my $type = lc shift @a;
208 foreach my $element (@a){
213 if($type eq ""){clear();return;}
214 if($name eq ""){$name=$type}
216 $MPD{'state'}="Searching...";
217 Irssi::statusbar_items_redraw('mpdbar');
221 eval { @plylist = $mpd->playlist->as_items; };
224 $MPD{'state'}="Error: $@";
225 Irssi::statusbar_items_redraw('mpdbar');
230 while( (my $track = shift @plylist) && not defined $tracknr) {
231 if($track->{$type} =~ /$name/i) {
232 eval { $mpd->playlist->deleteid($track->{'id'}); };
234 $MPD{'state'}="Error: $@";
235 Irssi::statusbar_items_redraw('mpdbar');
242 my ($args, $server, $witem) = @_;
243 my @a = split(/ /, $args);
249 foreach my $element (@a){
254 if($name eq ""){$name=$type;$type='artist';}
257 $MPD{'state'}="Searching...";
258 Irssi::statusbar_items_redraw('mpdbar');
261 eval { @files = $mpd->collection->all_items_simple; };
263 $MPD{'state'}="Error: $@";
264 Irssi::statusbar_items_redraw('mpdbar');
268 if($type eq 'title') {
269 eval { @files = $mpd->collection->songs_with_title_partial($name); };
270 } elsif($type eq 'album') {
271 eval { @files = $mpd->collection->songs_from_album_partial($name); };
273 eval { @files = $mpd->collection->songs_by_artist_partial($name); };
277 $MPD{'state'}="Error: $@";
278 Irssi::statusbar_items_redraw('mpdbar');
283 $MPD{'state'}="Adding...";
284 Irssi::statusbar_items_redraw('mpdbar');
286 eval { foreach(@files){$mpd->playlist->add($_->{'file'}) if exists $_->{'file'}} };
288 $MPD{'state'}="Error: $@";
289 Irssi::statusbar_items_redraw('mpdbar');
294 my ($args, $server, $witem) = @_;
297 add($args, $server, $witem);
298 eval { $mpd->play(0); };
300 $MPD{'state'}="Error: $@";
301 Irssi::statusbar_items_redraw('mpdbar');
307 my ($args, $server, $witem) = @_;
308 if($args<0 and $args>100){return;}
310 my $seektime = $MPD{'current'}->{'time'} * ($args/100);
311 $mpd->seek($seektime);
315 my ($args, $server, $witem) = @_;
317 Irssi::print("Current volume: ".$MPD{'status'}->{'volume'});
320 if($args<0 and $args>100){return;}
325 my ($args, $server, $witem) = @_;
326 if($args=~/(1|on)/i){
328 }elsif($args=~/(0|off)/i){
336 my ($args, $server, $witem) = @_;
337 if($args=~/(1|on)/i){
339 }elsif($args=~/(0|off)/i){
347 Irssi::statusbar_items_redraw('mpdbar');
348 if($MPD{'current'}->{'title'}){
349 Irssi::active_win()->print( $MPD{'current'}->{'title'});
351 Irssi::active_win()->print( $MPD{'current'}->{'file'});
354 Irssi::active_win()->print( $MPD{'state'}." #".$MPD{'status'}->{'song'}."/".$MPD{'status'}->{'playlistlength'}.
355 " ".$MPD{'status'}->{'time'}->{'sofar'}." (".$MPD{'status'}->{'time'}->{'percent'}."%)");
356 my $repeat = $MPD{'status'}->{'repeat'}?"on":"off";
357 my $random = $MPD{'status'}->{'random'}?"on":"off";
358 Irssi::active_win()->print( "volume: ".$MPD{'status'}->{'volume'}."% repeat: ".$repeat.
359 " random: ".$random);
362 eval { $mpd->stop; };
364 $MPD{'state'}="Error: $@";
365 Irssi::statusbar_items_redraw('mpdbar');
371 eval { $mpd->pause; };
373 $MPD{'state'}="Error: $@";
374 Irssi::statusbar_items_redraw('mpdbar');
378 eval { $mpd->next; };
380 $MPD{'state'}="Error: $@";
381 Irssi::statusbar_items_redraw('mpdbar');
385 eval { $mpd->prev; };
387 $MPD{'state'}="Error: $@";
388 Irssi::statusbar_items_redraw('mpdbar');
392 eval { $mpd->playlist->clear; };
394 $MPD{'state'}="Error: $@";
395 Irssi::statusbar_items_redraw('mpdbar');
399 ############################################################################
400 # Setup the statusbar
403 my ($item, $get_size_only) = @_;
406 return unless $MPD{'status'};
408 $info.=$MPD{'state'}." " if(Irssi::settings_get_bool('mpd_show_state'));
409 if($MPD{'current'}->{'title'}) {
410 $info.=$MPD{'current'}->{'artist'}." - " if(Irssi::settings_get_bool('mpd_show_artist'));
411 $info.=$MPD{'current'}->{'album'}." - " if(Irssi::settings_get_bool('mpd_show_album'));
412 $info.=$MPD{'current'}->{'title'}." " if(Irssi::settings_get_bool('mpd_show_title'));
415 $info.=$MPD{'current'}->{'file'}." ";
419 if(Irssi::settings_get_bool('mpd_show_time')) {
420 $info.= $MPD{'status'}->{'time'}->{'sofar'}."/".$MPD{'status'}->{'time'}->{'total'};
424 if(Irssi::settings_get_bool('mpd_show_percent')) {
425 $info.= int($MPD{'status'}->{'time'}->{'percent'}+0.5)."%";
429 if(Irssi::settings_get_bool('mpd_show_volume')) {
430 $info.= "Volume: ".$MPD{'status'}->{'volume'}."%";
434 if(Irssi::settings_get_bool('mpd_show_mode')) {
435 my $mode = $MPD{'status'}->{'repeat'}?"r":"";
436 $mode .= $MPD{'status'}->{'random'}?"z":"";
442 $item->default_handler($get_size_only, undef, $info, 1)
445 ############################################################################
446 # Refresh the statusbar
452 eval { $status = $mpd->status; };
454 $MPD{'state'}="Error: $@";
455 Irssi::statusbar_items_redraw('mpdbar');
459 eval { $csong = $mpd->current; };
461 $MPD{'state'}="Error: $@";
462 Irssi::statusbar_items_redraw('mpdbar');
466 $MPD{'status'} = $status;
467 $MPD{'current'} = $csong;
468 $MPD{'state'} = $STATE{$status->{'state'}} || "?";
470 Irssi::statusbar_items_redraw('mpdbar');
473 ############################################################################
474 # Print songtitle etc to active window.
476 my @actions=("np: ");
477 my $t = $MPD{'current'}->{'title'};
478 my $a = $MPD{'current'}->{'artist'};
479 Irssi::active_win()->command("/me ".$actions[rand(@actions)]."$a - $t");
482 ############################################################################
485 Irssi::statusbar_item_register('mpdbar', '{sb $0 $1 $2-}', 'mpdbar_setup');
486 Irssi::statusbars_recreate_items();
487 Irssi::timeout_add(1000, 'mpdbar_refresh', undef);
489 Irssi::command_bind('mshow','show');
490 Irssi::command_bind('mstop','stop');
491 Irssi::command_bind('mrepeat','repeat');
492 Irssi::command_bind('mrandom','random');
493 Irssi::command_bind('mplay','play');
494 Irssi::command_bind('mload','load');
495 Irssi::command_bind('madd','add');
496 Irssi::command_bind('mseek','seek');
497 Irssi::command_bind('mnext','next');
498 Irssi::command_bind('mprev','prev');
499 Irssi::command_bind('mpause','pause');
500 Irssi::command_bind('mvolume','volume');
501 Irssi::command_bind('mclear','clear');
502 Irssi::command_bind('minfo','info');
503 Irssi::command_bind('mremove','remove');