+ $thumb = "$c$thumb$c" if (-f $thumb);
+ push @results, $thumb;
+ }
+ close THUMB;
+ die("mpdthumb failed") if ($?);
+
+ return @results;
+}
+
+# add_track_metadata(hashref, key, value)
+#
+# Inserts the given key into the referenced hash; if the key already exists
+# in the hash then the hash element is converted to an array reference (if
+# it isn't already) and the value is appended to that array.
+sub add_track_metadata {
+ my ($entry, $key, $value) = @_;
+
+ if (exists($entry->{$key})) {
+ my $ref = $entry->{$key};
+
+ if (reftype($ref) ne "ARRAY") {
+ return if ($ref eq $value);
+
+ $ref = [$ref];
+ $entry->{$key} = $ref;
+ }
+
+ push(@$ref, $value) unless (any {$_ eq $value} @$ref);
+ } else {
+ $entry->{$key} = $value;
+ }
+}
+
+# get_track_metadata(hashref, key)
+#
+# Return the values associated with the given metadata key as a list.
+sub get_track_metadata {
+ my ($entry, $key) = @_;
+
+ return () unless (exists($entry->{$key}));
+
+ my $ref = $entry->{$key};
+ return @$ref if (reftype($ref) eq "ARRAY");
+ return $ref
+}
+
+# Given a music filename, search for the cover art in the same directory.
+sub mpd_cover_filename {
+ my ($dir) = @_;
+ my $file;
+
+ $dir =~ s/\/[^\/]*$//;
+ foreach ("cover.png", "cover.jpg", "cover.tiff", "cover.bmp") {
+ if (-f "$dir/$_") {
+ $file = "$dir/$_";
+ last;
+ }
+ }
+ return unless defined $file;
+
+ # Follow one level of symbolic link to get to the scans directory.
+ $file = readlink($file) // $file;
+ $file = "$dir/$file" unless ($file =~ /^\//);
+ return $file;
+}
+
+# Generate the cover art entry in the top menu.
+sub top_track_cover {
+ my ($entry) = @_;
+
+ ($entry->{thumb}) = get_item_thumbnails($entry->{file});
+ print "$entry->{thumb}\n";
+ if ($entry->{thumb}) {
+ my $file = "$MUSIC/$entry->{file}";
+ my $cover = mpd_cover_filename($file);
+
+ $cover = fvwm_shell_literal($cover // $file);
+ fvwm_cmd_unquoted("AddToMenu", MPD::escape($menu),
+ MPD::escape($entry->{thumb}),
+ "Exec", "exec", "geeqie", $cover);
+ }
+}
+
+# Generate the "Title:" entry in the top menu.
+sub top_track_title {
+ my ($entry) = @_;
+ my @submenu;
+
+ my ($mbid) = get_track_metadata($entry, "MUSICBRAINZ_RELEASETRACKID");
+ if ($mbid) {
+ @submenu = make_submenu("$menu-$mbid", "--track-id=$mbid")
+ } else {
+ ($mbid) = get_track_metadata($entry, "MUSICBRAINZ_TRACKID");
+ @submenu = make_submenu("$menu-track-$mbid", "--recording-id=$mbid")
+ if ($mbid);
+ }
+
+ fvwm_cmd("AddToMenu", $menu,
+ fvwm_label_escape("Title:\t$entry->{Title}"),
+ @submenu);
+}
+
+# Generate the "Artist:" entry in the top menu.
+sub top_track_artist {
+ my ($entry) = @_;
+ my @submenu;
+
+ # TODO: multi-artist tracks should get multiple artist menus; for now
+ # just combine the releases from all artists.
+ my @mbids = get_track_metadata($entry, "MUSICBRAINZ_ARTISTID");
+ if (@mbids) {
+ @submenu = make_submenu("$menu-TopArtist",
+ map { "--artist-id=$_" } @mbids);
+ }
+
+ fvwm_cmd("AddToMenu", $menu,
+ fvwm_label_escape("Artist:\t$entry->{Artist}"),
+ @submenu);
+}
+
+# Generate the "Album:" entry in the top menu.
+sub top_track_album {
+ my ($entry) = @_;
+ my @submenu;
+ my $mbid;
+
+ if (($mbid) = get_track_metadata($entry, "MUSICBRAINZ_ALBUMID")) {
+ @submenu = make_submenu("$menu-$mbid", "--album-id=$mbid");
+ } elsif (($mbid) = get_track_metadata($entry, "MUSICBRAINZ_TRACKID")) {
+ # Standalone recording
+ my @a = get_track_metadata($entry, "MUSICBRAINZ_ARTISTID");
+ my ($album) = get_track_metadata($entry, "Album");
+
+ @submenu = make_submenu("$menu-$mbid", "--album-name=$album",
+ map { "--artist-id=$_" } @a);
+
+ }
+
+ fvwm_cmd("AddToMenu", $menu,
+ fvwm_label_escape("Album:\t$entry->{Album}"),
+ @submenu);
+}
+
+# Given a work MBID, return a hash reference containing all tracks
+# linked to that work. The hash keys are filenames.
+sub get_tracks_by_work_mbid {
+ my %matches;