Esempio n. 1
0
        public void filter_should_return_none_existing_files_ignoring_case(FilterFilesType filter)
        {
            WindowsOnly();

            var files = GivenFiles(new[]
            {
                "C:\\file1.avi".AsOsAgnostic(),
                "C:\\FILE2.avi".AsOsAgnostic(),
                "C:\\file3.avi".AsOsAgnostic()
            });

            Mocker.GetMock <IMediaFileRepository>()
            .Setup(c => c.GetFileWithPath(It.IsAny <List <string> >()))
            .Returns(new List <TrackFile>
            {
                new TrackFile
                {
                    Path     = "C:\\file2.avi".AsOsAgnostic(),
                    Modified = _lastWrite
                }
            });

            Subject.FilterUnchangedFiles(files, filter).Should().HaveCount(2);
            Subject.FilterUnchangedFiles(files, filter).Select(x => x.FullName).Should().NotContain("C:\\file2.avi".AsOsAgnostic());
        }
Esempio n. 2
0
 public RescanFoldersCommand(List <string> folders, FilterFilesType filter, bool addNewArtists, List <int> artistIds)
 {
     Folders       = folders;
     Filter        = filter;
     AddNewArtists = addNewArtists;
     ArtistIds     = artistIds;
 }
Esempio n. 3
0
 public RescanFoldersCommand(List <string> folders, FilterFilesType filter, bool addNewAuthors, List <int> authorIds)
 {
     Folders       = folders;
     Filter        = filter;
     AddNewAuthors = addNewAuthors;
     AuthorIds     = authorIds;
 }
Esempio n. 4
0
        public void filter_should_return_existing_file_if_size_changed(FilterFilesType filter)
        {
            FileSystem.AddFile("C:\\file1.avi".AsOsAgnostic(), new MockFileData("".PadRight(10))
            {
                LastWriteTime = _lastWrite
            });
            FileSystem.AddFile("C:\\file2.avi".AsOsAgnostic(), new MockFileData("".PadRight(11))
            {
                LastWriteTime = _lastWrite
            });
            FileSystem.AddFile("C:\\file3.avi".AsOsAgnostic(), new MockFileData("".PadRight(10))
            {
                LastWriteTime = _lastWrite
            });

            var files = FileSystem.AllFiles.Select(x => DiskProvider.GetFileInfo(x)).ToList();

            Mocker.GetMock <IMediaFileRepository>()
            .Setup(c => c.GetFileWithPath(It.IsAny <List <string> >()))
            .Returns(new List <TrackFile>
            {
                new TrackFile
                {
                    Path     = "C:\\file2.avi".AsOsAgnostic(),
                    Size     = 10,
                    Modified = _lastWrite
                }
            });

            Subject.FilterUnchangedFiles(files, filter).Should().HaveCount(3);
            Subject.FilterUnchangedFiles(files, filter).Select(x => x.FullName).Should().Contain("C:\\file2.avi".AsOsAgnostic());
        }
Esempio n. 5
0
        public List <ManualImportItem> GetMediaFiles(string path, string downloadId, FilterFilesType filter, bool replaceExistingFiles)
        {
            if (downloadId.IsNotNullOrWhiteSpace())
            {
                var trackedDownload = _trackedDownloadService.Find(downloadId);

                if (trackedDownload == null)
                {
                    return(new List <ManualImportItem>());
                }

                path = trackedDownload.DownloadItem.OutputPath.FullPath;
            }

            if (!_diskProvider.FolderExists(path))
            {
                if (!_diskProvider.FileExists(path))
                {
                    return(new List <ManualImportItem>());
                }

                var decision = _importDecisionMaker.GetImportDecisions(new List <IFileInfo> {
                    _diskProvider.GetFileInfo(path)
                }, null, null, null, null, null, FilterFilesType.None, true, false, !replaceExistingFiles);
                var result = MapItem(decision.First(), Path.GetDirectoryName(path), downloadId, replaceExistingFiles, false);

                return(new List <ManualImportItem> {
                    result
                });
            }

            return(ProcessFolder(path, downloadId, filter, replaceExistingFiles));
        }
