]> git.draconx.ca Git - irssi-scripts.git/blob - mpdsplat.pl
3a46cbe19b1a6395cec783726e123fae4aba6437
[irssi-scripts.git] / mpdsplat.pl
1 # Copyright © 2008, 2010 Nick Bowler
2 #
3 # License WTFPL2: Do What The Fuck You Want To Public License, version 2.
4 # This is free software: you are free to do what the fuck you want to.
5 # There is NO WARRANTY, to the extent permitted by law.
6 #
7 # MPDSplat helps you annoy your friends by posting your MPD status.  By
8 # posting to public channels, you can piss off a wider audience.
9
10 use strict;
11 use vars qw($VERSION %IRSSI);
12
13 use utf8;
14 use encoding 'utf8';
15 use IO::Socket::INET6;
16
17 $VERSION = '0.2';
18 %IRSSI = (
19         authors     => 'Nick Bowler',
20         contact     => 'nbowler@draconx.ca',
21         name        => 'MPDSplat',
22         description => 'Annoy your friends with MPD status information.',
23         license     => 'WTFPL2',
24 );
25
26 # MPD Connection Settings
27 $ENV{"MPD_HOST"} = "localhost" unless ($ENV{"MPD_HOST"});
28 $ENV{"MPD_PORT"} = 6600        unless ($ENV{"MPD_PORT"});
29 Irssi::settings_add_str("mpd", "mpd_host", $ENV{"MPD_HOST"});
30 Irssi::settings_add_int("mpd", "mpd_port", $ENV{"MPD_PORT"});
31
32 # Open a connection to MPD.
33 sub mpd_open {
34         my $sock = new IO::Socket::INET6(
35                 PeerAddr => Irssi::settings_get_str("mpd_host"),
36                 PeerPort => Irssi::settings_get_int("mpd_port"),
37                 Proto    => 'tcp',
38         ) or do {
39                 print CLIENTERROR "failed to open MPD socket: $!.";
40                 return undef;
41         };
42         binmode($sock, ":utf8");
43
44         # Grab the MPD version.
45         if (!(<$sock> =~ /^OK MPD ([0-9]+)\.([0-9]+)\.([0-9]+)$/)) {
46                 print CLIENTERROR "failed MPD handshake: $!.";
47                 return undef;
48         }
49
50         return $sock;
51 }
52
53 sub mpd_currentsong {
54         my ($sock) = @_;
55         my %data;
56
57         # Get MPD status.
58         print $sock "status\n";
59         while (<$sock>) {
60                 last if (/^OK/);
61                 do { print CLIENTERROR "$_"; return undef } if (/^ACK/);
62
63                 if (/^(\w+): (.*)$/) {
64                         $data{$1} = $2;
65                 }
66         }
67         return %data if (!defined $data{"songid"});
68
69         # Get song info
70         print $sock "playlistid $data{songid}\n";
71         while (<$sock>) {
72                 last if (/^OK/);
73                 do { print CLIENTERROR "$_"; return undef } if (/^ACK/);
74
75                 if (/^(\w+): (.*)$/) {
76                         $data{$1} = $2;
77                 }
78         }
79
80         return %data;
81 }
82
83 sub mpd_close {
84         my ($sock) = @_;
85         print $sock "close\n";
86         close $sock;
87 }
88
89 sub fileformat {
90         ($_) = @_;
91
92         return "vorbis" if (/\.ogg$/);
93         return "flac"   if (/\.flac$/);
94         return "mp3"    if (/\.mp3$/);
95 }
96
97 sub cmd_current {
98         my ($data, $server, $witem) = @_;
99         my ($window, $local) = (Irssi::active_win());
100
101         my $sock = mpd_open() or return;
102         my %info = mpd_currentsong($sock) or return;
103         mpd_close($sock);
104
105         if ($info{'state'} eq "stop") {
106                 $window->print("MPD is currently stopped.");
107                 return;
108         }
109
110         my $text = "$info{Artist} – $info{Title}, "
111                  . "track $info{Track}"
112                  . ($info{Disc} > 1 ? ", disc $info{Disc} " : "")
113                  . " of “$info{Album}” "
114                  . "($info{bitrate}kbps " . fileformat($info{'file'}) . ")";
115
116         # If the active window is not a channel or query, display locally.
117         $local = 1 unless ($witem && ($witem->{type} eq "CHANNEL"
118                                    || $witem->{type} eq "QUERY"));
119         
120         if ($local) {
121                 $window->print($text);
122         } elsif ($data) {
123                 $data =~ s/\s.*//;
124                 $witem->command("SAY $data: /me is listening to $text.");
125         } else {
126                 $witem->command("SAY /me is listening to $text.");
127         }
128 }
129 Irssi::command_bind('mpd', 'cmd_current');