From 020f9f800a804c638d6432711be319c5b9bfb988 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Sat, 29 Jun 2019 15:16:37 -0400 Subject: [PATCH] mpdmenu: Use MBIDs for artists instead of name matching. This enables much more accurate artist menus, working properly with variant spellings and whatnot. --- mpdmenu.pl | 80 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 27 deletions(-) diff --git a/mpdmenu.pl b/mpdmenu.pl index 241ab8e..5968843 100755 --- a/mpdmenu.pl +++ b/mpdmenu.pl @@ -37,7 +37,8 @@ my $host = $ENV{MPD_HOST} // "localhost"; my $port = $ENV{MPD_PORT} // "6600"; my $sock; -my ($albumid, $artist, $title); +my ($albumid, $title); +my %artistids; my $menu; my $mode = "top"; @@ -263,9 +264,15 @@ sub top_track_title { # 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}"), @@ -315,6 +322,36 @@ sub get_tracks_by_release_mbid { 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 { @@ -392,22 +429,23 @@ Options: -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. @@ -538,30 +576,18 @@ if ($mode eq "top") { } } 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"); -- 2.43.0