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