+# Connect to MPD.
+$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;
+ my %state;
+
+ $menu //= "MenuMPD";
+
+ MPD::exec("status");
+ while (<$sock>) {
+ last if (/^OK/);
+ die($_) if (/^ACK/);
+
+ if (/^(\w+): (.*)$/) {
+ $state{$1} = $2;
+ }
+ }
+
+ MPD::exec("currentsong");
+ while (<$sock>) {
+ last if (/^OK/);
+ die($_) if (/^ACK/);
+
+ if (/^(\w+): (.*)$/) {
+ add_track_metadata(\%current, $1, $2);
+ }
+ }
+
+ my $playstate = $state{state} eq "play" ? "Playing"
+ : $state{state} eq "stop" ? "Stopped"
+ : $state{state} eq "pause" ? "Paused"
+ : "Unknown";
+ fvwm_cmd("AddToMenu", $menu, $playstate, "Title");
+
+ if (exists($current{file})) {
+ top_track_cover(\%current);
+ top_track_title(\%current);
+ top_track_artist(\%current);
+ top_track_album(\%current);
+ } else {
+ fvwm_cmd("AddToMenu", $menu, "[current track unavailable]");
+ }
+
+ if ($state{state} =~ /^p/) {
+ my $pp = $state{state} eq "pause" ? "lay" : "ause";
+
+ fvwm_cmd("AddToMenu", $menu, "", "Nop");
+ fvwm_cmd("AddToMenu", $menu, "Next%next.svg:16x16%",
+ "Exec", "exec", "$FindBin::Bin/mpdexec.pl", "next");
+ fvwm_cmd("AddToMenu", $menu, "P$pp%p$pp.svg:16x16%",
+ "Exec", "exec", "$FindBin::Bin/mpdexec.pl", "p$pp");
+ fvwm_cmd("AddToMenu", $menu, "Stop%stop.svg:16x16%",
+ "Exec", "exec", "$FindBin::Bin/mpdexec.pl", "stop");
+ fvwm_cmd("AddToMenu", $menu, "Prev%prev.svg:16x16%",
+ "Exec", "exec", "$FindBin::Bin/mpdexec.pl", "previous");
+ } elsif ($state{state} eq "stop") {
+ fvwm_cmd("AddToMenu", $menu, "", "Nop");
+ fvwm_cmd("AddToMenu", $menu, "Play%play.svg:16x16%",
+ "Exec", "exec", "$FindBin::Bin/mpdexec.pl", "play");
+ }
+} elsif ($mode eq "album") {
+ my $matches = get_tracks_by_release_mbid($albumid);
+ my @notqueued = ();
+
+ $menu //= "MenuMPDAlbum";
+
+ my $track_max = max(map { $_->{Track} } values %$matches);
+ my $disc_max = max(map { $_->{Disc} } values %$matches);
+
+ # CDs have a max of 99 tracks and I hope 100+-disc-releases
+ # don't exist so this is fine.
+ my $track_digits = $track_max >= 10 ? 2 : 1;
+ my $disc_digits = $disc_max > 1 ? $disc_max >= 10 ? 2 : 1 : 0;
+ my $currentdisc;
+
+ fvwm_cmd("AddToMenu", $menu);
+ fvwm_cmd("+", "Release not found", "Title") unless keys %$matches;
+ foreach my $file (sort { albumsort($matches, $a, $b) } keys %$matches) {
+ my $entry = $matches->{$file};
+
+ # Format disc/track numbers
+ $entry->{trackfmt} = sprintf("%*.*s%.*s%*d\t",
+ $disc_digits, $disc_digits, $entry->{Disc},
+ $disc_digits, "-",
+ $track_digits, $entry->{Track});
+ $entry->{trackfmt} =~ s/ /\N{U+2007}/g;
+
+ unless (exists $entry->{Id}) {
+ my ($id) = get_ids_by_filename($file);
+ if (defined $id) {
+ $entry->{Id} = $id;
+ } else {
+ push @notqueued, $entry;
+ next;
+ }
+ }
+
+ if (defined $currentdisc && $currentdisc != $entry->{Disc}) {
+ fvwm_cmd("+", "", "Nop");
+ }
+ $currentdisc = $entry->{Disc};
+
+ fvwm_cmd("+", menu_trackname($entry), "Exec",
+ "exec", "$FindBin::Bin/mpdexec.pl",
+ "playid", $entry->{Id});
+ }
+
+ fvwm_cmd("+", "Not in play queue", "Title") if @notqueued;
+ foreach my $entry (@notqueued) {
+ fvwm_cmd("+", menu_trackname($entry));
+ }
+} elsif ($mode eq "artist") {
+ # Create an artist menu.
+ my $matches = get_releases_by_artist_mbid(keys %artistids);
+ my $entry;
+
+ $menu //= "MenuMPDArtist";
+
+ my @mbids = sort { datesort($matches, $a, $b) } keys %$matches;
+ my @files = map { $matches->{$_}->{file} } @mbids;
+ my @thumbs = get_item_thumbnails({ small => 1 }, @files);
+ fvwm_cmd("AddToMenu", $menu, "No releases found", "Title") unless @mbids;
+
+ foreach my $mbid (@mbids) {
+ my $entry = $matches->{$mbid};
+ my $thumb = shift @thumbs;
+
+ my @submenu = make_submenu("$topmenu-$mbid",
+ "--album-id=$mbid");
+ fvwm_cmd("AddToMenu", $menu,
+ $thumb . fvwm_label_escape($entry->{Album}),
+ @submenu);
+ }
+} elsif ($mode eq "track") {
+ my $matches = get_tracks_by_track_mbid($trackid);
+ my @notqueued;
+
+ $menu //= "MenuMPDTrack";
+
+ my @files = sort { datesort($matches, $a, $b) } keys %$matches;
+ my @thumbs = get_item_thumbnails({ small => 1 }, @files);
+
+ fvwm_cmd("AddToMenu", $menu);
+ fvwm_cmd("+", "No tracks found", "Title") unless @files;
+ foreach my $file (@files) {
+ my $entry = $matches->{$file};
+ $entry->{thumb} = shift @thumbs;
+
+ unless (exists $entry->{Id}) {
+ my ($id) = get_ids_by_filename($file);
+ if (defined $id) {
+ $entry->{Id} = $id;
+ } else {
+ push @notqueued, $entry;
+ next;
+ }
+ }
+
+ fvwm_cmd("+", menu_trackname($entry), "Exec",
+ "exec", "$FindBin::Bin/mpdexec.pl",
+ "playid", $entry->{Id});
+ }
+
+ fvwm_cmd("+", "Not in play queue", "Title") if @notqueued;
+ foreach my $entry (@notqueued) {
+ fvwm_cmd("+", menu_trackname($entry));