Пример #1
0
        public AudioBook(ScanDirectory dir)
        {
            AudioBookDirectoryPath = dir.FullPath;
            Files = new List <AudioFile>();
            foreach (ScanFile file in dir.ScanFiles.Where(x => x.IsAudioFile))
            {
                Files.Add(new AudioFile(file));
            }

            Files.Sort((file1, file2) => file1.TrackNumber.CompareTo(file2.TrackNumber));
        }
Пример #2
0
 public MainViewModel()
 {
     MessengerInstance.Register <SettingMG>(this, ProcessingMG);
     Settings = SettingsManager.GetSettings();
     if (!SettingsManager.IsExist())
     {
         Settings = new SettingMG("C:\\Users\\PC\\source\\repos", 0, 0, 0);
     }
     scanner   = new ScanDirectory(Settings.DirectoryPath);
     Solutions = scanner.GetSolutions();
     UpdateCollection();
 }
Пример #3
0
 private void bScanDir_Click(object sender, EventArgs e)
 {
     if (MainForm.startScan)                                     // start or stop scanning
     {
         scandir = new ScanDirectory(form);
         scandir.startScan();
     }
     else
     {
         scandir.stopScan();
     }
 }
Пример #4
0
 private void AddDirectoryContents(string path)
 {
     try
     {
         var scanDirectory = new ScanDirectory(_sender._logger, _sender._excludeList,
                                               false, _cancellationTokenSource.Token);
         foreach (var srcEntry in scanDirectory.ScanPath(_sender._srcPath, path))
         {
             _sender.AddChange(FsSenderChange.CreateChange(srcEntry.Path));
         }
     }
     catch (OperationCanceledException)
     {
     }
 }
Пример #5
0
        private void OnScanDirectory(ScanDirectory message)
        {
            var dir    = message.Directory;
            var result = new ScanDirectoryResults
            {
                TaskId = message.TaskId
            };

            if (dir is null || !dir.Exists)
            {
                Context.Parent.Tell(result);
                return;
            }

            _log.Debug("Scanning directory: {@Directory}", dir.FullName);

            var dirList = dir.GetDirectories();
            var files   = dir.GetFiles();

            result.Diretories = dirList.Length;

            foreach (var f in files)
            {
                if (f.Exists)
                {
                    _eventService.Emit(EventTypes.IO.DirectoryFileFound, f);
                }
            }

            _log.Debug("Scanning directory: {@Directory}, found {@Files} files", dir.FullName, files.Length);

            foreach (var d in dirList)
            {
                if (d.Exists)
                {
                    Context.Parent.Tell(new ScanDirectory
                    {
                        Directory = d,
                        TaskId    = message.TaskId
                    });
                }
            }

            Context.Parent.Tell(result);
        }
Пример #6
0
        /// <summary>
        /// Scan for audiobooks recursively from start directory up to the maximum recursion depth (20)
        /// Warning: This will recognize each directory as an audiobook with the files therein as tracks, it will not detect individual files as individual books
        /// </summary>
        /// <param name="directoryInfo">Starting directory information</param>
        /// <param name="depth">Current recursion depth, should be set to default (0) expect for recursive calls</param>
        /// <returns>Collection of detected audiobook folders with each audio file therein as a track</returns>
        private IEnumerable <AudioBook> ScanForBooks(DirectoryInfo directoryInfo, int depth = 0)
        {
            ScanDirectory dir = new ScanDirectory(directoryInfo);

            if (dir.ScanFiles.Count > 0)
            {
                //Attempt to group directory's files into albums
                IEnumerable <IGrouping <string, ScanFile> > albumGroups = dir.ScanFiles.GroupBy(x => x?.Tags?.AlbumName ?? "");
                foreach (var albumGroup in albumGroups)
                {
                    //Assume that groups of files with the same album are an audiobook
                    if (albumGroup.Count() > 1 && albumGroup.Key != "")
                    {
                        //remove from pool of files remaining in directory
                        dir.ScanFiles.RemoveAll(x => albumGroup.Contains(x));
                        yield return(new AudioBook(new ScanDirectory(dir.FullPath, albumGroup.ToList())));
                    }
                }

                //only return remaining files as audiobook if the album grouping method missed some
                if (dir.ScanFiles.Count > 0)
                {
                    yield return(dir.ToAudioBook());
                }
            }

            //recurse into child directories
            foreach (DirectoryInfo childDirectory in directoryInfo.EnumerateDirectories())
            {
                //break at specified depth to prevent infinite loops and such
                if (depth == MaxRecursionDepth)
                {
                    yield break;
                }
                foreach (AudioBook audioBook in ScanForBooks(childDirectory, depth + 1))
                {
                    yield return(audioBook);
                }
            }
        }
