]> git.draconx.ca Git - mpdhacks.git/blobdiff - mpdmenu.pl
Fix quoting of single quotes in MPD protocol.
[mpdhacks.git] / mpdmenu.pl
index 8e597e7f9c704c3b585ecd29043aace22fe61b35..3a84f7855bcda3ddfb60c92d41f06657b2bb45f6 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.
@@ -24,6 +24,9 @@ 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,
@@ -38,33 +41,14 @@ my $port  = $ENV{MPD_PORT} // "6600";
 my $sock;
 
 my ($albumid, $trackid);
-my %artistids;
-my $menu;
+my ($topmenu, $menu);
 my $mode = "top";
-
-# 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;
-}
+my %artistids;
 
 # 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 } @_);
+       my $cmd = join(' ', map { MPD::escape } @_);
 
        print $sock "$cmd\n";
 }
@@ -74,7 +58,7 @@ sub fvwm_cmd_unquoted {
 }
 
 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
@@ -112,7 +96,7 @@ sub fvwm_label_escape {
 sub make_submenu {
        my $name = shift;
        $name =~ s/-/_/g;
-       unshift @_, ("exec", $SELF, "--menu=$name");
+       unshift @_, ("exec", $SELF, "--topmenu=$topmenu", "--menu=$name");
 
         fvwm_cmd("DestroyFunc", "Make$name");
         fvwm_cmd("AddToFunc", "Make$name");
@@ -120,14 +104,14 @@ sub make_submenu {
 
         fvwm_cmd("DestroyMenu", $name);
         fvwm_cmd("AddToMenu", $name, "DynamicPopupAction", "Make$name");
-        fvwm_cmd("AddToFunc", "KillMenuMPD", "I", "DestroyMenu", $name);
+        fvwm_cmd("AddToFunc", "Kill$topmenu", "I", "DestroyMenu", $name);
 
         fvwm_cmd("DestroyFunc", "Make$name");
         fvwm_cmd("AddToFunc", "Make$name");
         fvwm_cmd("+", "I", "DestroyMenu", $name);
         fvwm_cmd("+", "I", "-PipeRead",
                 join(' ', map { fvwm_shell_literal } @_));
-        fvwm_cmd("AddToFunc", "KillMenuMPD", "I", "DestroyFunc", "Make$name");
+        fvwm_cmd("AddToFunc", "Kill$topmenu", "I", "DestroyFunc", "Make$name");
 
        return ("Popup", $name);
 }
@@ -243,8 +227,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);
        }
 }
@@ -514,8 +498,16 @@ GetOptions(
 
        'V|version'   => sub { print_version(); exit },
        'H|help'      => sub { print_help(); exit },
+
+       'topmenu=s'   => \$topmenu, # top menu name (for submenu generation)
 ) or do { print_usage; exit 1 };
 
+unless (defined $menu) {
+       $topmenu //= "MenuMPD";
+       $menu = $topmenu . ($mode ne "top" ? $mode : "");
+}
+$topmenu //= $menu;
+
 # Connect to MPD.
 $sock = new IO::Socket::INET6(
        PeerAddr => $host,
@@ -658,7 +650,8 @@ if ($mode eq "top") {
                my $entry = $matches->{$mbid};
                my $thumb = shift @thumbs;
 
-               my @submenu = make_submenu("$menu-$mbid", "--album-id=$mbid");
+               my @submenu = make_submenu("$topmenu-$mbid",
+                                          "--album-id=$mbid");
                fvwm_cmd("AddToMenu", $menu,
                         $thumb . fvwm_label_escape($entry->{Album}),
                         @submenu);