Esempio n. 6
0
        public void filter_unmatched_should_not_return_existing_file_if_matched(FilterFilesType filter)
        {
            FileSystem.AddFile("C:\\file1.avi".AsOsAgnostic(), new MockFileData("".PadRight(10))
            {
                LastWriteTime = _lastWrite
            });
            FileSystem.AddFile("C:\\file2.avi".AsOsAgnostic(), new MockFileData("".PadRight(10))
            {
                LastWriteTime = _lastWrite
            });
            FileSystem.AddFile("C:\\file3.avi".AsOsAgnostic(), new MockFileData("".PadRight(10))
            {
                LastWriteTime = _lastWrite
            });

            var files = FileSystem.AllFiles.Select(x => DiskProvider.GetFileInfo(x)).ToList();

            Mocker.GetMock <IMediaFileRepository>()
            .Setup(c => c.GetFilesWithBasePath(It.IsAny <string>()))
            .Returns(new List <TrackFile>
            {
                new TrackFile {
                    Path     = "C:\\file2.avi".AsOsAgnostic(),
                    Size     = 10,
                    Modified = _lastWrite,
                    Tracks   = Builder <Track> .CreateListOfSize(1).Build() as List <Track>
                }
            });

            Subject.FilterUnchangedFiles(files, _artist, filter).Should().HaveCount(2);
            Subject.FilterUnchangedFiles(files, _artist, filter).Select(x => x.FullName).Should().NotContain("C:\\file2.avi".AsOsAgnostic());
        }
Esempio n. 7
0
        public List <IFileInfo> FilterUnchangedFiles(List <IFileInfo> files, FilterFilesType filter)
        {
            if (filter == FilterFilesType.None)
            {
                return(files);
            }

            _logger.Debug($"Filtering {files.Count} files for unchanged files");

            var knownFiles = GetFileWithPath(files.Select(x => x.FullName).ToList());

            _logger.Trace($"Got {knownFiles.Count} existing files");

            if (!knownFiles.Any())
            {
                return(files);
            }

            var combined = files
                           .Join(knownFiles,
                                 f => f.FullName,
                                 af => af.Path,
                                 (f, af) => new { DiskFile = f, DbFile = af },
                                 PathEqualityComparer.Instance)
                           .ToList();

            _logger.Trace($"Matched paths for {combined.Count} files");

            List <IFileInfo> unwanted = null;

            if (filter == FilterFilesType.Known)
            {
                unwanted = combined
                           .Where(x => x.DiskFile.Length == x.DbFile.Size &&
                                  Math.Abs((x.DiskFile.LastWriteTimeUtc - x.DbFile.Modified).TotalSeconds) <= 1)
                           .Select(x => x.DiskFile)
                           .ToList();
                _logger.Trace($"{unwanted.Count} unchanged existing files");
            }
            else if (filter == FilterFilesType.Matched)
            {
                unwanted = combined
                           .Where(x => x.DiskFile.Length == x.DbFile.Size &&
                                  Math.Abs((x.DiskFile.LastWriteTimeUtc - x.DbFile.Modified).TotalSeconds) <= 1 &&
                                  (x.DbFile.Edition == null || (x.DbFile.Edition.IsLoaded && x.DbFile.Edition.Value != null)))
                           .Select(x => x.DiskFile)
                           .ToList();
                _logger.Trace($"{unwanted.Count} unchanged and matched files");
            }
            else
            {
                throw new ArgumentException("Unrecognised value of FilterFilesType filter");
            }

            return(files.Except(unwanted).ToList());
        }