Пример #7
0
        private void Scan()
        {
            var            sw      = SlimStopwatch.StartNew();
            List <FsEntry> srcList = null;
            Dictionary <string, FsEntry> destList;

            /*
             * Start agent before scan source
             *
             * Old timeline: [Main thread]       Start ... Initialize ... Scan destination ... Finish
             *               [Secondary thread]  Scan source ................................. Finish
             *
             * New timeline: [Main thread]       Start ... Initialize ... Scan destination ... Finish
             *               [Secondary thread]            Scan source ....................... Finish
             *
             * A failed start could cause unnecessary scanning source in old timeline.
             * No need to scan source before start in most cases because it is about as fast as the scan destination.
             */
            using (var tokenSource = CancellationTokenSource.CreateLinkedTokenSource(_cancellationTokenSource.Token))
            {
                var cancellationToken = tokenSource.Token;
                cancellationToken.ThrowIfCancellationRequested();

                _agentStarter.Start();

                // scan source
                var task = Task.Run(() =>
                {
                    try
                    {
                        var swScanSource  = SlimStopwatch.StartNew();
                        var scanDirectory =
                            new ScanDirectory(_logger, _excludeList, cancellationToken: cancellationToken);
                        srcList = scanDirectory.ScanPath(_srcPath).ToList();
                        cancellationToken.ThrowIfCancellationRequested();
                        _logger.Log($"Scanned source {srcList.Count} items in {swScanSource.ElapsedMilliseconds} ms");
                    }
                    catch (OperationCanceledException)
                    {
                        srcList = null;
                    }
                }, cancellationToken);

                try
                {
                    var swScanDestination = SlimStopwatch.StartNew();
                    // scan destination
                    var response = _agentStarter.SendCommand <ScanResponse>(new ScanRequest(_logger));
                    destList = response.FileList.ToDictionary(x => x.Path, y => y);
                    _logger.Log(
                        $"Scanned destination {destList.Count} items in {swScanDestination.ElapsedMilliseconds} ms");
                    task.Wait(cancellationToken);
                }
                catch (Exception)
                {
                    tokenSource.Cancel();
                    throw;
                }
            }

            // During scan, changes could come from file system events or from PathScanner, we should not overwrite them.
            var  itemsCount  = 0;
            long changesSize = 0;

            lock (_changes)
            {
                foreach (var srcEntry in srcList)
                {
                    if (!destList.TryGetValue(srcEntry.Path, out var destEntry))
                    {
                        destEntry = FsEntry.Empty;
                    }

                    // Skip changed srcEntry
                    if (!_changes.ContainsKey(srcEntry.Path))
                    {
                        // add to changes (no replace)
                        if (!srcEntry.Equals(destEntry))
                        {
                            itemsCount++;
                            if (!srcEntry.IsDirectory)
                            {
                                changesSize += srcEntry.Length;
                            }
                            AddChange(FsSenderChange.CreateChange(srcEntry), false);
                        }
                    }

                    if (!destEntry.IsEmpty)
                    {
                        destList.Remove(destEntry.Path);
                    }
                }

                // add deletes
                foreach (var destEntry in destList.Values)
                {
                    // Skip changed destEntry
                    if (!_changes.ContainsKey(destEntry.Path))
                    {
                        itemsCount++;
                        AddChange(FsSenderChange.CreateRemove(destEntry.Path), false);
                    }
                }
            }

            _needToScan = false;
            _logger.Log(
                $"Scanned in {sw.ElapsedMilliseconds} ms, {itemsCount} items, {PrettySize(changesSize)} to send");
            UpdateHasWork();
        }
