Added initial audio library logic.

This commit is contained in:
2025-02-27 00:46:36 -05:00
parent c1a7d23096
commit e2af19d9bb
7 changed files with 248 additions and 0 deletions

View File

@@ -9,6 +9,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="ManagedBass" Version="3.1.1" /> <PackageReference Include="ManagedBass" Version="3.1.1" />
<PackageReference Include="ManagedBass.Flac" Version="3.1.1" /> <PackageReference Include="ManagedBass.Flac" Version="3.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.2" /> <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.2" /> <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.2" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.2" />

View File

@@ -0,0 +1,114 @@
using Microsoft.EntityFrameworkCore;
namespace Harmonia.Core.Library;
public class AudioLibraryContext(DbContextOptions options) : DbContext(options)
{
public DbSet<Location> Locations { get; set; }
public DbSet<Folder> Folders { get; set; }
public DbSet<Song> Songs { get; set; }
public DbSet<SongTag> 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<Location>()
.HasKey(x => x.LocationId);
modelBuilder
.Entity<Location>()
.HasMany(x => x.Folders)
.WithOne(x => x.Location)
.OnDelete(DeleteBehavior.ClientCascade);
}
private static void ConfigureFolder(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Folder>()
.HasKey(x => x.FolderId);
modelBuilder
.Entity<Folder>()
//.HasIndex(x => new { x.LocationId, x.Name })
.HasIndex(x => new { x.Name })
.IsUnique(true);
modelBuilder
.Entity<Folder>()
.HasMany(x => x.Songs)
.WithOne(x => x.Folder)
.OnDelete(DeleteBehavior.ClientCascade);
}
private static void ConfigureSong(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Song>()
.HasKey(x => x.SongId);
modelBuilder
.Entity<Song>()
.HasIndex(x => new { x.FolderId, x.FileName })
.IsUnique(true);
modelBuilder.Entity<Song>()
.HasOne(x => x.SongTag)
.WithOne(x => x.Song)
.OnDelete(DeleteBehavior.ClientCascade);
}
private static void ConfigureSongTag(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<SongTag>()
.HasKey(x => x.SongTagId);
modelBuilder
.Entity<SongTag>()
.HasIndex(x => x.SongId)
.IsUnique(true);
modelBuilder
.Entity<SongTag>()
.HasIndex(x => x.Album);
modelBuilder
.Entity<SongTag>()
.HasIndex(x => x.Title);
modelBuilder
.Entity<SongTag>()
.HasIndex(x => x.Artist);
modelBuilder
.Entity<SongTag>()
.HasIndex(x => x.AlbumArtist);
modelBuilder
.Entity<SongTag>()
.HasIndex(x => x.DiscNumber);
modelBuilder
.Entity<SongTag>()
.HasIndex(x => x.TrackNumber);
modelBuilder
.Entity<SongTag>()
.HasIndex(x => x.Genre);
modelBuilder
.Entity<SongTag>()
.HasIndex(x => x.ReleaseDate);
}
}

View File

@@ -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<Song> Songs { get; set; } = [];
}

View File

@@ -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<EventArgs>? LocationAdded;
event EventHandler<EventArgs>? LocationRemoved;
event EventHandler<EventArgs>? ScanStarted;
event EventHandler<EventArgs>? ScanFinished;
}
public class AudioLibrary : IAudioLibrary
{
private readonly List<string> _locations = [];
public event EventHandler<EventArgs>? LocationAdded;
public event EventHandler<EventArgs>? LocationRemoved;
public event EventHandler<EventArgs>? ScanStarted;
public event EventHandler<EventArgs>? 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());
}
}

View File

@@ -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<Folder> Folders { get; set; } = [];
}

View File

@@ -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; }
}

View File

@@ -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; }
}