my $port = $ENV{MPD_PORT} // "6600";
my $sock;
-my ($albumid, $artist, $title);
+my ($albumid, $title);
+my %artistids;
my $menu;
my $mode = "top";
# Generate the "Artist:" entry in the top menu.
sub top_track_artist {
my ($entry) = @_;
+ my @submenu;
- my @submenu = make_submenu("$menu-TopArtist",
- "--artist=$entry->{Artist}");
+ # 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}"),
return \%matches;
}
+# Given an artist MBID, return a hash reference containing associated
+# releases in the MPD database. The hash keys are release MBIDs.
+#
+# Since MPD returns results on a per-track basis, each entry in the
+# hash has the metadata for one unspecified track from that release.
+sub get_releases_by_artist_mbid {
+ my %releases;
+ my $entry;
+
+ foreach my $mbid (@_) {
+ mpd_exec("search", "(MUSICBRAINZ_ARTISTID == \"$mbid\")");
+ while (<$sock>) {
+ last if (/^OK/);
+ die($_) if (/^ACK/);
+
+ if (/^(\w+): (.*)$/) {
+ if ($1 eq "file") {
+ $entry = {};
+ } elsif ($1 eq "MUSICBRAINZ_ALBUMID") {
+ $releases{$2} //= $entry;
+ }
+
+ add_track_metadata($entry, $1, $2);
+ }
+ }
+ }
+
+ return \%releases;
+}
+
# Given a filename, return the IDs (if any) for that file in the
# current MPD play queue.
sub get_ids_by_filename {
-p, --port=PORT Connect to the MPD server on PORT, overriding defaults.
-m, --menu=NAME Set the name of the generated menu.
--album-id=MBID Generate a menu for the given release MBID.
+ --artist-id=MBID Generate a menu for the given artist MBID.
-V, --version Print a version message and then exit.
-H, --help Print this message and then exit.
EOF
}
GetOptions(
- 'host|h=s' => \$host,
- 'port|p=s' => \$port,
- 'menu|m=s' => \$menu,
+ 'host|h=s' => \$host,
+ 'port|p=s' => \$port,
+ 'menu|m=s' => \$menu,
- 'album-id=s' => sub { $albumid = $_[1]; $mode = "album"; },
- 'artist=s' => sub { $artist = $_[1]; $mode = "artist"; },
- 'title=s' => sub { $title = $_[1]; $mode = "track"; },
+ 'artist-id=s' => sub { $artistids{$_[1]} = 1; $mode = "artist"; },
+ 'album-id=s' => sub { $albumid = $_[1]; $mode = "album"; },
+ 'title=s' => sub { $title = $_[1]; $mode = "track"; },
- 'V|version' => sub { print_version(); exit },
- 'H|help' => sub { print_help(); exit },
+ 'V|version' => sub { print_version(); exit },
+ 'H|help' => sub { print_help(); exit },
) or do { print_usage; exit 1 };
# Connect to MPD.
}
} elsif ($mode eq "artist") {
# Create an artist menu.
- my %matches;
+ my $matches = get_releases_by_artist_mbid(keys %artistids);
my $entry;
$menu //= "MenuMPDArtist";
- mpd_exec("playlistfind", "artist", $artist);
- while (<$sock>) {
- last if (/^OK/);
- die($_) if (/^ACK/);
-
- if (/^(\w+): (.*)$/) {
- $entry = {} if ($1 eq "file");
- $matches{$2} //= $entry if ($1 eq "MUSICBRAINZ_ALBUMID");
- add_track_metadata($entry, $1, $2);
- }
- }
-
- my @mbids = sort { datesort(\%matches, $a, $b) } keys %matches;
- my @files = map { $matches{$_}->{file} } @mbids;
+ 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 $entry = $matches->{$mbid};
my $thumb = shift @thumbs;
my @submenu = make_submenu("$menu-$mbid", "--album-id=$mbid");