Пример #8
0
        private FsChangeResult ApplyFsChange(FsChange fsChange, FileMaskList excludeList)
        {
            var path = Path.Combine(BasePath, fsChange.Path);
            FsChangeResultCode resultCode = FsChangeResultCode.None;
            string             error      = null;

            // Change file | Remove |  Rename + Change directory
            if (fsChange.IsChange && !fsChange.IsDirectory)
            {
                try
                {
                    if (fsChange.HasBody && Reader.ReadFsChangeBody(path, fsChange))
                    {
                        resultCode = FsChangeResultCode.Ok;
                    }
                    else
                    {
                        // error occurred in sender
                        error      = "Sender error";
                        resultCode = FsChangeResultCode.SenderError;
                    }
                }
                catch (EndOfStreamException)
                {
                    // end of data
                    throw;
                }
                catch (Exception ex)
                {
                    resultCode = FsChangeResultCode.Error;
                    error      = ex.Message;
                }
            }
            else if (fsChange.IsRemove)
            {
                // directory
                if (Directory.Exists(path))
                {
                    var       scanDirectory = new ScanDirectory(Logger, excludeList, false);
                    Exception exception     = null;
                    foreach (var fsEntry in scanDirectory.ScanPath(BasePath, fsChange.Path))
                    {
                        var fsEntryPath = Path.Combine(BasePath, fsEntry.Path);
                        try
                        {
                            if (fsEntry.IsDirectory)
                            {
                                Directory.Delete(fsEntryPath, false);
                            }
                            else
                            {
                                File.Delete(fsEntryPath);
                            }
                        }
                        catch (Exception ex)
                        {
                            exception ??= ex;
                            Logger.Log($"Error deleting {fsEntryPath}: {ex.Message}", LogLevel.Warning);
                        }
                    }

                    try
                    {
                        Directory.Delete(path, false);
                    }
                    catch (Exception ex)
                    {
                        exception ??= ex;
                        Logger.Log($"Error deleting {path}: {ex.Message}", LogLevel.Warning);
                    }

                    if (exception == null)
                    {
                        resultCode = FsChangeResultCode.Ok;
                    }
                    else
                    {
                        // scan directory see any file -> error (handle excludes)
                        if (scanDirectory.ScanPath(BasePath, fsChange.Path).Any(x => !x.IsDirectory))
                        {
                            resultCode = FsChangeResultCode.Error;
                            error      = exception.Message;
                        }
                        else
                        {
                            resultCode = FsChangeResultCode.Ok;
                        }
                    }
                }
                else if (File.Exists(path))
                {
                    try
                    {
                        File.Delete(path);
                        resultCode = FsChangeResultCode.Ok;
                    }
                    catch (Exception ex)
                    {
                        resultCode = FsChangeResultCode.Error;
                        error      = ex.Message;
                    }
                }
                else
                {
                    resultCode = FsChangeResultCode.Ok;
                }
            }
            else
            {
                if (fsChange.IsChange && fsChange.IsDirectory)
                {
                    try
                    {
                        var directoryPath = fsChange.IsRename ? Path.Combine(BasePath, fsChange.OldPath) : path;
                        Directory.CreateDirectory(directoryPath);
                        Directory.SetLastWriteTime(directoryPath, fsChange.LastWriteTime);
                        resultCode = FsChangeResultCode.Ok;
                    }
                    catch (Exception ex)
                    {
                        error      = ex.Message;
                        resultCode = FsChangeResultCode.Error;
                    }
                }

                if (resultCode != FsChangeResultCode.Error && fsChange.IsRename)
                {
                    try
                    {
                        var oldPath = Path.Combine(BasePath, fsChange.OldPath);
                        if (Directory.Exists(oldPath))
                        {
                            Directory.Move(oldPath, path);
                        }
                        else
                        {
                            File.Move(oldPath, path, true);
                        }

                        resultCode = FsChangeResultCode.Ok;
                    }
                    catch (Exception ex)
                    {
                        error      = ex.Message;
                        resultCode = FsChangeResultCode.Error;
                    }
                }
            }

            if (resultCode == FsChangeResultCode.None)
            {
                resultCode = FsChangeResultCode.Error;
                error      = "Unknown change type";
            }

            return(new FsChangeResult
            {
                ChangeType = fsChange.ChangeType,
                Path = fsChange.Path,
                ResultCode = resultCode,
                ErrorMessage = error
            });
        }