tag/mbz/mbz.go
David Howden 9534e41d81 Added mbz subpackage for extracting MusicBrainz-specific tags.
This is a rewrite of pull request #11 which was a first attempt at this (thanks @xhenner for starting this).
2015-06-06 16:35:39 +10:00

126 lines
2.9 KiB
Go

// Package mbz extracts MusicBrainz Picard-specific tags from general tag metadata.
// See https://picard.musicbrainz.org/docs/mappings/ for more information.
package mbz
import (
"strings"
"github.com/dhowden/tag"
)
// Info is a structure which contains MusicBrainz identifier information.
type Info struct {
AcoustID string
Album string
AlbumArtist string
Artist string
ReleaseGroup string
Track string
}
// Supported MusicBrainz tag names
const (
TagAcoustID = "acoustid_id"
TagAlbum = "musicbrainz_albumid"
TagAlbumArtist = "musicbrainz_albumartistid"
TagArtist = "musicbrainz_artistid"
TagReleaseGroup = "musicbrainz_releasegroupid"
TagTrack = "musicbrainz_recordingid"
)
// UFIDProviderURL is the URL that we match inside a UFID tag.
const UFIDProviderURL = "http://musicbrainz.org"
// Mapping between the internal picard tag names and aliases.
var tags = map[string]string{
TagAcoustID: "Acoustid Id",
TagAlbum: "MusicBrainz Album Id",
TagAlbumArtist: "MusicBrainz Album Artist Id",
TagArtist: "MusicBrainz Artist Id",
TagReleaseGroup: "MusicBrainz Release Group Id",
TagTrack: "MusicBrainz Track Id",
}
func (i *Info) set(t, v string) {
switch t {
case TagAcoustID:
i.AcoustID = v
case TagAlbum:
i.Album = v
case TagAlbumArtist:
i.AlbumArtist = v
case TagArtist:
i.Artist = v
case TagReleaseGroup:
i.ReleaseGroup = v
case TagTrack:
i.Track = v
}
}
// Set the MusicBrainz tag to the given value.
func (i *Info) Set(t, v string) {
if _, ok := tags[t]; ok {
i.set(t, v)
return
}
for k, tt := range tags {
if tt == t {
i.set(k, v)
return
}
}
}
// extractID3 attempts to extract MusicBrainz Picard tags from m.Raw(), where m.Format
// is assumed to be a supported version of ID3.
func extractID3(m tag.Metadata) *Info {
var txxx, ufid string
switch m.Format() {
case tag.ID3v2_2:
txxx, ufid = "TXX", "UFI"
case tag.ID3v2_3, tag.ID3v2_4:
txxx, ufid = "TXXX", "UFID"
}
i := &Info{}
for k, v := range m.Raw() {
switch {
case strings.HasPrefix(k, txxx):
if str, ok := v.(*tag.Comm); ok {
i.Set(str.Description, str.Text)
}
case strings.HasPrefix(k, ufid):
if id, ok := v.(*tag.UFID); ok {
if id.Provider == UFIDProviderURL {
i.Set(TagTrack, string(id.Identifier))
}
}
}
}
return i
}
// extractMP4Vorbis attempts to extract MusicBrainz Picard tags from m.Raw(), where m.Format
// is assumed to be MP4 or VORBIS.
func extractMP4Vorbis(m tag.Metadata) *Info {
i := &Info{}
for t, v := range m.Raw() {
if s, ok := v.(string); ok {
i.Set(t, s)
}
}
return i
}
// Extract tags created by MusicBrainz Picard which can be used with with the MusicBrainz and LastFM APIs.
// See https://picard.musicbrainz.org/docs/mappings/ for more information.
func Extract(m tag.Metadata) *Info {
switch m.Format() {
case tag.ID3v2_2, tag.ID3v2_3, tag.ID3v2_4:
return extractID3(m)
}
return extractMP4Vorbis(m)
}