/var/www/www.irssi.org-old/scripts/html/amarok_ssh.pl
1 # amarok by Tobias 'camel69' Wulff
2
3 use strict;
4 use vars qw($VERSION %IRSSI);
5 $VERSION = "1.0";
6 %IRSSI = (
7 authors => "Tobias 'camel69' Wulff",
8 contact => "camel69(at)codeeye.de",
9 name => "amaroK (via ssh)",
10 description => "Retrievs song infos and controls amaroK via dcop, optionally running on another computer via ssh",
11 license => "Public Domain",
12 commands => "amarok",
13 url => "http://www.codeeye.de/irssi/"
14 );
15
16 use Irssi;
17
18 Irssi::settings_add_bool('amarok', 'amarok_use_ssh', 1);
19 Irssi::settings_add_str('amarok', 'amarok_ssh_client', 'localhost');
20 Irssi::settings_add_str('amarok', 'amarok_dcop_user', '');
21
22 sub show_help() {
23 my $help = $IRSSI{name}." ".$VERSION."
24 /amarok song [loud]
25 Prints the artist and title of the song which is currently played.
26 If the argument loud is given, all users in the current channel can
27 see what song you are currently listening.
28 /amarok time [loud]
29 Prints the total time of the song as well as the played time
30 and remaining time. Same behaviour for given argument loud
31 as above.
32 /amarok pause
33 Pauses (or unpauses) the current song.
34 /amarok play
35 Plays the current song (again).
36 /amarok stop
37 Stops the current song.
38 /amarok next
39 Skips to the next song.
40 /amarok prev
41 Skips to the previous song.
42 /amarok seek [+|-]secs|min:secs
43 Seeks to the given position. If + or - is given amaroK seeks
44 relatively the amount of minutes and/or seconds to the
45 current position.
46 /amarok vol [0 to 100]
47 Prints or changes the output volume of amaroK.
48 /amarok mute
49 Toggles between volume 0 and the last used volume.
50 /amarok help
51 Prints this help text.
52
53 Settings you can change with /SET
54 amarok_use_ssh: Enable or disable remote amaroK'ing
55 amarok_ssh_client: IP or hostname of the remote pc
56 amarok_dcop_user: user who is running dcop and amaroK";
57
58 print CLIENTCRAP $help;
59 }
60
61 my $preprint = '%Bamarok%n> ';
62
63 # Load settings
64 my $amarok_use_ssh = Irssi::settings_get_bool('amarok_use_ssh');
65 my $ssh_client = Irssi::settings_get_str('amarok_ssh_client');
66 my $dcop_user = Irssi::settings_get_str('amarok_dcop_user');
67
68 sub cmd ($) {
69 my ($postcmd) = @_;
70 my $dcop_precmd = 'dcop --user '.$dcop_user.' amarok player';
71
72 if ($amarok_use_ssh == 1) {
73 #print "ssh ".$ssh_client." '".$dcop_precmd." ".$postcmd."'";
74 return `ssh $ssh_client '$dcop_precmd $postcmd'`;
75 } else {
76 #print $dcop_precmd.' '.$postcmd;
77 return `$dcop_precmd $postcmd`;
78 }
79 }
80
81 sub amarokSong ($$) {
82 my($witem, $me_cmd) = @_;
83 if ($me_cmd == 1) {
84 if (!$witem or $witem->{type} ne 'CHANNEL') {
85 print CLIENTCRAP $preprint."The option 'loud' can only be used in channels.";
86 return;
87 }
88 }
89
90 my $artist = cmd('artist');
91 my $title = cmd('title');
92 my $text = 'listening to '.$artist.' - '.$title;
93 $text =~ s/\n//g;
94
95 if ($me_cmd == 1) {
96 $witem->command("ME is ".$text);
97 } else {
98 print CLIENTCRAP $preprint.$text;
99 }
100 }
101
102 sub amarokTime($$) {
103 my ($witem, $me_cmd) = @_;
104 if ($me_cmd == 1 and (!$witem or $witem->{type} ne 'CHANNEL')) {
105 print CLIENTCRAP $preprint."The option 'loud' can only be used in channels.";
106 return;
107 }
108
109 # Zeiten in Sekunden holen
110 my $time_total_secs = cmd('trackTotalTime');
111 my $time_played_secs = cmd('trackCurrentTime');
112 my $time_remaining_secs = $time_total_secs - $time_played_secs;
113
114 # Zeiten in richtige Minutenangabe umwandeln
115 my @time_total = (0, $time_total_secs % 60);
116 $time_total[0] = ($time_total_secs - $time_total[1]) / 60;
117 my @time_played = (0, $time_played_secs % 60);
118 $time_played[0] = ($time_played_secs - $time_played[1]) / 60;
119 my @time_remaining = (0, $time_remaining_secs % 60);
120 $time_remaining[0] = ($time_remaining_secs - $time_remaining[1]) / 60;
121
122 # Text bauen und ausgeben
123 # Gesamtzeit
124 my $text = 'Total time of track is '.$time_total[0].':';
125 if ($time_total[1] < 10) { $text .= '0'; }
126 $text .= $time_total[1];
127
128 # Gespielte Zeit
129 $text .= ' (played: '.$time_played[0].':';
130 if ($time_played[1] < 10) { $text .= '0'; }
131 $text .= $time_played[1];
132
133 # Verbleibende Zeit
134 $text .= ' / remaining: '.$time_remaining[0].':';
135 if ($time_remaining[1] < 10) { $text .= '0'; }
136 $text .= $time_remaining[1].')';
137
138 if ($me_cmd == 1) {
139 $witem->command("SAY ".$text);
140 } else {
141 print CLIENTCRAP $preprint.$text;
142 }
143 }
144
145 sub amarokSeek ($) {
146 my($time) = @_;
147
148 # format correct?
149 # just seconds: + or -, some numbers (seconds)
150 # mm:ss format: + or -, some numbers (minutes), :, 2 numbers (seconds)
151 if ($time !~ /^(\+|-)?[0-9]+$/ and
152 $time !~ /^(\+|-)?[0-9]+:[0-9]{2}$/) {
153 print CLIENTCRAP $preprint.'%RERROR%n: Wrong time format (see help for correct format)!';
154 return;
155 }
156
157 my $origtime = cmd('trackCurrentTime');
158
159 # Assume there's no + or -
160 my $seek_sign = '';
161
162 # Check for + or - in $time
163 # If a sign is found save it in $seek_sign and remove
164 # it from $time.
165 $_ = $time;
166 if (/^\+/) {
167 $seek_sign = '+';
168 $time =~ s/^\+//g;
169 } elsif (/^-/) {
170 $seek_sign = '-';
171 $time =~ s/^-//g;
172 }
173
174 # Now split $timearg at ':' if there's one
175 my @timeparts = split(/:/, $time);
176
177 # time has format mm:ss
178 if (defined $timeparts[1]) {
179 # Convert $time into secs
180 $time = 60 * $timeparts[0] + $timeparts[1];
181 }
182
183 # if there's a + or - recalc $time
184 if ($seek_sign eq '+') {
185 $time = $origtime + $time;
186 } elsif ($seek_sign eq '-') {
187 $time = $origtime - $time;
188 }
189
190 # print and do it
191 cmd('seek '.$time);
192 my $newtime = cmd('currentTime');
193 chomp($newtime);
194 print CLIENTCRAP $preprint.'Seeked to '.$newtime.'.';
195 }
196
197 sub cmd_amarok ($$$) {
198 my ($args, $server, $witem) = @_;
199 my @arg = split(/ /, $args);
200
201 # enough arguments?
202 if (scalar(@arg) == 0) {
203 print CLIENTCRAP $preprint.'%RERROR%n: not enough arguments!';
204 return;
205 }
206
207 my $loud = 0;
208 if (defined $arg[1] && $arg[1] eq 'loud') { $loud = 1; }
209
210 # is amaroK running?
211 # if so, is it currently playing?
212 # status = 0: stopped
213 # = 1: paused
214 # = 2: playing
215 my $status = cmd('status');
216 if ($status eq 'call failed') {
217 print CLIENTCRAP $preprint.'%RERROR%n: amaroK is not running!';
218 return;
219 } elsif ($status == 0 && $arg[0] ne 'play' && $arg[0] ne 'help' && $arg[0] ne 'vol' && $arg[0] ne 'mute') {
220 print CLIENTCRAP $preprint.'%RERROR%n: amaroK is not playing yet!';
221 print CLIENTCRAP $preprint.'Only the play, vol, mute and help commands are available.';
222 return;
223 }
224
225 # amaroK is running and playing or some commands are available though.
226 if ($arg[0] eq 'song') {
227 amarokSong($witem, $loud);
228 } elsif ($arg[0] eq 'time') {
229 amarokTime($witem, $loud);
230 } elsif ($arg[0] eq 'pause') {
231 cmd('pause');
232 if ($status == 1) {
233 print CLIENTCRAP $preprint.'Song unpaused.';
234 } elsif ($status == 2) {
235 print CLIENTCRAP $preprint.'Song paused.';
236 }
237 } elsif ($arg[0] eq 'next') {
238 cmd('next');
239 print CLIENTCRAP $preprint.'Skipped to next song.';
240 } elsif ($arg[0] eq 'prev') {
241 cmd('prev');
242 print CLIENTCRAP $preprint.'Skipped to previous song.';
243 } elsif ($arg[0] eq 'play') {
244 cmd('play');
245 print CLIENTCRAP $preprint.'Playing song.';
246 } elsif ($arg[0] eq 'stop') {
247 cmd('stop');
248 print CLIENTCRAP $preprint.'Song stopped.';
249 } elsif ($arg[0] eq 'seek') {
250 if (!(defined $arg[1])) {
251 print CLIENTCRAP $preprint.'Not enough arguments.';
252 } else {
253 amarokSeek($arg[1]);
254 }
255 } elsif ($arg[0] eq 'vol') {
256 if (!(defined $arg[1])) {
257 my $o_vol = cmd('getVolume');
258 chomp($o_vol);
259 print CLIENTCRAP $preprint.'Current volume is '.$o_vol.'%%.';
260 } else {
261 if ($arg[1] < 0 or $arg[1] > 100) {
262 print CLIENTCRAP $preprint.'Given volume is out of range (0-100)';
263 return;
264 }
265 cmd('setVolume '.$arg[1]);
266 print CLIENTCRAP $preprint.'Volume changed to '.$arg[1].'%%.';
267 }
268 } elsif ($arg[0] eq 'mute') {
269 cmd('mute');
270 print CLIENTCRAP $preprint.'Mute toggled.';
271 } elsif ($arg[0] eq 'help') {
272 show_help();
273 } else {
274 print CLIENTCRAP $preprint.'%RERROR%n: Unknown command!';
275 }
276 }
277
278 Irssi::command_bind('amarok' => \&cmd_amarok);
279
280 foreach my $cmd ('song', 'time', 'pause', 'play', 'stop', 'next', 'prev', 'seek', 'vol', 'mute', 'help') {
281 Irssi::command_bind('amarok '.$cmd =>
282 sub { cmd_amarok("$cmd ".$_[0], $_[1], $_[2]); } );
283 }
284
285 print CLIENTCRAP $preprint.$IRSSI{name}.' '.$VERSION.' loaded: type /amarok help for help';