Esempio n. 8
0
        public void filter_should_return_all_files_if_no_existing_files(FilterFilesType filter)
        {
            var files = GivenFiles(new[]
            {
                "C:\\file1.avi".AsOsAgnostic(),
                "C:\\file2.avi".AsOsAgnostic(),
                "C:\\file3.avi".AsOsAgnostic()
            });

            Mocker.GetMock <IMediaFileRepository>()
            .Setup(c => c.GetFileWithPath(It.IsAny <List <string> >()))
            .Returns(new List <TrackFile>());

            Subject.FilterUnchangedFiles(files, filter).Should().BeEquivalentTo(files);
        }
Esempio n. 9
0
        public void filter_should_not_change_casing(FilterFilesType filter)
        {
            var files = GivenFiles(new[]
            {
                "C:\\FILE1.avi".AsOsAgnostic()
            });

            Mocker.GetMock <IMediaFileRepository>()
            .Setup(c => c.GetFileWithPath(It.IsAny <List <string> >()))
            .Returns(new List <TrackFile>());

            Subject.FilterUnchangedFiles(files, filter).Should().HaveCount(1);
            Subject.FilterUnchangedFiles(files, filter).Select(x => x.FullName).Should().NotContain(files.First().FullName.ToLower());
            Subject.FilterUnchangedFiles(files, filter).Should().Contain(files.First());
        }
Esempio n. 10
0
        public void filter_should_return_nothing_if_all_files_exist(FilterFilesType filter)
        {
            var files = GivenFiles(new []
            {
                "C:\\file1.avi".AsOsAgnostic(),
                "C:\\file2.avi".AsOsAgnostic(),
                "C:\\file3.avi".AsOsAgnostic()
            });

            Mocker.GetMock <IMediaFileRepository>()
            .Setup(c => c.GetFilesWithBasePath(It.IsAny <string>()))
            .Returns(files.Select(f => new TrackFile {
                Path     = f.FullName,
                Modified = _lastWrite
            }).ToList());

            Subject.FilterUnchangedFiles(files, _artist, filter).Should().BeEmpty();
        }
Esempio n. 11
0
        public void filter_should_return_none_existing_files_not_ignoring_case(FilterFilesType filter)
        {
            MonoOnly();

            var files = GivenFiles(new []
            {
                "C:\\file1.avi".AsOsAgnostic(),
                "C:\\FILE2.avi".AsOsAgnostic(),
                "C:\\file3.avi".AsOsAgnostic()
            });

            Mocker.GetMock <IMediaFileRepository>()
            .Setup(c => c.GetFilesWithBasePath(It.IsAny <string>()))
            .Returns(new List <TrackFile>
            {
                new TrackFile {
                    Path     = "C:\\file2.avi".AsOsAgnostic(),
                    Modified = _lastWrite
                }
            });

            Subject.FilterUnchangedFiles(files, _artist, filter).Should().HaveCount(3);
        }
