Added initial database audio library class logic.
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
namespace Harmonia.Core.Library;
|
||||
using Harmonia.Core.Scanner;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SongModel = Harmonia.Core.Models.Song;
|
||||
|
||||
namespace Harmonia.Core.Library;
|
||||
|
||||
public interface IAudioLibrary
|
||||
{
|
||||
@@ -14,24 +18,21 @@ public interface IAudioLibrary
|
||||
event EventHandler<EventArgs>? ScanFinished;
|
||||
}
|
||||
|
||||
public class AudioLibrary : IAudioLibrary
|
||||
public abstract 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;
|
||||
|
||||
protected abstract bool IncludeLocation(string path);
|
||||
protected abstract void ScanLocation(string path);
|
||||
|
||||
public void AddLocation(string path)
|
||||
{
|
||||
if (_locations.Contains(path))
|
||||
if (IncludeLocation(path) == false)
|
||||
return;
|
||||
|
||||
// TODO: CHeck for subpaths
|
||||
|
||||
_locations.Add(path);
|
||||
|
||||
LocationAdded?.Invoke(this, new EventArgs());
|
||||
}
|
||||
|
||||
@@ -44,8 +45,8 @@ public class AudioLibrary : IAudioLibrary
|
||||
{
|
||||
foreach (string path in paths)
|
||||
{
|
||||
if (_locations.Contains(path) == false)
|
||||
continue;
|
||||
//if (_locations.Contains(path) == false)
|
||||
// continue;
|
||||
|
||||
|
||||
}
|
||||
@@ -65,3 +66,136 @@ public class AudioLibrary : IAudioLibrary
|
||||
ScanFinished?.Invoke(this, new EventArgs());
|
||||
}
|
||||
}
|
||||
|
||||
public class AudioDatabaseLibrary(IAudioFileScanner audioFileScanner, AudioLibraryContext context) : AudioLibrary
|
||||
{
|
||||
protected override bool IncludeLocation(string path)
|
||||
{
|
||||
if (CanAddLocation(path) == false)
|
||||
return false;
|
||||
|
||||
Location location = GetLocation(path) ?? CreateLocation(path);
|
||||
ScanLocation(location);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool CanAddLocation(string path)
|
||||
{
|
||||
return context.Folders.Any(folder => folder.Name == path) == false;
|
||||
}
|
||||
|
||||
private Location CreateLocation(string path)
|
||||
{
|
||||
Location location = new()
|
||||
{
|
||||
Name = path,
|
||||
Type = 0
|
||||
};
|
||||
|
||||
context.Locations.Add(location);
|
||||
context.SaveChanges();
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
private Location? GetLocation(string path)
|
||||
{
|
||||
return context.Locations.FirstOrDefault(location => location.Name == path);
|
||||
}
|
||||
|
||||
protected override void ScanLocation(string path)
|
||||
{
|
||||
Location? location = GetLocation(path);
|
||||
|
||||
if (location == null)
|
||||
return;
|
||||
|
||||
ScanLocation(location);
|
||||
}
|
||||
|
||||
private void ScanLocation(Location location)
|
||||
{
|
||||
SongModel[] songModels = audioFileScanner.GetSongsFromPath(location.Name);
|
||||
|
||||
AddFolders(location, songModels);
|
||||
AddSongs(songModels);
|
||||
|
||||
// Remove old songs, and clear out folders that no longer hold songs
|
||||
}
|
||||
|
||||
private void AddFolders(Location location, SongModel[] songModels)
|
||||
{
|
||||
string[] folderNames = [.. songModels.Select(songModel => Directory.GetParent(songModel.FileName)?.FullName ?? string.Empty)
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x))
|
||||
.Distinct()];
|
||||
|
||||
Folder[] folders = [.. context.Folders.Where(folder => folder.Location == location)];
|
||||
}
|
||||
|
||||
private void AddSongs(SongModel[] songModels)
|
||||
{
|
||||
foreach (SongModel songModel in songModels)
|
||||
{
|
||||
Folder? folder = context.Folders.FirstOrDefault(x => x.Name == songModel.FileDirectory);
|
||||
|
||||
if (folder == null)
|
||||
continue;
|
||||
|
||||
Song song = AddOrUpdateSong(songModel, folder);
|
||||
AddOrUpdateSongTag(songModel, song);
|
||||
}
|
||||
}
|
||||
|
||||
private Song AddOrUpdateSong(SongModel songModel, Folder folder)
|
||||
{
|
||||
string shortFileName = Path.GetFileName(songModel.FileName);
|
||||
|
||||
var song = context.Songs.FirstOrDefault(x => x.Folder == folder && string.Equals(x.FileName, shortFileName, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (song == null)
|
||||
{
|
||||
song = new()
|
||||
{
|
||||
FileName = shortFileName,
|
||||
Folder = folder
|
||||
};
|
||||
|
||||
context.Songs.Add(song);
|
||||
}
|
||||
|
||||
song.Size = (long)songModel.Size;
|
||||
song.Duration = songModel.Length.Ticks;
|
||||
song.Modified = songModel.LastModified;
|
||||
song.BitRate = (int)songModel.BitRate;
|
||||
song.SampleRate = (int)songModel.SampleRate;
|
||||
|
||||
return song;
|
||||
}
|
||||
|
||||
private SongTag AddOrUpdateSongTag(SongModel songModel, Song song)
|
||||
{
|
||||
var songTag = context.SongTags.FirstOrDefault(x => x.Song == song);
|
||||
|
||||
if (songTag == null)
|
||||
{
|
||||
songTag = new SongTag()
|
||||
{
|
||||
Song = song
|
||||
};
|
||||
|
||||
context.SongTags.Add(songTag);
|
||||
}
|
||||
|
||||
songTag.Title = songModel.Title;
|
||||
songTag.Album = songModel.Album;
|
||||
songTag.Artist = string.Join(";", songModel.Artists);
|
||||
songTag.AlbumArtist = string.Join(";", songModel.AlbumArtists);
|
||||
songTag.TrackNumber = songModel.TrackNumber;
|
||||
songTag.DiscNumber = songModel.DiscNumber;
|
||||
songTag.Genre = songModel.Genre;
|
||||
songTag.ReleaseDate = songModel.Year != null ? new DateTime(songModel.Year.Value, 1, 1) : null;
|
||||
|
||||
return songTag;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
using Harmonia.Core.Imaging;
|
||||
using Harmonia.Core.Engine;
|
||||
using Harmonia.Core.Imaging;
|
||||
using Harmonia.Core.Models;
|
||||
using Harmonia.Core.Tags;
|
||||
|
||||
namespace Harmonia.Core.Scanner;
|
||||
|
||||
public class AudioFileScanner(ITagResolver tagResolver, IAudioImageExtractor audioImageExtractor) : IAudioFileScanner
|
||||
public class AudioFileScanner(IAudioEngine audioEngine, ITagResolver tagResolver, IAudioImageExtractor audioImageExtractor) : IAudioFileScanner
|
||||
{
|
||||
public Song[] GetSongs(string[] fileNames)
|
||||
{
|
||||
@@ -54,4 +55,33 @@ public class AudioFileScanner(ITagResolver tagResolver, IAudioImageExtractor aud
|
||||
|
||||
return song;
|
||||
}
|
||||
|
||||
public Song[] GetSongsFromPath(string path)
|
||||
{
|
||||
FileInfo[] fileInfoList = GetAllFilesFromDirectory(path);
|
||||
string[] fileNames = [.. fileInfoList.Select(x => x.FullName)];
|
||||
|
||||
return GetSongs(fileNames);
|
||||
}
|
||||
|
||||
private FileInfo[] GetAllFilesFromDirectory(string directoryName)
|
||||
{
|
||||
DirectoryInfo directoryInfo = new(directoryName);
|
||||
|
||||
if (directoryInfo.Exists == false)
|
||||
return [];
|
||||
|
||||
List<FileInfo> fileInfoList = [];
|
||||
|
||||
var directories = directoryInfo.GetDirectories().Where(x => x.Attributes.HasFlag(FileAttributes.Hidden) == false);
|
||||
|
||||
var extensions = audioEngine.SupportedFormats.Select(x => x.Replace("*.", ".").ToLower()).ToList();
|
||||
var files = directoryInfo.EnumerateFiles("*.*", SearchOption.AllDirectories).Where(x => x.Attributes.HasFlag(FileAttributes.Hidden) == false);
|
||||
var songFiles = files.Where(x => extensions.Contains(x.Extension.ToLower())).OrderBy(x => x.Name);
|
||||
|
||||
foreach (FileInfo fileInfo in songFiles)
|
||||
fileInfoList.Add(fileInfo);
|
||||
|
||||
return [.. fileInfoList];
|
||||
}
|
||||
}
|
||||
@@ -5,4 +5,5 @@ namespace Harmonia.Core.Scanner;
|
||||
public interface IAudioFileScanner
|
||||
{
|
||||
Song[] GetSongs(string[] fileNames);
|
||||
Song[] GetSongsFromPath(string path);
|
||||
}
|
||||
Reference in New Issue
Block a user