From e2af19d9bbf73a5fdfde5aa48da078bed74d7d1a Mon Sep 17 00:00:00 2001 From: Brian Bicknell Date: Thu, 27 Feb 2025 00:46:36 -0500 Subject: [PATCH] Added initial audio library logic. --- Harmonia.Core/Harmonia.Core.csproj | 1 + Harmonia.Core/Library/AudioLibraryContext.cs | 114 +++++++++++++++++++ Harmonia.Core/Library/Folder.cs | 16 +++ Harmonia.Core/Library/IAudioLibrary.cs | 67 +++++++++++ Harmonia.Core/Library/Location.cs | 10 ++ Harmonia.Core/Library/Song.cs | 22 ++++ Harmonia.Core/Library/SongTag.cs | 18 +++ 7 files changed, 248 insertions(+) create mode 100644 Harmonia.Core/Library/AudioLibraryContext.cs create mode 100644 Harmonia.Core/Library/Folder.cs create mode 100644 Harmonia.Core/Library/IAudioLibrary.cs create mode 100644 Harmonia.Core/Library/Location.cs create mode 100644 Harmonia.Core/Library/Song.cs create mode 100644 Harmonia.Core/Library/SongTag.cs diff --git a/Harmonia.Core/Harmonia.Core.csproj b/Harmonia.Core/Harmonia.Core.csproj index 7bef851..8719bc4 100644 --- a/Harmonia.Core/Harmonia.Core.csproj +++ b/Harmonia.Core/Harmonia.Core.csproj @@ -9,6 +9,7 @@ + diff --git a/Harmonia.Core/Library/AudioLibraryContext.cs b/Harmonia.Core/Library/AudioLibraryContext.cs new file mode 100644 index 0000000..81a7d0e --- /dev/null +++ b/Harmonia.Core/Library/AudioLibraryContext.cs @@ -0,0 +1,114 @@ +using Microsoft.EntityFrameworkCore; + +namespace Harmonia.Core.Library; + +public class AudioLibraryContext(DbContextOptions options) : DbContext(options) +{ + public DbSet Locations { get; set; } + public DbSet Folders { get; set; } + public DbSet Songs { get; set; } + public DbSet SongTags { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + ConfigureLocation(modelBuilder); + ConfigureFolder(modelBuilder); + ConfigureSong(modelBuilder); + ConfigureSongTag(modelBuilder); + } + + private static void ConfigureLocation(ModelBuilder modelBuilder) + { + modelBuilder + .Entity() + .HasKey(x => x.LocationId); + + modelBuilder + .Entity() + .HasMany(x => x.Folders) + .WithOne(x => x.Location) + .OnDelete(DeleteBehavior.ClientCascade); + } + + private static void ConfigureFolder(ModelBuilder modelBuilder) + { + modelBuilder + .Entity() + .HasKey(x => x.FolderId); + + modelBuilder + .Entity() + //.HasIndex(x => new { x.LocationId, x.Name }) + .HasIndex(x => new { x.Name }) + .IsUnique(true); + + modelBuilder + .Entity() + .HasMany(x => x.Songs) + .WithOne(x => x.Folder) + .OnDelete(DeleteBehavior.ClientCascade); + } + + private static void ConfigureSong(ModelBuilder modelBuilder) + { + modelBuilder + .Entity() + .HasKey(x => x.SongId); + + modelBuilder + .Entity() + .HasIndex(x => new { x.FolderId, x.FileName }) + .IsUnique(true); + + modelBuilder.Entity() + .HasOne(x => x.SongTag) + .WithOne(x => x.Song) + .OnDelete(DeleteBehavior.ClientCascade); + } + + private static void ConfigureSongTag(ModelBuilder modelBuilder) + { + modelBuilder + .Entity() + .HasKey(x => x.SongTagId); + + modelBuilder + .Entity() + .HasIndex(x => x.SongId) + .IsUnique(true); + + modelBuilder + .Entity() + .HasIndex(x => x.Album); + + modelBuilder + .Entity() + .HasIndex(x => x.Title); + + modelBuilder + .Entity() + .HasIndex(x => x.Artist); + + modelBuilder + .Entity() + .HasIndex(x => x.AlbumArtist); + + modelBuilder + .Entity() + .HasIndex(x => x.DiscNumber); + + modelBuilder + .Entity() + .HasIndex(x => x.TrackNumber); + + modelBuilder + .Entity() + .HasIndex(x => x.Genre); + + modelBuilder + .Entity() + .HasIndex(x => x.ReleaseDate); + } +} \ No newline at end of file diff --git a/Harmonia.Core/Library/Folder.cs b/Harmonia.Core/Library/Folder.cs new file mode 100644 index 0000000..6a973e3 --- /dev/null +++ b/Harmonia.Core/Library/Folder.cs @@ -0,0 +1,16 @@ +namespace Harmonia.Core.Library; + +public class Folder +{ + public int FolderId { get; set; } + + public int? ParentFolderId { get; set; } + public Folder? ParentFolder { get; set; } + + public required string Name { get; set; } + + public int LocationId { get; set; } + public required Location Location { get; set; } + + public virtual ICollection Songs { get; set; } = []; +} \ No newline at end of file diff --git a/Harmonia.Core/Library/IAudioLibrary.cs b/Harmonia.Core/Library/IAudioLibrary.cs new file mode 100644 index 0000000..f351cf0 --- /dev/null +++ b/Harmonia.Core/Library/IAudioLibrary.cs @@ -0,0 +1,67 @@ +namespace Harmonia.Core.Library; + +public interface IAudioLibrary +{ + void AddLocation(string path); + void RemoveLocation(string path); + void RemoveLocations(string[] paths); + void Scan(string path); + void Scan(string[] paths); + + event EventHandler? LocationAdded; + event EventHandler? LocationRemoved; + event EventHandler? ScanStarted; + event EventHandler? ScanFinished; +} + +public class AudioLibrary : IAudioLibrary +{ + private readonly List _locations = []; + + public event EventHandler? LocationAdded; + public event EventHandler? LocationRemoved; + public event EventHandler? ScanStarted; + public event EventHandler? ScanFinished; + + public void AddLocation(string path) + { + if (_locations.Contains(path)) + return; + + // TODO: CHeck for subpaths + + _locations.Add(path); + + LocationAdded?.Invoke(this, new EventArgs()); + } + + public void RemoveLocation(string path) + { + RemoveLocations([path]); + } + + public void RemoveLocations(string[] paths) + { + foreach (string path in paths) + { + if (_locations.Contains(path) == false) + continue; + + + } + + LocationRemoved?.Invoke(this, new EventArgs()); + } + + public void Scan(string path) + { + Scan([path]); + } + + public void Scan(string[] paths) + { + ScanStarted?.Invoke(this, new EventArgs()); + + ScanFinished?.Invoke(this, new EventArgs()); + } +} \ No newline at end of file diff --git a/Harmonia.Core/Library/Location.cs b/Harmonia.Core/Library/Location.cs new file mode 100644 index 0000000..45d7c7e --- /dev/null +++ b/Harmonia.Core/Library/Location.cs @@ -0,0 +1,10 @@ +namespace Harmonia.Core.Library; + +public class Location +{ + public int LocationId { get; set; } + public int Type { get; set; } + public required string Name { get; set; } + + public virtual ICollection Folders { get; set; } = []; +} \ No newline at end of file diff --git a/Harmonia.Core/Library/Song.cs b/Harmonia.Core/Library/Song.cs new file mode 100644 index 0000000..ae7dc60 --- /dev/null +++ b/Harmonia.Core/Library/Song.cs @@ -0,0 +1,22 @@ +namespace Harmonia.Core.Library; + +public class Song +{ + public int SongId { get; set; } + + public int FolderId { get; set; } + public required Folder Folder { get; set; } + + public required string FileName { get; set; } + public long Size { get; set; } + public long Duration { get; set; } + public int BitRate { get; set; } + public int BitDepth { get; set; } + public int SampleRate { get; set; } + public DateTime Added { get; set; } + public DateTime? Modified { get; set; } + public int PlayCount { get; set; } + public int Rating { get; set; } + + public SongTag? SongTag { get; set; } +} \ No newline at end of file diff --git a/Harmonia.Core/Library/SongTag.cs b/Harmonia.Core/Library/SongTag.cs new file mode 100644 index 0000000..dfc0b49 --- /dev/null +++ b/Harmonia.Core/Library/SongTag.cs @@ -0,0 +1,18 @@ +namespace Harmonia.Core.Library; + +public partial class SongTag +{ + public int SongTagId { get; set; } + + public int SongId { get; set; } + public required Song Song { get; set; } + + public string? Album { get; set; } + public string? Title { get; set; } + public string? Artist { get; set; } + public string? AlbumArtist { get; set; } + public int? DiscNumber { get; set; } + public int? TrackNumber { get; set; } + public string? Genre { get; set; } + public DateTime? ReleaseDate { get; set; } +} \ No newline at end of file