Esempio n. 12
0
        public List <ImportDecision <LocalTrack> > GetImportDecisions(List <IFileInfo> musicFiles, Artist artist, Album album, AlbumRelease albumRelease, DownloadClientItem downloadClientItem, ParsedTrackInfo folderInfo, FilterFilesType filter, bool newDownload, bool singleRelease, bool includeExisting)
        {
            var watch = new System.Diagnostics.Stopwatch();

            watch.Start();

            var files = filter != FilterFilesType.None && (artist != null) ? _mediaFileService.FilterUnchangedFiles(musicFiles, artist, filter) : musicFiles;

            var localTracks = new List <LocalTrack>();
            var decisions   = new List <ImportDecision <LocalTrack> >();

            _logger.Debug("Analyzing {0}/{1} files.", files.Count, musicFiles.Count);

            if (!files.Any())
            {
                return(decisions);
            }

            ParsedAlbumInfo downloadClientItemInfo = null;

            if (downloadClientItem != null)
            {
                downloadClientItemInfo = Parser.Parser.ParseAlbumTitle(downloadClientItem.Title);
            }

            foreach (var file in files)
            {
                var localTrack = new LocalTrack
                {
                    Artist = artist,
                    Album  = album,
                    DownloadClientAlbumInfo = downloadClientItemInfo,
                    FolderTrackInfo         = folderInfo,
                    Path           = file.FullName,
                    Size           = file.Length,
                    Modified       = file.LastWriteTimeUtc,
                    FileTrackInfo  = _audioTagService.ReadTags(file.FullName),
                    ExistingFile   = !newDownload,
                    AdditionalFile = false
                };

                try
                {
                    // TODO fix otherfiles?
                    _augmentingService.Augment(localTrack, true);
                    localTracks.Add(localTrack);
                }
                catch (AugmentingFailedException)
                {
                    decisions.Add(new ImportDecision <LocalTrack>(localTrack, new Rejection("Unable to parse file")));
                }
                catch (Exception e)
                {
                    _logger.Error(e, "Couldn't import file. {0}", localTrack.Path);

                    decisions.Add(new ImportDecision <LocalTrack>(localTrack, new Rejection("Unexpected error processing file")));
                }
            }

            _logger.Debug($"Tags parsed for {files.Count} files in {watch.ElapsedMilliseconds}ms");

            var releases = _identificationService.Identify(localTracks, artist, album, albumRelease, newDownload, singleRelease, includeExisting);

            foreach (var release in releases)
            {
                release.NewDownload = newDownload;
                var releaseDecision = GetDecision(release);

                foreach (var localTrack in release.LocalTracks)
                {
                    if (releaseDecision.Approved)
                    {
                        decisions.AddIfNotNull(GetDecision(localTrack));
                    }
                    else
                    {
                        decisions.Add(new ImportDecision <LocalTrack>(localTrack, releaseDecision.Rejections.ToArray()));
                    }
                }
            }

            return(decisions);
        }
Esempio n. 13
0
 public RescanArtistCommand(FilterFilesType filter = FilterFilesType.Known)
 {
     Filter = filter;
 }
Esempio n. 14
0
        public Tuple <List <LocalTrack>, List <ImportDecision <LocalTrack> > > GetLocalTracks(List <IFileInfo> musicFiles, DownloadClientItem downloadClientItem, ParsedTrackInfo folderInfo, FilterFilesType filter)
        {
            var watch = new System.Diagnostics.Stopwatch();

            watch.Start();

            var files = _mediaFileService.FilterUnchangedFiles(musicFiles, filter);

            var localTracks = new List <LocalTrack>();
            var decisions   = new List <ImportDecision <LocalTrack> >();

            _logger.Debug("Analyzing {0}/{1} files.", files.Count, musicFiles.Count);

            if (!files.Any())
            {
                return(Tuple.Create(localTracks, decisions));
            }

            ParsedAlbumInfo downloadClientItemInfo = null;

            if (downloadClientItem != null)
            {
                downloadClientItemInfo = Parser.Parser.ParseAlbumTitle(downloadClientItem.Title);
            }

            int i = 1;

            foreach (var file in files)
            {
                _logger.ProgressInfo($"Reading file {i++}/{files.Count}");

                var localTrack = new LocalTrack
                {
                    DownloadClientAlbumInfo = downloadClientItemInfo,
                    FolderTrackInfo         = folderInfo,
                    Path           = file.FullName,
                    Size           = file.Length,
                    Modified       = file.LastWriteTimeUtc,
                    FileTrackInfo  = _audioTagService.ReadTags(file.FullName),
                    AdditionalFile = false
                };

                try
                {
                    // TODO fix otherfiles?
                    _augmentingService.Augment(localTrack, true);
                    localTracks.Add(localTrack);
                }
                catch (AugmentingFailedException)
                {
                    decisions.Add(new ImportDecision <LocalTrack>(localTrack, new Rejection("Unable to parse file")));
                }
                catch (Exception e)
                {
                    _logger.Error(e, "Couldn't import file. {0}", localTrack.Path);

                    decisions.Add(new ImportDecision <LocalTrack>(localTrack, new Rejection("Unexpected error processing file")));
                }
            }

            _logger.Debug($"Tags parsed for {files.Count} files in {watch.ElapsedMilliseconds}ms");

            return(Tuple.Create(localTracks, decisions));
        }
