mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-05 13:37:38 +03:00
Add "inspect" command to CLI
This commit is contained in:
parent
ea7ba22699
commit
798b03eabd
6 changed files with 154 additions and 37 deletions
99
cmd/inspect.go
Normal file
99
cmd/inspect.go
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/navidrome/navidrome/conf"
|
||||||
|
"github.com/navidrome/navidrome/log"
|
||||||
|
"github.com/navidrome/navidrome/model"
|
||||||
|
"github.com/navidrome/navidrome/scanner"
|
||||||
|
"github.com/navidrome/navidrome/scanner/metadata"
|
||||||
|
"github.com/navidrome/navidrome/tests"
|
||||||
|
"github.com/pelletier/go-toml/v2"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
extractor string
|
||||||
|
format string
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
inspectCmd.Flags().StringVarP(&extractor, "extractor", "x", "", "extractor to use (ffmpeg or taglib, default: auto)")
|
||||||
|
inspectCmd.Flags().StringVarP(&format, "format", "f", "pretty", "output format (pretty, toml, yaml, json, jsonindent)")
|
||||||
|
rootCmd.AddCommand(inspectCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
var inspectCmd = &cobra.Command{
|
||||||
|
Use: "inspect [files to inspect]",
|
||||||
|
Short: "Inspect tags",
|
||||||
|
Long: "Show file tags as seen by Navidrome",
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
runInspector(args)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var marshalers = map[string]func(interface{}) ([]byte, error){
|
||||||
|
"pretty": prettyMarshal,
|
||||||
|
"toml": toml.Marshal,
|
||||||
|
"yaml": yaml.Marshal,
|
||||||
|
"json": json.Marshal,
|
||||||
|
"jsonindent": func(v interface{}) ([]byte, error) {
|
||||||
|
return json.MarshalIndent(v, "", " ")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func prettyMarshal(v interface{}) ([]byte, error) {
|
||||||
|
out := v.([]inspectorOutput)
|
||||||
|
var res strings.Builder
|
||||||
|
for i := range out {
|
||||||
|
res.WriteString(fmt.Sprintf("====================\nFile: %s\n\n", out[i].File))
|
||||||
|
t, _ := toml.Marshal(out[i].RawTags)
|
||||||
|
res.WriteString(fmt.Sprintf("Raw tags:\n%s\n\n", t))
|
||||||
|
t, _ = toml.Marshal(out[i].MappedTags)
|
||||||
|
res.WriteString(fmt.Sprintf("Mapped tags:\n%s\n\n", t))
|
||||||
|
}
|
||||||
|
return []byte(res.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type inspectorOutput struct {
|
||||||
|
File string
|
||||||
|
RawTags metadata.ParsedTags
|
||||||
|
MappedTags model.MediaFile
|
||||||
|
}
|
||||||
|
|
||||||
|
func runInspector(args []string) {
|
||||||
|
if extractor != "" {
|
||||||
|
conf.Server.Scanner.Extractor = extractor
|
||||||
|
}
|
||||||
|
log.Info("Using extractor", "extractor", conf.Server.Scanner.Extractor)
|
||||||
|
md, err := metadata.Extract(args...)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Error extracting tags", err)
|
||||||
|
}
|
||||||
|
mapper := scanner.NewMediaFileMapper(conf.Server.MusicFolder, &tests.MockedGenreRepo{})
|
||||||
|
marshal := marshalers[format]
|
||||||
|
if marshal == nil {
|
||||||
|
log.Fatal("Invalid format", "format", format)
|
||||||
|
}
|
||||||
|
var out []inspectorOutput
|
||||||
|
for k, v := range md {
|
||||||
|
if !model.IsAudioFile(k) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(v.Tags) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out = append(out, inspectorOutput{
|
||||||
|
File: k,
|
||||||
|
RawTags: v.Tags,
|
||||||
|
MappedTags: mapper.ToMediaFile(v),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
data, _ := marshal(out)
|
||||||
|
fmt.Println(string(data))
|
||||||
|
}
|
|
@ -15,20 +15,20 @@ import (
|
||||||
"github.com/navidrome/navidrome/utils"
|
"github.com/navidrome/navidrome/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
type mediaFileMapper struct {
|
type MediaFileMapper struct {
|
||||||
rootFolder string
|
rootFolder string
|
||||||
genres model.GenreRepository
|
genres model.GenreRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMediaFileMapper(rootFolder string, genres model.GenreRepository) *mediaFileMapper {
|
func NewMediaFileMapper(rootFolder string, genres model.GenreRepository) *MediaFileMapper {
|
||||||
return &mediaFileMapper{
|
return &MediaFileMapper{
|
||||||
rootFolder: rootFolder,
|
rootFolder: rootFolder,
|
||||||
genres: genres,
|
genres: genres,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Move most of these mapping functions to setters in the model.MediaFile
|
// TODO Move most of these mapping functions to setters in the model.MediaFile
|
||||||
func (s mediaFileMapper) toMediaFile(md metadata.Tags) model.MediaFile {
|
func (s MediaFileMapper) ToMediaFile(md metadata.Tags) model.MediaFile {
|
||||||
mf := &model.MediaFile{}
|
mf := &model.MediaFile{}
|
||||||
mf.ID = s.trackID(md)
|
mf.ID = s.trackID(md)
|
||||||
mf.Year, mf.Date, mf.OriginalYear, mf.OriginalDate, mf.ReleaseYear, mf.ReleaseDate = s.mapDates(md)
|
mf.Year, mf.Date, mf.OriginalYear, mf.OriginalDate, mf.ReleaseYear, mf.ReleaseDate = s.mapDates(md)
|
||||||
|
@ -86,7 +86,7 @@ func sanitizeFieldForSorting(originalValue string) string {
|
||||||
return utils.NoArticle(v)
|
return utils.NoArticle(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s mediaFileMapper) mapTrackTitle(md metadata.Tags) string {
|
func (s MediaFileMapper) mapTrackTitle(md metadata.Tags) string {
|
||||||
if md.Title() == "" {
|
if md.Title() == "" {
|
||||||
s := strings.TrimPrefix(md.FilePath(), s.rootFolder+string(os.PathSeparator))
|
s := strings.TrimPrefix(md.FilePath(), s.rootFolder+string(os.PathSeparator))
|
||||||
e := filepath.Ext(s)
|
e := filepath.Ext(s)
|
||||||
|
@ -95,7 +95,7 @@ func (s mediaFileMapper) mapTrackTitle(md metadata.Tags) string {
|
||||||
return md.Title()
|
return md.Title()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s mediaFileMapper) mapAlbumArtistName(md metadata.Tags) string {
|
func (s MediaFileMapper) mapAlbumArtistName(md metadata.Tags) string {
|
||||||
switch {
|
switch {
|
||||||
case md.AlbumArtist() != "":
|
case md.AlbumArtist() != "":
|
||||||
return md.AlbumArtist()
|
return md.AlbumArtist()
|
||||||
|
@ -108,14 +108,14 @@ func (s mediaFileMapper) mapAlbumArtistName(md metadata.Tags) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s mediaFileMapper) mapArtistName(md metadata.Tags) string {
|
func (s MediaFileMapper) mapArtistName(md metadata.Tags) string {
|
||||||
if md.Artist() != "" {
|
if md.Artist() != "" {
|
||||||
return md.Artist()
|
return md.Artist()
|
||||||
}
|
}
|
||||||
return consts.UnknownArtist
|
return consts.UnknownArtist
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s mediaFileMapper) mapAlbumName(md metadata.Tags) string {
|
func (s MediaFileMapper) mapAlbumName(md metadata.Tags) string {
|
||||||
name := md.Album()
|
name := md.Album()
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return consts.UnknownAlbum
|
return consts.UnknownAlbum
|
||||||
|
@ -123,11 +123,11 @@ func (s mediaFileMapper) mapAlbumName(md metadata.Tags) string {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s mediaFileMapper) trackID(md metadata.Tags) string {
|
func (s MediaFileMapper) trackID(md metadata.Tags) string {
|
||||||
return fmt.Sprintf("%x", md5.Sum([]byte(md.FilePath())))
|
return fmt.Sprintf("%x", md5.Sum([]byte(md.FilePath())))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s mediaFileMapper) albumID(md metadata.Tags, releaseDate string) string {
|
func (s MediaFileMapper) albumID(md metadata.Tags, releaseDate string) string {
|
||||||
albumPath := strings.ToLower(fmt.Sprintf("%s\\%s", s.mapAlbumArtistName(md), s.mapAlbumName(md)))
|
albumPath := strings.ToLower(fmt.Sprintf("%s\\%s", s.mapAlbumArtistName(md), s.mapAlbumName(md)))
|
||||||
if !conf.Server.Scanner.GroupAlbumReleases {
|
if !conf.Server.Scanner.GroupAlbumReleases {
|
||||||
if len(releaseDate) != 0 {
|
if len(releaseDate) != 0 {
|
||||||
|
@ -137,15 +137,15 @@ func (s mediaFileMapper) albumID(md metadata.Tags, releaseDate string) string {
|
||||||
return fmt.Sprintf("%x", md5.Sum([]byte(albumPath)))
|
return fmt.Sprintf("%x", md5.Sum([]byte(albumPath)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s mediaFileMapper) artistID(md metadata.Tags) string {
|
func (s MediaFileMapper) artistID(md metadata.Tags) string {
|
||||||
return fmt.Sprintf("%x", md5.Sum([]byte(strings.ToLower(s.mapArtistName(md)))))
|
return fmt.Sprintf("%x", md5.Sum([]byte(strings.ToLower(s.mapArtistName(md)))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s mediaFileMapper) albumArtistID(md metadata.Tags) string {
|
func (s MediaFileMapper) albumArtistID(md metadata.Tags) string {
|
||||||
return fmt.Sprintf("%x", md5.Sum([]byte(strings.ToLower(s.mapAlbumArtistName(md)))))
|
return fmt.Sprintf("%x", md5.Sum([]byte(strings.ToLower(s.mapAlbumArtistName(md)))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s mediaFileMapper) mapGenres(genres []string) (string, model.Genres) {
|
func (s MediaFileMapper) mapGenres(genres []string) (string, model.Genres) {
|
||||||
var result model.Genres
|
var result model.Genres
|
||||||
unique := map[string]struct{}{}
|
unique := map[string]struct{}{}
|
||||||
var all []string
|
var all []string
|
||||||
|
@ -174,7 +174,7 @@ func (s mediaFileMapper) mapGenres(genres []string) (string, model.Genres) {
|
||||||
return result[0].Name, result
|
return result[0].Name, result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s mediaFileMapper) mapDates(md metadata.Tags) (year int, date string,
|
func (s MediaFileMapper) mapDates(md metadata.Tags) (year int, date string,
|
||||||
originalYear int, originalDate string,
|
originalYear int, originalDate string,
|
||||||
releaseYear int, releaseDate string) {
|
releaseYear int, releaseDate string) {
|
||||||
// Start with defaults
|
// Start with defaults
|
||||||
|
|
|
@ -12,11 +12,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("mapping", func() {
|
var _ = Describe("mapping", func() {
|
||||||
Describe("mediaFileMapper", func() {
|
Describe("MediaFileMapper", func() {
|
||||||
var mapper *mediaFileMapper
|
var mapper *MediaFileMapper
|
||||||
Describe("mapTrackTitle", func() {
|
Describe("mapTrackTitle", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
mapper = newMediaFileMapper("/music", nil)
|
mapper = NewMediaFileMapper("/music", nil)
|
||||||
})
|
})
|
||||||
It("returns the Title when it is available", func() {
|
It("returns the Title when it is available", func() {
|
||||||
md := metadata.NewTag("/music/artist/album01/Song.mp3", nil, metadata.ParsedTags{"title": []string{"This is not a love song"}})
|
md := metadata.NewTag("/music/artist/album01/Song.mp3", nil, metadata.ParsedTags{"title": []string{"This is not a love song"}})
|
||||||
|
@ -37,7 +37,7 @@ var _ = Describe("mapping", func() {
|
||||||
ds := &tests.MockDataStore{}
|
ds := &tests.MockDataStore{}
|
||||||
gr = ds.Genre(ctx)
|
gr = ds.Genre(ctx)
|
||||||
gr = newCachedGenreRepository(ctx, gr)
|
gr = newCachedGenreRepository(ctx, gr)
|
||||||
mapper = newMediaFileMapper("/", gr)
|
mapper = NewMediaFileMapper("/", gr)
|
||||||
})
|
})
|
||||||
|
|
||||||
It("returns empty if no genres are available", func() {
|
It("returns empty if no genres are available", func() {
|
||||||
|
@ -79,7 +79,7 @@ var _ = Describe("mapping", func() {
|
||||||
Describe("mapDates", func() {
|
Describe("mapDates", func() {
|
||||||
var md metadata.Tags
|
var md metadata.Tags
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
mapper = newMediaFileMapper("/", nil)
|
mapper = NewMediaFileMapper("/", nil)
|
||||||
})
|
})
|
||||||
Context("when all date fields are provided", func() {
|
Context("when all date fields are provided", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
|
|
|
@ -58,25 +58,35 @@ func Extract(files ...string) (map[string]Tags, error) {
|
||||||
|
|
||||||
func NewTag(filePath string, fileInfo os.FileInfo, tags ParsedTags) Tags {
|
func NewTag(filePath string, fileInfo os.FileInfo, tags ParsedTags) Tags {
|
||||||
for t, values := range tags {
|
for t, values := range tags {
|
||||||
tags[t] = removeDuplicates(values)
|
values = removeDuplicatesAndEmpty(values)
|
||||||
|
if len(values) == 0 {
|
||||||
|
delete(tags, t)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tags[t] = values
|
||||||
}
|
}
|
||||||
return Tags{
|
return Tags{
|
||||||
filePath: filePath,
|
filePath: filePath,
|
||||||
fileInfo: fileInfo,
|
fileInfo: fileInfo,
|
||||||
tags: tags,
|
Tags: tags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeDuplicates(values []string) []string {
|
func removeDuplicatesAndEmpty(values []string) []string {
|
||||||
encountered := map[string]struct{}{}
|
encountered := map[string]struct{}{}
|
||||||
|
empty := true
|
||||||
var result []string
|
var result []string
|
||||||
for _, v := range values {
|
for _, v := range values {
|
||||||
if _, ok := encountered[v]; ok {
|
if _, ok := encountered[v]; ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
encountered[v] = struct{}{}
|
encountered[v] = struct{}{}
|
||||||
|
empty = empty && v == ""
|
||||||
result = append(result, v)
|
result = append(result, v)
|
||||||
}
|
}
|
||||||
|
if empty {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +110,7 @@ func (p ParsedTags) Map(customMappings ParsedTags) ParsedTags {
|
||||||
type Tags struct {
|
type Tags struct {
|
||||||
filePath string
|
filePath string
|
||||||
fileInfo os.FileInfo
|
fileInfo os.FileInfo
|
||||||
tags ParsedTags
|
Tags ParsedTags
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common tags
|
// Common tags
|
||||||
|
@ -207,7 +217,7 @@ func (t Tags) getPeakValue(tagName string) float64 {
|
||||||
|
|
||||||
func (t Tags) getTags(tagNames ...string) []string {
|
func (t Tags) getTags(tagNames ...string) []string {
|
||||||
for _, tag := range tagNames {
|
for _, tag := range tagNames {
|
||||||
if v, ok := t.tags[tag]; ok {
|
if v, ok := t.Tags[tag]; ok {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -225,7 +235,7 @@ func (t Tags) getFirstTagValue(tagNames ...string) string {
|
||||||
func (t Tags) getAllTagValues(tagNames ...string) []string {
|
func (t Tags) getAllTagValues(tagNames ...string) []string {
|
||||||
var values []string
|
var values []string
|
||||||
for _, tag := range tagNames {
|
for _, tag := range tagNames {
|
||||||
if v, ok := t.tags[tag]; ok {
|
if v, ok := t.Tags[tag]; ok {
|
||||||
values = append(values, v...)
|
values = append(values, v...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ var _ = Describe("Tags", func() {
|
||||||
DescribeTable("getDate",
|
DescribeTable("getDate",
|
||||||
func(tag string, expectedYear int, expectedDate string) {
|
func(tag string, expectedYear int, expectedDate string) {
|
||||||
md := &Tags{}
|
md := &Tags{}
|
||||||
md.tags = map[string][]string{"date": {tag}}
|
md.Tags = map[string][]string{"date": {tag}}
|
||||||
testYear, testDate := md.Date()
|
testYear, testDate := md.Date()
|
||||||
Expect(testYear).To(Equal(expectedYear))
|
Expect(testYear).To(Equal(expectedYear))
|
||||||
Expect(testDate).To(Equal(expectedDate))
|
Expect(testDate).To(Equal(expectedDate))
|
||||||
|
@ -29,7 +29,7 @@ var _ = Describe("Tags", func() {
|
||||||
Describe("getMbzID", func() {
|
Describe("getMbzID", func() {
|
||||||
It("return a valid MBID", func() {
|
It("return a valid MBID", func() {
|
||||||
md := &Tags{}
|
md := &Tags{}
|
||||||
md.tags = map[string][]string{
|
md.Tags = map[string][]string{
|
||||||
"musicbrainz_trackid": {"8f84da07-09a0-477b-b216-cc982dabcde1"},
|
"musicbrainz_trackid": {"8f84da07-09a0-477b-b216-cc982dabcde1"},
|
||||||
"musicbrainz_releasetrackid": {"6caf16d3-0b20-3fe6-8020-52e31831bc11"},
|
"musicbrainz_releasetrackid": {"6caf16d3-0b20-3fe6-8020-52e31831bc11"},
|
||||||
"musicbrainz_albumid": {"f68c985d-f18b-4f4a-b7f0-87837cf3fbf9"},
|
"musicbrainz_albumid": {"f68c985d-f18b-4f4a-b7f0-87837cf3fbf9"},
|
||||||
|
@ -44,7 +44,7 @@ var _ = Describe("Tags", func() {
|
||||||
})
|
})
|
||||||
It("return empty string for invalid MBID", func() {
|
It("return empty string for invalid MBID", func() {
|
||||||
md := &Tags{}
|
md := &Tags{}
|
||||||
md.tags = map[string][]string{
|
md.Tags = map[string][]string{
|
||||||
"musicbrainz_trackid": {"11406732-6"},
|
"musicbrainz_trackid": {"11406732-6"},
|
||||||
"musicbrainz_albumid": {"11406732"},
|
"musicbrainz_albumid": {"11406732"},
|
||||||
"musicbrainz_artistid": {"200455"},
|
"musicbrainz_artistid": {"200455"},
|
||||||
|
@ -60,7 +60,7 @@ var _ = Describe("Tags", func() {
|
||||||
Describe("getAllTagValues", func() {
|
Describe("getAllTagValues", func() {
|
||||||
It("returns values from all tag names", func() {
|
It("returns values from all tag names", func() {
|
||||||
md := &Tags{}
|
md := &Tags{}
|
||||||
md.tags = map[string][]string{
|
md.Tags = map[string][]string{
|
||||||
"genre": {"Rock", "Pop", "New Wave"},
|
"genre": {"Rock", "Pop", "New Wave"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,23 +68,31 @@ var _ = Describe("Tags", func() {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("removeDuplicates", func() {
|
Describe("removeDuplicatesAndEmpty", func() {
|
||||||
It("removes duplicates", func() {
|
It("removes duplicates", func() {
|
||||||
md := NewTag("/music/artist/album01/Song.mp3", nil, ParsedTags{
|
md := NewTag("/music/artist/album01/Song.mp3", nil, ParsedTags{
|
||||||
"genre": []string{"pop", "rock", "pop"},
|
"genre": []string{"pop", "rock", "pop"},
|
||||||
"date": []string{"2023-03-01", "2023-03-01"},
|
"date": []string{"2023-03-01", "2023-03-01"},
|
||||||
"mood": []string{"happy", "sad"},
|
"mood": []string{"happy", "sad"},
|
||||||
})
|
})
|
||||||
Expect(md.tags).To(HaveKeyWithValue("genre", []string{"pop", "rock"}))
|
Expect(md.Tags).To(HaveKeyWithValue("genre", []string{"pop", "rock"}))
|
||||||
Expect(md.tags).To(HaveKeyWithValue("date", []string{"2023-03-01"}))
|
Expect(md.Tags).To(HaveKeyWithValue("date", []string{"2023-03-01"}))
|
||||||
Expect(md.tags).To(HaveKeyWithValue("mood", []string{"happy", "sad"}))
|
Expect(md.Tags).To(HaveKeyWithValue("mood", []string{"happy", "sad"}))
|
||||||
|
})
|
||||||
|
It("removes empty tags", func() {
|
||||||
|
md := NewTag("/music/artist/album01/Song.mp3", nil, ParsedTags{
|
||||||
|
"genre": []string{"pop", "rock", "pop"},
|
||||||
|
"mood": []string{"", ""},
|
||||||
|
})
|
||||||
|
Expect(md.Tags).To(HaveKeyWithValue("genre", []string{"pop", "rock"}))
|
||||||
|
Expect(md.Tags).ToNot(HaveKey("mood"))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("Bpm", func() {
|
Describe("Bpm", func() {
|
||||||
var t *Tags
|
var t *Tags
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
t = &Tags{tags: map[string][]string{
|
t = &Tags{Tags: map[string][]string{
|
||||||
"fbpm": []string{"141.7"},
|
"fbpm": []string{"141.7"},
|
||||||
}}
|
}}
|
||||||
})
|
})
|
||||||
|
|
|
@ -27,7 +27,7 @@ type TagScanner struct {
|
||||||
ds model.DataStore
|
ds model.DataStore
|
||||||
plsSync *playlistImporter
|
plsSync *playlistImporter
|
||||||
cnt *counters
|
cnt *counters
|
||||||
mapper *mediaFileMapper
|
mapper *MediaFileMapper
|
||||||
cacheWarmer artwork.CacheWarmer
|
cacheWarmer artwork.CacheWarmer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ func (s *TagScanner) Scan(ctx context.Context, lastModifiedSince time.Time, prog
|
||||||
var changedDirs []string
|
var changedDirs []string
|
||||||
s.cnt = &counters{}
|
s.cnt = &counters{}
|
||||||
genres := newCachedGenreRepository(ctx, s.ds.Genre(ctx))
|
genres := newCachedGenreRepository(ctx, s.ds.Genre(ctx))
|
||||||
s.mapper = newMediaFileMapper(s.rootFolder, genres)
|
s.mapper = NewMediaFileMapper(s.rootFolder, genres)
|
||||||
refresher := newRefresher(s.ds, s.cacheWarmer, allFSDirs)
|
refresher := newRefresher(s.ds, s.cacheWarmer, allFSDirs)
|
||||||
|
|
||||||
log.Trace(ctx, "Loading directory tree from music folder", "folder", s.rootFolder)
|
log.Trace(ctx, "Loading directory tree from music folder", "folder", s.rootFolder)
|
||||||
|
@ -386,7 +386,7 @@ func (s *TagScanner) loadTracks(filePaths []string) (model.MediaFiles, error) {
|
||||||
|
|
||||||
var mfs model.MediaFiles
|
var mfs model.MediaFiles
|
||||||
for _, md := range mds {
|
for _, md := range mds {
|
||||||
mf := s.mapper.toMediaFile(md)
|
mf := s.mapper.ToMediaFile(md)
|
||||||
mfs = append(mfs, mf)
|
mfs = append(mfs, mf)
|
||||||
}
|
}
|
||||||
return mfs, nil
|
return mfs, nil
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue