X-Git-Url: https://git.draconx.ca/gitweb/mpdhacks.git/blobdiff_plain/82b8d686ad89f91d69f8bdcca3b469c4065e6b1c..f1a45f3dd740c5b55cd44ff09548d49791191863:/mpdmenu.pl diff --git a/mpdmenu.pl b/mpdmenu.pl index a12eb4c..3cc0e35 100755 --- a/mpdmenu.pl +++ b/mpdmenu.pl @@ -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/);