html/iMPD.pl
1 #/usr/bin/perl -w
2 ########################################################################
3 #
4 # iMPD - irssi MPD controller
5 # Copyright (C) 2004 Shawn Fogle (starz@antisocial.com)
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #
21 ########################################################################
22 #
23 # iMPD - irssi MPD
24 #
25 # Requirements: mpc, mpd (http://musicpd.org)
26 #
27 # Please report b00gs to http://www.musicpd.org/forum/viewtopic.php?t=19
28 # Get the latest and greatest from pulling the module at musicpd's
29 # SVN (module iMPD).
30 #
31 # OK, This is the a script for irssi/mpc/mpd for people who want to
32 # control mpd from irssi. It's very bloated, and featureful, but this
33 # is a good thing because it's just a perl script and you really don't
34 # ever need to use anything that's in here that doesn't pertain to you.
35 # If you need it (or want it) it's most likely in here.
36 #
37 # I am up for suggestions, alot of this may not work for you, and
38 # I will not fix it unless you tell me about it.
39 #
40 # I do not believe in backwards compatibility if that means it gets in
41 # the way of development, so this is probably needs the latest and
42 # greatest due to changes in mpc/mpd.
43 #
44 ########################################################################
45 # Changes
46 ########################################################################
47 #
48 # 0.0.0m->0.0.0n
49 #
50 # - Added Move / Crossfade
51 #
52 # - Fixed problems with finding mpc if it's in your path.
53 #
54 # - Began work on AddNext (Adding next in the queue, unless it's on
55 # random or shuffle, don't know if it will ever be added but this
56 # release needs to make it out soon to fix path b00g.
57 #
58 # - Finally attached the GPL to make this fully GPLv2 compatible
59 #
60 ########################################################################
61 # Buglist / Wishlist / Todo (In no particular order)
62 ########################################################################
63 #
64 # - Have to be able to tell if MPD goes down, so it can gracefully
65 # shutdown the statusbar, so it doesn't try and access mpc every
66 # 5 seconds (gets even worse if mpdbar_refresh is faster than
67 # default). This will more than likely be fixed by the MPD module.
68 # Note to self: Script unloading self leads to _bad_problems ;p
69 #
70 # - Update issues will go away in 0.11.0 (see musicpd.org) due to
71 # update being non-blocking from there on out (hopefully ;p)
72 #
73 ########################################################################
74 # You don't need to edit below this unless you know what you're doing :)
75 ########################################################################
76
77 use File::Basename;
78 use Irssi;
79 use Irssi::TextUI;
80 use strict;
81 use vars qw($VERSION %ENABLED %SAVE_VARS %IRSSI %COUNT %SET);
82
83 $VERSION = '0.0.0n';
84 %IRSSI = (
85 authors => 'Santabutthead',
86 contact => 'starz@antisocial.com',
87 name => 'iMPD',
88 description => 'This controls Music Player Daemon from the familiar irssi interface',
89 license => 'GPL v2',
90 url => 'http://www.musicpd.org'
91 );
92
93 # Create $SET{'mpc_override'}="/outside/path" if mpc's not in your path
94
95 ### DO NOT EDIT THESE! Use /set mpd_host /set mpd_port ###
96
97 $SET{'port'} = "2100";
98 $SET{'host'} = "127.0.0.1";
99
100 ### Let's go ahead and set this up, so irssi doesn't have a tantrum ###
101
102 Irssi::signal_add('setup changed' => \&read_settings);
103 Irssi::settings_add_bool('misc', 'mpdbar_bottom', 0);
104 Irssi::settings_add_bool('misc', 'mpdbar_top', 0);
105 Irssi::settings_add_bool('misc', 'mpdbar_window', 0);
106 Irssi::settings_add_bool('misc', 'current_window', '0');
107 Irssi::settings_add_int('misc', 'output_window', '1');
108 Irssi::settings_add_int('misc', 'mpd_port', '2100');
109 Irssi::settings_add_str('misc', 'mpd_host', '127.0.0.1');
110 Irssi::signal_add_first('command script unload', \&cleanup);
111 Irssi::signal_add_first('command script load', \&cleanup);
112 Irssi::signal_add('setup changed' => \&mpdbar_refresh);
113 # Keep the $2- to treat spaces right
114 Irssi::statusbar_item_register('mpdbar', '{sb $0 $1 $2-}', 'mpdbar_setup');
115 Irssi::statusbars_recreate_items();
116
117 #######################################################################
118
119 print "For usage information on iMPD type /mhelp";
120
121 sub add {
122 if ($_[0]) {
123 &read_settings;
124 my $j;
125 ¤t_window;
126 if ($_[0] =~ /^album\s/ or $_[0]=~ /^filename\s/ or $_[0]=~ /^title\s/ or $_[0]=~ /^artist\s/ ) {
127 my @i = split / /, $_[0];
128 $j = $i[0];
129 $_[0] =~ s/^(\w+)\s//;
130 } else {
131 $j = "filename";
132 }
133 Irssi::command( "$SET{'intrairssi'} search $j \Q$_[0]\E | $SET{'intrashell'} add" );
134 &set_active;
135 } else {
136 print "%W/madd (album|artist|filename|title) {search term} {search term}..%w";
137 print " - Search for {search term} and automagically add it to the end of the queue";
138 print " - This command does not support play number. (it doesn't make sense)";
139 print " - If not specified it will use filename by default";
140 }
141 }
142
143 sub addall {
144 &read_settings;
145 ¤t_window;
146 Irssi::command( "$SET{'intrairssi'} add \"\"" );
147 &set_active;
148 }
149
150 sub addallPlay {
151 &read_settings;
152 ¤t_window;
153 Irssi::command( "$SET{'intrairssi'} add \"\" && $SET{'intrashell'} play" );
154 &mpdbar_refresh; # Impatience
155 &set_active;
156 }
157
158 sub addallShufflePlay {
159 &read_settings;
160 ¤t_window;
161 Irssi::command( "$SET{'intrairssi'} add \"\" && $SET{'intrashell'} shuffle && $SET{'intrashell'} play" );
162 &mpdbar_refresh; # Impatience
163 &set_active;
164 }
165
166 sub addNext { # This does not work yet, but doesn't hurt being here until it does :)
167 if ($_[0]) {
168 &read_settings;
169 my $j;
170 ¤t_window;
171 &song_count;
172 if ($_[0] =~ /^album\s/ or $_[0]=~ /^filename\s/ or $_[0]=~ /^title\s/ or $_[0]=~ /^artist\s/ ) {
173 my @i = split / /, $_[0];
174 $j = $i[0];
175 $_[0] =~ s/^(\w+)\s//;
176 } else {
177 $j = "filename";
178 }
179 Irssi::command( "$SET{'intrairssi'} search $j \Q$_[0]\E | $SET{'intrashell'} add" );
180 my $new_pos =~ $COUNT{'song'}++;
181 my $playcount =~ $COUNT{'playlist'}++;
182 Irssi::command( "$SET{'intrairssi'} mpc $playcount $new_pos");
183 #random detect stuff here;
184 &set_active;
185 } else {
186 print "%W/maddnext (album|artist|filename|title) {search term} {search term}..%w";
187 print " - Search for {search term} and automagically add it to the next position in";
188 print " - the queue. This command does not support play number. (it doesn't make sense)";
189 print " - If not specified it will use filename by default";
190 }
191 }
192
193 sub addPlay {
194 if ($_[0]) {
195 &read_settings;
196 my $j;
197 ¤t_window;
198 if ($_[0]=~ /^album\s/ or $_[0]=~ /^filename\s/ or $_[0]=~ /^title\s/ or $_[0]=~ /^artist\s/ ) {
199 my @i = split / /, $_[0];
200 $j = $i[0];
201 $_[0] =~ s/^(\w+)\s//;
202 } else {
203 $j = "filename";
204 }
205 Irssi::command( "$SET{'intrairssi'} search $j \Q$_[0]\E | $SET{'intrashell'} add && $SET{'intrashell'} play" );
206 &mpdbar_refresh; # Impatience
207 &set_active;
208 } else {
209 print "%W/map (add play) (album|artist|filename|title) {search term} {search term}..%w";
210 print " - Search for {search term} and automagically add it to the end of the queue";
211 print " - This command does not support play number. (it doesn't make sense)";
212 print " - If not specified it will use filename by default";
213 }
214 }
215
216 sub addShuffle {
217 if ($_[0]) {
218 &read_settings;
219 my $j;
220 ¤t_window;
221 if ($_[0] =~ /^album\s/ or $_[0]=~ /^filename\s/ or $_[0]=~ /^title\s/ or $_[0]=~ /^artist\s/ ) {
222 my @i = split / /, $_[0];
223 $j = $i[0];
224 $_[0] =~ s/^(\w+)\s//;
225 } else {
226 $j = "filename";
227 }
228 Irssi::command( "$SET{'intrairssi'} search $j \Q$_[0]\E | $SET{'intrashell'} add && $SET{'intrashell'} shuffle" );
229 &set_active;
230 } else {
231 print "%W/mas (add shuffle) (album|artist|filename|title) {search term} {search term}..%w";
232 print " - Search for {search term} and automagically add it to the end of the queue";
233 print " - This command does not support play number. (it doesn't make sense)";
234 print " - If not specified it will use filename by default";
235 }
236 }
237
238 sub addShufflePlay {
239 if ($_[0]) {
240 &read_settings;
241 my $j;
242 ¤t_window;
243 if ($_[0] =~ /^album\s/ or $_[0]=~ /^filename\s/ or $_[0]=~ /^title\s/ or $_[0]=~ /^artist\s/ ) {
244 my @i = split / /, $_[0];
245 $j = $i[0];
246 $_[0] =~ s/^(\w+)\s//;
247 } else {
248 $j = "filename";
249 }
250 Irssi::command( "$SET{'intrairssi'} search $j \Q$_[0]\E | $SET{'intrashell'} add && $SET{'intrashell'} shuffle && $SET{'intrashell'} play" );
251 &mpdbar_refresh; # Impatience
252 &set_active;
253 } else {
254 print "%W/masp (add shuffle play) (album|artist|filename|title) {search term} {search term}..%w";
255 print " - Search for {search term} and automagically add it to the end of the queue";
256 print " - This command does not support play number. (it doesn't make sense)";
257 print " - If not specified it will use filename by default";
258 }
259 }
260
261
262 sub cleanup {
263 my ($file) = Irssi::get_irssi_dir."/iMPD.conf";
264
265 open CONF, "> $file";
266 for my $net (sort keys %SAVE_VARS) {
267 print CONF "$net\t$SAVE_VARS{$net}\n";
268 close CONF;
269 }
270 Irssi::command( "statusbar mpdbar disable" );
271 }
272
273 sub clear {
274 &read_settings;
275 ¤t_window;
276 Irssi::command( "$SET{'intrairssi'} clear" );
277 &mpdbar_refresh; # Impatience
278 &set_active;
279 }
280
281 sub clearAddAllPlay {
282 &read_settings;
283 ¤t_window;
284 Irssi::command( "$SET{'intrairssi'} clear && $SET{'intrashell'} add \"\" && $SET{'intrashell'} play" );
285 &mpdbar_refresh; # Impatience
286 &set_active;
287 }
288
289 sub clearAddAllShufflePlay {
290 &read_settings;
291 ¤t_window;
292 Irssi::command( "$SET{'intrairssi'} clear && $SET{'intrashell'} add \"\" && $SET{'intrashell'} shuffle && $SET{'intrashell'} play" );
293 &mpdbar_refresh; # Impatience
294 &set_active;
295 }
296
297 sub clearAddPlay {
298 if ($_[0]) {
299 &read_settings;
300 my $j;
301 ¤t_window;
302 if ($_[0] =~ /^album\s/ or $_[0]=~ /^filename\s/ or $_[0]=~ /^title\s/ or $_[0]=~ /^artist\s/ ) {
303 my @i = split / /, $_[0];
304 $j = $i[0];
305 $_[0] =~ s/^(\w+)\s//;
306 } else {
307 $j = "filename";
308 }
309 Irssi::command( "$SET{'intrairssi'} clear && $SET{'intrashell'} search $j \Q$_[0]\E | $SET{'intrashell'} add && $SET{'intrashell'} play" );
310 &mpdbar_refresh; # Impatience
311 &set_active;
312 } else {
313 print "%W/mcap (clear add play) (album|artist|filename|title) {search term} {search term}..%w";
314 print " - Search for {search term} and automagically add it to the end of the queue";
315 print " - This command does not support play number. (it doesn't make sense)";
316 print " - If not specified it will use filename by default";
317 }
318 }
319
320 sub clearAddShufflePlay {
321 if ($_[0]) {
322 &read_settings;
323 my $j;
324 ¤t_window;
325 if ($_[0] =~ /^album\s/ or $_[0]=~ /^filename\s/ or $_[0]=~ /^title\s/ or $_[0]=~ /^artist\s/ ) {
326 my @i = split / /, $_[0];
327 $j = $i[0];
328 $_[0] =~ s/^(\w+)\s//;
329 } else {
330 $j = "filename";
331 }
332 Irssi::command( "$SET{'intrairssi'} clear && $SET{'intrashell'} search $j \Q$_[0]\E | $SET{'intrashell'} add && $SET{'intrashell'} shuffle && $SET{'intrashell'} play" );
333 &mpdbar_refresh; # Impatience
334 &set_active;
335 } else {
336 print "%W/mcasp (clear add shuffle play) (album|artist|filename|title) {search term} {search term}..%w";
337 print " - Search for {search term} and automagically add it to the end of the queue";
338 print " - This command does not support play number. (it doesn't make sense)";
339 print " - If not specified it will use filename by default";
340 }
341 }
342
343 sub clearback {
344 &read_settings;
345 &song_count;
346 ¤t_window;
347 Irssi::command( "$SET{'intrairssi'} del $COUNT{'sr1'}" );
348 &set_active;
349 }
350
351 sub crossfade {
352 &read_settings;
353 if ($_[0] =~ m/\d{1-4}/) {
354 ¤t_window;
355 Irssi::command( "$SET{'intrairssi'} crossfade $_[0]" );
356 &mpdbar_refresh; # Impatience
357 &set_active;
358 } else {
359 print "%W/mcrossfade <num> %w- Number of seconds to crossfade between songs";
360 }
361 }
362
363 sub current_status{
364 &read_settings;
365 ¤t_window;
366 my $i = `$SET{'intrashell'}`;
367 chomp($i);
368 $SET{'active'}->print( $i );
369 &set_active;
370 return;
371 }
372
373 sub current_window {
374 $SET{'active'} = Irssi::active_win();
375 if (! $SET{'current'}) {
376 Irssi::window_find_refnum($SET{'output'})->set_active;
377 }
378 }
379
380 sub delete {
381 if($_[0]) {
382 my (@i,$j,$k);
383 @i = split / /, $_[0];
384 $j = shift(@i);
385
386 &read_settings;
387 ¤t_window;
388 # You may ask why? This is for the future when del (hopefully) has useful output
389 $k = "$SET{'intrairssi'} playlist | grep \"$j\" | $SET{'intrashell'} del";
390 $_[0] =~ s/^(\w+)\s//;
391 $k = "$k && $SET{'intrashell'} playlist | grep \"$_[0]\" | $SET{'intrashell'} del";
392 Irssi::command( "$k" );
393 &set_active;
394 } else {
395 print"%W/mdel {search term} {search term}..%w";
396 print" - Search for {search term} and automagically";
397 print" - delete it from the queue";
398 }
399 }
400
401 sub iMPD_help {
402 my $mpd_help = <<MPD_HELP;
403 %r---=[ %WMusic Control Commands %r]=---%w
404 %W/mmute %w- Mutes/Unmutes the volume
405 %W/mnext %w- Starts playing next song on playlist
406 %W/mpause %w- Pauses playing
407 %W/mplay <number> %w- Starts MPD (with optional number of song
408 to start on)
409 %W/mprev %w- Previous Song
410 %W/mstop <minutes> <m|h|d> %w- Stops the current playlist,
411 options are minutes, hours and days, seconds
412 are the default
413 %W/mupdate %w- Update MPD Database
414 %W/mvolume <value> (0-100) %w- Sets the volume on the OSS mixer
415 to <value> (0-100)
416
417 %r---=[ %WSearch Commands %r]=---%w
418 %W/madd (album|artist|filename|title) {search term} {search term} ..%w
419 %w- Search for {search term} and automagically
420 add it to the end of the queue, upto 5 search terms
421 - If not specified it will use filename by default
422 %W/mdel {search term} {search term} ..%w
423 %w- Search for {search term} and automagically
424 delete it from the queue
425 %W/msearch (album|artist|filename|title) {search term} {search term}..%w
426 %w- Search for {search term}
427 - If not specified it will use filename by default
428
429 %r---=[ %WNavigation/Playlist Commands %r]=---%w
430 %W/maddall %w- Add all known music to the playlist
431 %W/mclear %w- Clear the current playlist
432 %W/mclearback %w- Clears all songs before the current playing song
433 %W/mcrossfade <num> %w- Number of seconds to crossfade between songs
434 %W/mls [<directory>] %w- Lists all files/folders in <directory>
435 %W/mmove <num> <num> %w- Move song on playlist
436 %W/mplaylist <range> %w- Print entire playlist if there's no range
437 - Otherwise will print the range (i.e. 1-10)
438 %W/mplaylistls %w- List available playlists
439 %W/mplaylistload <file> %w- Load playlist <file>
440 %W/mplaylistrm <file> %w- Remove (delete) playlist <file>
441 %W/mplaylistsave <file> %w- Save playlist <file>
442 %W/mpls {search term} {search term}...%w
443 %w- Playlist search {search term}
444 %W/mseek <num> %w- Seeks to the spot specified for the current file, in terms of percent time (0-100)
445 %W/mshuffle %w- Shuffle the MPD playlist
446 %W/mrandom %w- Play the playlist randomly
447 %W/mwipe %w- Remove all songs but the one currently playing
448
449 %r---=[ %WMiscellaneous Commands %r]=---%w
450 %W/mhelp %w- This screen
451 %W/mloud %w- Show everyone in the current window the MPD stats
452 %W/mlouder %w- Show everyone in the current window the MPD stats
453 *use with caution*
454 %W/minfo %w- Show MPD Status in the status window
455 %W/mrm <num> <num>.. %w- Remove song from the current playlist (by number
456 %w- or number range)
457 See Also: /mhelpadv
458 /mhelpmpdbar
459 /set mpd_host mpd_port
460 /set mpd_current_window mpd_output_window (EXPERIMENTAL)
461 MPD_HELP
462 print $mpd_help;
463 }
464
465 sub iMPD_helpAdv{
466 my $mpd_help_advanced = <<MPD_HELP_ADVANCED;
467 %r---=[ %WCombination Commands %r]=---%w
468 These do not take play arguments.
469 %W/map {search term} {search term} .. %w- Add, Play
470 %W/maap %w- Addall, Play
471 %W/maasp %w- Addall, Shuffle, Play
472 %W/mas {search term} {search term} .. %w- Add, Shuffle
473 %W/masp {search term} {search term} .. %w- Add, Shuffle, Play
474 %W/mcap {search term} {search term} .. %w- Clear, Add, Play
475 %W/mcaap %w- Clear, Addall, Play
476 %W/mcaasp %w- Clear, Addall, Shuffle, Play
477 %W/mcasp {search term} {search term} .. %w- Clear, Add, Shuffle, Play
478 %W/mwa {search term} {search term} .. %w- Wipe, Add,
479 %W/mwaa %w- Wipe, Addall
480 %W/mwaas %w- Wipe, Addall, Shuffle
481 %W/mwas {search term} {search term} .. %w- Wipe, Add, Shuffle
482
483 See Also: /set mpd_port mpd_host
484 /set mpd_current_window mpd_output_window (EXPERIMENTAL)
485 MPD_HELP_ADVANCED
486 print $mpd_help_advanced;
487 }
488
489 sub load_settings {
490 my ($file) = Irssi::get_irssi_dir."/iMPD.conf";
491
492 open CONF, "< $file";
493 while (<CONF>) {
494 my($net,$val) = split;
495 if ($net && $val) {
496 $SAVE_VARS{$net} = $val;
497 }
498 close CONF;
499 }
500 }
501
502 # For those who want to be loud/annoying :)
503 sub loud {
504 &read_settings;
505 my ($i,$j);
506 my @split = `$SET{'intrashell'}`;
507
508 if (! $split[1]) {
509 Irssi::print( "iMPD is not currently playing" );
510 return;
511 }
512
513 $i = basename $split[0];
514 $i =~ s/[_]/ /g;
515 # Feel free to put your personal PERL regexps here ;p
516 # Experiment with these to do some wicked stuff to your loud output.
517 # $i =~ s/.mp3//ig;
518 # $i =~ s/.flac//ig;
519 # $i =~ s/.flc//ig;
520 # $i =~ s/.ogg//ig;
521 # $i =~ s/^\p{0,2}//;
522 # $i =~ s/[.]//g;
523 $i = substr($i,0,-1);
524
525 Irssi::active_win->command( "/me is listening to $i" );
526 close Reader;
527 }
528
529 sub louder {
530 &read_settings;
531 my @split=`$SET{'intrashell'}`;
532 chomp(@split);
533 Irssi::active_win->command( "/say $split[0]" );
534 Irssi::active_win->command( "/say $split[1]" );
535 Irssi::active_win->command( "/say $split[2]" );
536 close Reader;
537 }
538
539 sub ls {
540 if ($_[0]) {
541 &read_settings;
542 ¤t_window;
543 $_[0] =~ "\Q$_[0]\E";
544 $_[0] =~ s/^\\//; # Rid of beginning / it doesn't delimit correctly.
545 $_[0] =~ s/\///; # Help out the degenerates.
546 Irssi::command( "$SET{'intrairssi'} ls " . "\Q$_[0]\E" );
547 &set_active;
548 } else {
549 print "%W/mls [<directory>] %w- Lists all files/folders in <directory>.";
550 }
551 }
552
553 sub lsplaylists {
554 &read_settings;
555 ¤t_window;
556 Irssi::command( "$SET{'intrairssi'} lsplaylists" );
557 &set_active;
558 }
559
560 sub move {
561 &read_settings;
562 if ($_[0] =~ m/\d{1,2}\s{1,2}/) {
563 ¤t_window;
564 Irssi::command( "$SET{'intrairssi'} move $_[0]" );
565 &mpdbar_refresh; # Impatience
566 &set_active;
567 } else {
568 print "%W/mmove <num> <num> %w- Move song on playlist";
569 }
570 }
571
572 sub mpdbar_help {
573 my $mpdbarhelp = <<MPDBAR_HELP;
574 mpdbar was made to be a simple way to get your statusbar up and
575 to hide it when it's not playing. If you feel that I'm not being
576 flexable enough in my choices you're free to setup a statusbar
577 without these commands or present me with an idea for a new
578 mpdbar command. But the current ones are:
579
580 /set mpdbar_bottom on -
581 This command will (obviously) display a mpdbar on the bottom.
582
583 /set mpdbar_refresh <num> -
584 This command will set the refresh in seconds, it defaults to
585 5 seconds, you might be able to set it higher although I don't
586 recommend setting it higher if your mpd server is across a
587 network (of any kind ;p).
588
589 /set mpdbar_top on
590 This command will (obviously) display a mpdbar on the top.
591
592 /set mpdbar_window on
593 This command will (not-so-obviously) display a mpdbar next to your
594 current window statusbar.
595 MPDBAR_HELP
596 print $mpdbarhelp;
597 }
598
599 sub mpdbar_get_stats {
600 ### Variable map ###
601 # $SET{'stat_time'}-Time/Percent(change)
602 # $SET{'stat_current'}-Status(change)
603 # $SET{'songbase'}-basename filename
604 if(Irssi::settings_get_bool('mpdbar_bottom') or
605 Irssi::settings_get_bool('mpdbar_top') or
606 Irssi::settings_get_bool('mpdbar_window')) {
607 &read_settings;
608
609 ($SET{'stat1'},$SET{'stat2'},$SET{'stat3'}) = undef;
610 ($SET{'stat1'},$SET{'stat2'},$SET{'stat3'}) = `$SET{'intrashell'}`;
611 chomp($SET{'stat1'},$SET{'stat2'},$SET{'stat3'});
612
613 if ($SET{'stat2'} =~ m/(\d{1,5}\:\d{1,2}\s\(\d{1,3}\%\))/) {
614 $SET{'stat_time'} = $1;
615 }
616 if ($SET{'stat2'} =~ m/\[(\w+)\]/) {
617 $SET{'stat_current'} = $1;
618 }
619 if($SET{'stat2'} and $SET{'stat1'} =~ m/\//g) { # Not sure if this will have an effect :/
620 $SET{'songbase'} = basename $SET{'stat1'};
621 } else {
622 $SET{'songbase'} = $SET{'stat1'};
623 }
624 }
625 }
626
627 sub mpdbar_refresh {
628 if(Irssi::settings_get_bool('mpdbar_bottom') or
629 Irssi::settings_get_bool('mpdbar_top') or
630 Irssi::settings_get_bool('mpdbar_window')) {
631 &mpdbar_get_stats;
632 if (Irssi::settings_get_bool('mpdbar_bottom') and Irssi::settings_get_bool('mpdbar_top')) {
633 Irssi::print( "Have not implemented ability to mpdbar top and bottom at the same time" );
634 Irssi::print( "That's fine though, I'll just set it to the bottom for you for now" );
635 Irssi::settings_set_bool('mpdbar_bottom',1);
636 Irssi::settings_set_bool('mpdbar_top',0);
637 }
638 if (Irssi::settings_get_bool('mpdbar_window') and $SET{'stat2'}) {
639 $ENABLED{'window'} = "1";
640 Irssi::command( "statusbar window add mpdbar" );
641 Irssi::command( "statusbar window enable mpdbar" );
642 } else {
643 if($ENABLED{'window'} == 1) {
644 Irssi::command( "statusbar window remove mpdbar" );
645 $ENABLED{'window'} = 0;
646 }
647 }
648 if (Irssi::settings_get_bool('mpdbar_bottom') and $SET{'stat2'} and ! $ENABLED{'top'}) {
649 $ENABLED{'bottom'} = "1";
650 Irssi::command( "statusbar mpdbar placement bottom" );
651 Irssi::command( "statusbar mpdbar position 2" );
652 Irssi::command( "statusbar mpdbar enable" );
653 Irssi::command( "statusbar mpdbar add mpdbar" );
654 Irssi::command( "statusbar mpdbar visible active" );
655 } else {
656 if($ENABLED{'bottom'} == 1){
657 Irssi::command( "statusbar mpdbar remove mpdbar" );
658 Irssi::command( "statusbar mpdbar disable" );
659 $ENABLED{'bottom'} = 0;
660 }
661 }
662 if (Irssi::settings_get_bool('mpdbar_top') and $SET{'stat2'} and ! $ENABLED{'bottom'}) {
663 $ENABLED{'top'} = "1";
664 Irssi::command( "statusbar mpdbar placement top" );
665 Irssi::command( "statusbar mpdbar position 2" );
666 Irssi::command( "statusbar mpdbar enable" );
667 Irssi::command( "statusbar mpdbar add mpdbar" );
668 Irssi::command( "statusbar mpdbar visible active" );
669 } else {
670 if($ENABLED{'top'} == 1){
671 Irssi::command( "statusbar mpdbar remove mpdbar" );
672 Irssi::command( "statusbar mpdbar disable" );
673 $ENABLED{'top'} = 0;
674 }
675 }
676 }
677 }
678
679 sub mpdbar_setup {
680 my ($item, $get_size_only) = @_;
681 if (! $SET{'stat2'}) { # If it's not on
682 $item->default_handler($get_size_only, undef, "$SET{'stat2'}", 1);
683 } else {
684 $SET{'stat_current'} =~ s/$SET{'stat_current'}/\u\L$SET{'stat_current'}/;
685 $item->default_handler($get_size_only, undef, "$SET{'stat_current'} $SET{'songbase'} $SET{'stat_time'}", 1);
686 }
687 }
688
689 sub mute {
690 &read_settings;
691 ¤t_window;
692
693 my @i = `$SET{'intrashell'}`;
694 my $j;
695 # This next conditional is for when the music is not playing
696 if (exists $i[2]) {
697 $j = $i[2];
698 } else {
699 $j = $i[0];
700 }
701 if ($j =~ m/volume\:\s{0,2}(\d{1,3})\%/) {
702 $j = $1;
703 }
704
705 if ($j != 0 and ! $SAVE_VARS{'muted'} == 0) {
706 print "Warning: Not currently muted, although it said it was";
707 delete $SAVE_VARS{'muted'}
708 }
709 if ($j == 0 and ! $SAVE_VARS{'muted'}) {
710 print "Error: Volume is currently muted, but I don't know how it got there. Manually set the volume please.";
711 delete $SAVE_VARS{'muted'};
712 }
713 if (!$SAVE_VARS{'muted'}) {
714 $SAVE_VARS{'muted'} = $j;
715 `$SET{'intrashell'} volume 0`;
716 print "Sound is muted, to unmute just hit /mmute again";
717 } else {
718 `$SET{'intrashell'} volume $SAVE_VARS{'muted'}`;
719 print "Reset the volume back to it's originial position ($SAVE_VARS{'muted'}%)";
720 delete $SAVE_VARS{'muted'};
721 }
722 }
723
724 sub next {
725 &read_settings;
726 ¤t_window;
727 Irssi::command( "$SET{'intrairssi'} next" );
728 &set_active;
729 &mpdbar_refresh; # Impatience
730 }
731
732 sub pause {
733 &read_settings;
734 ¤t_window;
735 Irssi::command( "$SET{'intrairssi'} pause" );
736 &mpdbar_refresh; # Impatience
737 &set_active;
738 }
739
740 sub play {
741 &read_settings;
742 my $i;
743 ¤t_window;
744 if ($_[0] =~ m/\d{1,6}/) {
745 $i = $_[0];
746 }
747 Irssi::command( "$SET{'intrairssi'} play $i" );
748 &mpdbar_refresh; # Impatience
749 &set_active;
750 }
751
752 sub playlist {
753 &read_settings;
754 my @playlist;
755 if ($_[0] =~ m/\d{1,6}\-\d{1,6}/) {
756 my ($head,$tail);
757 my @playlist = `$SET{'intrashell'} playlist`;
758 ($head, $tail) = split /-/, $_[0];
759
760 # OK, just understand I'm here for you if you're
761 # tired enough to let this happen to you.
762 if($head > $tail) {
763 my $i;
764 $i = $head;
765 $head = $tail;
766 $tail = $i;
767 }
768
769 $head =~ $head--;
770 $tail = $tail - $head;
771 chomp $head;
772 chomp $tail;
773
774 @playlist = splice(@playlist,$head,$tail);
775 my $i = pop(@playlist);
776 chomp $i;
777 push (@playlist,$i);
778 print @playlist;
779 } else {
780 ¤t_window;
781 Irssi::command( "$SET{'intrairssi'} playlist" );
782 &set_active;
783 }
784 }
785
786 sub playlist_load {
787 if ($_[0]) {
788 &read_settings;
789 ¤t_window;
790 Irssi::command( "$SET{'intrairssi'} load \Q$_[0]\E" );
791 &set_active;
792 } else {
793 print "%W/mplaylistload <file> %w- Load playlist <file>";
794 }
795 }
796
797 sub playlist_remove {
798 if ($_[0]) {
799 &read_settings;
800 ¤t_window;
801 Irssi::command( "$SET{'intrairssi'} rm \Q$_[0]\E" );
802 &set_active;
803 }
804 }
805
806 sub playlist_save {
807 if ($_[0]) {
808 &read_settings;
809 ¤t_window;
810 Irssi::command( "$SET{'intrairssi'} save \Q$_[0]\E" );
811 &set_active;
812 } else {
813 print "%W/mplaylistsave <file> %w- Save playlist <file>";
814 }
815 }
816
817 sub playlistsearch {
818 if ($_[0]) {
819 &read_settings;
820 my @i = split / /, $_[0];
821 ¤t_window;
822 foreach(@i) {
823 Irssi::command( "$SET{'intrairssi'} playlist | grep $_" );
824 }
825 &set_active;
826 } else {
827 print "%W/pls {search term} {search term}..%w";
828 print " - Search for {search term} and automagically and show the playlist entry";
829 }
830 }
831
832 sub previous {
833 &read_settings;
834 ¤t_window;
835 Irssi::command( "$SET{'intrairssi'} prev" );
836 &mpdbar_refresh; # Impatience
837 &set_active;
838 }
839
840 sub random{
841 &read_settings;
842 ¤t_window;
843 Irssi::command( "$SET{'intrairssi'} random" );
844 &set_active;
845 }
846
847 sub read_settings {
848 ($SET{'mbar_time'}) && Irssi::timeout_remove($SET{'mbar_time'});
849 $SET{'mbar_time'}=Irssi::timeout_add(Irssi::settings_get_int('mpdbar_refresh') * 1000, 'mpdbar_refresh', undef);
850
851 $SET{'current'} = Irssi::settings_get_bool('current_window');
852 $SET{'output'} = Irssi::settings_get_int('output_window');
853
854 if (Irssi::settings_get_int( "mpd_port" )) {
855 $SET{'port'} = Irssi::settings_get_int( "mpd_port" );
856 $SET{'port'} = "MPD_PORT=$SET{'port'}"
857 }
858 if (Irssi::settings_get_str( "mpd_host" )) {
859 $SET{'host'} = Irssi::settings_get_str( "mpd_host" );
860 $SET{'host'} = "MPD_HOST=$SET{'host'}"
861 }
862 my $MPC_BIN;
863 if ( ! -x $SET{'mpc_override'} ) {
864 my @paths = split/:/,$ENV{'PATH'};
865
866 foreach(@paths) {
867 my $path = $_;
868 if( -x "$path" . "/" . "mpc" ) {
869 $MPC_BIN = "$path/mpc";
870 }
871 }
872 } else {
873 $MPC_BIN = $SET{'mpc_override'};
874 }
875
876 if (! $MPC_BIN) {
877 print "mpc was not found in any of the known paths";
878 print "mpc is required to use this script, please download it from http://musicpd.org/files.php";
879 }
880
881 $SET{'intrashell'} = "$SET{'port'} $SET{'host'} $MPC_BIN";
882 $SET{'intrairssi'} = "exec - $SET{'intrashell'}";
883 }
884
885 sub repeat {
886 &read_settings;
887 ¤t_window;
888 Irssi::command( "$SET{'intrairssi'} repeat" );
889 &set_active;
890 }
891
892 sub remove_song {
893 &read_settings;
894 if ($_[0] =~ m/\d{1,6}/ or $_[0] =~ m/\d{1,6}\-\d{1,6}/) {
895 ¤t_window;
896 Irssi::command( "$SET{'intrairssi'} del $_[0]" );
897 &mpdbar_refresh; # Impatience
898 &set_active;
899 } else {
900 print "%W/mrm <num> <num>.. %w- Remove song from the current playlist (by number)";
901 print "%w - Note that <num> can be a range also";
902 }
903 }
904
905 sub search {
906 if ($_[0]) {
907 &read_settings;
908 my $j;
909 ¤t_window;
910 if ($_[0] =~ /^album\s/ or $_[0]=~ /^filename\s/ or $_[0]=~ /^title\s/ or $_[0]=~ /^artist\s/ ) {
911 my @i = split / /, $_[0];
912 $j = $i[0];
913 $_[0] =~ s/^(\w+)\s//;
914 } else {
915 $j = "filename";
916 }
917 Irssi::command( "$SET{'intrairssi'} search $j \Q$_[0]\E" );
918 &set_active;
919 } else {
920 print "%W/search (album|artist|filename|title) {search term} {search term}..%w";
921 print " - Search for {search term} and automagically add it to the end of the queue";
922 print " - If not specified it will use filename by default";
923 }
924 }
925
926 sub seek {
927 &read_settings;
928 if ($_[0] =~ m/\d{1-3}/) {
929 ¤t_window;
930 Irssi::command( "$SET{'intrairssi'} seek $_[0]" );
931 &mpdbar_refresh; # Impatience
932 &set_active;
933 } else {
934 print "%W/mseek <num> %w- Seeks to the spot specified for the current file, in terms of percent time (0-100)";
935 }
936 }
937
938 sub set_active {
939 if (! $SET{'current'}) {
940 $SET{'active'}->set_active;
941 }
942 }
943
944 sub shuffle{
945 &read_settings;
946 ¤t_window;
947 Irssi::command( "$SET{'intrairssi'} shuffle" );
948 &set_active;
949 }
950
951 sub song_count {
952 %COUNT = undef;
953
954 my @counts = `$SET{'intrashell'}`;
955 chomp(@counts);
956
957 if ($counts[1] =~ m/\#(\d{1,6})\//) {
958 $COUNT{'song'} = $1;
959 }
960 if ($counts[1] =~ m/\/(\d{1,6})\s/) {
961 $COUNT{'playlist'} = $1;
962 }
963 if ($COUNT{'song'} > 1) {
964 my $i = $COUNT{'song'} - 1;
965 $COUNT{'sr1'} = "1-$i";
966 }
967 if ($COUNT{'song'} < $COUNT{'playlist'}){# and $COUNT{'song'} != $COUNT{'playlist'}) {
968 my $i = $COUNT{'song'} + 1;
969 $COUNT{'sr2'} = "$i-$COUNT{'playlist'}";
970 }
971 }
972
973 sub stop {
974 &read_settings;
975 my ($i,$time);
976 if ($_[0]) {
977 my $unit;
978 ($time, $unit) = split / /, $_[0];
979 if ($unit =~ /minute/i or $unit =~ /minutes/i) {
980 $time = ($time * 60);
981 }
982 if ($unit =~ /hour/i or $unit =~ /hours/i) {
983 $time = ($time * 86400);
984 }
985 #ok. it's ridiculous to use this script for days, but in any case here ya go.
986 if ($unit =~ /day/i or $unit =~ /days/i) {
987 $time = ($time * 2073600);
988 }
989 $time = $time . "s";
990 $i = "exec - /bin/sleep $time && $SET{'intrashell'} stop";
991 } else {
992 $i = "$SET{'intrairssi'} stop";
993 }
994 ¤t_window;
995 Irssi::command( "$i" );
996 &mpdbar_refresh; # Impatience
997 &set_active;
998 }
999
1000 sub update {
1001 &read_settings;
1002 ¤t_window;
1003 Irssi::command( "$SET{'intrairssi'} update" );
1004 Irssi::print( "Irssi will not be accepting commands while updating" );
1005 &set_active;
1006 }
1007
1008 sub volume {
1009 &read_settings;
1010 ¤t_window;
1011 my (@i,$j);
1012 if ($_[0] =~ m/\d{1,3}/) {
1013 @i = `$SET{'intrashell'} volume $_[0]`;
1014 } else {
1015 @i = `$SET{'intrashell'}`;
1016 }
1017 # This next conditional is for when the music is not playing
1018 if (exists $i[2]) {
1019 $j = $i[2];
1020 } else {
1021 $j = $i[0];
1022 }
1023 if ($j =~ m/volume\:\s{0,2}(\d{1,3})\%/) {
1024 $j = $1;
1025 }
1026 # OK, if anyone wants to tell me _why_ this seems to be the only way
1027 # to get a "%" on the end please feel free (suspected to be due to
1028 # color codes
1029 if ($_[0]) {
1030 Irssi::print( "The volume is at $j%" . "%" );
1031 } else {
1032 $SET{'active'}->print( "The volume is at $j%" . "%" );
1033 }
1034 &set_active;
1035 }
1036
1037 sub wipe {
1038 &read_settings;
1039 ¤t_window;
1040 &song_count;
1041 if($COUNT{'sr1'} or $COUNT{'sr2'}) {
1042 Irssi::command( "$SET{'intrairssi'} del $COUNT{'sr1'} $COUNT{'sr2'}" );
1043 } else {
1044 Irssi::print( "Can't wipe when there's only one song in the playlist" );
1045 }
1046 &set_active;
1047 }
1048
1049 sub wipeAdd{
1050 if ($_[0]) {
1051 &read_settings;
1052 &song_count;
1053 my $j;
1054 if ($_[0] =~ /^album\s/ or $_[0]=~ /^filename\s/ or $_[0]=~ /^title\s/ or $_[0]=~ /^artist\s/ ) {
1055 my @i = split / /, $_[0];
1056 $j = $i[0];
1057 $_[0] =~ s/^(\w+)\s//;
1058 } else {
1059 $j = "filename";
1060 }
1061 ¤t_window;
1062 if($COUNT{'sr1'} or $COUNT{'sr2'}) {
1063 Irssi::command( "$SET{'intrairssi'} del $COUNT{'sr1'} $COUNT{'sr2'} && $SET{'intrashell'} search $j \Q$_[0]\E | $SET{'intrashell'} add" );
1064 } else { # Do the thinking for the person
1065 Irssi::command( "$SET{'intrairssi'} search $j \Q$_[0]\E | $SET{'intrashell'} add" );
1066 }
1067 &set_active;
1068 } else {
1069 print "%W/mwa (wipe add) (album|artist|filename|title) {search term} {search term}..%w";
1070 print " - Search for {search term} and automagically add it to the end of the queue";
1071 print " - This command does not support play number. (it doesn't make sense)";
1072 print " - If not specified it will use filename by default"
1073 }
1074 }
1075
1076 sub wipeAddall{
1077 &read_settings;
1078 &song_count;
1079 ¤t_window;
1080 if($COUNT{'sr1'} or $COUNT{'sr2'}) {
1081 Irssi::command( "$SET{'intrairssi'} del $COUNT{'sr1'} $COUNT{'sr2'} && $SET{'intrashell'} add \"\"" );
1082 } else {
1083 Irssi::command( "$SET{'intrairssi'} add \"\"" );
1084 }
1085 &set_active;
1086 }
1087
1088 sub wipeAddallShuffle{
1089 &read_settings;
1090 &song_count;
1091 ¤t_window;
1092 if($COUNT{'sr1'} or $COUNT{'sr2'}) {
1093 Irssi::command( "$SET{'intrairssi'} del $COUNT{'sr1'} $COUNT{'sr2'} && $SET{'intrashell'} add \"\" && $SET{'intrashell'} shuffle" );
1094 } else {
1095 Irssi::command( "$SET{'intrairssi'} add \"\" && $SET{'intrashell'} shuffle" );
1096 }
1097 &set_active;
1098 }
1099
1100 sub wipeAddShuffle{
1101 if ($_[0]) {
1102 &read_settings;
1103 my $j;
1104 if ($_[0] =~ /^album\s/ or $_[0]=~ /^filename\s/ or $_[0]=~ /^title\s/ or $_[0]=~ /^artist\s/ ) {
1105 my @i = split / /, $_[0];
1106 $j = $i[0];
1107 $_[0] =~ s/^(\w+)\s//;
1108 } else {
1109 $j = "filename";
1110 }
1111 &song_count;
1112 ¤t_window;
1113 if($COUNT{'sr1'} or $COUNT{'sr2'}) {
1114 Irssi::command( "$SET{'intrairssi'} del $COUNT{'sr1'} $COUNT{'sr2'} && $SET{'intrashell'} search $j \Q$_[0]\E | $SET{'intrashell'} add && $SET{'intrashell'} shuffle" );
1115 } else {
1116 Irssi::command( "$SET{'intrairssi'} search $j \Q$_[0]\E | $SET{'intrashell'} add && $SET{'intrashell'} shuffle" );
1117 }
1118 &set_active;
1119 } else {
1120 print "%W/mwas (wipe add shuffle) (album|artist|filename|title) {search term} {search term}..%w";
1121 print " - Search for {search term} and automagically add it to the end of the queue";
1122 print " - This command does not support play number. (it doesn't make sense)";
1123 print " - If not specified it will use filename by default";
1124 }
1125 }
1126 Irssi::settings_add_int('misc', 'mpdbar_refresh', '5');
1127
1128 &load_settings;
1129 &mpdbar_refresh;
1130
1131 Irssi::command_bind madd => \&add;
1132 Irssi::command_bind maddall => \&addall;
1133 # Irssi::command_bind maddnext => \&addNext;
1134 Irssi::command_bind maap => \&addallPlay;
1135 Irssi::command_bind maasp => \&addallShufflePlay;
1136 Irssi::command_bind mas => \&addShuffle;
1137 Irssi::command_bind masp => \&addShufflePlay;
1138 Irssi::command_bind map => \&addPlay;
1139 Irssi::command_bind mclear => \&clear;
1140 Irssi::command_bind mclearback => \&clearback;
1141 Irssi::command_bind mcaap => \&clearAddAllPlay;
1142 Irssi::command_bind mcaasp => \&clearAddAllShufflePlay;
1143 Irssi::command_bind mcap => \&clearAddPlay;
1144 Irssi::command_bind mcasp => \&clearAddShufflePlay;
1145 Irssi::command_bind mdel => \&delete;
1146 Irssi::command_bind mls => \&ls;
1147 Irssi::command_bind mhelp => \&iMPD_help;
1148 Irssi::command_bind mhelpadv => \&iMPD_helpAdv;
1149 Irssi::command_bind minfo => \¤t_status;
1150 Irssi::command_bind mloud => \&loud;
1151 Irssi::command_bind mlouder => \&louder;
1152 Irssi::command_bind mmute => \&mute;
1153 Irssi::command_bind mnext => \&next;
1154 Irssi::command_bind mpause => \&pause;
1155 Irssi::command_bind mhelpmpdbar => \&mpdbar_help;
1156 Irssi::command_bind mmove => \&move;
1157 Irssi::command_bind mplay => \&play;
1158 Irssi::command_bind mplaylist => \&playlist;
1159 Irssi::command_bind mpls => \&playlistsearch;
1160 Irssi::command_bind mplaylistls => \&lsplaylists;
1161 Irssi::command_bind mplaylistload => \&playlist_load;
1162 Irssi::command_bind mplaylistrm => \&playlist_remove;
1163 Irssi::command_bind mplaylistsave => \&playlist_save;
1164 Irssi::command_bind mprev => \&previous;
1165 Irssi::command_bind mrandom => \&random;
1166 Irssi::command_bind mrepeat => \&repeat;
1167 Irssi::command_bind mrm => \&remove_song;
1168 Irssi::command_bind mseek => \&seek;
1169 Irssi::command_bind msearch => \&search;
1170 Irssi::command_bind mshuffle => \&shuffle;
1171 Irssi::command_bind mstop => \&stop;
1172 Irssi::command_bind mupdate => \&update;
1173 Irssi::command_bind mvolume => \&volume;
1174 Irssi::command_bind mwa => \&wipeAdd;
1175 Irssi::command_bind mwaa => \&wipeAddall;
1176 Irssi::command_bind mwaas => \&wipeAddallShuffle;
1177 Irssi::command_bind mwas => \&wipeAddShuffle;
1178 Irssi::command_bind mwipe => \&wipe;