Esempio n. 15
0
        public void Scan(List <string> folders = null, FilterFilesType filter = FilterFilesType.Known, bool addNewAuthors = false, List <int> authorIds = null)
        {
            if (folders == null)
            {
                folders = _rootFolderService.All().Select(x => x.Path).ToList();
            }

            if (authorIds == null)
            {
                authorIds = new List <int>();
            }

            var mediaFileList = new List <IFileInfo>();

            var musicFilesStopwatch = Stopwatch.StartNew();

            foreach (var folder in folders)
            {
                // We could be scanning a root folder or a subset of a root folder.  If it's a subset,
                // check if the root folder exists before cleaning.
                var rootFolder = _rootFolderService.GetBestRootFolder(folder);

                if (rootFolder == null)
                {
                    _logger.Error("Not scanning {0}, it's not a subdirectory of a defined root folder", folder);
                    return;
                }

                var folderExists = _diskProvider.FolderExists(folder);

                if (!folderExists)
                {
                    if (!_diskProvider.FolderExists(rootFolder.Path))
                    {
                        _logger.Warn("Authors' root folder ({0}) doesn't exist.", rootFolder);
                        var skippedAuthors = _authorService.GetAuthors(authorIds);
                        skippedAuthors.ForEach(x => _eventAggregator.PublishEvent(new AuthorScanSkippedEvent(x, AuthorScanSkippedReason.RootFolderDoesNotExist)));
                        return;
                    }

                    if (_diskProvider.FolderEmpty(rootFolder.Path))
                    {
                        _logger.Warn("Authors' root folder ({0}) is empty.", rootFolder);
                        var skippedAuthors = _authorService.GetAuthors(authorIds);
                        skippedAuthors.ForEach(x => _eventAggregator.PublishEvent(new AuthorScanSkippedEvent(x, AuthorScanSkippedReason.RootFolderIsEmpty)));
                        return;
                    }
                }

                if (!folderExists)
                {
                    _logger.Debug("Specified scan folder ({0}) doesn't exist.", folder);

                    CleanMediaFiles(folder, new List <string>());
                    continue;
                }

                _logger.ProgressInfo("Scanning {0}", folder);

                var files = FilterFiles(folder, GetBookFiles(folder));

                if (!files.Any())
                {
                    _logger.Warn("Scan folder {0} is empty.", folder);
                    continue;
                }

                CleanMediaFiles(folder, files.Select(x => x.FullName).ToList());
                mediaFileList.AddRange(files);
            }

            musicFilesStopwatch.Stop();
            _logger.Trace("Finished getting track files for:\n{0} [{1}]", folders.ConcatToString("\n"), musicFilesStopwatch.Elapsed);

            var decisionsStopwatch = Stopwatch.StartNew();

            var config = new ImportDecisionMakerConfig
            {
                Filter          = filter,
                IncludeExisting = true,
                AddNewAuthors   = addNewAuthors
            };

            var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, null, null, config);

            decisionsStopwatch.Stop();
            _logger.Debug("Import decisions complete [{0}]", decisionsStopwatch.Elapsed);

            var importStopwatch = Stopwatch.StartNew();

            _importApprovedTracks.Import(decisions, false);

            // decisions may have been filtered to just new files.  Anything new and approved will have been inserted.
            // Now we need to make sure anything new but not approved gets inserted
            // Note that knownFiles will include anything imported just now
            var knownFiles = new List <BookFile>();

            folders.ForEach(x => knownFiles.AddRange(_mediaFileService.GetFilesWithBasePath(x)));

            var newFiles = decisions
                           .ExceptBy(x => x.Item.Path, knownFiles, x => x.Path, PathEqualityComparer.Instance)
                           .Select(decision => new BookFile
            {
                Path      = decision.Item.Path,
                CalibreId = decision.Item.Path.ParseCalibreId(),
                Size      = decision.Item.Size,
                Modified  = decision.Item.Modified,
                DateAdded = DateTime.UtcNow,
                Quality   = decision.Item.Quality,
                MediaInfo = decision.Item.FileTrackInfo.MediaInfo,
                Edition   = decision.Item.Edition
            })
                           .ToList();

            _mediaFileService.AddMany(newFiles);

            _logger.Debug($"Inserted {newFiles.Count} new unmatched trackfiles");

            // finally update info on size/modified for existing files
            var updatedFiles = knownFiles
                               .Join(decisions,
                                     x => x.Path,
                                     x => x.Item.Path,
                                     (file, decision) => new
            {
                File = file,
                Item = decision.Item
            },
                                     PathEqualityComparer.Instance)
                               .Where(x => x.File.Size != x.Item.Size ||
                                      Math.Abs((x.File.Modified - x.Item.Modified).TotalSeconds) > 1)
                               .Select(x =>
            {
                x.File.Size      = x.Item.Size;
                x.File.Modified  = x.Item.Modified;
                x.File.MediaInfo = x.Item.FileTrackInfo.MediaInfo;
                x.File.Quality   = x.Item.Quality;
                return(x.File);
            })
                               .ToList();

            _mediaFileService.Update(updatedFiles);

            _logger.Debug($"Updated info for {updatedFiles.Count} known files");

            var authors = _authorService.GetAuthors(authorIds);

            foreach (var author in authors)
            {
                CompletedScanning(author);
            }

            importStopwatch.Stop();
            _logger.Debug("Book import complete for:\n{0} [{1}]", folders.ConcatToString("\n"), importStopwatch.Elapsed);
        }
