Added logic for tags and audio engine.

This commit is contained in:
2025-02-20 00:01:07 -05:00
parent 2bafd474a0
commit f8cda3105a
20 changed files with 316 additions and 10 deletions

View File

@@ -0,0 +1,9 @@
namespace Harmonia.Core.Engine;
public enum AudioPlaybackState
{
Stopped,
Playing,
Stalled,
Paused
}

View File

@@ -0,0 +1,22 @@
namespace Harmonia.Core.Engine;
public interface IAudioEngine
{
string[] SupportedFormats { get; }
string Source { get; }
TimeSpan Position { get; set; }
TimeSpan Length { get; }
float Volume { get; set; }
bool CanPause { get; }
bool IsMuted { get; set; }
AudioPlaybackState State { get; }
Task<bool> LoadAsync(string fileName);
void Play();
void Pause();
void Stop();
event EventHandler<PlaybackStoppedEventArgs> PlaybackStopped;
event EventHandler StreamFinished;
event EventHandler<PlaybackStateChangedEventArgs> StateChanged;
}

View File

@@ -0,0 +1,7 @@
namespace Harmonia.Core.Engine;
public class PlaybackStateChangedEventArgs(AudioPlaybackState oldState, AudioPlaybackState newState) : EventArgs
{
public AudioPlaybackState OldState { get; } = oldState;
public AudioPlaybackState State { get; } = newState;
}

View File

@@ -0,0 +1,6 @@
namespace Harmonia.Core.Engine;
public class PlaybackStoppedEventArgs(string message) : EventArgs
{
public string Message { get; } = message;
}

View File

@@ -6,4 +6,8 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="TagLibSharp" Version="2.3.0" />
</ItemGroup>
</Project> </Project>

View File

@@ -0,0 +1,13 @@
namespace Harmonia.Core.Playlists;
public interface IPlaylistManager
{
Playlist? CurrentPlaylist { get; set; }
void AddPlaylist();
void RemovePlaylist(Playlist playlist);
event EventHandler? CurrentPlaylistChanged;
event EventHandler<PlaylistAddedEventArgs> PlaylistAdded;
event EventHandler<PlaylistRemovedEventArgs> PlaylistRemoved;
}

View File

