From 6663c079e0acd4b4d95b27affe5453bee27de2eb Mon Sep 17 00:00:00 2001 From: Deluan Date: Thu, 27 Aug 2020 16:51:55 -0400 Subject: [PATCH] Add MBIDs to media_file, album and artist --- db/migration/20200827130401_add_more_tags.go | 57 ++++++++++++++++++++ model/album.go | 9 +++- model/artist.go | 1 + model/mediafile.go | 7 +++ persistence/album_repository.go | 1 + persistence/artist_repository.go | 1 + scanner/mapping.go | 7 +++ scanner/metadata/ffmpeg_test.go | 31 +++++++++++ scanner/metadata/metadata.go | 26 +++++++++ 9 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 db/migration/20200827130401_add_more_tags.go diff --git a/db/migration/20200827130401_add_more_tags.go b/db/migration/20200827130401_add_more_tags.go new file mode 100644 index 000000000..80bdf44f2 --- /dev/null +++ b/db/migration/20200827130401_add_more_tags.go @@ -0,0 +1,57 @@ +package migration + +import ( + "database/sql" + + "github.com/pressly/goose" +) + +func init() { + goose.AddMigration(upAddMoreTags, downAddMoreTags) +} + +func upAddMoreTags(tx *sql.Tx) error { + _, err := tx.Exec(` +alter table media_file + add mbz_track_id varchar(255); +alter table media_file + add mbz_album_id varchar(255); +alter table media_file + add mbz_artist_id varchar(255); +alter table media_file + add mbz_album_artist_id varchar(255); +alter table media_file + add mbz_album_type varchar(255); +alter table media_file + add mbz_album_comment varchar(255); +alter table media_file + add catalog_num varchar(255); + +alter table album + add mbz_album_id varchar(255); +alter table album + add mbz_album_artist_id varchar(255); +alter table album + add mbz_album_type varchar(255); +alter table album + add mbz_album_comment varchar(255); +alter table album + add catalog_num varchar(255); + +create index if not exists album_mbz_album_type + on album (mbz_album_type); + +alter table artist + add mbz_artist_id varchar(255); + +`) + if err != nil { + return err + } + notice(tx, "A full rescan needs to be performed to import more tags") + return forceFullRescan(tx) +} + +func downAddMoreTags(tx *sql.Tx) error { + return nil +} diff --git a/model/album.go b/model/album.go index 773a2c0de..cbb10f11f 100644 --- a/model/album.go +++ b/model/album.go @@ -9,9 +9,9 @@ type Album struct { Name string `json:"name"` CoverArtPath string `json:"coverArtPath"` CoverArtId string `json:"coverArtId"` - ArtistID string `json:"artistId" orm:"pk;column(artist_id)"` + ArtistID string `json:"artistId" orm:"column(artist_id)"` Artist string `json:"artist"` - AlbumArtistID string `json:"albumArtistId" orm:"pk;column(album_artist_id)"` + AlbumArtistID string `json:"albumArtistId" orm:"column(album_artist_id)"` AlbumArtist string `json:"albumArtist"` MaxYear int `json:"maxYear"` MinYear int `json:"minYear"` @@ -25,6 +25,11 @@ type Album struct { SortAlbumArtistName string `json:"sortAlbumArtistName"` OrderAlbumName string `json:"orderAlbumName"` OrderAlbumArtistName string `json:"orderAlbumArtistName"` + CatalogNum string `json:"catalogNum"` + MbzAlbumID string `json:"mbzAlbumId" orm:"column(mbz_album_id)"` + MbzAlbumArtistID string `json:"mbzAlbumArtistId" orm:"column(mbz_album_artist_id)"` + MbzAlbumType string `json:"mbzAlbumType"` + MbzAlbumComment string `json:"mbzAlbumComment"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` Size int64 `json:"size"` diff --git a/model/artist.go b/model/artist.go index 52bd88489..9f422d87c 100644 --- a/model/artist.go +++ b/model/artist.go @@ -11,6 +11,7 @@ type Artist struct { SortArtistName string `json:"sortArtistName"` OrderArtistName string `json:"orderArtistName"` Size int64 `json:"size"` + MbzArtistID string `json:"mbzArtistId" orm:"column(mbz_artist_id)"` } type Artists []Artist diff --git a/model/mediafile.go b/model/mediafile.go index 6c7c508bc..ce1e26a05 100644 --- a/model/mediafile.go +++ b/model/mediafile.go @@ -37,6 +37,13 @@ type MediaFile struct { OrderArtistName string `json:"orderArtistName"` OrderAlbumArtistName string `json:"orderAlbumArtistName"` Compilation bool `json:"compilation"` + CatalogNum string `json:"catalogNum"` + MbzTrackID string `json:"mbzTrackId" orm:"column(mbz_track_id)"` + MbzAlbumID string `json:"mbzAlbumId" orm:"column(mbz_album_id)"` + MbzArtistID string `json:"mbzArtistId" orm:"column(mbz_artist_id)"` + MbzAlbumArtistID string `json:"mbzAlbumArtistId" orm:"column(mbz_album_artist_id)"` + MbzAlbumType string `json:"mbzAlbumType"` + MbzAlbumComment string `json:"mbzAlbumComment"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` } diff --git a/persistence/album_repository.go b/persistence/album_repository.go index 3a59b1286..bc1bd232c 100644 --- a/persistence/album_repository.go +++ b/persistence/album_repository.go @@ -161,6 +161,7 @@ func (r *albumRepository) refresh(ids ...string) error { sel := Select(`f.album_id as id, f.album as name, f.artist, f.album_artist, f.artist_id, f.album_artist_id, f.sort_album_name, f.sort_artist_name, f.sort_album_artist_name, f.order_album_name, f.order_album_artist_name, f.path, + f.mbz_album_id, f.mbz_album_artist_id, f.mbz_album_type, f.mbz_album_comment, f.catalog_num, f.compilation, f.genre, max(f.year) as max_year, sum(f.duration) as duration, count(f.id) as song_count, a.id as current_id, group_concat(f.disc_subtitle, ' ') as disc_subtitles, diff --git a/persistence/artist_repository.go b/persistence/artist_repository.go index a8317fefc..fe4033a5e 100644 --- a/persistence/artist_repository.go +++ b/persistence/artist_repository.go @@ -144,6 +144,7 @@ func (r *artistRepository) refresh(ids ...string) error { } var artists []refreshArtist sel := Select("f.album_artist_id as id", "f.album_artist as name", "count(*) as album_count", "a.id as current_id", + "f.mbz_album_artist_id as mbz_artist_id", "f.sort_album_artist_name as sort_artist_name", "f.order_album_artist_name as order_artist_name", "sum(f.song_count) as song_count", "sum(f.size) as size"). From("album f"). diff --git a/scanner/mapping.go b/scanner/mapping.go index 2e5ff0dec..27142fe61 100644 --- a/scanner/mapping.go +++ b/scanner/mapping.go @@ -52,6 +52,13 @@ func (s *mediaFileMapper) toMediaFile(md metadata.Metadata) model.MediaFile { mf.OrderAlbumName = sanitizeFieldForSorting(mf.Album) mf.OrderArtistName = sanitizeFieldForSorting(mf.Artist) mf.OrderAlbumArtistName = sanitizeFieldForSorting(mf.AlbumArtist) + mf.CatalogNum = md.CatalogNum() + mf.MbzTrackID = md.MbzTrackID() + mf.MbzAlbumID = md.MbzAlbumID() + mf.MbzArtistID = md.MbzArtistID() + mf.MbzAlbumArtistID = md.MbzAlbumArtistID() + mf.MbzAlbumType = md.MbzAlbumType() + mf.MbzAlbumComment = md.MbzAlbumComment() // TODO Get Creation time. https://github.com/djherbis/times ? mf.CreatedAt = md.ModificationTime() diff --git a/scanner/metadata/ffmpeg_test.go b/scanner/metadata/ffmpeg_test.go index 1b2a91f3b..5a6afbe26 100644 --- a/scanner/metadata/ffmpeg_test.go +++ b/scanner/metadata/ffmpeg_test.go @@ -52,6 +52,37 @@ var _ = Describe("ffmpegExtractor", func() { }) Context("extractMetadata", func() { + It("extracts MusicBrainz custom tags", func() { + const output = ` +Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'Colt 45 - Underground Post-Punk, Tropical Tapes, Lo Fi Electronics And Others Sounds From Brazil (1983 - 1993) Selected By Tetine/01-06 X.m4a': + Metadata: + title : X + artist : Saara Saara + composer : Servio Tulio & Raul Rachid + album : Colt 45 - Underground Post-Punk, Tropical Tapes, Lo Fi Electronics And Others Sounds From Brazil (1983 - 1993) Selected By Tetine + genre : Alternative + MusicBrainz Release Group Id: 0 + MusicBrainz Album Artist Id: 194 + MusicBrainz Artist Id: 200455 + MusicBrainz Album Release Country: Unknown + MusicBrainz Album Id: 11406732 + MusicBrainz Track Id: 11406732-6 + Label : Slum Dunk Music + publisher : Slum Dunk Music + MusicBrainz Album Type: Compilation + MusicBrainz Album Comment: MP3 + CATALOGNUMBER : SLUM DUNK MUSIC 009 +` + md, _ := extractMetadata("tests/fixtures/test.mp3", output) + Expect(md.CatalogNum()).To(Equal("SLUM DUNK MUSIC 009")) + Expect(md.MbzTrackID()).To(Equal("11406732-6")) + Expect(md.MbzAlbumID()).To(Equal("11406732")) + Expect(md.MbzArtistID()).To(Equal("200455")) + Expect(md.MbzAlbumArtistID()).To(Equal("194")) + Expect(md.MbzAlbumType()).To(Equal("Compilation")) + Expect(md.MbzAlbumComment()).To(Equal("MP3")) + }) + It("detects embedded cover art correctly", func() { const output = ` Input #0, mp3, from '/Users/deluan/Music/iTunes/iTunes Media/Music/Compilations/Putumayo Presents Blues Lounge/09 Pablo's Blues.mp3': diff --git a/scanner/metadata/metadata.go b/scanner/metadata/metadata.go index 14b559bbd..b9a4585ad 100644 --- a/scanner/metadata/metadata.go +++ b/scanner/metadata/metadata.go @@ -51,6 +51,13 @@ type Metadata interface { HasPicture() bool Comment() string Compilation() bool + CatalogNum() string + MbzTrackID() string + MbzAlbumID() string + MbzArtistID() string + MbzAlbumArtistID() string + MbzAlbumType() string + MbzAlbumComment() string Duration() float32 BitRate() int ModificationTime() time.Time @@ -87,6 +94,25 @@ func (m *baseMetadata) DiscNumber() (int, int) { return m.parseTuple("disc", "d func (m *baseMetadata) DiscSubtitle() string { return m.getTag("tsst", "discsubtitle", "setsubtitle") } +func (m *baseMetadata) CatalogNum() string { return m.getTag("catalognumber") } +func (m *baseMetadata) MbzTrackID() string { + return m.getTag("musicbrainz_trackid", "musicbrainz track id") +} +func (m *baseMetadata) MbzAlbumID() string { + return m.getTag("musicbrainz_albumid", "musicbrainz album id") +} +func (m *baseMetadata) MbzArtistID() string { + return m.getTag("musicbrainz_artistid", "musicbrainz artist id") +} +func (m *baseMetadata) MbzAlbumArtistID() string { + return m.getTag("musicbrainz_albumartistid", "musicbrainz album artist id") +} +func (m *baseMetadata) MbzAlbumType() string { + return m.getTag("musicbrainz_albumtype", "musicbrainz album type") +} +func (m *baseMetadata) MbzAlbumComment() string { + return m.getTag("musicbrainz_albumcomment", "musicbrainz album comment") +} func (m *baseMetadata) ModificationTime() time.Time { return m.fileInfo.ModTime() } func (m *baseMetadata) Size() int64 { return m.fileInfo.Size() }