Esempio n. 16
0
        private List <ManualImportItem> ProcessFolder(string folder, string downloadId, FilterFilesType filter, bool replaceExistingFiles)
        {
            var directoryInfo = new DirectoryInfo(folder);
            var artist        = _parsingService.GetArtist(directoryInfo.Name);

            if (artist == null && downloadId.IsNotNullOrWhiteSpace())
            {
                var trackedDownload = _trackedDownloadService.Find(downloadId);
                artist = trackedDownload.RemoteAlbum?.Artist;
            }

            var folderInfo  = Parser.Parser.ParseMusicTitle(directoryInfo.Name);
            var artistFiles = _diskScanService.GetAudioFiles(folder).ToList();
            var decisions   = _importDecisionMaker.GetImportDecisions(artistFiles, artist, null, null, null, folderInfo, filter, true, false, !replaceExistingFiles);

            // paths will be different for new and old files which is why we need to map separately
            var newFiles = artistFiles.Join(decisions,
                                            f => f.FullName,
                                            d => d.Item.Path,
                                            (f, d) => new { File = f, Decision = d },
                                            PathEqualityComparer.Instance);

            var newItems          = newFiles.Select(x => MapItem(x.Decision, folder, downloadId, replaceExistingFiles, false));
            var existingDecisions = decisions.Except(newFiles.Select(x => x.Decision));
            var existingItems     = existingDecisions.Select(x => MapItem(x, x.Item.Artist.Path, null, replaceExistingFiles, false));

            return(newItems.Concat(existingItems).ToList());
        }
