]> git.draconx.ca Git - mpdhacks.git/commitdiff
mpdmenu: Use MBIDs for artists instead of name matching.
authorNick Bowler <nbowler@draconx.ca>
Sat, 29 Jun 2019 19:16:37 +0000 (15:16 -0400)
committerNick Bowler <nbowler@draconx.ca>
Sun, 30 Jun 2019 14:34:19 +0000 (10:34 -0400)
This enables much more accurate artist menus, working properly with
variant spellings and whatnot.

mpdmenu.pl

index 241ab8e39076d49d7a07f3502a7c4d2a6b363849..5968843a0bfb5c8092dc71bafccd08eb06b6ca08 100755 (executable)
@@ -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");