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)); }
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(); }
private void bScanDir_Click(object sender, EventArgs e) { if (MainForm.startScan) // start or stop scanning { scandir = new ScanDirectory(form); scandir.startScan(); } else { scandir.stopScan(); } }
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) { } }
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); }
/// <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); } } }
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(); }
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 }); }