Esempio n. 17
0
        public void Scan(Artist artist, FilterFilesType filter = FilterFilesType.Known)
        {
            var rootFolder = _rootFolderService.GetBestRootFolderPath(artist.Path);

            if (!_diskProvider.FolderExists(rootFolder))
            {
                _logger.Warn("Artist' root folder ({0}) doesn't exist.", rootFolder);
                _eventAggregator.PublishEvent(new ArtistScanSkippedEvent(artist, ArtistScanSkippedReason.RootFolderDoesNotExist));
                return;
            }

            if (_diskProvider.GetDirectories(rootFolder).Empty())
            {
                _logger.Warn("Artist' root folder ({0}) is empty.", rootFolder);
                _eventAggregator.PublishEvent(new ArtistScanSkippedEvent(artist, ArtistScanSkippedReason.RootFolderIsEmpty));
                return;
            }

            _logger.ProgressInfo("Scanning {0}", artist.Name);

            if (!_diskProvider.FolderExists(artist.Path))
            {
                if (_configService.CreateEmptyArtistFolders)
                {
                    _logger.Debug("Creating missing artist folder: {0}", artist.Path);
                    _diskProvider.CreateFolder(artist.Path);
                    SetPermissions(artist.Path);
                }
                else
                {
                    _logger.Debug("Artist folder doesn't exist: {0}", artist.Path);
                }

                CleanMediaFiles(artist, new List <string>());
                CompletedScanning(artist);

                return;
            }

            var musicFilesStopwatch = Stopwatch.StartNew();
            var mediaFileList       = FilterFiles(artist.Path, GetAudioFiles(artist.Path)).ToList();

            musicFilesStopwatch.Stop();
            _logger.Trace("Finished getting track files for: {0} [{1}]", artist, musicFilesStopwatch.Elapsed);

            CleanMediaFiles(artist, mediaFileList.Select(x => x.FullName).ToList());

            var decisionsStopwatch = Stopwatch.StartNew();
            var decisions          = _importDecisionMaker.GetImportDecisions(mediaFileList, artist, filter, true);

            decisionsStopwatch.Stop();
            _logger.Debug("Import decisions complete for: {0} [{1}]", artist, decisionsStopwatch.Elapsed);

            var importStopwatch = Stopwatch.StartNew();

            _importApprovedTracks.Import(decisions, false);

            // decisions may have been filtered to just new files.  Anything new and approved will have been inserted.
            // Now we need to make sure anything new but not approved gets inserted
            // Note that knownFiles will include anything imported just now
            var knownFiles = _mediaFileService.GetFilesWithBasePath(artist.Path);

            var newFiles = decisions
                           .ExceptBy(x => x.Item.Path, knownFiles, x => x.Path, PathEqualityComparer.Instance)
                           .Select(decision => new TrackFile {
                Path      = decision.Item.Path,
                Size      = decision.Item.Size,
                Modified  = decision.Item.Modified,
                DateAdded = DateTime.UtcNow,
                Quality   = decision.Item.Quality,
                MediaInfo = decision.Item.FileTrackInfo.MediaInfo
            })
                           .ToList();

            _mediaFileService.AddMany(newFiles);

            _logger.Debug($"Inserted {newFiles.Count} new unmatched trackfiles");

            // finally update info on size/modified for existing files
            var updatedFiles = knownFiles
                               .Join(decisions,
                                     x => x.Path,
                                     x => x.Item.Path,
                                     (file, decision) => new {
                File = file,
                Item = decision.Item
            },
                                     PathEqualityComparer.Instance)
                               .Where(x => x.File.Size != x.Item.Size ||
                                      Math.Abs((x.File.Modified - x.Item.Modified).TotalSeconds) > 1)
                               .Select(x => {
                x.File.Size      = x.Item.Size;
                x.File.Modified  = x.Item.Modified;
                x.File.MediaInfo = x.Item.FileTrackInfo.MediaInfo;
                x.File.Quality   = x.Item.Quality;
                return(x.File);
            })
                               .ToList();

            _mediaFileService.Update(updatedFiles);

            _logger.Debug($"Updated info for {updatedFiles.Count} known files");

            RemoveEmptyArtistFolder(artist.Path);

            CompletedScanning(artist);
            importStopwatch.Stop();
            _logger.Debug("Track import complete for: {0} [{1}]", artist, importStopwatch.Elapsed);
        }
Esempio n. 18
0
 public RescanArtistCommand(int artistId, FilterFilesType filter = FilterFilesType.Known)
 {
     ArtistId = artistId;
     Filter   = filter;
 }
