1use strict;
2use Irssi;
3use Irssi::TextUI;
4use vars qw($VERSION %IRSSI);
5use Xmms;
6use Xmms::Remote ();
7
8#changed to recommended version system with onedigit.twodigits, sorry :)
9$VERSION = '2.01';
10%IRSSI = (
11	authors => 'Mikachu',
12	contact => 'Mikachu @ quakenet|freenode|arcnet|oftc',
13	description => 'A script to show playing xmms song in channel or in a statusbar, and also control xmms. Be sure to read through the script to see all features.',
14	name => 'l33t xmms music showing script',
15	license => 'GPL',
16	modules => 'Bundle::Xmms',
17	sbitems => 'l33tmusic'
18);
19
20#Stuff i've added recently that i can remember:
21#
22#fixed the -c parameter, now you can do stuff like
23#/l33tmusic -c / jump_to_timestr 1:24 to jump around
24#and /l33tmusic -c / pause to pause, and /l33tmusic
25#-c /echo get_playlist_pos to echo the position :)
26#
27#only answers to /ctcp music if xmms is actually on
28#(if someone /ctcp music nick 2 it will show your current+2
29#song in playlist as currently playing instead of saying
30#that it is the second next song, oh well :)
31#
32#some stuff now take a numerical argument as an offset
33#to the current position in the playlist
34#
35#Stuff i've added that i can't remember:
36#
37#if you expected to find something here you weren't thinking
38#look below for stuff
39
40#this function from nickcolor.pl
41my @colors = qw/2 3 4 5 6 7 9 10 11 12 13/;
42sub simple_hash {
43  my ($string) = @_;
44  chomp $string;
45  my @chars = split //, $string;
46  my $counter;
47
48  foreach my $char (@chars) {
49    $counter += ord $char;
50  }
51
52  $counter = $colors[$counter % 11];
53
54  return $counter;
55}
56
57sub getvars {
58	if ($_[0] =~ "songinfo") {
59		my ($position, $title, $time, $status, $filename);
60		my $xmmscontrol = Xmms::Remote->new;
61		my $wantedpos = $_[0];
62		$wantedpos =~ s/songinfo //;
63		unless ($wantedpos =~ /^-?\d+$/ && (( $wantedpos + $xmmscontrol->get_playlist_pos <= $xmmscontrol->get_playlist_length-1 && $wantedpos >= 0) || 0-$wantedpos <= $xmmscontrol->get_playlist_pos && $wantedpos <= 0) ) {
64			$wantedpos = 0;
65		}
66		my $wantedpos = $xmmscontrol->get_playlist_pos + $wantedpos;
67		$title = $xmmscontrol->get_playlist_title($wantedpos);
68		my $seconds = ($xmmscontrol->get_output_time/1000)%60;
69		my $tmp = length($seconds);
70		if($tmp == "1") {
71			$seconds = "0" . $seconds;
72		}
73		$position = int($xmmscontrol->get_output_time/60000) . ":" . $seconds;
74		$time = $xmmscontrol->get_playlist_timestr($wantedpos);
75		if ($xmmscontrol->is_playing) {
76			if ($xmmscontrol->is_paused) {
77				$status = "Paused";
78			} else {
79				$status = "Playing";
80			}
81		} else {
82			$status = "Stopped";
83		}
84		$filename = $xmmscontrol->get_playlist_file($wantedpos);
85
86		$title =~ s/[\r\n]/ /g;
87		$filename =~ s/[\r\n]/ /g;
88
89		return($position, $title, $time, $status, $filename);
90	} elsif ($_[0] =~ "filename") {
91		my $xmmscontrol = Xmms::Remote->new;
92		my $wantedpos = $_[0];
93		$wantedpos =~ s/filename //;
94		unless ($wantedpos =~ /^-?\d+$/ && (( $wantedpos + $xmmscontrol->get_playlist_pos <= $xmmscontrol->get_playlist_length-1 && $wantedpos >= 0) || 0-$wantedpos <= $xmmscontrol->get_playlist_pos && $wantedpos <= 0) ) {
95			$wantedpos = 0;
96		}
97		$wantedpos = $xmmscontrol->get_playlist_pos + $wantedpos;
98		$filename = $xmmscontrol->get_playlist_file($wantedpos);
99		$filename =~ s/[\r\n]/ /g;
100		return($filename);
101	}
102}
103
104sub ctcp_info {
105 if (Irssi::settings_get_bool('l33tctcp_enabled') && Xmms::Remote->new->is_running) {
106	my ($server, $msg, $nick, $address, $channel) = @_;
107	my ($p, $n, $t, $s) = getvars("songinfo $msg");
108	my $reply = Irssi::settings_get_str('l33tctcpreply');
109	$reply =~ s/(\$\w+)/$1/eeg;
110	$server->command("^notice $nick $reply");
111	Irssi::statusbar_items_redraw('l33tmusic');
112 }
113}
114
115sub triggersend {
116	my $trigger = Irssi::settings_get_str('l33ttrigger');
117	if ($_[1] =~ /^$trigger/) {
118		if (Irssi::settings_get_bool('l33ttrigger_enabled')) {
119			$_[1] =~ s/$trigger //g;
120			$_[1] = getvars("filename $_[1]");
121			$_[0]->command("DCC SEND $_[2] \"$filename\"");
122		} else {
123			$_[0]->command("^notice $_[2] Trigger currently disabled");
124		}
125	}
126}
127
128sub themainthingie {
129	if (Xmms::Remote->new->is_running) {
130		my ($msg, $server, $nick, $address, $channel) = @_;
131		my $command;
132		my ($p, $n, $t, $s, $f) = getvars("songinfo 0");
133		#The -m switch will echo the info in the status window,
134		#I have this bound to meta-q :), takes a numerical argument
135		#same as the -s switch
136		if ($msg =~ "^-m") {
137			$msg =~ s/^-m //;
138			my ($p, $n, $t, $s, $f) = getvars("songinfo " . $msg);
139			print CLIENTCRAP "" . simple_hash("$n") . "$n ($p / $t)";
140			$command = "";
141		#This allows a fully customized message, to be used in
142		#aliases, since it's not fun to write the full thing every
143		#time
144		} elsif ($msg =~ "^-e") {
145			$msg =~ s/^\-e //;
146			$command = "$msg";
147		#The -c switch is now fixed mostly, it seems that you
148		#can do whatever you want, and if it happens to match
149		#a proper command such as jump_to_timestr and you pass
150		#the right parameter, it works, otherwise i made it not
151		#crash anymore, weee :)
152		} elsif ($msg =~ "^-c") {
153			$msg =~ s/^\-c //;
154			my $thingie;
155			my ($msg, $reply, $param) = split(/ /, "$msg", 3);
156			if ($param) {
157				return unless eval {
158					$thingie = Xmms::Remote->new->$reply($param);
159				}
160			} else {
161				return unless eval {
162					$thingie = Xmms::Remote->new->$reply;
163				}
164			}
165			if ($thingie) {
166				$command = "$msg $thingie";
167			}
168		#The -f switch has been removed, please use
169		#/l33tmusic -e /colme or /colsay from the
170		#ascii.pl script to get better functionality
171
172		#This switch will send the currently playing song to
173		#the nick on the command line, takes a numerical
174		#argument like the -m switch
175		} elsif ($msg =~ "^-s") {
176			$msg =~ s/^-s //;
177			(my $friend, $msg) = split " ", $msg;
178			$friend =~ s/ //;
179			my ($p, $n, $t, $s, $f) = getvars("songinfo " . $msg);
180			$server->command("dcc send $friend \"$f\"");
181		#If a string was given, put it in front of the info, and
182		#anything after a # after the info. If nothing is in front
183		#of the #, throw in the string from the settings.
184		} elsif ($msg) {
185			my $msg2;
186			$msg =~ s/(\$\w+)/$1/eeg;
187			($msg, $msg2) = split "#", $msg;
188			if ($msg =~ /^$/) {
189				$msg = Irssi::settings_get_str('l33tstringplaying');
190			}
191			$command = "me $msg $n ($p / $t) $msg2";
192		#Just go with the defaults
193		} else {
194			if ( $s eq "Playing" ) {
195				$command = Irssi::settings_get_str('l33tstringplaying');
196				$command = Irssi::settings_get_str('l33tstringaction') . " $command " . Irssi::settings_get_str('l33tstringsongformat');
197			} else {
198				$command = "echo Xmms is $s";
199			}
200		}
201		$command =~ s/(\$\w+)/$1/eeg;
202		$command =~ s/\s+/ /g;
203		if ($command) {
204			Irssi::active_win()->command("$command");
205		}
206	}else {
207		Irssi::active_win()->command("echo Xmms isn't currently running");
208	}
209}
210
211sub checkformpg123 {
212	my ($msg, $server, $witem) = @_;
213	if ($msg =~ /^Playing( MPEG stream from )?/) {
214		$msg =~ s/Playing MPEG stream from //;
215		$msg =~ s/Playing //;
216		$msg =~ s/%20/ /g;
217		$msg =~ s/\.(mp3|ogg)( \.\.\.)?//i;
218		$msg =~ s/_/ /g;
219		$msg =~ s/oc remix//i;
220		$msg = Irssi::settings_get_str('l33tstringaction') . " " . Irssi::settings_get_str('l33tstringplayingmpg123') . " $msg";
221		Irssi::signal_stop();
222		Irssi::signal_remove('send text', 'checkformpg123');
223		Irssi::signal_emit('send command', $msg, $server, $witem);
224		Irssi::signal_add('send text', 'checkformpg123');
225	}
226
227}
228
229my $statusbar_item;
230my $refresh_tag;
231my $scrollpos=0;
232sub refresh_statusbar {
233	my ($p, $no, $t, $s, $f) = getvars("songinfo 0");
234	my $width=Irssi::active_win()->{width};
235	my $n;
236	my $others = Irssi::settings_get_str('l33tstatusbar');
237	$others =~ s/\%.//g;
238	$others =~ s/\$n//g;
239	$others =~ s/(\$\w+)/$1/eeg;
240	my $maxlength=$width - length($others);
241	if (length($no) > $maxlength) {
242		my $middlethingie = Irssi::settings_get_str('l33tmiddlethingie');
243		$no = "$no $middlethingie";
244		$n=substr(substr($no, $scrollpos, length($no)) . substr($no, 0, $scrollpos), 0, $maxlength);
245		$scrollpos++;
246		$scrollpos=0 if ($scrollpos + 1 > length($no));
247	} else {
248		$n = $no;
249	}
250	$n =~ s/\%/\%\%/g;
251	$statusbar_item = Irssi::settings_get_str('l33tstatusbar');
252	$statusbar_item =~ s/(\$\w+)/$1/eeg;
253	Irssi::statusbar_items_redraw('l33tmusic');
254}
255
256sub l33tmusic_statusbar {
257	my ($item, $get_size_only) = @_;
258	$item->default_handler($get_size_only, "$statusbar_item", undef, 1);
259}
260
261
262Irssi::signal_add('send text', 'checkformpg123');
263Irssi::command_bind('l33tmusic', 'themainthingie');
264Irssi::settings_add_str('infopipe', 'l33tstringaction', '/me');
265Irssi::settings_add_str('infopipe', 'l33tstringplayingmpg123', 'is listening to');
266Irssi::settings_add_str('infopipe', 'l33tstringplaying', 'is listening to');
267Irssi::settings_add_str('infopipe', 'l33tstatusbar', '$n ($p / $t)');
268Irssi::settings_add_str('infopipe', 'l33tstatusbarrefresh', '500');
269Irssi::settings_add_str('infopipe', 'l33tmiddlethingie', '*** ');
270Irssi::settings_add_str('infopipe', 'l33tstringsongformat', '$n ($p / $t)');
271Irssi::settings_add_str('infopipe', 'l33tctcpreply', 'I\'m listening to $n ($p / $t) Status: $s');
272Irssi::settings_add_str('infopipe', 'l33ttrigger', '�yourtriggerhere');
273Irssi::settings_add_bool('infopipe', 'l33ttrigger_enabled', 0);
274Irssi::settings_add_bool('infopipe', 'l33tctcp_enabled', 0);
275Irssi::settings_add_bool('infopipe', 'l33twarning_read', 0);
276Irssi::signal_add("ctcp msg music", "ctcp_info");
277Irssi::signal_add_last("message public", "triggersend");
278Irssi::statusbar_item_register('l33tmusic', undef, 'l33tmusic_statusbar');
279$refresh_tag=Irssi::timeout_add(Irssi::settings_get_str('l33tstatusbarrefresh'), 'refresh_statusbar', undef);
280unless (Irssi::settings_get_bool('l33twarning_read')) {
281	print CLIENTCRAP "Type /set l33t to see all available settings. To remove this message, please type /set l33twarning_read on. Type /set l33t to list all options.";
282	print CLIENTCRAP "If you want statusbar, add \'l33tmusic = { placement = \"top\"; items = { l33tmusic = { }; }; };\' to your config file, above \'topic = {\', and do a /reload.";
283}
284