diff --git a/conf/app.conf b/conf/app.conf index d0bc73b01..08974d432 100644 --- a/conf/app.conf +++ b/conf/app.conf @@ -14,7 +14,8 @@ user=deluan password=wordpass dbPath=./devDb downsampleCommand=ffmpeg -i %s -map 0:0 -b:a %bk -v 0 -f mp3 - -ignorePlsFolders = true +plsIgnoreFolders = true +plsIgnoredPatterns = ^iCloud;^CDs para;^Skipped;^Christian [dev] disableValidation = true diff --git a/domain/playlist.go b/domain/playlist.go index 7dc3c0215..c2c656cd4 100644 --- a/domain/playlist.go +++ b/domain/playlist.go @@ -1,9 +1,10 @@ package domain type Playlist struct { - Id string - Name string - Tracks []string + Id string + Name string + FullPath string + Tracks []string } type PlaylistRepository interface { diff --git a/scanner/itunes_scanner.go b/scanner/itunes_scanner.go index 47f8311a0..cf3748288 100644 --- a/scanner/itunes_scanner.go +++ b/scanner/itunes_scanner.go @@ -12,6 +12,8 @@ import ( "html" + "regexp" + "github.com/astaxie/beego" "github.com/deluan/gosonic/domain" "github.com/deluan/itl" @@ -23,9 +25,16 @@ type ItunesScanner struct { albums map[string]*domain.Album artists map[string]*domain.Artist playlists map[string]*domain.Playlist + pplaylists map[string]plsRelation lastModifiedSince time.Time } +type plsRelation struct { + pID string + parentPID string + name string +} + func (s *ItunesScanner) ScanLibrary(lastModifiedSince time.Time, path string) (int, error) { beego.Info("Starting iTunes import from:", path) beego.Info("Checking for updates since", lastModifiedSince.String()) @@ -41,6 +50,7 @@ func (s *ItunesScanner) ScanLibrary(lastModifiedSince time.Time, path string) (i s.albums = make(map[string]*domain.Album) s.artists = make(map[string]*domain.Artist) s.playlists = make(map[string]*domain.Playlist) + s.pplaylists = make(map[string]plsRelation) i := 0 for _, t := range l.Tracks { @@ -55,13 +65,18 @@ func (s *ItunesScanner) ScanLibrary(lastModifiedSince time.Time, path string) (i } } - ignFolders, _ := beego.AppConfig.Bool("ignorePlsFolders") + ignFolders, _ := beego.AppConfig.Bool("plsIgnoreFolders") + ignPatterns := beego.AppConfig.Strings("plsIgnoredPatterns") for _, p := range l.Playlists { - if p.Master || p.Music || (ignFolders && p.Folder) { + rel := plsRelation{pID: p.PlaylistPersistentID, parentPID: p.ParentPersistentID, name: unescape(p.Name)} + s.pplaylists[p.PlaylistPersistentID] = rel + fullPath := s.fullPath(p.PlaylistPersistentID) + + if s.skipPlaylist(&p, ignFolders, ignPatterns, fullPath) { continue } - s.collectPlaylists(&p) + s.collectPlaylists(&p, fullPath) } beego.Debug("Processed", len(l.Playlists), "playlists.") @@ -81,10 +96,26 @@ func (s *ItunesScanner) Playlists() map[string]*domain.Playlist { return s.playlists } -func (s *ItunesScanner) collectPlaylists(p *itl.Playlist) { +func (s *ItunesScanner) skipPlaylist(p *itl.Playlist, ignFolders bool, ignPatterns []string, fullPath string) bool { + if p.Master || p.Music || (ignFolders && p.Folder) { + return true + } + + for _, p := range ignPatterns { + m, _ := regexp.MatchString(p, fullPath) + if m { + return true + } + } + + return false +} + +func (s *ItunesScanner) collectPlaylists(p *itl.Playlist, fullPath string) { pl := &domain.Playlist{} pl.Id = strconv.Itoa(p.PlaylistID) - pl.Name = p.Name + pl.Name = unescape(p.Name) + pl.FullPath = fullPath pl.Tracks = make([]string, 0, len(p.PlaylistItems)) for _, item := range p.PlaylistItems { id := strconv.Itoa(item.TrackID) @@ -97,6 +128,17 @@ func (s *ItunesScanner) collectPlaylists(p *itl.Playlist) { } } +func (s *ItunesScanner) fullPath(pID string) string { + rel, found := s.pplaylists[pID] + if !found { + return "" + } + if rel.parentPID == "" { + return rel.name + } + return fmt.Sprintf("%s > %s", s.fullPath(rel.parentPID), rel.name) +} + func (s *ItunesScanner) collectMediaFiles(t *itl.Track) *domain.MediaFile { mf := &domain.MediaFile{} mf.Id = strconv.Itoa(t.TrackID)