Esempio n. 19
0
        private List <ManualImportItem> ProcessFolder(string folder, string downloadId, Artist artist, FilterFilesType filter, bool replaceExistingFiles)
        {
            DownloadClientItem downloadClientItem = null;
            var directoryInfo = new DirectoryInfo(folder);

            artist = artist ?? _parsingService.GetArtist(directoryInfo.Name);

            if (downloadId.IsNotNullOrWhiteSpace())
            {
                var trackedDownload = _trackedDownloadService.Find(downloadId);
                downloadClientItem = trackedDownload.DownloadItem;

                if (artist == null)
                {
                    artist = trackedDownload.RemoteAlbum?.Artist;
                }
            }

            var artistFiles = _diskScanService.GetAudioFiles(folder).ToList();
            var idOverrides = new IdentificationOverrides
            {
                Artist = artist
            };
            var itemInfo = new ImportDecisionMakerInfo
            {
                DownloadClientItem = downloadClientItem,
                ParsedTrackInfo    = Parser.Parser.ParseMusicTitle(directoryInfo.Name)
            };
            var config = new ImportDecisionMakerConfig
            {
                Filter          = filter,
                NewDownload     = true,
                SingleRelease   = false,
                IncludeExisting = !replaceExistingFiles,
                AddNewArtists   = false
            };

            var decisions = _importDecisionMaker.GetImportDecisions(artistFiles, idOverrides, itemInfo, config);

            // paths will be different for new and old files which is why we need to map separately
            var newFiles = artistFiles.Join(decisions,
                                            f => f.FullName,
                                            d => d.Item.Path,
                                            (f, d) => new { File = f, Decision = d },
                                            PathEqualityComparer.Instance);

            var newItems          = newFiles.Select(x => MapItem(x.Decision, downloadId, replaceExistingFiles, false));
            var existingDecisions = decisions.Except(newFiles.Select(x => x.Decision));
            var existingItems     = existingDecisions.Select(x => MapItem(x, null, replaceExistingFiles, false));

            return(newItems.Concat(existingItems).ToList());
        }
Esempio n. 20
0
 public List <ImportDecision <LocalTrack> > GetImportDecisions(List <IFileInfo> musicFiles, Artist artist, FilterFilesType filter, bool includeExisting)
 {
     return(GetImportDecisions(musicFiles, artist, null, null, null, null, filter, false, false, true));
 }
Esempio n. 21
0
        public List <ManualImportItem> GetMediaFiles(string path, string downloadId, Artist artist, FilterFilesType filter, bool replaceExistingFiles)
        {
            if (downloadId.IsNotNullOrWhiteSpace())
            {
                var trackedDownload = _trackedDownloadService.Find(downloadId);

                if (trackedDownload == null)
                {
                    return(new List <ManualImportItem>());
                }

                if (trackedDownload.ImportItem == null)
                {
                    trackedDownload.ImportItem = _provideImportItemService.ProvideImportItem(trackedDownload.DownloadItem, trackedDownload.ImportItem);
                }

                path = trackedDownload.ImportItem.OutputPath.FullPath;
            }

            if (!_diskProvider.FolderExists(path))
            {
                if (!_diskProvider.FileExists(path))
                {
                    return(new List <ManualImportItem>());
                }

                var files = new List <IFileInfo> {
                    _diskProvider.GetFileInfo(path)
                };

                var config = new ImportDecisionMakerConfig
                {
                    Filter          = FilterFilesType.None,
                    NewDownload     = true,
                    SingleRelease   = false,
                    IncludeExisting = !replaceExistingFiles,
                    AddNewArtists   = false
                };

                var decision = _importDecisionMaker.GetImportDecisions(files, null, null, config);
                var result   = MapItem(decision.First(), downloadId, replaceExistingFiles, false);

                return(new List <ManualImportItem> {
                    result
                });
            }

            return(ProcessFolder(path, downloadId, artist, filter, replaceExistingFiles));
        }