diff --git a/Harmonia.Core/Engine/AudioPlaybackState.cs b/Harmonia.Core/Engine/AudioPlaybackState.cs new file mode 100644 index 0000000..a203097 --- /dev/null +++ b/Harmonia.Core/Engine/AudioPlaybackState.cs @@ -0,0 +1,9 @@ +namespace Harmonia.Core.Engine; + +public enum AudioPlaybackState +{ + Stopped, + Playing, + Stalled, + Paused +} \ No newline at end of file diff --git a/Harmonia.Core/Engine/IAudioEngine.cs b/Harmonia.Core/Engine/IAudioEngine.cs new file mode 100644 index 0000000..686a219 --- /dev/null +++ b/Harmonia.Core/Engine/IAudioEngine.cs @@ -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 LoadAsync(string fileName); + void Play(); + void Pause(); + void Stop(); + + event EventHandler PlaybackStopped; + event EventHandler StreamFinished; + event EventHandler StateChanged; +} \ No newline at end of file diff --git a/Harmonia.Core/Engine/PlaybackStateChangedEventArgs.cs b/Harmonia.Core/Engine/PlaybackStateChangedEventArgs.cs new file mode 100644 index 0000000..91920ce --- /dev/null +++ b/Harmonia.Core/Engine/PlaybackStateChangedEventArgs.cs @@ -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; +} \ No newline at end of file diff --git a/Harmonia.Core/Engine/PlaybackStoppedEventArgs.cs b/Harmonia.Core/Engine/PlaybackStoppedEventArgs.cs new file mode 100644 index 0000000..262df2a --- /dev/null +++ b/Harmonia.Core/Engine/PlaybackStoppedEventArgs.cs @@ -0,0 +1,6 @@ +namespace Harmonia.Core.Engine; + +public class PlaybackStoppedEventArgs(string message) : EventArgs +{ + public string Message { get; } = message; +} \ No newline at end of file diff --git a/Harmonia.Core/Harmonia.Core.csproj b/Harmonia.Core/Harmonia.Core.csproj index 125f4c9..3afc37a 100644 --- a/Harmonia.Core/Harmonia.Core.csproj +++ b/Harmonia.Core/Harmonia.Core.csproj @@ -6,4 +6,8 @@ enable + + + + diff --git a/Harmonia.Core/Playlists/IPlaylistManager.cs b/Harmonia.Core/Playlists/IPlaylistManager.cs new file mode 100644 index 0000000..2d2f35e --- /dev/null +++ b/Harmonia.Core/Playlists/IPlaylistManager.cs @@ -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 PlaylistAdded; + event EventHandler PlaylistRemoved; +} \ No newline at end of file diff --git a/Harmonia.Core/Models/Playlist.cs b/Harmonia.Core/Playlists/Playlist.cs similarity index 97% rename from Harmonia.Core/Models/Playlist.cs rename to Harmonia.Core/Playlists/Playlist.cs index 28e4b7e..b6caf55 100644 --- a/Harmonia.Core/Models/Playlist.cs +++ b/Harmonia.Core/Playlists/Playlist.cs @@ -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 { diff --git a/Harmonia.Core/Playlists/PlaylistAddedEventArgs.cs b/Harmonia.Core/Playlists/PlaylistAddedEventArgs.cs new file mode 100644 index 0000000..7e5930e --- /dev/null +++ b/Harmonia.Core/Playlists/PlaylistAddedEventArgs.cs @@ -0,0 +1,6 @@ +namespace Harmonia.Core.Playlists; + +public class PlaylistAddedEventArgs(Playlist playlist) : EventArgs +{ + public readonly Playlist Playlist = playlist; +} \ No newline at end of file diff --git a/Harmonia.Core/Playlists/PlaylistManager.cs b/Harmonia.Core/Playlists/PlaylistManager.cs new file mode 100644 index 0000000..b7dc6d6 --- /dev/null +++ b/Harmonia.Core/Playlists/PlaylistManager.cs @@ -0,0 +1,43 @@ +using Harmonia.Core.Data; + +namespace Harmonia.Core.Playlists; + +public class PlaylistManager(IRepository 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? PlaylistAdded; + public event EventHandler? 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)); + } +} \ No newline at end of file diff --git a/Harmonia.Core/Playlists/PlaylistRemovedEventArgs.cs b/Harmonia.Core/Playlists/PlaylistRemovedEventArgs.cs new file mode 100644 index 0000000..8649626 --- /dev/null +++ b/Harmonia.Core/Playlists/PlaylistRemovedEventArgs.cs @@ -0,0 +1,6 @@ +namespace Harmonia.Core.Playlists; + +public class PlaylistRemovedEventArgs(Playlist playlist) : EventArgs +{ + public readonly Playlist Playlist = playlist; +} \ No newline at end of file diff --git a/Harmonia.Core/Data/PlaylistRepository.cs b/Harmonia.Core/Playlists/PlaylistRepository.cs similarity index 89% rename from Harmonia.Core/Data/PlaylistRepository.cs rename to Harmonia.Core/Playlists/PlaylistRepository.cs index d7402e6..359d891 100644 --- a/Harmonia.Core/Data/PlaylistRepository.cs +++ b/Harmonia.Core/Playlists/PlaylistRepository.cs @@ -1,6 +1,6 @@ -using Harmonia.Core.Models; +using Harmonia.Core.Data; -namespace Harmonia.Core.Data; +namespace Harmonia.Core.Playlists; public class PlaylistRepository : JsonFileRepository { diff --git a/Harmonia.Core/Models/PlaylistSong.cs b/Harmonia.Core/Playlists/PlaylistSong.cs similarity index 67% rename from Harmonia.Core/Models/PlaylistSong.cs rename to Harmonia.Core/Playlists/PlaylistSong.cs index 361db92..e18bf64 100644 --- a/Harmonia.Core/Models/PlaylistSong.cs +++ b/Harmonia.Core/Playlists/PlaylistSong.cs @@ -1,4 +1,6 @@ -namespace Harmonia.Core.Models; +using Harmonia.Core.Models; + +namespace Harmonia.Core.Playlists; public class PlaylistSong(Song song) { diff --git a/Harmonia.Core/Events/PlaylistUpdateAction.cs b/Harmonia.Core/Playlists/PlaylistUpdateAction.cs similarity index 91% rename from Harmonia.Core/Events/PlaylistUpdateAction.cs rename to Harmonia.Core/Playlists/PlaylistUpdateAction.cs index 695fd89..d192184 100644 --- a/Harmonia.Core/Events/PlaylistUpdateAction.cs +++ b/Harmonia.Core/Playlists/PlaylistUpdateAction.cs @@ -1,4 +1,4 @@ -namespace Harmonia.Core.Events; +namespace Harmonia.Core.Playlists; public enum PlaylistUpdateAction { diff --git a/Harmonia.Core/Events/PlaylistUpdatedEventArgs.cs b/Harmonia.Core/Playlists/PlaylistUpdatedEventArgs.cs similarity index 83% rename from Harmonia.Core/Events/PlaylistUpdatedEventArgs.cs rename to Harmonia.Core/Playlists/PlaylistUpdatedEventArgs.cs index 45e3fdb..ddbb1c1 100644 --- a/Harmonia.Core/Events/PlaylistUpdatedEventArgs.cs +++ b/Harmonia.Core/Playlists/PlaylistUpdatedEventArgs.cs @@ -1,6 +1,4 @@ -using Harmonia.Core.Models; - -namespace Harmonia.Core.Events; +namespace Harmonia.Core.Playlists; public class PlaylistUpdatedEventArgs : EventArgs { diff --git a/Harmonia.Core/Tags/ITagResolver.cs b/Harmonia.Core/Tags/ITagResolver.cs new file mode 100644 index 0000000..6cc40ae --- /dev/null +++ b/Harmonia.Core/Tags/ITagResolver.cs @@ -0,0 +1,6 @@ +namespace Harmonia.Core.Tags; + +public interface ITagResolver +{ + SongTagInfo GetSongTagInfo(string fileName); +} \ No newline at end of file diff --git a/Harmonia.Core/Tags/PictureTag.cs b/Harmonia.Core/Tags/PictureTag.cs new file mode 100644 index 0000000..ced44dc --- /dev/null +++ b/Harmonia.Core/Tags/PictureTag.cs @@ -0,0 +1,8 @@ +namespace Harmonia.Core.Tags; + +public class PictureTag +{ + public required string MimeType; + public required PictureType PictureType; + public required byte[] Data; +} \ No newline at end of file diff --git a/Harmonia.Core/Tags/PictureType.cs b/Harmonia.Core/Tags/PictureType.cs new file mode 100644 index 0000000..63e19cf --- /dev/null +++ b/Harmonia.Core/Tags/PictureType.cs @@ -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 +} \ No newline at end of file diff --git a/Harmonia.Core/Tags/SongTagInfo.cs b/Harmonia.Core/Tags/SongTagInfo.cs new file mode 100644 index 0000000..2d79b40 --- /dev/null +++ b/Harmonia.Core/Tags/SongTagInfo.cs @@ -0,0 +1,18 @@ +namespace Harmonia.Core.Tags; + +public class SongTagInfo +{ + public string? Title { get; set; } + public string? Album { get; set; } + public List Artists { get; set; } = []; + public List 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 Pictures { get; set; } = []; + public Dictionary Other { get; set; } = []; +} \ No newline at end of file diff --git a/Harmonia.Core/Tags/TagLibTagResolver.cs b/Harmonia.Core/Tags/TagLibTagResolver.cs new file mode 100644 index 0000000..053008b --- /dev/null +++ b/Harmonia.Core/Tags/TagLibTagResolver.cs @@ -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; + } +} \ No newline at end of file diff --git a/Harmonia.Tests/PlaylistTests.cs b/Harmonia.Tests/PlaylistTests.cs index d1bd254..10a3957 100644 --- a/Harmonia.Tests/PlaylistTests.cs +++ b/Harmonia.Tests/PlaylistTests.cs @@ -1,4 +1,6 @@ using Harmonia.Core.Models; +using Harmonia.Core.Playlists; +using NSubstitute; using Shouldly; using System.ComponentModel; @@ -123,4 +125,10 @@ public class PlaylistTests playlist.Songs.Count.ShouldBe(3); } + + //public void Get_Playlists() + //{ + // //PlaylistRepository playlistRepository = new(); + // //playlistRepository.Get().Returns() + //} } \ No newline at end of file