]> git.draconx.ca Git - mpdhacks.git/blobdiff - mpdmenu.pl
mpdthumb: Add --help and --version options.
[mpdhacks.git] / mpdmenu.pl
index a12eb4c39350e6948ed8fd75fd37058d0aef854c..3cc0e350d02e1d85f68377153163b41432de9145 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/perl
 #
-# Copyright © 2008,2010,2012,2019 Nick Bowler
+# Copyright © 2008,2010,2012,2020 Nick Bowler
 #
 # Silly little script to generate an FVWM menu with various bits of MPD
 # status information and controls.
@@ -18,12 +18,14 @@ 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);
 use FindBin;
 
+use lib "$FindBin::Bin";
+use MPDHacks;
+
 use constant {
        MPD_MJR_MIN => 0,
        MPD_MNR_MIN => 21,
@@ -33,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);
@@ -42,39 +42,12 @@ my ($topmenu, $menu);
 my $mode = "top";
 my %artistids;
 
-# Quotes the argument so that it is presented as a single argument to MPD
-# at the protocol level.  This also works OK for most FVWM arguments.
-sub escape {
-       my $s = @_[0] // $_;
-
-       # No way to encode literal newlines in the protocol, so we
-       # convert any newlines in the arguments into a space, which
-       # can help with quoting.
-       $s =~ s/\n/ /g;
-
-       if (/[ \t\\"]/) {
-               $s =~ s/[\\"]/\\$&/g;
-               return "\"$s\"";
-       }
-
-       $s =~ s/^\s*$/"$&"/;
-       return $s;
-}
-
-# Submit a command to the MPD server; each argument to this function
-# is quoted and sent as a single argument to MPD.
-sub mpd_exec {
-       my $cmd = join(' ', map { escape } @_);
-
-       print $sock "$cmd\n";
-}
-
 sub fvwm_cmd_unquoted {
        print join(' ', @_), "\n";
 }
 
 sub fvwm_cmd {
-       fvwm_cmd_unquoted(map { escape } @_);
+       fvwm_cmd_unquoted(map { MPD::escape } @_);
 }
 
 # Quotes the argument in such a way that it is passed unadulterated by
@@ -243,8 +216,8 @@ sub top_track_cover {
                my $cover = mpd_cover_filename($file);
 
                $cover = fvwm_shell_literal($cover // $file);
-               fvwm_cmd_unquoted("AddToMenu", escape($menu),
-                                 escape($entry->{thumb}),
+               fvwm_cmd_unquoted("AddToMenu", MPD::escape($menu),
+                                 MPD::escape($entry->{thumb}),
                                  "Exec", "exec", "geeqie", $cover);
        }
 }
@@ -300,7 +273,7 @@ sub get_tracks_by_work_mbid {
        my $entry;
 
        foreach my $mbid (@_) {
-               mpd_exec("search", "(MUSICBRAINZ_WORKID == \"$mbid\")");
+               MPD::exec("search", "(MUSICBRAINZ_WORKID == \"$mbid\")");
                while (<$sock>) {
                        last if (/^OK/);
                        die($_) if (/^ACK/);
@@ -329,13 +302,13 @@ sub get_tracks_by_work_mbid {
 # Currently tracks are considered "related" if their associated recordings
 # have at least one work in common.
 sub get_tracks_by_track_mbid {
-       my ($mbid) = @_;
+       my ($mbid, $tagname) = (@_, "MUSICBRAINZ_RELEASETRACKID");
        my %source;
        my %matches;
        my $entry;
 
        return \%matches unless ($mbid);
-       mpd_exec("search", "(MUSICBRAINZ_RELEASETRACKID == \"$mbid\")");
+       MPD::exec("search", "(MUSICBRAINZ_RELEASETRACKID == \"$mbid\")");
        while (<$sock>) {
                last if (/^OK/);
                die($_) if (/^ACK/);
@@ -367,7 +340,7 @@ sub get_tracks_by_release_mbid {
        my $entry;
 
        return \%matches unless ($mbid);
-       mpd_exec("search", "(MUSICBRAINZ_ALBUMID == \"$mbid\")");
+       MPD::exec("search", "(MUSICBRAINZ_ALBUMID == \"$mbid\")");
        while (<$sock>) {
                last if (/^OK/);
                die($_) if (/^ACK/);
@@ -399,7 +372,7 @@ sub get_releases_by_artist_mbid {
        my $entry;
 
        foreach my $mbid (@_) {
-               mpd_exec("search", "(MUSICBRAINZ_ARTISTID == \"$mbid\")");
+               MPD::exec("search", "(MUSICBRAINZ_ARTISTID == \"$mbid\")");
                while (<$sock>) {
                        last if (/^OK/);
                        die($_) if (/^ACK/);
@@ -425,7 +398,7 @@ sub get_ids_by_filename {
        my ($file) = @_;
        my @results = ();
 
-       mpd_exec("playlistfind", "file", $file);
+       MPD::exec("playlistfind", "file", $file);
        while (<$sock>) {
                last if (/^OK/);
                die($_) if (/^ACK/);
@@ -480,10 +453,10 @@ EOF
 }
 
 sub print_usage {
-       my $fh = $_[1] // *STDERR;
+       my ($fh) = (@_, *STDERR);
 
        print $fh "Usage: $0 [options]\n";
-       print "Try $0 --help for more information.\n" unless (@_ > 0);
+       print $fh "Try $0 --help for more information.\n" unless (@_ > 0);
 }
 
 sub print_help {
@@ -504,8 +477,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"; },
@@ -525,21 +498,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;
@@ -547,7 +508,7 @@ if ($mode eq "top") {
 
        $menu //= "MenuMPD";
 
-       mpd_exec("status");
+       MPD::exec("status");
        while (<$sock>) {
                last if (/^OK/);
                die($_) if (/^ACK/);
@@ -557,7 +518,7 @@ if ($mode eq "top") {
                }
        }
 
-       mpd_exec("currentsong");
+       MPD::exec("currentsong");
        while (<$sock>) {
                last if (/^OK/);
                die($_) if (/^ACK/);