use Exporter;
our ($VERSION, @ISA, @EXPORT);
+use IO::Socket::INET6;
+use IO::Socket::UNIX;
+
$VERSION = 0;
@ISA = qw(Exporter);
@EXPORT = qw();
+our $host = $ENV{MPD_HOST} // "localhost";
+our $port = $ENV{MPD_PORT} // 6600;
+our $sock;
+
+our ($major, $minor, $revision);
+
+# MPD::connect([ARGS])
+#
+# Connect to MPD based on the current settings of $MPD::host and $MPD::port.
+#
+# The following key-value arguments may optionally be specified:
+#
+# binmode => socket binmode, e.g., :utf8 or :raw. The default is :utf8.
+#
+# Text in the MPD protocol is always UTF-8 encoded but some
+# commands return raw binary data which can be easier to
+# handle in :raw mode.
+#
+# On failure, an error message is printed and undef is returned.
+sub connect {
+ my %args = @_;
+
+ if ($host =~ /^[@\/]/) {
+ $host =~ s/^@/\0/;
+ $sock = new IO::Socket::UNIX(Type => SOCK_STREAM(),
+ Peer => $host)
+ } else {
+ $sock = new IO::Socket::INET6(PeerAddr => $host,
+ PeerPort => $port,
+ Proto => 'tcp',
+ Timeout => 2)
+ }
+ die "MPD connection failed: $!\n" unless $sock;
+
+ binmode($sock, $args{binmode} // ":utf8");
+ unless (<$sock> =~ /^OK MPD ([0-9]+)\.([0-9]+)\.([0-9]+)$/) {
+ $sock->close();
+ die "MPD failed to announce version: $!\n";
+ }
+
+ ($major, $minor, $revision) = ($1, $2, $3);
+ return $sock;
+}
+
+# min_version(x, y, z)
+#
+# Returns true iff the MPD protocol version is at least x.y.z.
+sub min_version {
+ my ($maj, $min, $rev) = @_;
+
+ if (defined $maj) {
+ return 1 if $maj < $major;
+ return 0 if $maj > $major;
+ }
+
+ if (defined $min) {
+ return 1 if $min < $minor;
+ return 0 if $min > $minor;
+ }
+
+ if (defined $rev) {
+ return 1 if $rev < $revision;
+ return 0 if $rev > $revision;
+ }
+
+ return 1;
+}
+
# Returns the argument (or $_ if no arguments are supplied) quoted so that it
# can be presented as a single command argument to MPD at the protocol level.
sub escape {
binmode(STDOUT, ":utf8");
binmode(STDIN, ":utf8");
-use IO::Socket::INET6;
use Getopt::Long qw(:config gnu_getopt);
use lib "$FindBin::Bin";
use MPDHacks;
-my $host = $ENV{MPD_HOST} // "localhost";
-my $port = $ENV{MPD_PORT} // 6600;
my ($quiet, $binary, $ignore_errors, $download);
sub print_version {
}
GetOptions(
- 'host|h=s' => \$host,
- 'port|p=s' => \$port,
+ 'host|h=s' => \$MPD::host,
+ 'port|p=s' => \$MPD::port,
'quiet|q' => \$quiet,
'no-quiet' => sub { $quiet = 0; },
}
$quiet = 1 if (defined($binary) && $binary eq "");
-my $sock = new IO::Socket::INET6(
- PeerAddr => $host,
- PeerPort => $port,
- Proto => 'tcp',
-) or die "failed to connect to MPD: $!";
-#binmode($sock, ":utf8");
-binmode($sock);
-
-if (!(<$sock> =~ /^OK MPD ([0-9]+)\.([0-9]+)\.([0-9]+)$/)) {
- die "MPD failed to announce version: $!";
-}
+my $sock = MPD::connect(binmode => ":raw");
sub read_binary {
my ($count) = @_;
decode_argv(Encode::FB_CROAK);
binmode(STDOUT, ":utf8");
-use IO::Socket::INET6;
use Getopt::Long qw(:config gnu_getopt);
use Scalar::Util qw(reftype);
use List::Util qw(any max);
my $SELF = "$FindBin::Bin/$FindBin::Script";
my $MUSIC = $ENV{MUSIC} // "/srv/music";
-my $host = $ENV{MPD_HOST} // "localhost";
-my $port = $ENV{MPD_PORT} // "6600";
my $sock;
my ($albumid, $trackid);
}
GetOptions(
- 'host|h=s' => \$host,
- 'port|p=s' => \$port,
+ 'host|h=s' => \$MPD::host,
+ 'port|p=s' => \$MPD::port,
'menu|m=s' => \$menu,
'artist-id=s' => sub { $artistids{$_[1]} = 1; $mode = "artist"; },
$topmenu //= $menu;
# Connect to MPD.
-$sock = new IO::Socket::INET6(
- PeerAddr => $host,
- PeerPort => $port,
- Proto => 'tcp',
- Timeout => 2
-) or die("could not open socket: $!.\n");
-binmode($sock, ":utf8");
-
-die("could not connect to MPD: $!.\n")
- if (!(<$sock> =~ /^OK MPD ([0-9]+)\.([0-9]+)\.([0-9]+)$/));
-
-die("MPD version $1.$2.$3 insufficient.\n")
- if ( ($1 < MPD_MJR_MIN)
- || ($1 == MPD_MJR_MIN && $2 < MPD_MNR_MIN)
- || ($1 == MPD_MJR_MIN && $2 == MPD_MNR_MIN && $3 < MPD_REV_MIN));
+$sock = MPD::connect();
+die("MPD version $MPD::major.$MPD::minor.$MPD::revision insufficient.")
+ unless MPD::min_version(MPD_MJR_MIN, MPD_MNR_MIN, MPD_REV_MIN);
if ($mode eq "top") {
my %current;
decode_argv(Encode::FB_CROAK);
binmode(STDOUT, ":utf8");
-use IO::Socket::INET6;
-use IO::Socket::UNIX;
use Getopt::Long qw(:config gnu_getopt);
use lib "$FindBin::Bin";
use MPDHacks;
-my $host = $ENV{MPD_HOST} // "localhost";
-my $port = $ENV{MPD_PORT} // 6600;
my $sock;
# Submit a command to the MPD server; each argument to this function
}
GetOptions(
- 'host|h=s' => \$host,
- 'port|p=s' => \$port,
+ 'host|h=s' => \$MPD::host,
+ 'port|p=s' => \$MPD::port,
'V|version' => sub { print_version(); exit },
'H|help' => sub { print_help(); exit },
print_usage(); exit 1
};
-# Connect to MPD.
-if ($host =~ /^[@\/]/) {
- $host =~ s/^@/\0/;
- $sock = new IO::Socket::UNIX(Type => SOCK_STREAM(), Peer => $host);
-} else {
- $sock = new IO::Socket::INET6(PeerAddr => $host,
- PeerPort => $port,
- Proto => 'tcp');
-}
-$sock or die "failed to connect to MPD: $!";
-binmode($sock, ":utf8");
-
-if (!(<$sock> =~ /^OK MPD ([0-9]+)\.([0-9]+)\.([0-9]+)$/)) {
- die "MPD failed to announce version: $!";
-}
+$sock = MPD::connect();
# Retrieve the current play queue and target play queue.
my $current = get_tracks_in_play_queue();