@@ -1,7 +1,7 @@
using Harmonia.Core.Events; using Harmonia.Core.Extensions;
using Harmonia.Core.Extensions; using Harmonia.Core.Models;
namespace Harmonia.Core.Models; namespace Harmonia.Core.Playlists;
public class Playlist public class Playlist
{ {

View File

@@ -0,0 +1,6 @@
namespace Harmonia.Core.Playlists;
public class PlaylistAddedEventArgs(Playlist playlist) : EventArgs
{
public readonly Playlist Playlist = playlist;
}

View File

@@ -0,0 +1,43 @@
using Harmonia.Core.Data;
namespace Harmonia.Core.Playlists;
public class PlaylistManager(IRepository<Playlist> playlistRepository) : IPlaylistManager
{
private Playlist? _currentPlaylist;
public Playlist? CurrentPlaylist
{
get
{
return _currentPlaylist;
}
set
{
_currentPlaylist = value;
CurrentPlaylistChanged?.Invoke(this, new());
}
}
public event EventHandler? CurrentPlaylistChanged;
public event EventHandler<PlaylistAddedEventArgs>? PlaylistAdded;
public event EventHandler<PlaylistRemovedEventArgs>? PlaylistRemoved;
public void AddPlaylist()
{
Playlist playlist = new()
{
Name = "New Playlist"
};
playlistRepository.Save(playlist);
PlaylistAdded?.Invoke(this, new(playlist));
}
public void RemovePlaylist(Playlist playlist)
{
playlistRepository.Delete(playlist);
PlaylistRemoved?.Invoke(this, new(playlist));
}
}

View File

@@ -0,0 +1,6 @@
namespace Harmonia.Core.Playlists;
public class PlaylistRemovedEventArgs(Playlist playlist) : EventArgs
{
public readonly Playlist Playlist = playlist;
}

View File

@@ -1,6 +1,6 @@
using Harmonia.Core.Models; using Harmonia.Core.Data;
namespace Harmonia.Core.Data; namespace Harmonia.Core.Playlists;
public class PlaylistRepository : JsonFileRepository<Playlist> public class PlaylistRepository : JsonFileRepository<Playlist>
{ {

View File

@@ -1,4 +1,6 @@
namespace Harmonia.Core.Models; using Harmonia.Core.Models;
namespace Harmonia.Core.Playlists;
public class PlaylistSong(Song song) public class PlaylistSong(Song song)
{ {

View File

@@ -1,4 +1,4 @@
namespace Harmonia.Core.Events; namespace Harmonia.Core.Playlists;
public enum PlaylistUpdateAction public enum PlaylistUpdateAction
{ {

View File

@@ -1,6 +1,4 @@
using Harmonia.Core.Models; namespace Harmonia.Core.Playlists;
namespace Harmonia.Core.Events;
public class PlaylistUpdatedEventArgs : EventArgs public class PlaylistUpdatedEventArgs : EventArgs
{ {

View File

@@ -0,0 +1,6 @@
namespace Harmonia.Core.Tags;
public interface ITagResolver
{
SongTagInfo GetSongTagInfo(string fileName);
}

View File

@@ -0,0 +1,8 @@
namespace Harmonia.Core.Tags;
public class PictureTag
{
public required string MimeType;
public required PictureType PictureType;
public required byte[] Data;
}

View File

@@ -0,0 +1,96 @@
namespace Harmonia.Core.Tags;
//
// Summary:
// Picture Types.
public enum PictureType
{
//
// Summary:
// Other.
Other = 0,
//
// Summary:
// File Icon.
FileIcon = 1,
//
// Summary:
// Other File Icon.
OtherFileIcon = 2,
//
// Summary:
// Front Cover.
FrontCover = 3,
//
// Summary:
// Back Cover.
BackCover = 4,
//
// Summary:
// Leaflet Page.
LeafletPage = 5,
//
// Summary:
// Media.
Media = 6,
//
// Summary:
// Soloist.
Soloist = 7,
//
// Summary:
// Artist.
Artist = 8,
//
// Summary:
// Conductor.
Conductor = 9,
//
// Summary:
// Band.
Band = 10,
//
// Summary:
// Composer.
Composer = 11,
//
// Summary:
// Lyricist.
Lyricist = 12,
//
// Summary:
// Recording Location.
RecordingLocation = 13,
//
// Summary:
// During Recording.
DuringRecording = 14,
//
// Summary:
// During Performance.
DuringPerformance = 15,
//
// Summary:
// Movie.
Movie = 16,
//
// Summary:
// A Bright Coloured Fish.
ABrightColouredFish = 17,
//
// Summary:
// Illustration.
Illustration = 18,
//
// Summary:
// Band Logo.
BandLogo = 19,
//
// Summary:
// Publisher Logo.
PublisherLogo = 20,
//
// Summary:
// Not A Picture
NotAPicture = 255
}

View File

@@ -0,0 +1,18 @@
namespace Harmonia.Core.Tags;
public class SongTagInfo
{
public string? Title { get; set; }
public string? Album { get; set; }
public List<string> Artists { get; set; } = [];
public List<string> AlbumArtists { get; set; } = [];
public int? DiscNumber { get; set; }
public int? TrackNumber { get; set; }
public TimeSpan Length { get; set; } = TimeSpan.Zero;
public int? Year { get; set; }
public string? Genre { get; set; }
public int BitRate { get; set; }
public int SampleRate { get; set; }
public List<PictureTag> Pictures { get; set; } = [];
public Dictionary<string, string> Other { get; set; } = [];
}

View File

@@ -0,0 +1,54 @@
namespace Harmonia.Core.Tags;
public class TagLibTagResolver : ITagResolver
{
public SongTagInfo GetSongTagInfo(string fileName)
{
var songTagInfo = new SongTagInfo();
using (var tagFile = TagLib.File.Create(fileName))
{
int? discNumber = null;
int? trackNumber = null;
int? year = null;
if (tagFile.Tag.Track > 0)
trackNumber = Convert.ToInt32(tagFile.Tag.Track);
if (tagFile.Tag.Disc > 0)
discNumber = Convert.ToInt32(tagFile.Tag.Disc);
if (tagFile.Tag.Year > 0)
year = Convert.ToInt32(tagFile.Tag.Year);
songTagInfo.Title = tagFile.Tag.Title;
songTagInfo.Album = tagFile.Tag.Album;
songTagInfo.Artists = tagFile.Tag.Performers.Select(x => x.Trim()).ToList();
songTagInfo.AlbumArtists = tagFile.Tag.AlbumArtists.Select(x => x.Trim()).ToList();
songTagInfo.DiscNumber = discNumber;
songTagInfo.TrackNumber = trackNumber;
songTagInfo.Length = tagFile.Properties.Duration;
songTagInfo.Year = year;
songTagInfo.Genre = tagFile.Tag.JoinedGenres;
songTagInfo.BitRate = tagFile.Properties.AudioBitrate;
songTagInfo.SampleRate = tagFile.Properties.AudioSampleRate;
foreach (var picture in tagFile.Tag.Pictures)
{
if (picture.Type == TagLib.PictureType.NotAPicture)
continue;
var pictureTag = new PictureTag()
{
MimeType = picture.MimeType,
PictureType = (PictureType)picture.Type,
Data = picture.Data.Data
};
songTagInfo.Pictures.Add(pictureTag);
};
}
return songTagInfo;
}
}

View File

@@ -1,4 +1,6 @@
using Harmonia.Core.Models; using Harmonia.Core.Models;
using Harmonia.Core.Playlists;
using NSubstitute;
using Shouldly; using Shouldly;
using System.ComponentModel; using System.ComponentModel;
@@ -123,4 +125,10 @@ public class PlaylistTests
playlist.Songs.Count.ShouldBe(3); playlist.Songs.Count.ShouldBe(3);
} }
//public void Get_Playlists()
//{
// //PlaylistRepository playlistRepository = new();
// //playlistRepository.Get().Returns()
//}
} }