]> git.draconx.ca Git - mpdhacks.git/commitdiff
Factor out MPD connection code.
authorNick Bowler <nbowler@draconx.ca>
Tue, 5 May 2020 03:01:06 +0000 (23:01 -0400)
committerNick Bowler <nbowler@draconx.ca>
Wed, 6 May 2020 01:27:34 +0000 (21:27 -0400)
Instead of having three different copies of the MPD connection code in
the perl scripts, let's put it all in one place.  Now mpdreload is no
longer the only script that supports UNIX socket connections.

MPDHacks.pm
mpdexec.pl
mpdmenu.pl
mpdreload.pl

index 2c76c2f703c54621423741ad05e4a1dcdbd6cb1d..94c0acc518dbad5067eb1c4456c4877ee169955d 100644 (file)
@@ -13,10 +13,81 @@ use strict;
 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 {
index 8147f1d185c96fe4aec99a2399de5d63c6a1e279..496c5581ff53b9f9f411f75d22fb8aaebb88f00d 100755 (executable)
@@ -20,7 +20,6 @@ decode_argv(Encode::FB_CROAK);
 
 binmode(STDOUT, ":utf8");
 binmode(STDIN, ":utf8");
-use IO::Socket::INET6;
 
 use Getopt::Long qw(:config gnu_getopt);
 
@@ -28,8 +27,6 @@ use FindBin;
 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 {
@@ -77,8 +74,8 @@ EOF
 }
 
 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; },
@@ -104,17 +101,7 @@ if ($binary) {
 }
 $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) = @_;
index 3a84f7855bcda3ddfb60c92d41f06657b2bb45f6..4916d2a4ac09f0d25c8184226a5e7e30a50cd0b1 100755 (executable)
@@ -18,7 +18,6 @@ use Encode::Locale qw(decode_argv);
 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);
@@ -36,8 +35,6 @@ use constant {
 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);
@@ -488,8 +485,8 @@ EOF
 }
 
 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"; },
@@ -509,21 +506,9 @@ unless (defined $menu) {
 $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;
index fcbbcc3e5cb122fcbe28edacfb75460d2b7238d6..ba822ae9de8cf05946038d43472726e59b5bc4d5 100755 (executable)
@@ -17,8 +17,6 @@ use Encode::Locale qw(decode_argv);
 decode_argv(Encode::FB_CROAK);
 
 binmode(STDOUT, ":utf8");
-use IO::Socket::INET6;
-use IO::Socket::UNIX;
 
 use Getopt::Long qw(:config gnu_getopt);
 
@@ -26,8 +24,6 @@ use FindBin;
 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
@@ -124,8 +120,8 @@ EOF
 }
 
 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 },
@@ -138,21 +134,7 @@ if (@ARGV != 1) {
        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();