Initial commit: Add ShadowStream media application with file scanning and classification

This commit is contained in:
unknown
2025-05-23 20:17:46 +02:00
commit 323fc9e120
955 changed files with 25791 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace file_finder__test;
public class FileClassifier
{
public async Task<(List<string> musicFiles, List<string> videoFiles)> ClassifyFilesAsync(
List<string> allFiles,
List<string> musicExtensions,
List<string> videoExtensions)
{
int coreCount = Environment.ProcessorCount;
int totalFiles = allFiles.Count;
int chunkSize = (int)Math.Ceiling((double)totalFiles / coreCount);
var musicBag = new ConcurrentBag<string>();
var videoBag = new ConcurrentBag<string>();
var tasks = new List<Task>();
for (int i = 0; i < coreCount; i++)
{
int start = i * chunkSize;
int end = Math.Min(start + chunkSize, totalFiles);
tasks.Add(Task.Run(() =>
{
for (int j = start; j < end; j++)
{
string file = allFiles[j];
string ext = Path.GetExtension(file)?.ToLowerInvariant();
if (ext == null)
continue;
if (musicExtensions.Contains(ext))
musicBag.Add(file);
else if (videoExtensions.Contains(ext))
videoBag.Add(file);
}
}));
}
await Task.WhenAll(tasks);
return (new List<string>(musicBag), new List<string>(videoBag));
}
}

View File

@@ -0,0 +1,79 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
public class FileScanner
{
private readonly string[] _extensions;
private readonly ConcurrentBag<string> _foundFiles = new ConcurrentBag<string>();
public FileScanner(string[] extensions)
{
_extensions = extensions.Select(e => e.ToLower()).ToArray();
}
public async Task<List<string>> ScanAllDrivesAsync()
{
var drives = new List<string>();
foreach (var drive in DriveInfo.GetDrives())
{
if (!drive.IsReady) continue;
Console.WriteLine($"Scanning {drive.Name} ...");
string root = drive.RootDirectory.FullName;
drives.Add(root);
}
return drives.ToList();
}
public async Task<List<string>> ScanDriveParallel(string rootPath)
{
var folderQueue = new ConcurrentQueue<string>();
folderQueue.Enqueue(rootPath);
var folderWorkers = new List<Task>();
//add Preformance testing here later
int maxWorkers = Environment.ProcessorCount/2;
for (int i = 0; i < maxWorkers; i++)
{
folderWorkers.Add(Task.Run(() =>
{
while (folderQueue.TryDequeue(out string currentPath))
{
try
{
// Check files
foreach (var file in Directory.GetFiles(currentPath))
{
if (_extensions.Any(ext => file.EndsWith(ext, StringComparison.OrdinalIgnoreCase)))
{
//Console.WriteLine(file);
_foundFiles.Add(file);
}
}
// Enqueue subdirectories
foreach (var dir in Directory.GetDirectories(currentPath))
{
folderQueue.Enqueue(dir);
}
}
catch
{
// Skip inaccessible folders silently
}
}
}));
}
Task.WaitAll(folderWorkers.ToArray());
return _foundFiles.ToList();
}
}

View File

@@ -0,0 +1,49 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
public class VideoSeparator
{
private readonly Regex episodePattern = new Regex(@"E\d{1,3}", RegexOptions.IgnoreCase);
public async Task<(List<string> seriesFiles, List<string> movieFiles)> SeparateVideosAsync(List<string> videoFiles)
{
int coreCount = Environment.ProcessorCount;
int totalFiles = videoFiles.Count;
int chunkSize = (int)Math.Ceiling((double)totalFiles / coreCount);
var seriesBag = new ConcurrentBag<string>();
var movieBag = new ConcurrentBag<string>();
var tasks = new List<Task>();
for (int i = 0; i < coreCount; i++)
{
int start = i * chunkSize;
int end = Math.Min(start + chunkSize, totalFiles);
tasks.Add(Task.Run(() =>
{
for (int j = start; j < end; j++)
{
string path = videoFiles[j];
string filename = Path.GetFileNameWithoutExtension(path);
if (filename == null)
continue;
if (episodePattern.IsMatch(filename))
seriesBag.Add(path);
else
movieBag.Add(path);
}
}));
}
await Task.WhenAll(tasks);
return (new List<string>(seriesBag), new List<string>(movieBag));
}
}