From 245efd6477e7480ff6d87d3e4de08fa2093899cc Mon Sep 17 00:00:00 2001 From: Kim Hugener-Ohlsen Date: Fri, 2 Mar 2018 12:14:26 +0100 Subject: [PATCH] Rewrote most of the library --- .gitignore | 4 + {src => Sources}/MpcNET.Test/LibMpcTest.cs | 0 {src => Sources}/MpcNET.Test/MpcMock.cs | 0 .../MpcNET.Test/MpcNET.Test.csproj | 0 {src => Sources}/MpcNET.Test/MpdConf.cs | 0 {src => Sources}/MpcNET.Test/MpdMock.cs | 0 .../MpcNET.Test/Properties/AssemblyInfo.cs | 0 .../Ghost-Sounds.mp3 | Bin .../short-trouser-pants-zip-closing.mp3 | Bin ...tarting-engine-Ford-Mondeo-Mk-3-diesel.mp3 | Bin .../pouring-water-into-mug-of-coffee.mp3 | Bin .../central-locking-Ford-Mondeo-Mk-3.mp3 | Bin .../Directory With Spaces/coin-spin-light.mp3 | Bin .../finger-snap-click.mp3 | Bin .../Music/Directory/2-Kids-Laughing.mp3 | Bin .../Directory/ambient-noise-server-room.mp3 | Bin .../Music/_My Directory/gas-fire-lighting.mp3 | Bin .../Music/teaspoon-stirring-mug-of-coffee.mp3 | Bin .../Server/Music/whistle-kettle-boiling.mp3 | Bin .../wine-glass-double-chink-clink-cheers.mp3 | Bin .../MpcNET.Test/Server/OpenAL32.dll | Bin .../Server/Playlists/Playlist One.m3u | 0 .../Server/Playlists/Playlist Two.m3u | 0 .../Server/Playlists/_My Playlist.m3u | 0 .../MpcNET.Test/Server/StartLocal.bat | 0 {src => Sources}/MpcNET.Test/Server/mpd.conf | 0 {src => Sources}/MpcNET.Test/Server/mpd.db | 0 {src => Sources}/MpcNET.Test/Server/mpd.exe | Bin .../MpcNET.Test/Server/mpd_log.txt | 0 .../MpcNET.Test/Server/openal-info.exe | Bin .../MpcNET.Test/Server/winmm-info.exe | Bin {src => Sources}/MpcNET.Test/TestOutput.cs | 0 .../MpcNET.Test/Tests/DatabaseCommandsTest.cs | 0 .../MpcNET.Test/Tests/MpdMessageExtension.cs | 0 .../MpcNET.Test/Tests/OutputCommandsTest.cs | 0 .../Tests/PlaylistsCommandsTest.cs | 0 .../Tests/ReflectionCommandsTest.cs | 0 {src => Sources}/MpcNET.sln | 0 Sources/MpcNET/CommandFactory.cs | 74 ++ .../Commands/CurrentPlaylistCommandFactory.cs | 95 ++ .../MpcNET/Commands/Database/FindCommand.cs | 36 + .../Commands/Database/ListAllCommand.cs | 17 +- .../MpcNET/Commands/Database/ListCommand.cs | 31 + .../MpcNET/Commands/Database/UpdateCommand.cs | 46 + .../MpcNET/Commands/DatabaseCommandFactory.cs | 52 + .../ICurrentPlaylistCommandFactory.cs | 71 ++ .../Commands/IDatabaseCommandFactory.cs | 40 + .../MpcNET/Commands/IOutputCommandFactory.cs | 45 + .../Commands/IPlaybackCommandFactory.cs | 71 ++ .../Commands/IReflectionCommandFactory.cs | 42 + .../MpcNET/Commands/IStatusCommandFactory.cs | 29 + .../Commands/IStoredPlaylistCommandFactory.cs | 45 + .../Commands/Output/DisableOutputCommand.cs | 31 + .../Commands/Output/EnableOutputCommand.cs | 31 + .../MpcNET/Commands/Output/OutputsCommand.cs | 35 + .../Commands/Output/ToggleOutputCommand.cs | 30 + .../MpcNET/Commands/OutputCommandFactory.cs | 57 + .../MpcNET/Commands/Playback/NextCommand.cs | 20 + .../MpcNET/Commands/Playback/PlayCommand.cs | 43 + .../Commands/Playback/PlayPauseCommand.cs | 20 + .../Commands/Playback/PreviousCommand.cs | 20 + .../Commands/Playback/SetVolumeCommand.cs | 31 + .../MpcNET/Commands/Playback/StopCommand.cs | 20 + .../MpcNET/Commands/PlaybackCommandFactory.cs | 95 ++ .../MpcNET/Commands/Playlist/AddCommand.cs | 30 + .../MpcNET/Commands/Playlist/AddIdCommand.cs | 30 + .../MpcNET/Commands/Playlist/ClearCommand.cs | 23 + .../MpcNET/Commands/Playlist/DeleteCommand.cs | 30 + .../Commands/Playlist/DeleteIdCommand.cs | 30 + .../Commands/Playlist/ListPlaylistCommand.cs | 34 + .../Playlist/ListPlaylistInfoCommand.cs | 31 + .../Commands/Playlist/ListPlaylistsCommand.cs | 39 + .../MpcNET/Commands/Playlist/LoadCommand.cs | 30 + .../Commands/Playlist/PlaylistCommand.cs | 27 + .../Commands/Playlist/PlaylistIdCommand.cs | 31 + .../Commands/Playlist/PlaylistInfoCommand.cs | 24 + .../Commands/Reflection/CommandsCommand.cs | 27 + .../Commands/Reflection/DecodersCommand.cs | 18 +- .../Commands/Reflection/TagTypesCommand.cs | 28 + .../Commands/Reflection/UrlHandlersCommand.cs | 26 + .../Commands/ReflectionCommandFactory.cs | 54 + .../Commands/Status/CurrentSongCommand.cs | 21 + Sources/MpcNET/Commands/Status/IdleCommand.cs | 35 + .../MpcNET/Commands/Status/NoIdleCommand.cs | 20 + .../MpcNET/Commands/Status/StatusCommand.cs | 91 +- .../MpcNET/Commands/StatusCommandFactory.cs | 35 + .../Commands/StoredPlaylistCommandFactory.cs | 57 + Sources/MpcNET/Constants.cs | 17 + .../MpcNET/Exceptions/CommandNullException.cs | 20 + .../Exceptions/EmptyResponseException.cs | 26 + .../MpcNET/Exceptions/MpcConnectException.cs | 26 + Sources/MpcNET/Exceptions/MpcException.cs | 26 + Sources/MpcNET/ICommandFactory.cs | 72 ++ Sources/MpcNET/IMpcCommand.cs | 30 + Sources/MpcNET/IMpcConnection.cs | 45 + Sources/MpcNET/IMpcConnectionObserver.cs | 77 ++ Sources/MpcNET/Message/ErrorMpdMessage.cs | 23 + Sources/MpcNET/Message/ErrorMpdResponse.cs | 44 + Sources/MpcNET/Message/IMpdMessage.cs | 39 + Sources/MpcNET/Message/IMpdRequest.cs | 23 + Sources/MpcNET/Message/IMpdResponse.cs | 31 + Sources/MpcNET/Message/IMpdResponseResult.cs | 54 + Sources/MpcNET/Message/MpdMessage.cs | 65 + Sources/MpcNET/Message/MpdRequest.cs | 33 + Sources/MpcNET/Message/MpdResponse.cs | 44 + Sources/MpcNET/Message/MpdResponseResult.cs | 75 ++ Sources/MpcNET/MpcConnection.cs | 261 ++++ {src => Sources}/MpcNET/MpcNET.csproj | 21 +- Sources/MpcNET/MpdDirectoryListing.cs | 46 + {src => Sources}/MpcNET/MpdState.cs | 11 +- Sources/MpcNET/MpdStatistics.cs | 130 ++ {src => Sources}/MpcNET/MpdStatus.cs | 115 +- .../MpcNET/Properties/AssemblyInfo.cs | 8 +- Sources/MpcNET/Tags/FindTags.cs | 46 + Sources/MpcNET/Tags/ITag.cs | 22 + Sources/MpcNET/Tags/MpdTags.cs | 134 ++ Sources/MpcNET/Tags/Tag.cs | 18 + Sources/MpcNET/Types/IMpdFile.cs | 207 +++ Sources/MpcNET/Types/IMpdFilePath.cs | 22 + Sources/MpcNET/Types/MpdDecoderPlugin.cs | 70 ++ Sources/MpcNET/Types/MpdDirectory.cs | 60 + {src => Sources}/MpcNET/Types/MpdFile.cs | 72 +- Sources/MpcNET/Types/MpdOutput.cs | 51 + Sources/MpcNET/Types/MpdPlaylist.cs | 47 + Sources/MpcNET/stylecop.json | 24 + src/MpcNET/Commands/Commands.Database.cs | 33 - src/MpcNET/Commands/Commands.Output.cs | 35 - src/MpcNET/Commands/Commands.Playback.cs | 24 - src/MpcNET/Commands/Commands.Playlists.cs | 85 -- src/MpcNET/Commands/Commands.Reflection.cs | 35 - src/MpcNET/Commands/Commands.Status.cs | 24 - src/MpcNET/Commands/Database/FindCommand.cs | 30 - src/MpcNET/Commands/Database/ListCommand.cs | 25 - src/MpcNET/Commands/Database/UpdateCommand.cs | 54 - .../Commands/Output/DisableOutputCommand.cs | 25 - .../Commands/Output/EnableOutputCommand.cs | 25 - src/MpcNET/Commands/Output/OutputsCommand.cs | 29 - .../Commands/Output/ToggleOutputCommand.cs | 24 - src/MpcNET/Commands/Playback/NextCommand.cs | 14 - src/MpcNET/Commands/Playback/PlayCommand.cs | 33 - .../Commands/Playback/PlayPauseCommand.cs | 14 - .../Commands/Playback/PreviousCommand.cs | 14 - src/MpcNET/Commands/Playback/StopCommand.cs | 14 - src/MpcNET/Commands/Playlist/AddCommand.cs | 24 - src/MpcNET/Commands/Playlist/AddIdCommand.cs | 24 - src/MpcNET/Commands/Playlist/ClearCommand.cs | 17 - src/MpcNET/Commands/Playlist/DeleteCommand.cs | 24 - .../Commands/Playlist/DeleteIdCommand.cs | 24 - .../Commands/Playlist/ListPlaylistCommand.cs | 28 - .../Playlist/ListPlaylistInfoCommand.cs | 25 - .../Commands/Playlist/ListPlaylistsCommand.cs | 33 - src/MpcNET/Commands/Playlist/LoadCommand.cs | 24 - .../Commands/Playlist/PlaylistCommand.cs | 21 - .../Commands/Playlist/PlaylistIdCommand.cs | 25 - .../Commands/Playlist/PlaylistInfoCommand.cs | 18 - .../Commands/Reflection/CommandsCommand.cs | 22 - .../Commands/Reflection/TagTypesCommand.cs | 22 - .../Commands/Reflection/UrlHandlersCommand.cs | 20 - .../Commands/Status/CurrentSongCommand.cs | 15 - src/MpcNET/Constants.cs | 10 - src/MpcNET/Exception.cs | 69 - src/MpcNET/IMpcCommand.cs | 11 - src/MpcNET/Message/IMpdMessage.cs | 10 - src/MpcNET/Message/MpdMessage.cs | 61 - src/MpcNET/Message/MpdRequest.cs | 17 - src/MpcNET/Message/MpdResponse.cs | 20 - src/MpcNET/Message/MpdResponseState.cs | 66 - src/MpcNET/Mpc.cs | 1114 ----------------- src/MpcNET/MpcConnection.cs | 164 --- src/MpcNET/MpdDirectoryListing.cs | 67 - src/MpcNET/MpdStatistics.cs | 114 -- src/MpcNET/Tags/FindTags.cs | 13 - src/MpcNET/Tags/MpdTags.cs | 24 - src/MpcNET/Tags/Tag.cs | 18 - src/MpcNET/Types/IMpdFile.cs | 93 -- src/MpcNET/Types/IMpdFilePath.cs | 7 - src/MpcNET/Types/MpdDecoderPlugin.cs | 37 - src/MpcNET/Types/MpdDirectory.cs | 30 - src/MpcNET/Types/MpdOutput.cs | 23 - src/MpcNET/Types/MpdPlaylist.cs | 24 - src/MpcNET/Utils/CheckNotNullExtension.cs | 15 - 181 files changed, 3927 insertions(+), 3020 deletions(-) rename {src => Sources}/MpcNET.Test/LibMpcTest.cs (100%) rename {src => Sources}/MpcNET.Test/MpcMock.cs (100%) rename {src => Sources}/MpcNET.Test/MpcNET.Test.csproj (100%) rename {src => Sources}/MpcNET.Test/MpdConf.cs (100%) rename {src => Sources}/MpcNET.Test/MpdMock.cs (100%) rename {src => Sources}/MpcNET.Test/Properties/AssemblyInfo.cs (100%) rename {src => Sources}/MpcNET.Test/Server/Music/A long name directory with some spaces/Ghost-Sounds.mp3 (100%) rename {src => Sources}/MpcNET.Test/Server/Music/A long name directory with some spaces/Sub Directory Two/short-trouser-pants-zip-closing.mp3 (100%) rename {src => Sources}/MpcNET.Test/Server/Music/A long name directory with some spaces/Sub Directory Two/starting-engine-Ford-Mondeo-Mk-3-diesel.mp3 (100%) rename {src => Sources}/MpcNET.Test/Server/Music/A long name directory with some spaces/pouring-water-into-mug-of-coffee.mp3 (100%) rename {src => Sources}/MpcNET.Test/Server/Music/Directory With Spaces/SubDirectory One/central-locking-Ford-Mondeo-Mk-3.mp3 (100%) rename {src => Sources}/MpcNET.Test/Server/Music/Directory With Spaces/coin-spin-light.mp3 (100%) rename {src => Sources}/MpcNET.Test/Server/Music/Directory With Spaces/finger-snap-click.mp3 (100%) rename {src => Sources}/MpcNET.Test/Server/Music/Directory/2-Kids-Laughing.mp3 (100%) rename {src => Sources}/MpcNET.Test/Server/Music/Directory/ambient-noise-server-room.mp3 (100%) rename {src => Sources}/MpcNET.Test/Server/Music/_My Directory/gas-fire-lighting.mp3 (100%) rename {src => Sources}/MpcNET.Test/Server/Music/teaspoon-stirring-mug-of-coffee.mp3 (100%) rename {src => Sources}/MpcNET.Test/Server/Music/whistle-kettle-boiling.mp3 (100%) rename {src => Sources}/MpcNET.Test/Server/Music/wine-glass-double-chink-clink-cheers.mp3 (100%) rename {src => Sources}/MpcNET.Test/Server/OpenAL32.dll (100%) rename {src => Sources}/MpcNET.Test/Server/Playlists/Playlist One.m3u (100%) rename {src => Sources}/MpcNET.Test/Server/Playlists/Playlist Two.m3u (100%) rename {src => Sources}/MpcNET.Test/Server/Playlists/_My Playlist.m3u (100%) rename {src => Sources}/MpcNET.Test/Server/StartLocal.bat (100%) rename {src => Sources}/MpcNET.Test/Server/mpd.conf (100%) rename {src => Sources}/MpcNET.Test/Server/mpd.db (100%) rename {src => Sources}/MpcNET.Test/Server/mpd.exe (100%) rename {src => Sources}/MpcNET.Test/Server/mpd_log.txt (100%) rename {src => Sources}/MpcNET.Test/Server/openal-info.exe (100%) rename {src => Sources}/MpcNET.Test/Server/winmm-info.exe (100%) rename {src => Sources}/MpcNET.Test/TestOutput.cs (100%) rename {src => Sources}/MpcNET.Test/Tests/DatabaseCommandsTest.cs (100%) rename {src => Sources}/MpcNET.Test/Tests/MpdMessageExtension.cs (100%) rename {src => Sources}/MpcNET.Test/Tests/OutputCommandsTest.cs (100%) rename {src => Sources}/MpcNET.Test/Tests/PlaylistsCommandsTest.cs (100%) rename {src => Sources}/MpcNET.Test/Tests/ReflectionCommandsTest.cs (100%) rename {src => Sources}/MpcNET.sln (100%) create mode 100644 Sources/MpcNET/CommandFactory.cs create mode 100644 Sources/MpcNET/Commands/CurrentPlaylistCommandFactory.cs create mode 100644 Sources/MpcNET/Commands/Database/FindCommand.cs rename {src => Sources}/MpcNET/Commands/Database/ListAllCommand.cs (54%) create mode 100644 Sources/MpcNET/Commands/Database/ListCommand.cs create mode 100644 Sources/MpcNET/Commands/Database/UpdateCommand.cs create mode 100644 Sources/MpcNET/Commands/DatabaseCommandFactory.cs create mode 100644 Sources/MpcNET/Commands/ICurrentPlaylistCommandFactory.cs create mode 100644 Sources/MpcNET/Commands/IDatabaseCommandFactory.cs create mode 100644 Sources/MpcNET/Commands/IOutputCommandFactory.cs create mode 100644 Sources/MpcNET/Commands/IPlaybackCommandFactory.cs create mode 100644 Sources/MpcNET/Commands/IReflectionCommandFactory.cs create mode 100644 Sources/MpcNET/Commands/IStatusCommandFactory.cs create mode 100644 Sources/MpcNET/Commands/IStoredPlaylistCommandFactory.cs create mode 100644 Sources/MpcNET/Commands/Output/DisableOutputCommand.cs create mode 100644 Sources/MpcNET/Commands/Output/EnableOutputCommand.cs create mode 100644 Sources/MpcNET/Commands/Output/OutputsCommand.cs create mode 100644 Sources/MpcNET/Commands/Output/ToggleOutputCommand.cs create mode 100644 Sources/MpcNET/Commands/OutputCommandFactory.cs create mode 100644 Sources/MpcNET/Commands/Playback/NextCommand.cs create mode 100644 Sources/MpcNET/Commands/Playback/PlayCommand.cs create mode 100644 Sources/MpcNET/Commands/Playback/PlayPauseCommand.cs create mode 100644 Sources/MpcNET/Commands/Playback/PreviousCommand.cs create mode 100644 Sources/MpcNET/Commands/Playback/SetVolumeCommand.cs create mode 100644 Sources/MpcNET/Commands/Playback/StopCommand.cs create mode 100644 Sources/MpcNET/Commands/PlaybackCommandFactory.cs create mode 100644 Sources/MpcNET/Commands/Playlist/AddCommand.cs create mode 100644 Sources/MpcNET/Commands/Playlist/AddIdCommand.cs create mode 100644 Sources/MpcNET/Commands/Playlist/ClearCommand.cs create mode 100644 Sources/MpcNET/Commands/Playlist/DeleteCommand.cs create mode 100644 Sources/MpcNET/Commands/Playlist/DeleteIdCommand.cs create mode 100644 Sources/MpcNET/Commands/Playlist/ListPlaylistCommand.cs create mode 100644 Sources/MpcNET/Commands/Playlist/ListPlaylistInfoCommand.cs create mode 100644 Sources/MpcNET/Commands/Playlist/ListPlaylistsCommand.cs create mode 100644 Sources/MpcNET/Commands/Playlist/LoadCommand.cs create mode 100644 Sources/MpcNET/Commands/Playlist/PlaylistCommand.cs create mode 100644 Sources/MpcNET/Commands/Playlist/PlaylistIdCommand.cs create mode 100644 Sources/MpcNET/Commands/Playlist/PlaylistInfoCommand.cs create mode 100644 Sources/MpcNET/Commands/Reflection/CommandsCommand.cs rename {src => Sources}/MpcNET/Commands/Reflection/DecodersCommand.cs (58%) create mode 100644 Sources/MpcNET/Commands/Reflection/TagTypesCommand.cs create mode 100644 Sources/MpcNET/Commands/Reflection/UrlHandlersCommand.cs create mode 100644 Sources/MpcNET/Commands/ReflectionCommandFactory.cs create mode 100644 Sources/MpcNET/Commands/Status/CurrentSongCommand.cs create mode 100644 Sources/MpcNET/Commands/Status/IdleCommand.cs create mode 100644 Sources/MpcNET/Commands/Status/NoIdleCommand.cs rename {src => Sources}/MpcNET/Commands/Status/StatusCommand.cs (56%) create mode 100644 Sources/MpcNET/Commands/StatusCommandFactory.cs create mode 100644 Sources/MpcNET/Commands/StoredPlaylistCommandFactory.cs create mode 100644 Sources/MpcNET/Constants.cs create mode 100644 Sources/MpcNET/Exceptions/CommandNullException.cs create mode 100644 Sources/MpcNET/Exceptions/EmptyResponseException.cs create mode 100644 Sources/MpcNET/Exceptions/MpcConnectException.cs create mode 100644 Sources/MpcNET/Exceptions/MpcException.cs create mode 100644 Sources/MpcNET/ICommandFactory.cs create mode 100644 Sources/MpcNET/IMpcCommand.cs create mode 100644 Sources/MpcNET/IMpcConnection.cs create mode 100644 Sources/MpcNET/IMpcConnectionObserver.cs create mode 100644 Sources/MpcNET/Message/ErrorMpdMessage.cs create mode 100644 Sources/MpcNET/Message/ErrorMpdResponse.cs create mode 100644 Sources/MpcNET/Message/IMpdMessage.cs create mode 100644 Sources/MpcNET/Message/IMpdRequest.cs create mode 100644 Sources/MpcNET/Message/IMpdResponse.cs create mode 100644 Sources/MpcNET/Message/IMpdResponseResult.cs create mode 100644 Sources/MpcNET/Message/MpdMessage.cs create mode 100644 Sources/MpcNET/Message/MpdRequest.cs create mode 100644 Sources/MpcNET/Message/MpdResponse.cs create mode 100644 Sources/MpcNET/Message/MpdResponseResult.cs create mode 100644 Sources/MpcNET/MpcConnection.cs rename {src => Sources}/MpcNET/MpcNET.csproj (50%) create mode 100644 Sources/MpcNET/MpdDirectoryListing.cs rename {src => Sources}/MpcNET/MpdState.cs (54%) create mode 100644 Sources/MpcNET/MpdStatistics.cs rename {src => Sources}/MpcNET/MpdStatus.cs (61%) rename {src => Sources}/MpcNET/Properties/AssemblyInfo.cs (60%) create mode 100644 Sources/MpcNET/Tags/FindTags.cs create mode 100644 Sources/MpcNET/Tags/ITag.cs create mode 100644 Sources/MpcNET/Tags/MpdTags.cs create mode 100644 Sources/MpcNET/Tags/Tag.cs create mode 100644 Sources/MpcNET/Types/IMpdFile.cs create mode 100644 Sources/MpcNET/Types/IMpdFilePath.cs create mode 100644 Sources/MpcNET/Types/MpdDecoderPlugin.cs create mode 100644 Sources/MpcNET/Types/MpdDirectory.cs rename {src => Sources}/MpcNET/Types/MpdFile.cs (81%) create mode 100644 Sources/MpcNET/Types/MpdOutput.cs create mode 100644 Sources/MpcNET/Types/MpdPlaylist.cs create mode 100644 Sources/MpcNET/stylecop.json delete mode 100644 src/MpcNET/Commands/Commands.Database.cs delete mode 100644 src/MpcNET/Commands/Commands.Output.cs delete mode 100644 src/MpcNET/Commands/Commands.Playback.cs delete mode 100644 src/MpcNET/Commands/Commands.Playlists.cs delete mode 100644 src/MpcNET/Commands/Commands.Reflection.cs delete mode 100644 src/MpcNET/Commands/Commands.Status.cs delete mode 100644 src/MpcNET/Commands/Database/FindCommand.cs delete mode 100644 src/MpcNET/Commands/Database/ListCommand.cs delete mode 100644 src/MpcNET/Commands/Database/UpdateCommand.cs delete mode 100644 src/MpcNET/Commands/Output/DisableOutputCommand.cs delete mode 100644 src/MpcNET/Commands/Output/EnableOutputCommand.cs delete mode 100644 src/MpcNET/Commands/Output/OutputsCommand.cs delete mode 100644 src/MpcNET/Commands/Output/ToggleOutputCommand.cs delete mode 100644 src/MpcNET/Commands/Playback/NextCommand.cs delete mode 100644 src/MpcNET/Commands/Playback/PlayCommand.cs delete mode 100644 src/MpcNET/Commands/Playback/PlayPauseCommand.cs delete mode 100644 src/MpcNET/Commands/Playback/PreviousCommand.cs delete mode 100644 src/MpcNET/Commands/Playback/StopCommand.cs delete mode 100644 src/MpcNET/Commands/Playlist/AddCommand.cs delete mode 100644 src/MpcNET/Commands/Playlist/AddIdCommand.cs delete mode 100644 src/MpcNET/Commands/Playlist/ClearCommand.cs delete mode 100644 src/MpcNET/Commands/Playlist/DeleteCommand.cs delete mode 100644 src/MpcNET/Commands/Playlist/DeleteIdCommand.cs delete mode 100644 src/MpcNET/Commands/Playlist/ListPlaylistCommand.cs delete mode 100644 src/MpcNET/Commands/Playlist/ListPlaylistInfoCommand.cs delete mode 100644 src/MpcNET/Commands/Playlist/ListPlaylistsCommand.cs delete mode 100644 src/MpcNET/Commands/Playlist/LoadCommand.cs delete mode 100644 src/MpcNET/Commands/Playlist/PlaylistCommand.cs delete mode 100644 src/MpcNET/Commands/Playlist/PlaylistIdCommand.cs delete mode 100644 src/MpcNET/Commands/Playlist/PlaylistInfoCommand.cs delete mode 100644 src/MpcNET/Commands/Reflection/CommandsCommand.cs delete mode 100644 src/MpcNET/Commands/Reflection/TagTypesCommand.cs delete mode 100644 src/MpcNET/Commands/Reflection/UrlHandlersCommand.cs delete mode 100644 src/MpcNET/Commands/Status/CurrentSongCommand.cs delete mode 100644 src/MpcNET/Constants.cs delete mode 100644 src/MpcNET/Exception.cs delete mode 100644 src/MpcNET/IMpcCommand.cs delete mode 100644 src/MpcNET/Message/IMpdMessage.cs delete mode 100644 src/MpcNET/Message/MpdMessage.cs delete mode 100644 src/MpcNET/Message/MpdRequest.cs delete mode 100644 src/MpcNET/Message/MpdResponse.cs delete mode 100644 src/MpcNET/Message/MpdResponseState.cs delete mode 100644 src/MpcNET/Mpc.cs delete mode 100644 src/MpcNET/MpcConnection.cs delete mode 100644 src/MpcNET/MpdDirectoryListing.cs delete mode 100644 src/MpcNET/MpdStatistics.cs delete mode 100644 src/MpcNET/Tags/FindTags.cs delete mode 100644 src/MpcNET/Tags/MpdTags.cs delete mode 100644 src/MpcNET/Tags/Tag.cs delete mode 100644 src/MpcNET/Types/IMpdFile.cs delete mode 100644 src/MpcNET/Types/IMpdFilePath.cs delete mode 100644 src/MpcNET/Types/MpdDecoderPlugin.cs delete mode 100644 src/MpcNET/Types/MpdDirectory.cs delete mode 100644 src/MpcNET/Types/MpdOutput.cs delete mode 100644 src/MpcNET/Types/MpdPlaylist.cs delete mode 100644 src/MpcNET/Utils/CheckNotNullExtension.cs diff --git a/.gitignore b/.gitignore index 1bc7f48..665e7fc 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,7 @@ /src/MpcNET/MpcNET.csproj.DotSettings /.vs *.user +/Sources/.vs/MpcNET/v15 +/Sources/MpcNET/bin/Debug/netstandard2.0 +/Sources/MpcNET/obj +/Sources/MpcNET.Test/obj diff --git a/src/MpcNET.Test/LibMpcTest.cs b/Sources/MpcNET.Test/LibMpcTest.cs similarity index 100% rename from src/MpcNET.Test/LibMpcTest.cs rename to Sources/MpcNET.Test/LibMpcTest.cs diff --git a/src/MpcNET.Test/MpcMock.cs b/Sources/MpcNET.Test/MpcMock.cs similarity index 100% rename from src/MpcNET.Test/MpcMock.cs rename to Sources/MpcNET.Test/MpcMock.cs diff --git a/src/MpcNET.Test/MpcNET.Test.csproj b/Sources/MpcNET.Test/MpcNET.Test.csproj similarity index 100% rename from src/MpcNET.Test/MpcNET.Test.csproj rename to Sources/MpcNET.Test/MpcNET.Test.csproj diff --git a/src/MpcNET.Test/MpdConf.cs b/Sources/MpcNET.Test/MpdConf.cs similarity index 100% rename from src/MpcNET.Test/MpdConf.cs rename to Sources/MpcNET.Test/MpdConf.cs diff --git a/src/MpcNET.Test/MpdMock.cs b/Sources/MpcNET.Test/MpdMock.cs similarity index 100% rename from src/MpcNET.Test/MpdMock.cs rename to Sources/MpcNET.Test/MpdMock.cs diff --git a/src/MpcNET.Test/Properties/AssemblyInfo.cs b/Sources/MpcNET.Test/Properties/AssemblyInfo.cs similarity index 100% rename from src/MpcNET.Test/Properties/AssemblyInfo.cs rename to Sources/MpcNET.Test/Properties/AssemblyInfo.cs diff --git a/src/MpcNET.Test/Server/Music/A long name directory with some spaces/Ghost-Sounds.mp3 b/Sources/MpcNET.Test/Server/Music/A long name directory with some spaces/Ghost-Sounds.mp3 similarity index 100% rename from src/MpcNET.Test/Server/Music/A long name directory with some spaces/Ghost-Sounds.mp3 rename to Sources/MpcNET.Test/Server/Music/A long name directory with some spaces/Ghost-Sounds.mp3 diff --git a/src/MpcNET.Test/Server/Music/A long name directory with some spaces/Sub Directory Two/short-trouser-pants-zip-closing.mp3 b/Sources/MpcNET.Test/Server/Music/A long name directory with some spaces/Sub Directory Two/short-trouser-pants-zip-closing.mp3 similarity index 100% rename from src/MpcNET.Test/Server/Music/A long name directory with some spaces/Sub Directory Two/short-trouser-pants-zip-closing.mp3 rename to Sources/MpcNET.Test/Server/Music/A long name directory with some spaces/Sub Directory Two/short-trouser-pants-zip-closing.mp3 diff --git a/src/MpcNET.Test/Server/Music/A long name directory with some spaces/Sub Directory Two/starting-engine-Ford-Mondeo-Mk-3-diesel.mp3 b/Sources/MpcNET.Test/Server/Music/A long name directory with some spaces/Sub Directory Two/starting-engine-Ford-Mondeo-Mk-3-diesel.mp3 similarity index 100% rename from src/MpcNET.Test/Server/Music/A long name directory with some spaces/Sub Directory Two/starting-engine-Ford-Mondeo-Mk-3-diesel.mp3 rename to Sources/MpcNET.Test/Server/Music/A long name directory with some spaces/Sub Directory Two/starting-engine-Ford-Mondeo-Mk-3-diesel.mp3 diff --git a/src/MpcNET.Test/Server/Music/A long name directory with some spaces/pouring-water-into-mug-of-coffee.mp3 b/Sources/MpcNET.Test/Server/Music/A long name directory with some spaces/pouring-water-into-mug-of-coffee.mp3 similarity index 100% rename from src/MpcNET.Test/Server/Music/A long name directory with some spaces/pouring-water-into-mug-of-coffee.mp3 rename to Sources/MpcNET.Test/Server/Music/A long name directory with some spaces/pouring-water-into-mug-of-coffee.mp3 diff --git a/src/MpcNET.Test/Server/Music/Directory With Spaces/SubDirectory One/central-locking-Ford-Mondeo-Mk-3.mp3 b/Sources/MpcNET.Test/Server/Music/Directory With Spaces/SubDirectory One/central-locking-Ford-Mondeo-Mk-3.mp3 similarity index 100% rename from src/MpcNET.Test/Server/Music/Directory With Spaces/SubDirectory One/central-locking-Ford-Mondeo-Mk-3.mp3 rename to Sources/MpcNET.Test/Server/Music/Directory With Spaces/SubDirectory One/central-locking-Ford-Mondeo-Mk-3.mp3 diff --git a/src/MpcNET.Test/Server/Music/Directory With Spaces/coin-spin-light.mp3 b/Sources/MpcNET.Test/Server/Music/Directory With Spaces/coin-spin-light.mp3 similarity index 100% rename from src/MpcNET.Test/Server/Music/Directory With Spaces/coin-spin-light.mp3 rename to Sources/MpcNET.Test/Server/Music/Directory With Spaces/coin-spin-light.mp3 diff --git a/src/MpcNET.Test/Server/Music/Directory With Spaces/finger-snap-click.mp3 b/Sources/MpcNET.Test/Server/Music/Directory With Spaces/finger-snap-click.mp3 similarity index 100% rename from src/MpcNET.Test/Server/Music/Directory With Spaces/finger-snap-click.mp3 rename to Sources/MpcNET.Test/Server/Music/Directory With Spaces/finger-snap-click.mp3 diff --git a/src/MpcNET.Test/Server/Music/Directory/2-Kids-Laughing.mp3 b/Sources/MpcNET.Test/Server/Music/Directory/2-Kids-Laughing.mp3 similarity index 100% rename from src/MpcNET.Test/Server/Music/Directory/2-Kids-Laughing.mp3 rename to Sources/MpcNET.Test/Server/Music/Directory/2-Kids-Laughing.mp3 diff --git a/src/MpcNET.Test/Server/Music/Directory/ambient-noise-server-room.mp3 b/Sources/MpcNET.Test/Server/Music/Directory/ambient-noise-server-room.mp3 similarity index 100% rename from src/MpcNET.Test/Server/Music/Directory/ambient-noise-server-room.mp3 rename to Sources/MpcNET.Test/Server/Music/Directory/ambient-noise-server-room.mp3 diff --git a/src/MpcNET.Test/Server/Music/_My Directory/gas-fire-lighting.mp3 b/Sources/MpcNET.Test/Server/Music/_My Directory/gas-fire-lighting.mp3 similarity index 100% rename from src/MpcNET.Test/Server/Music/_My Directory/gas-fire-lighting.mp3 rename to Sources/MpcNET.Test/Server/Music/_My Directory/gas-fire-lighting.mp3 diff --git a/src/MpcNET.Test/Server/Music/teaspoon-stirring-mug-of-coffee.mp3 b/Sources/MpcNET.Test/Server/Music/teaspoon-stirring-mug-of-coffee.mp3 similarity index 100% rename from src/MpcNET.Test/Server/Music/teaspoon-stirring-mug-of-coffee.mp3 rename to Sources/MpcNET.Test/Server/Music/teaspoon-stirring-mug-of-coffee.mp3 diff --git a/src/MpcNET.Test/Server/Music/whistle-kettle-boiling.mp3 b/Sources/MpcNET.Test/Server/Music/whistle-kettle-boiling.mp3 similarity index 100% rename from src/MpcNET.Test/Server/Music/whistle-kettle-boiling.mp3 rename to Sources/MpcNET.Test/Server/Music/whistle-kettle-boiling.mp3 diff --git a/src/MpcNET.Test/Server/Music/wine-glass-double-chink-clink-cheers.mp3 b/Sources/MpcNET.Test/Server/Music/wine-glass-double-chink-clink-cheers.mp3 similarity index 100% rename from src/MpcNET.Test/Server/Music/wine-glass-double-chink-clink-cheers.mp3 rename to Sources/MpcNET.Test/Server/Music/wine-glass-double-chink-clink-cheers.mp3 diff --git a/src/MpcNET.Test/Server/OpenAL32.dll b/Sources/MpcNET.Test/Server/OpenAL32.dll similarity index 100% rename from src/MpcNET.Test/Server/OpenAL32.dll rename to Sources/MpcNET.Test/Server/OpenAL32.dll diff --git a/src/MpcNET.Test/Server/Playlists/Playlist One.m3u b/Sources/MpcNET.Test/Server/Playlists/Playlist One.m3u similarity index 100% rename from src/MpcNET.Test/Server/Playlists/Playlist One.m3u rename to Sources/MpcNET.Test/Server/Playlists/Playlist One.m3u diff --git a/src/MpcNET.Test/Server/Playlists/Playlist Two.m3u b/Sources/MpcNET.Test/Server/Playlists/Playlist Two.m3u similarity index 100% rename from src/MpcNET.Test/Server/Playlists/Playlist Two.m3u rename to Sources/MpcNET.Test/Server/Playlists/Playlist Two.m3u diff --git a/src/MpcNET.Test/Server/Playlists/_My Playlist.m3u b/Sources/MpcNET.Test/Server/Playlists/_My Playlist.m3u similarity index 100% rename from src/MpcNET.Test/Server/Playlists/_My Playlist.m3u rename to Sources/MpcNET.Test/Server/Playlists/_My Playlist.m3u diff --git a/src/MpcNET.Test/Server/StartLocal.bat b/Sources/MpcNET.Test/Server/StartLocal.bat similarity index 100% rename from src/MpcNET.Test/Server/StartLocal.bat rename to Sources/MpcNET.Test/Server/StartLocal.bat diff --git a/src/MpcNET.Test/Server/mpd.conf b/Sources/MpcNET.Test/Server/mpd.conf similarity index 100% rename from src/MpcNET.Test/Server/mpd.conf rename to Sources/MpcNET.Test/Server/mpd.conf diff --git a/src/MpcNET.Test/Server/mpd.db b/Sources/MpcNET.Test/Server/mpd.db similarity index 100% rename from src/MpcNET.Test/Server/mpd.db rename to Sources/MpcNET.Test/Server/mpd.db diff --git a/src/MpcNET.Test/Server/mpd.exe b/Sources/MpcNET.Test/Server/mpd.exe similarity index 100% rename from src/MpcNET.Test/Server/mpd.exe rename to Sources/MpcNET.Test/Server/mpd.exe diff --git a/src/MpcNET.Test/Server/mpd_log.txt b/Sources/MpcNET.Test/Server/mpd_log.txt similarity index 100% rename from src/MpcNET.Test/Server/mpd_log.txt rename to Sources/MpcNET.Test/Server/mpd_log.txt diff --git a/src/MpcNET.Test/Server/openal-info.exe b/Sources/MpcNET.Test/Server/openal-info.exe similarity index 100% rename from src/MpcNET.Test/Server/openal-info.exe rename to Sources/MpcNET.Test/Server/openal-info.exe diff --git a/src/MpcNET.Test/Server/winmm-info.exe b/Sources/MpcNET.Test/Server/winmm-info.exe similarity index 100% rename from src/MpcNET.Test/Server/winmm-info.exe rename to Sources/MpcNET.Test/Server/winmm-info.exe diff --git a/src/MpcNET.Test/TestOutput.cs b/Sources/MpcNET.Test/TestOutput.cs similarity index 100% rename from src/MpcNET.Test/TestOutput.cs rename to Sources/MpcNET.Test/TestOutput.cs diff --git a/src/MpcNET.Test/Tests/DatabaseCommandsTest.cs b/Sources/MpcNET.Test/Tests/DatabaseCommandsTest.cs similarity index 100% rename from src/MpcNET.Test/Tests/DatabaseCommandsTest.cs rename to Sources/MpcNET.Test/Tests/DatabaseCommandsTest.cs diff --git a/src/MpcNET.Test/Tests/MpdMessageExtension.cs b/Sources/MpcNET.Test/Tests/MpdMessageExtension.cs similarity index 100% rename from src/MpcNET.Test/Tests/MpdMessageExtension.cs rename to Sources/MpcNET.Test/Tests/MpdMessageExtension.cs diff --git a/src/MpcNET.Test/Tests/OutputCommandsTest.cs b/Sources/MpcNET.Test/Tests/OutputCommandsTest.cs similarity index 100% rename from src/MpcNET.Test/Tests/OutputCommandsTest.cs rename to Sources/MpcNET.Test/Tests/OutputCommandsTest.cs diff --git a/src/MpcNET.Test/Tests/PlaylistsCommandsTest.cs b/Sources/MpcNET.Test/Tests/PlaylistsCommandsTest.cs similarity index 100% rename from src/MpcNET.Test/Tests/PlaylistsCommandsTest.cs rename to Sources/MpcNET.Test/Tests/PlaylistsCommandsTest.cs diff --git a/src/MpcNET.Test/Tests/ReflectionCommandsTest.cs b/Sources/MpcNET.Test/Tests/ReflectionCommandsTest.cs similarity index 100% rename from src/MpcNET.Test/Tests/ReflectionCommandsTest.cs rename to Sources/MpcNET.Test/Tests/ReflectionCommandsTest.cs diff --git a/src/MpcNET.sln b/Sources/MpcNET.sln similarity index 100% rename from src/MpcNET.sln rename to Sources/MpcNET.sln diff --git a/Sources/MpcNET/CommandFactory.cs b/Sources/MpcNET/CommandFactory.cs new file mode 100644 index 0000000..1b01c5d --- /dev/null +++ b/Sources/MpcNET/CommandFactory.cs @@ -0,0 +1,74 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace MpcNET +{ + using MpcNET.Commands; + + /// + /// Provides MPD commands. + /// + /// + public class CommandFactory : ICommandFactory + { + /// + /// Gets the status command factory. + /// + /// + /// The status. + /// + public IStatusCommandFactory Status { get; } = new StatusCommandFactory(); + + /// + /// Gets the database command factory. + /// + /// + /// The database. + /// + public IDatabaseCommandFactory Database { get; } = new DatabaseCommandFactory(); + + /// + /// Gets the reflection command factory. + /// + /// + /// The reflection. + /// + public IReflectionCommandFactory Reflection { get; } = new ReflectionCommandFactory(); + + /// + /// Gets the stored playlist command factory. + /// + /// + /// The stored playlist. + /// + public IStoredPlaylistCommandFactory StoredPlaylist { get; } = new StoredPlaylistCommandFactory(); + + /// + /// Gets the current playlist command factory. + /// + /// + /// The current playlist. + /// + public ICurrentPlaylistCommandFactory CurrentPlaylist { get; } = new CurrentPlaylistCommandFactory(); + + /// + /// Gets the playback command factory. + /// + /// + /// The playback. + /// + public IPlaybackCommandFactory Playback { get; } = new PlaybackCommandFactory(); + + /// + /// Gets the output command factory. + /// + /// + /// The output. + /// + public IOutputCommandFactory Output { get; } = new OutputCommandFactory(); + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/CurrentPlaylistCommandFactory.cs b/Sources/MpcNET/Commands/CurrentPlaylistCommandFactory.cs new file mode 100644 index 0000000..d06e805 --- /dev/null +++ b/Sources/MpcNET/Commands/CurrentPlaylistCommandFactory.cs @@ -0,0 +1,95 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands +{ + using System.Collections.Generic; + using MpcNET.Commands.Playlist; + using MpcNET.Types; + + /// + /// https://www.musicpd.org/doc/protocol/queue.html + /// + public class CurrentPlaylistCommandFactory : ICurrentPlaylistCommandFactory + { + /// + /// Command: add + /// + /// The directory. + /// An . + public IMpcCommand AddDirectory(string directory) + { + return new AddCommand(directory); + } + + /// + /// Command: addid + /// + /// The song path. + /// An . + public IMpcCommand AddSong(string songPath) + { + return new AddIdCommand(songPath); + } + + /// + /// Command: clear + /// + /// An . + public IMpcCommand Clear() + { + return new ClearCommand(); + } + + /// + /// Command: playlist + /// + /// A . + public IMpcCommand> GetAllSongsInfo() + { + return new PlaylistCommand(); + } + + /// + /// Command: delete + /// + /// The position. + /// A . + public IMpcCommand RemoveSongByPosition(int position) + { + return new DeleteCommand(position); + } + + /// + /// Command: deleteid + /// + /// The song identifier. + /// A . + public IMpcCommand RemoveSongById(int songId) + { + return new DeleteIdCommand(songId); + } + + /// + /// Command: playlistid + /// + /// The song identifier. + /// A . + public IMpcCommand> GetSongMetadata(int songId) + { + return new PlaylistIdCommand(songId); + } + + /// + /// Command: playlistinfo + /// + /// A . + public IMpcCommand> GetAllSongMetadata() + { + return new PlaylistInfoCommand(); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Database/FindCommand.cs b/Sources/MpcNET/Commands/Database/FindCommand.cs new file mode 100644 index 0000000..d82168e --- /dev/null +++ b/Sources/MpcNET/Commands/Database/FindCommand.cs @@ -0,0 +1,36 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Database +{ + using System.Collections.Generic; + using MpcNET.Tags; + using MpcNET.Types; + + /// + /// Finds songs in the database that is exactly "searchText". + /// + internal class FindCommand : IMpcCommand> + { + private readonly ITag tag; + private readonly string searchText; + + public FindCommand(ITag tag, string searchText) + { + this.tag = tag; + this.searchText = searchText; + } + + public string Serialize() => string.Join(" ", "find", this.tag.Value, this.searchText); + + public IEnumerable Deserialize(IReadOnlyList> response) + { + return MpdFile.CreateList(response); + } + } + + // TODO: rescan +} diff --git a/src/MpcNET/Commands/Database/ListAllCommand.cs b/Sources/MpcNET/Commands/Database/ListAllCommand.cs similarity index 54% rename from src/MpcNET/Commands/Database/ListAllCommand.cs rename to Sources/MpcNET/Commands/Database/ListAllCommand.cs index 727171b..b2dba1a 100644 --- a/src/MpcNET/Commands/Database/ListAllCommand.cs +++ b/Sources/MpcNET/Commands/Database/ListAllCommand.cs @@ -1,18 +1,23 @@ -using System.Collections.Generic; -using System.Linq; -using MpcNET.Types; - +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- namespace MpcNET.Commands.Database { + using System.Collections.Generic; + using System.Linq; + using MpcNET.Types; /// /// Lists all songs and directories in URI. /// internal class ListAllCommand : IMpcCommand> { - public string Value => "listall"; + public string Serialize() => "listall"; - public IEnumerable FormatResponse(IList> response) + public IEnumerable Deserialize(IReadOnlyList> response) { var rootDirectory = new List { diff --git a/Sources/MpcNET/Commands/Database/ListCommand.cs b/Sources/MpcNET/Commands/Database/ListCommand.cs new file mode 100644 index 0000000..f76371f --- /dev/null +++ b/Sources/MpcNET/Commands/Database/ListCommand.cs @@ -0,0 +1,31 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Database +{ + using System.Collections.Generic; + using MpcNET.Tags; + + internal class ListCommand : IMpcCommand + { + private readonly ITag tag; + + public ListCommand(ITag tag) + { + this.tag = tag; + } + + public string Serialize() => string.Join(" ", "list", this.tag); + + public string Deserialize(IReadOnlyList> response) + { + // TODO: + return response.ToString(); + } + } + + // TODO: rescan +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Database/UpdateCommand.cs b/Sources/MpcNET/Commands/Database/UpdateCommand.cs new file mode 100644 index 0000000..bb3fd7d --- /dev/null +++ b/Sources/MpcNET/Commands/Database/UpdateCommand.cs @@ -0,0 +1,46 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Database +{ + using System.Collections.Generic; + + internal class UpdateCommand : IMpcCommand + { + private readonly string uri; + + public UpdateCommand(string uri) + { + this.uri = uri; + } + + public string Serialize() + { + if (string.IsNullOrEmpty(this.uri)) + { + return "update"; + } + + var newUri = this.uri; + if (this.uri.StartsWith(@"""")) + { + newUri = @"""" + this.uri; + } + + if (this.uri.EndsWith(@"""")) + { + newUri = this.uri + @""""; + } + + return string.Join(" ", "update", newUri); + } + + public string Deserialize(IReadOnlyList> response) + { + return string.Join(", ", response); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/DatabaseCommandFactory.cs b/Sources/MpcNET/Commands/DatabaseCommandFactory.cs new file mode 100644 index 0000000..20bdd71 --- /dev/null +++ b/Sources/MpcNET/Commands/DatabaseCommandFactory.cs @@ -0,0 +1,52 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands +{ + using System.Collections.Generic; + using MpcNET.Commands.Database; + using MpcNET.Tags; + using MpcNET.Types; + + /// + /// https://www.musicpd.org/doc/protocol/database.html + /// + public class DatabaseCommandFactory : IDatabaseCommandFactory + { + /// + /// Finds the specified tag. + /// + /// The tag. + /// The search text. + /// An . + public IMpcCommand> Find(ITag tag, string searchText) + { + return new FindCommand(tag, searchText); + } + + /// + /// Updates the specified URI. + /// + /// The URI. + /// An . + public IMpcCommand Update(string uri = null) + { + return new UpdateCommand(uri); + } + + /// + /// Lists all. + /// + /// A . + public IMpcCommand> ListAll() + { + return new ListAllCommand(); + } + + // TODO: count + // TODO: rescan + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/ICurrentPlaylistCommandFactory.cs b/Sources/MpcNET/Commands/ICurrentPlaylistCommandFactory.cs new file mode 100644 index 0000000..dcb3944 --- /dev/null +++ b/Sources/MpcNET/Commands/ICurrentPlaylistCommandFactory.cs @@ -0,0 +1,71 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands +{ + using System.Collections.Generic; + using MpcNET.Commands.Playlist; + using MpcNET.Types; + + /// + /// Provides current playlist commands. + /// + public interface ICurrentPlaylistCommandFactory + { + /// + /// Command: add + /// + /// The directory. + /// An . + IMpcCommand AddDirectory(string directory); + + /// + /// Command: addid + /// + /// The song path. + /// An . + IMpcCommand AddSong(string songPath); + + /// + /// Command: clear + /// + /// An . + IMpcCommand Clear(); + + /// + /// Command: playlist + /// + /// A . + IMpcCommand> GetAllSongsInfo(); + + /// + /// Command: delete + /// + /// The position. + /// A . + IMpcCommand RemoveSongByPosition(int position); + + /// + /// Command: deleteid + /// + /// The song identifier. + /// A . + IMpcCommand RemoveSongById(int songId); + + /// + /// Command: playlistid + /// + /// The song identifier. + /// A . + IMpcCommand> GetSongMetadata(int songId); + + /// + /// Command: playlistinfo + /// + /// A . + IMpcCommand> GetAllSongMetadata(); + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/IDatabaseCommandFactory.cs b/Sources/MpcNET/Commands/IDatabaseCommandFactory.cs new file mode 100644 index 0000000..794eae2 --- /dev/null +++ b/Sources/MpcNET/Commands/IDatabaseCommandFactory.cs @@ -0,0 +1,40 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands +{ + using System.Collections.Generic; + using MpcNET.Commands.Database; + using MpcNET.Tags; + using MpcNET.Types; + + /// + /// Provides database commands. + /// + public interface IDatabaseCommandFactory + { + /// + /// Finds the specified tag. + /// + /// The tag. + /// The search text. + /// An . + IMpcCommand> Find(ITag tag, string searchText); + + /// + /// Updates the specified URI. + /// + /// The URI. + /// An . + IMpcCommand Update(string uri = null); + + /// + /// Lists all. + /// + /// A . + IMpcCommand> ListAll(); + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/IOutputCommandFactory.cs b/Sources/MpcNET/Commands/IOutputCommandFactory.cs new file mode 100644 index 0000000..466beab --- /dev/null +++ b/Sources/MpcNET/Commands/IOutputCommandFactory.cs @@ -0,0 +1,45 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands +{ + using System.Collections.Generic; + using MpcNET.Commands.Output; + using MpcNET.Types; + + /// + /// Provides output commands. + /// + public interface IOutputCommandFactory + { + /// + /// Outputses this instance. + /// + /// An . + IMpcCommand> Outputs(); + + /// + /// Disables the output. + /// + /// The output identifier. + /// A . + IMpcCommand DisableOutput(int outputId); + + /// + /// Enables the output. + /// + /// The output identifier. + /// A . + IMpcCommand EnableOutput(int outputId); + + /// + /// Toggles the output. + /// + /// The output identifier. + /// A . + IMpcCommand ToggleOutput(int outputId); + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/IPlaybackCommandFactory.cs b/Sources/MpcNET/Commands/IPlaybackCommandFactory.cs new file mode 100644 index 0000000..f7185f3 --- /dev/null +++ b/Sources/MpcNET/Commands/IPlaybackCommandFactory.cs @@ -0,0 +1,71 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands +{ + using MpcNET.Commands.Playback; + using MpcNET.Types; + + /// + /// Provides playback commands. + /// + public interface IPlaybackCommandFactory + { + /// + /// Get a next command. + /// + /// A . + IMpcCommand Next(); + + /// + /// Get a previous command. + /// + /// A . + IMpcCommand Previous(); + + /// + /// Gets a play-pause command. + /// + /// A . + IMpcCommand PlayPause(); + + /// + /// Gets a play command. + /// + /// The MPD file. + /// A . + IMpcCommand Play(IMpdFile mpdFile); + + /// + /// Gets a play command. + /// + /// The position. + /// A . + IMpcCommand Play(int position); + + /// + /// Gets a play command. + /// + /// The identifier. + /// A . + IMpcCommand PlayId(int id); + + /// + /// Gets a stop command. + /// + /// A . + IMpcCommand Stop(); + + /// + /// Sets the volume. + /// + /// The volume. + /// + /// A . + /// + IMpcCommand SetVolume(byte volume); + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/IReflectionCommandFactory.cs b/Sources/MpcNET/Commands/IReflectionCommandFactory.cs new file mode 100644 index 0000000..f9195be --- /dev/null +++ b/Sources/MpcNET/Commands/IReflectionCommandFactory.cs @@ -0,0 +1,42 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands +{ + using System.Collections.Generic; + using MpcNET.Commands.Reflection; + using MpcNET.Types; + + /// + /// Provides reflection commands. + /// + public interface IReflectionCommandFactory + { + /// + /// Gets a commands command. + /// + /// A . + IMpcCommand> Commands(); + + /// + /// Gets a tag types command. + /// + /// A . + IMpcCommand> TagTypes(); + + /// + /// Gets URL handlers command. + /// + /// A . + IMpcCommand> UrlHandlers(); + + /// + /// Gets a decoders command. + /// + /// A . + IMpcCommand> Decoders(); + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/IStatusCommandFactory.cs b/Sources/MpcNET/Commands/IStatusCommandFactory.cs new file mode 100644 index 0000000..f39f933 --- /dev/null +++ b/Sources/MpcNET/Commands/IStatusCommandFactory.cs @@ -0,0 +1,29 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands +{ + using MpcNET.Commands.Status; + using MpcNET.Types; + + /// + /// Provides status commands. + /// + public interface IStatusCommandFactory + { + /// + /// Gets a status command. + /// + /// A . + IMpcCommand GetStatus(); + + /// + /// Gets a current song command. + /// + /// A . + IMpcCommand GetCurrentSong(); + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/IStoredPlaylistCommandFactory.cs b/Sources/MpcNET/Commands/IStoredPlaylistCommandFactory.cs new file mode 100644 index 0000000..ef32fce --- /dev/null +++ b/Sources/MpcNET/Commands/IStoredPlaylistCommandFactory.cs @@ -0,0 +1,45 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands +{ + using System.Collections.Generic; + using MpcNET.Commands.Playlist; + using MpcNET.Types; + + /// + /// Provides stored playlist commands. + /// + public interface IStoredPlaylistCommandFactory + { + /// + /// Command: load + /// + /// Name of the playlist. + /// A . + IMpcCommand Load(string playlistName); + + /// + /// Command: listplaylist + /// + /// Name of the playlist. + /// A . + IMpcCommand> GetContent(string playlistName); + + /// + /// Command: listplaylistinfo + /// + /// Name of the playlist. + /// A . + IMpcCommand> GetContentWithMetadata(string playlistName); + + /// + /// Command: listplaylists + /// + /// A . + IMpcCommand> GetAll(); + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Output/DisableOutputCommand.cs b/Sources/MpcNET/Commands/Output/DisableOutputCommand.cs new file mode 100644 index 0000000..764be07 --- /dev/null +++ b/Sources/MpcNET/Commands/Output/DisableOutputCommand.cs @@ -0,0 +1,31 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Output +{ + using System.Collections.Generic; + + /// + /// Turns an output off. + /// + internal class DisableOutputCommand : IMpcCommand + { + private readonly int outputId; + + public DisableOutputCommand(int outputId) + { + this.outputId = outputId; + } + + public string Serialize() => string.Join(" ", "disableoutput", this.outputId); + + public string Deserialize(IReadOnlyList> response) + { + // Response should be empty. + return string.Join(", ", response); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Output/EnableOutputCommand.cs b/Sources/MpcNET/Commands/Output/EnableOutputCommand.cs new file mode 100644 index 0000000..a058acc --- /dev/null +++ b/Sources/MpcNET/Commands/Output/EnableOutputCommand.cs @@ -0,0 +1,31 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Output +{ + using System.Collections.Generic; + + /// + /// Turns an output on. + /// + internal class EnableOutputCommand : IMpcCommand + { + private readonly int outputId; + + public EnableOutputCommand(int outputId) + { + this.outputId = outputId; + } + + public string Serialize() => string.Join(" ", "enableoutput", this.outputId); + + public string Deserialize(IReadOnlyList> response) + { + // Response should be empty. + return string.Join(", ", response); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Output/OutputsCommand.cs b/Sources/MpcNET/Commands/Output/OutputsCommand.cs new file mode 100644 index 0000000..abaf1ea --- /dev/null +++ b/Sources/MpcNET/Commands/Output/OutputsCommand.cs @@ -0,0 +1,35 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Output +{ + using System.Collections.Generic; + using MpcNET.Types; + + /// + /// Shows information about all outputs. + /// + internal class OutputsCommand : IMpcCommand> + { + public string Serialize() => "outputs"; + + public IEnumerable Deserialize(IReadOnlyList> response) + { + var result = new List(); + + for (var i = 0; i < response.Count; i += 3) + { + var outputId = int.Parse(response[i].Value); + var outputName = response[i + 1].Value; + var outputEnabled = response[i + 2].Value == "1"; + + result.Add(new MpdOutput(outputId, outputName, outputEnabled)); + } + + return result; + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Output/ToggleOutputCommand.cs b/Sources/MpcNET/Commands/Output/ToggleOutputCommand.cs new file mode 100644 index 0000000..37ad118 --- /dev/null +++ b/Sources/MpcNET/Commands/Output/ToggleOutputCommand.cs @@ -0,0 +1,30 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Output +{ + using System.Collections.Generic; + + /// + /// Turns an output on or off, depending on the current state. + /// + internal class ToggleOutputCommand : IMpcCommand + { + private readonly int outputId; + + public ToggleOutputCommand(int outputId) + { + this.outputId = outputId; + } + + public string Serialize() => string.Join(" ", "toggleoutput", this.outputId); + + public string Deserialize(IReadOnlyList> response) + { + return string.Join(", ", response); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/OutputCommandFactory.cs b/Sources/MpcNET/Commands/OutputCommandFactory.cs new file mode 100644 index 0000000..e7c2761 --- /dev/null +++ b/Sources/MpcNET/Commands/OutputCommandFactory.cs @@ -0,0 +1,57 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands +{ + using System.Collections.Generic; + using MpcNET.Commands.Output; + using MpcNET.Types; + + /// + /// https://www.musicpd.org/doc/protocol/output_commands.html + /// + public class OutputCommandFactory : IOutputCommandFactory + { + /// + /// Outputses this instance. + /// + /// An . + public IMpcCommand> Outputs() + { + return new OutputsCommand(); + } + + /// + /// Disables the output. + /// + /// The output identifier. + /// A . + public IMpcCommand DisableOutput(int outputId) + { + return new DisableOutputCommand(outputId); + } + + /// + /// Enables the output. + /// + /// The output identifier. + /// A . + public IMpcCommand EnableOutput(int outputId) + { + return new EnableOutputCommand(outputId); + } + + /// + /// Toggles the output. + /// + /// The output identifier. + /// A . + public IMpcCommand ToggleOutput(int outputId) + { + return new ToggleOutputCommand(outputId); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Playback/NextCommand.cs b/Sources/MpcNET/Commands/Playback/NextCommand.cs new file mode 100644 index 0000000..b9e72dc --- /dev/null +++ b/Sources/MpcNET/Commands/Playback/NextCommand.cs @@ -0,0 +1,20 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Playback +{ + using System.Collections.Generic; + + internal class NextCommand : IMpcCommand + { + public string Serialize() => string.Join(" ", "next"); + + public string Deserialize(IReadOnlyList> response) + { + return string.Join(", ", response); + } + } +} diff --git a/Sources/MpcNET/Commands/Playback/PlayCommand.cs b/Sources/MpcNET/Commands/Playback/PlayCommand.cs new file mode 100644 index 0000000..93de049 --- /dev/null +++ b/Sources/MpcNET/Commands/Playback/PlayCommand.cs @@ -0,0 +1,43 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Playback +{ + using System; + using System.Collections.Generic; + using MpcNET.Types; + + internal class PlayCommand : IMpcCommand + { + private readonly int position; + private readonly int id; + + public PlayCommand(int position, int id) + { + this.position = position; + this.id = id; + if (this.position == MpdFile.NoPos && this.id == MpdFile.NoId) + { + throw new ArgumentException("PlayCommand requires Id or Position"); + } + } + + public string Serialize() + { + if (this.id != MpdFile.NoId) + { + return string.Join(" ", "playid", this.id); + } + + return string.Join(" ", "play", this.position); + } + + public string Deserialize(IReadOnlyList> response) + { + return string.Join(", ", response); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Playback/PlayPauseCommand.cs b/Sources/MpcNET/Commands/Playback/PlayPauseCommand.cs new file mode 100644 index 0000000..201d448 --- /dev/null +++ b/Sources/MpcNET/Commands/Playback/PlayPauseCommand.cs @@ -0,0 +1,20 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Playback +{ + using System.Collections.Generic; + + internal class PlayPauseCommand : IMpcCommand + { + public string Serialize() => string.Join(" ", "pause"); + + public string Deserialize(IReadOnlyList> response) + { + return string.Join(", ", response); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Playback/PreviousCommand.cs b/Sources/MpcNET/Commands/Playback/PreviousCommand.cs new file mode 100644 index 0000000..42f83aa --- /dev/null +++ b/Sources/MpcNET/Commands/Playback/PreviousCommand.cs @@ -0,0 +1,20 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Playback +{ + using System.Collections.Generic; + + internal class PreviousCommand : IMpcCommand + { + public string Serialize() => string.Join(" ", "previous"); + + public string Deserialize(IReadOnlyList> response) + { + return string.Join(", ", response); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Playback/SetVolumeCommand.cs b/Sources/MpcNET/Commands/Playback/SetVolumeCommand.cs new file mode 100644 index 0000000..d7a10f5 --- /dev/null +++ b/Sources/MpcNET/Commands/Playback/SetVolumeCommand.cs @@ -0,0 +1,31 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace MpcNET.Commands.Playback +{ + using System.Collections.Generic; + + internal class SetVolumeCommand : IMpcCommand + { + private readonly byte volume; + + public SetVolumeCommand(byte volume) + { + this.volume = volume; + } + + public string Serialize() + { + return string.Join(" ", "setvol", this.volume); + } + + public string Deserialize(IReadOnlyList> response) + { + return string.Join(", ", response); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Playback/StopCommand.cs b/Sources/MpcNET/Commands/Playback/StopCommand.cs new file mode 100644 index 0000000..5445d07 --- /dev/null +++ b/Sources/MpcNET/Commands/Playback/StopCommand.cs @@ -0,0 +1,20 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Playback +{ + using System.Collections.Generic; + + internal class StopCommand : IMpcCommand + { + public string Serialize() => string.Join(" ", "stop"); + + public string Deserialize(IReadOnlyList> response) + { + return string.Join(", ", response); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/PlaybackCommandFactory.cs b/Sources/MpcNET/Commands/PlaybackCommandFactory.cs new file mode 100644 index 0000000..0ac9f81 --- /dev/null +++ b/Sources/MpcNET/Commands/PlaybackCommandFactory.cs @@ -0,0 +1,95 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands +{ + using MpcNET.Commands.Playback; + using MpcNET.Types; + + /// + /// https://www.musicpd.org/doc/protocol/playback_commands.html + /// + public class PlaybackCommandFactory : IPlaybackCommandFactory + { + /// + /// Get a next command. + /// + /// A . + public IMpcCommand Next() + { + return new NextCommand(); + } + + /// + /// Get a previous command. + /// + /// A . + public IMpcCommand Previous() + { + return new PreviousCommand(); + } + + /// + /// Gets a play-pause command. + /// + /// A . + public IMpcCommand PlayPause() + { + return new PlayPauseCommand(); + } + + /// + /// Gets a play command. + /// + /// The MPD file. + /// A . + public IMpcCommand Play(IMpdFile mpdFile) + { + return new PlayCommand(mpdFile.Id, mpdFile.Position); + } + + /// + /// Gets a play command. + /// + /// The position. + /// A . + public IMpcCommand Play(int position) + { + return new PlayCommand(position, MpdFile.NoId); + } + + /// + /// Gets a play command. + /// + /// The identifier. + /// A . + public IMpcCommand PlayId(int id) + { + return new PlayCommand(MpdFile.NoPos, id); + } + + /// + /// Gets a stop command. + /// + /// A . + public IMpcCommand Stop() + { + return new StopCommand(); + } + + /// + /// Sets the volume. + /// + /// The volume. + /// + /// A . + /// + public IMpcCommand SetVolume(byte volume) + { + return new SetVolumeCommand(volume); + } + } +} diff --git a/Sources/MpcNET/Commands/Playlist/AddCommand.cs b/Sources/MpcNET/Commands/Playlist/AddCommand.cs new file mode 100644 index 0000000..8dc0498 --- /dev/null +++ b/Sources/MpcNET/Commands/Playlist/AddCommand.cs @@ -0,0 +1,30 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Playlist +{ + using System.Collections.Generic; + + /// + /// Adds the file URI to the playlist (directories add recursively). URI can also be a single file. + /// + internal class AddCommand : IMpcCommand + { + private readonly string uri; + + public AddCommand(string uri) + { + this.uri = uri; + } + + public string Serialize() => string.Join(" ", "add", $"\"{this.uri}\""); + + public string Deserialize(IReadOnlyList> response) + { + return string.Join(", ", response); + } + } +} diff --git a/Sources/MpcNET/Commands/Playlist/AddIdCommand.cs b/Sources/MpcNET/Commands/Playlist/AddIdCommand.cs new file mode 100644 index 0000000..09d4cd2 --- /dev/null +++ b/Sources/MpcNET/Commands/Playlist/AddIdCommand.cs @@ -0,0 +1,30 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Playlist +{ + using System.Collections.Generic; + + /// + /// Adds a song to the playlist (non-recursive) and returns the song id. + /// + internal class AddIdCommand : IMpcCommand + { + private readonly string uri; + + public AddIdCommand(string uri) + { + this.uri = uri; + } + + public string Serialize() => string.Join(" ", "addid", $"\"{this.uri}\""); + + public string Deserialize(IReadOnlyList> response) + { + return string.Join(", ", response); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Playlist/ClearCommand.cs b/Sources/MpcNET/Commands/Playlist/ClearCommand.cs new file mode 100644 index 0000000..a822b08 --- /dev/null +++ b/Sources/MpcNET/Commands/Playlist/ClearCommand.cs @@ -0,0 +1,23 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Playlist +{ + using System.Collections.Generic; + + /// + /// Clears the current playlist. + /// + internal class ClearCommand : IMpcCommand + { + public string Serialize() => "clear"; + + public string Deserialize(IReadOnlyList> response) + { + return string.Join(", ", response); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Playlist/DeleteCommand.cs b/Sources/MpcNET/Commands/Playlist/DeleteCommand.cs new file mode 100644 index 0000000..d923350 --- /dev/null +++ b/Sources/MpcNET/Commands/Playlist/DeleteCommand.cs @@ -0,0 +1,30 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Playlist +{ + using System.Collections.Generic; + + /// + /// Deletes a song from the playlist. + /// + internal class DeleteCommand : IMpcCommand + { + private readonly int position; + + public DeleteCommand(int position) + { + this.position = position; + } + + public string Serialize() => string.Join(" ", "delete", this.position); + + public string Deserialize(IReadOnlyList> response) + { + return string.Join(", ", response); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Playlist/DeleteIdCommand.cs b/Sources/MpcNET/Commands/Playlist/DeleteIdCommand.cs new file mode 100644 index 0000000..1083ee9 --- /dev/null +++ b/Sources/MpcNET/Commands/Playlist/DeleteIdCommand.cs @@ -0,0 +1,30 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Playlist +{ + using System.Collections.Generic; + + /// + /// Deletes the song SONGID from the playlist + /// + internal class DeleteIdCommand : IMpcCommand + { + private readonly int songId; + + public DeleteIdCommand(int songId) + { + this.songId = songId; + } + + public string Serialize() => string.Join(" ", "deleteid", this.songId); + + public string Deserialize(IReadOnlyList> response) + { + return string.Join(", ", response); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Playlist/ListPlaylistCommand.cs b/Sources/MpcNET/Commands/Playlist/ListPlaylistCommand.cs new file mode 100644 index 0000000..24af19f --- /dev/null +++ b/Sources/MpcNET/Commands/Playlist/ListPlaylistCommand.cs @@ -0,0 +1,34 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Playlist +{ + using System.Collections.Generic; + using System.Linq; + using MpcNET.Types; + + /// + /// Lists the songs in the playlist. + /// + internal class ListPlaylistCommand : IMpcCommand> + { + private readonly string playlistName; + + public ListPlaylistCommand(string playlistName) + { + this.playlistName = playlistName; + } + + public string Serialize() => string.Join(" ", "listplaylist", $"\"{this.playlistName}\""); + + public IEnumerable Deserialize(IReadOnlyList> response) + { + var results = response.Where(line => line.Key.Equals("file")).Select(line => new MpdFile(line.Value)); + + return results; + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Playlist/ListPlaylistInfoCommand.cs b/Sources/MpcNET/Commands/Playlist/ListPlaylistInfoCommand.cs new file mode 100644 index 0000000..f15aa53 --- /dev/null +++ b/Sources/MpcNET/Commands/Playlist/ListPlaylistInfoCommand.cs @@ -0,0 +1,31 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Playlist +{ + using System.Collections.Generic; + using MpcNET.Types; + + /// + /// Lists the songs with metadata in the playlist. + /// + internal class ListPlaylistInfoCommand : IMpcCommand> + { + private readonly string playlistName; + + public ListPlaylistInfoCommand(string playlistName) + { + this.playlistName = playlistName; + } + + public string Serialize() => string.Join(" ", "listplaylistinfo", $"\"{this.playlistName}\""); + + public IEnumerable Deserialize(IReadOnlyList> response) + { + return MpdFile.CreateList(response); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Playlist/ListPlaylistsCommand.cs b/Sources/MpcNET/Commands/Playlist/ListPlaylistsCommand.cs new file mode 100644 index 0000000..f6ac532 --- /dev/null +++ b/Sources/MpcNET/Commands/Playlist/ListPlaylistsCommand.cs @@ -0,0 +1,39 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Playlist +{ + using System.Collections.Generic; + using System.Linq; + using MpcNET.Types; + + /// + /// Prints a list of the playlist directory. + /// + internal class ListPlaylistsCommand : IMpcCommand> + { + public string Serialize() => "listplaylists"; + + public IEnumerable Deserialize(IReadOnlyList> response) + { + var result = new List(); + + foreach (var line in response) + { + if (line.Key.Equals("playlist")) + { + result.Add(new MpdPlaylist(line.Value)); + } + else if (line.Key.Equals("Last-Modified")) + { + result.Last().AddLastModified(line.Value); + } + } + + return result; + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Playlist/LoadCommand.cs b/Sources/MpcNET/Commands/Playlist/LoadCommand.cs new file mode 100644 index 0000000..b8f2cf6 --- /dev/null +++ b/Sources/MpcNET/Commands/Playlist/LoadCommand.cs @@ -0,0 +1,30 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Playlist +{ + using System.Collections.Generic; + + /// + /// Loads the playlist into the current queue. + /// + internal class LoadCommand : IMpcCommand + { + private readonly string playlistName; + + public LoadCommand(string playlistName) + { + this.playlistName = playlistName; + } + + public string Serialize() => string.Join(" ", "load", $"\"{this.playlistName}\""); + + public string Deserialize(IReadOnlyList> response) + { + return string.Join(", ", response); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Playlist/PlaylistCommand.cs b/Sources/MpcNET/Commands/Playlist/PlaylistCommand.cs new file mode 100644 index 0000000..be557be --- /dev/null +++ b/Sources/MpcNET/Commands/Playlist/PlaylistCommand.cs @@ -0,0 +1,27 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Playlist +{ + using System.Collections.Generic; + using System.Linq; + using MpcNET.Types; + + /// + /// Displays the current playlist. + /// + internal class PlaylistCommand : IMpcCommand> + { + public string Serialize() => "playlist"; + + public IEnumerable Deserialize(IReadOnlyList> response) + { + var results = response.Select(line => MpdFile.Create(line.Value, int.Parse(line.Key))); + + return results; + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Playlist/PlaylistIdCommand.cs b/Sources/MpcNET/Commands/Playlist/PlaylistIdCommand.cs new file mode 100644 index 0000000..8e5c847 --- /dev/null +++ b/Sources/MpcNET/Commands/Playlist/PlaylistIdCommand.cs @@ -0,0 +1,31 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Playlist +{ + using System.Collections.Generic; + using MpcNET.Types; + + /// + /// Displays song ID in the playlist. + /// + internal class PlaylistIdCommand : IMpcCommand> + { + private readonly int songId; + + public PlaylistIdCommand(int songId) + { + this.songId = songId; + } + + public string Serialize() => string.Join(" ", new[] { "playlistid" }, this.songId); + + public IEnumerable Deserialize(IReadOnlyList> response) + { + return MpdFile.CreateList(response); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Playlist/PlaylistInfoCommand.cs b/Sources/MpcNET/Commands/Playlist/PlaylistInfoCommand.cs new file mode 100644 index 0000000..da0985f --- /dev/null +++ b/Sources/MpcNET/Commands/Playlist/PlaylistInfoCommand.cs @@ -0,0 +1,24 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Playlist +{ + using System.Collections.Generic; + using MpcNET.Types; + + /// + /// Displays a list of all songs in the playlist, + /// + internal class PlaylistInfoCommand : IMpcCommand> + { + public string Serialize() => "playlistinfo"; + + public IEnumerable Deserialize(IReadOnlyList> response) + { + return MpdFile.CreateList(response); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Reflection/CommandsCommand.cs b/Sources/MpcNET/Commands/Reflection/CommandsCommand.cs new file mode 100644 index 0000000..4fc13d9 --- /dev/null +++ b/Sources/MpcNET/Commands/Reflection/CommandsCommand.cs @@ -0,0 +1,27 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Reflection +{ + using System.Collections.Generic; + using System.Linq; + + /// + /// Shows which commands the current user has access to. + /// config : This command is only permitted to "local" clients (connected via UNIX domain socket). + /// + internal class CommandsCommand : IMpcCommand> + { + public string Serialize() => "commands"; + + public IEnumerable Deserialize(IReadOnlyList> response) + { + var result = response.Where(item => item.Key.Equals("command")).Select(item => item.Value); + + return result; + } + } +} diff --git a/src/MpcNET/Commands/Reflection/DecodersCommand.cs b/Sources/MpcNET/Commands/Reflection/DecodersCommand.cs similarity index 58% rename from src/MpcNET/Commands/Reflection/DecodersCommand.cs rename to Sources/MpcNET/Commands/Reflection/DecodersCommand.cs index 7d9101a..20ec239 100644 --- a/src/MpcNET/Commands/Reflection/DecodersCommand.cs +++ b/Sources/MpcNET/Commands/Reflection/DecodersCommand.cs @@ -1,16 +1,22 @@ -using System.Collections.Generic; -using MpcNET.Types; - +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- namespace MpcNET.Commands.Reflection { + using System.Collections.Generic; + using MpcNET.Types; + /// /// Print a list of decoder plugins, followed by their supported suffixes and MIME types. /// - public class DecodersCommand : IMpcCommand> + internal class DecodersCommand : IMpcCommand> { - public string Value => "decoders"; + public string Serialize() => "decoders"; - public IEnumerable FormatResponse(IList> response) + public IEnumerable Deserialize(IReadOnlyList> response) { var result = new List(); diff --git a/Sources/MpcNET/Commands/Reflection/TagTypesCommand.cs b/Sources/MpcNET/Commands/Reflection/TagTypesCommand.cs new file mode 100644 index 0000000..70db54f --- /dev/null +++ b/Sources/MpcNET/Commands/Reflection/TagTypesCommand.cs @@ -0,0 +1,28 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Reflection +{ + using System.Collections.Generic; + using System.Linq; + + // TODO: notcommands : Shows which commands the current user does not have access to. + + /// + /// Shows a list of available song metadata. + /// + internal class TagTypesCommand : IMpcCommand> + { + public string Serialize() => "tagtypes"; + + public IEnumerable Deserialize(IReadOnlyList> response) + { + var result = response.Where(item => item.Key.Equals("tagtype")).Select(item => item.Value); + + return result; + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Reflection/UrlHandlersCommand.cs b/Sources/MpcNET/Commands/Reflection/UrlHandlersCommand.cs new file mode 100644 index 0000000..51fdf0e --- /dev/null +++ b/Sources/MpcNET/Commands/Reflection/UrlHandlersCommand.cs @@ -0,0 +1,26 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Reflection +{ + using System.Collections.Generic; + using System.Linq; + + /// + /// Gets a list of available URL handlers. + /// + internal class UrlHandlersCommand : IMpcCommand> + { + public string Serialize() => "urlhandlers"; + + public IEnumerable Deserialize(IReadOnlyList> response) + { + var result = response.Where(item => item.Key.Equals("handler")).Select(item => item.Value); + + return result; + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/ReflectionCommandFactory.cs b/Sources/MpcNET/Commands/ReflectionCommandFactory.cs new file mode 100644 index 0000000..9bfa4ab --- /dev/null +++ b/Sources/MpcNET/Commands/ReflectionCommandFactory.cs @@ -0,0 +1,54 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands +{ + using System.Collections.Generic; + using MpcNET.Commands.Reflection; + using MpcNET.Types; + + /// + /// https://www.musicpd.org/doc/protocol/reflection_commands.html + /// + public class ReflectionCommandFactory : IReflectionCommandFactory + { + /// + /// Gets a commands command. + /// + /// A . + public IMpcCommand> Commands() + { + return new CommandsCommand(); + } + + /// + /// Gets a tag types command. + /// + /// A . + public IMpcCommand> TagTypes() + { + return new TagTypesCommand(); + } + + /// + /// Gets URL handlers command. + /// + /// A . + public IMpcCommand> UrlHandlers() + { + return new UrlHandlersCommand(); + } + + /// + /// Gets a decoders command. + /// + /// A . + public IMpcCommand> Decoders() + { + return new DecodersCommand(); + } + } +} diff --git a/Sources/MpcNET/Commands/Status/CurrentSongCommand.cs b/Sources/MpcNET/Commands/Status/CurrentSongCommand.cs new file mode 100644 index 0000000..fce8d76 --- /dev/null +++ b/Sources/MpcNET/Commands/Status/CurrentSongCommand.cs @@ -0,0 +1,21 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Status +{ + using System.Collections.Generic; + using MpcNET.Types; + + internal class CurrentSongCommand : IMpcCommand + { + public string Serialize() => "currentsong"; + + public IMpdFile Deserialize(IReadOnlyList> response) + { + return MpdFile.Create(response, 0).mpdFile; + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Status/IdleCommand.cs b/Sources/MpcNET/Commands/Status/IdleCommand.cs new file mode 100644 index 0000000..4b2e9c8 --- /dev/null +++ b/Sources/MpcNET/Commands/Status/IdleCommand.cs @@ -0,0 +1,35 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Status +{ + using System.Collections.Generic; + + internal class IdleCommand : IMpcCommand + { + private readonly string subSystem; + + public IdleCommand(string subSystem) + { + this.subSystem = subSystem; + } + + public string Serialize() + { + if (string.IsNullOrEmpty(this.subSystem)) + { + return "idle"; + } + + return "idle " + this.subSystem; + } + + public string Deserialize(IReadOnlyList> response) + { + return string.Join(", ", response); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Commands/Status/NoIdleCommand.cs b/Sources/MpcNET/Commands/Status/NoIdleCommand.cs new file mode 100644 index 0000000..7f6c511 --- /dev/null +++ b/Sources/MpcNET/Commands/Status/NoIdleCommand.cs @@ -0,0 +1,20 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands.Status +{ + using System.Collections.Generic; + + internal class NoIdleCommand : IMpcCommand + { + public string Serialize() => "noidle"; + + public string Deserialize(IReadOnlyList> response) + { + return string.Join(", ", response); + } + } +} \ No newline at end of file diff --git a/src/MpcNET/Commands/Status/StatusCommand.cs b/Sources/MpcNET/Commands/Status/StatusCommand.cs similarity index 56% rename from src/MpcNET/Commands/Status/StatusCommand.cs rename to Sources/MpcNET/Commands/Status/StatusCommand.cs index 38ec8c1..f978dd4 100644 --- a/src/MpcNET/Commands/Status/StatusCommand.cs +++ b/Sources/MpcNET/Commands/Status/StatusCommand.cs @@ -1,14 +1,41 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; - +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- namespace MpcNET.Commands.Status { + using System; + using System.Collections.Generic; + using System.Diagnostics; + internal class StatusCommand : IMpcCommand { - public string Value => "status"; + private const string VolumeText = "volume"; + private const string RepeatText = "repeat"; + private const string RandomText = "random"; + private const string SingleText = "single"; + private const string ConsumeText = "consume"; + private const string PlaylistText = "playlist"; + private const string PlaylistlengthText = "playlistlength"; + private const string SongText = "song"; + private const string SongidText = "songid"; + private const string NextsongText = "nextsong"; + private const string NextsongidText = "nextsongid"; + private const string BitrateText = "bitrate"; + private const string AudioText = "audio"; + private const string XfadeText = "xfade"; + private const string StateText = "state"; + private const string TimeText = "time"; + private const string ElapsedText = "elapsed"; + private const string DurationText = "duration"; + private const string MixrampDbText = "mixrampdb"; + private const string UpdatingDbText = "updating_db"; - public MpdStatus FormatResponse(IList> response) + public string Serialize() => "status"; + + public MpdStatus Deserialize(IReadOnlyList> response) { int volume = -1; bool repeat = false; @@ -29,6 +56,7 @@ namespace MpcNET.Commands.Status MpdState mpdState = MpdState.Unknown; TimeSpan elapsed; TimeSpan duration; + double mixrampDb = -1; int updatingDb = -1; string error = string.Empty; foreach (var keyValuePair in response) @@ -36,61 +64,66 @@ namespace MpcNET.Commands.Status var value = keyValuePair.Value; switch (keyValuePair.Key) { - case "volume": + case VolumeText: int.TryParse(value, out volume); break; - case "repeat": - repeat = "1" == value; + case RepeatText: + repeat = value == "1"; break; - case "random": - random = "1" == value; + case RandomText: + random = value == "1"; break; - case "single": - single = "1" == value; + case SingleText: + single = value == "1"; break; - case "consume": - consume = "1" == value; + case ConsumeText: + consume = value == "1"; break; - case "playlist": + case PlaylistText: int.TryParse(value, out playlist); break; - case "playlistlength": + case PlaylistlengthText: int.TryParse(value, out playlistLength); break; - case "song": + case SongText: int.TryParse(value, out playlistSong); break; - case "songid": + case SongidText: int.TryParse(value, out playlistSongId); break; - case "nextsong": + case NextsongText: int.TryParse(value, out playlistNextSong); break; - case "nextsongid": + case NextsongidText: int.TryParse(value, out playlistNextSongId); break; - case "bitrate": + case BitrateText: int.TryParse(value, out bitrate); break; - case "audio": + case AudioText: var audioFormat = value.Split(':'); int.TryParse(audioFormat[0], out audioSampleRate); int.TryParse(audioFormat[1], out audioBits); int.TryParse(audioFormat[2], out audioChannels); break; - case "xfade": + case XfadeText: int.TryParse(value, out crossfade); break; - case "state": + case StateText: Enum.TryParse(value, true, out mpdState); break; - case "elapsed": + case ElapsedText: elapsed = ParseTime(value); break; - case "duration": + case TimeText: + break; + case DurationText: duration = ParseTime(value); break; - case "updating_db": + case MixrampDbText: + double.TryParse(value, out mixrampDb); + break; + case UpdatingDbText: int.TryParse(value, out updatingDb); break; default: @@ -103,6 +136,8 @@ namespace MpcNET.Commands.Status volume, repeat, random, + consume, + single, playlist, playlistLength, crossfade, diff --git a/Sources/MpcNET/Commands/StatusCommandFactory.cs b/Sources/MpcNET/Commands/StatusCommandFactory.cs new file mode 100644 index 0000000..377663b --- /dev/null +++ b/Sources/MpcNET/Commands/StatusCommandFactory.cs @@ -0,0 +1,35 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands +{ + using MpcNET.Commands.Status; + using MpcNET.Types; + + /// + /// https://www.musicpd.org/doc/protocol/command_reference.html#status_commands + /// + public class StatusCommandFactory : IStatusCommandFactory + { + /// + /// Gets a status command. + /// + /// A . + public IMpcCommand GetStatus() + { + return new StatusCommand(); + } + + /// + /// Gets a current song command. + /// + /// A . + public IMpcCommand GetCurrentSong() + { + return new CurrentSongCommand(); + } + } +} diff --git a/Sources/MpcNET/Commands/StoredPlaylistCommandFactory.cs b/Sources/MpcNET/Commands/StoredPlaylistCommandFactory.cs new file mode 100644 index 0000000..55f2ed5 --- /dev/null +++ b/Sources/MpcNET/Commands/StoredPlaylistCommandFactory.cs @@ -0,0 +1,57 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Commands +{ + using System.Collections.Generic; + using MpcNET.Commands.Playlist; + using MpcNET.Types; + + /// + /// https://www.musicpd.org/doc/protocol/playlist_files.html + /// + public class StoredPlaylistCommandFactory : IStoredPlaylistCommandFactory + { + /// + /// Command: load + /// + /// Name of the playlist. + /// A . + public IMpcCommand Load(string playlistName) + { + return new LoadCommand(playlistName); + } + + /// + /// Command: listplaylist + /// + /// Name of the playlist. + /// A . + public IMpcCommand> GetContent(string playlistName) + { + return new ListPlaylistCommand(playlistName); + } + + /// + /// Command: listplaylistinfo + /// + /// Name of the playlist. + /// A . + public IMpcCommand> GetContentWithMetadata(string playlistName) + { + return new ListPlaylistInfoCommand(playlistName); + } + + /// + /// Command: listplaylists + /// + /// A . + public IMpcCommand> GetAll() + { + return new ListPlaylistsCommand(); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Constants.cs b/Sources/MpcNET/Constants.cs new file mode 100644 index 0000000..392a305 --- /dev/null +++ b/Sources/MpcNET/Constants.cs @@ -0,0 +1,17 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET +{ + internal class Constants + { + public static readonly string Ok = "OK"; + + public static readonly string Ack = "ACK"; + + public static readonly string FirstLinePrefix = "OK MPD "; + } +} diff --git a/Sources/MpcNET/Exceptions/CommandNullException.cs b/Sources/MpcNET/Exceptions/CommandNullException.cs new file mode 100644 index 0000000..0d74407 --- /dev/null +++ b/Sources/MpcNET/Exceptions/CommandNullException.cs @@ -0,0 +1,20 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Exceptions +{ + /// + /// Thrown by when the command is null. + /// + /// + public class CommandNullException : MpcException + { + internal CommandNullException() + : base("No command was specified") + { + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Exceptions/EmptyResponseException.cs b/Sources/MpcNET/Exceptions/EmptyResponseException.cs new file mode 100644 index 0000000..29c31b7 --- /dev/null +++ b/Sources/MpcNET/Exceptions/EmptyResponseException.cs @@ -0,0 +1,26 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Exceptions +{ + using System; + + /// + /// Exception throw when an empty response is received. + /// + /// + public class EmptyResponseException : MpcException + { + /// + /// Initializes a new instance of the class. + /// + /// The command. + public EmptyResponseException(string command) + : base($"The command: {command} returned no response") + { + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Exceptions/MpcConnectException.cs b/Sources/MpcNET/Exceptions/MpcConnectException.cs new file mode 100644 index 0000000..261ba9e --- /dev/null +++ b/Sources/MpcNET/Exceptions/MpcConnectException.cs @@ -0,0 +1,26 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Exceptions +{ + using System; + + /// + /// Exception thrown when there are problems with the . + /// + /// + public class MpcConnectException : MpcException + { + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + public MpcConnectException(string message) + : base(message) + { + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Exceptions/MpcException.cs b/Sources/MpcNET/Exceptions/MpcException.cs new file mode 100644 index 0000000..145644b --- /dev/null +++ b/Sources/MpcNET/Exceptions/MpcException.cs @@ -0,0 +1,26 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Exceptions +{ + using System; + + /// + /// Base class for all exceptions. + /// + /// + public class MpcException : Exception + { + /// + /// Initializes a new instance of the class. + /// + /// The message. + public MpcException(string message) + : base(message) + { + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/ICommandFactory.cs b/Sources/MpcNET/ICommandFactory.cs new file mode 100644 index 0000000..d886860 --- /dev/null +++ b/Sources/MpcNET/ICommandFactory.cs @@ -0,0 +1,72 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET +{ + using MpcNET.Commands; + + /// + /// Interface for providing specific command factories. + /// + public interface ICommandFactory + { + /// + /// Gets the status command factory. + /// + /// + /// The status. + /// + IStatusCommandFactory Status { get; } + + /// + /// Gets the database command factory. + /// + /// + /// The database. + /// + IDatabaseCommandFactory Database { get; } + + /// + /// Gets the reflection command factory. + /// + /// + /// The reflection. + /// + IReflectionCommandFactory Reflection { get; } + + /// + /// Gets the stored playlist command factory. + /// + /// + /// The stored playlist. + /// + IStoredPlaylistCommandFactory StoredPlaylist { get; } + + /// + /// Gets the current playlist command factory. + /// + /// + /// The current playlist. + /// + ICurrentPlaylistCommandFactory CurrentPlaylist { get; } + + /// + /// Gets the playback command factory. + /// + /// + /// The playback. + /// + IPlaybackCommandFactory Playback { get; } + + /// + /// Gets the output command factory. + /// + /// + /// The output. + /// + IOutputCommandFactory Output { get; } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/IMpcCommand.cs b/Sources/MpcNET/IMpcCommand.cs new file mode 100644 index 0000000..72779aa --- /dev/null +++ b/Sources/MpcNET/IMpcCommand.cs @@ -0,0 +1,30 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET +{ + using System.Collections.Generic; + + /// + /// Interface for implementing a MPD command. + /// + /// The type of the value. + public interface IMpcCommand + { + /// + /// Serializes the command. + /// + /// The serialize command. + string Serialize(); + + /// + /// Deserializes the specified response text pairs. + /// + /// The response. + /// The deserialized response. + TValue Deserialize(IReadOnlyList> response); + } +} \ No newline at end of file diff --git a/Sources/MpcNET/IMpcConnection.cs b/Sources/MpcNET/IMpcConnection.cs new file mode 100644 index 0000000..d551598 --- /dev/null +++ b/Sources/MpcNET/IMpcConnection.cs @@ -0,0 +1,45 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace MpcNET +{ + using System; + using System.Threading.Tasks; + using MpcNET.Message; + + /// + /// Interface for implementing an MPD connection. + /// + /// + public interface IMpcConnection : IDisposable + { + /// + /// Gets the version. + /// + string Version { get; } + + /// + /// Connects asynchronously. + /// + /// The connect task. + Task ConnectAsync(); + + /// + /// Disconnects asynchronously. + /// + /// The disconnect task. + Task DisconnectAsync(); + + /// + /// Sends the command asynchronously. + /// + /// The response type. + /// The command selector. + /// The send task. + Task> SendAsync(Func> commandSelector); + } +} \ No newline at end of file diff --git a/Sources/MpcNET/IMpcConnectionObserver.cs b/Sources/MpcNET/IMpcConnectionObserver.cs new file mode 100644 index 0000000..eccd421 --- /dev/null +++ b/Sources/MpcNET/IMpcConnectionObserver.cs @@ -0,0 +1,77 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET +{ + using System; + + /// + /// Interface for implementing an observer for . + /// + public interface IMpcConnectionObserver + { + /// + /// Called when connecting. + /// + /// if set to true [is reconnect]. + /// The connect attempt. + void Connecting(bool isReconnect, int connectAttempt); + + /// + /// Called when connection is accepted. + /// + /// if set to true [is reconnect]. + /// The connect attempt. + void ConnectionAccepted(bool isReconnect, int connectAttempt); + + /// + /// Called when connected. + /// + /// if set to true [is reconnect]. + /// The connect attempt. + /// The connection information. + void Connected(bool isReconnect, int connectAttempt, string connectionInfo); + + /// + /// Called when sending command. + /// + /// The command. + void Sending(string command); + + /// + /// Called when send exception occured. + /// + /// The command text. + /// The send attempt. + /// The exception. + void SendException(string commandText, int sendAttempt, Exception exception); + + /// + /// Called when send is retried. + /// + /// The command. + /// The send attempt. + void RetrySend(string command, int sendAttempt); + + /// + /// Called when response is read. + /// + /// The response line. + void ReadResponse(string responseLine); + + /// + /// Called when disconnecting. + /// + /// if set to true the disconnect was explicitly called. + void Disconnecting(bool isExplicitDisconnect); + + /// + /// Called when disconnected. + /// + /// if set to true the disconnect was explicitly called. + void Disconnected(bool isExplicitDisconnect); + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Message/ErrorMpdMessage.cs b/Sources/MpcNET/Message/ErrorMpdMessage.cs new file mode 100644 index 0000000..37a5f4f --- /dev/null +++ b/Sources/MpcNET/Message/ErrorMpdMessage.cs @@ -0,0 +1,23 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Message +{ + internal class ErrorMpdMessage : IMpdMessage + { + public ErrorMpdMessage(IMpcCommand command, ErrorMpdResponse errorResponse) + { + this.Request = new MpdRequest(command); + this.Response = errorResponse; + } + + public IMpdRequest Request { get; } + + public IMpdResponse Response { get; } + + public bool IsResponseValid => false; + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Message/ErrorMpdResponse.cs b/Sources/MpcNET/Message/ErrorMpdResponse.cs new file mode 100644 index 0000000..ff06242 --- /dev/null +++ b/Sources/MpcNET/Message/ErrorMpdResponse.cs @@ -0,0 +1,44 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Message +{ + using System; + + /// + /// Implementation of in case of an error. + /// + /// The content type. + /// + public class ErrorMpdResponse : IMpdResponse + { + /// + /// Initializes a new instance of the class. + /// + /// The exception. + public ErrorMpdResponse(Exception exception) + { + this.Result = new MpdResponseResult(null, false, exception); + this.Content = default(TContent); + } + + /// + /// Gets the state. + /// + /// + /// The state. + /// + public IMpdResponseResult Result { get; } + + /// + /// Gets the content. + /// + /// + /// The content. + /// + public TContent Content { get; } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Message/IMpdMessage.cs b/Sources/MpcNET/Message/IMpdMessage.cs new file mode 100644 index 0000000..18d5c2f --- /dev/null +++ b/Sources/MpcNET/Message/IMpdMessage.cs @@ -0,0 +1,39 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Message +{ + /// + /// Interface for implementing MPD message. + /// + /// The type of the content. + public interface IMpdMessage + { + /// + /// Gets the request. + /// + /// + /// The request. + /// + IMpdRequest Request { get; } + + /// + /// Gets the response. + /// + /// + /// The response. + /// + IMpdResponse Response { get; } + + /// + /// Gets a value indicating whether this instance is response valid. + /// + /// + /// true if this instance is response valid; otherwise, false. + /// + bool IsResponseValid { get; } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Message/IMpdRequest.cs b/Sources/MpcNET/Message/IMpdRequest.cs new file mode 100644 index 0000000..1941767 --- /dev/null +++ b/Sources/MpcNET/Message/IMpdRequest.cs @@ -0,0 +1,23 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Message +{ + /// + /// Interface for implementing a MPD request. + /// + /// The response content. + public interface IMpdRequest + { + /// + /// Gets the command. + /// + /// + /// The command. + /// + IMpcCommand Command { get; } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Message/IMpdResponse.cs b/Sources/MpcNET/Message/IMpdResponse.cs new file mode 100644 index 0000000..d3ce857 --- /dev/null +++ b/Sources/MpcNET/Message/IMpdResponse.cs @@ -0,0 +1,31 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Message +{ + /// + /// Represents response to a . + /// + /// The type of the content. + public interface IMpdResponse + { + /// + /// Gets the state. + /// + /// + /// The state. + /// + IMpdResponseResult Result { get; } + + /// + /// Gets the content. + /// + /// + /// The content. + /// + TContent Content { get; } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Message/IMpdResponseResult.cs b/Sources/MpcNET/Message/IMpdResponseResult.cs new file mode 100644 index 0000000..5e4264a --- /dev/null +++ b/Sources/MpcNET/Message/IMpdResponseResult.cs @@ -0,0 +1,54 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Message +{ + /// + /// Interface for implementing a MPD response result. + /// + public interface IMpdResponseResult + { + /// + /// Gets the status. + /// + /// + /// The status. + /// + string Status { get; } + + /// + /// Gets the error message. + /// + /// + /// The error message. + /// + string ErrorMessage { get; } + + /// + /// Gets the MPD error. + /// + /// + /// The MPD error. + /// + string MpdError { get; } + + /// + /// Gets a value indicating whether an error occured. + /// + /// + /// true if error; otherwise, false. + /// + bool Error { get; } + + /// + /// Gets a value indicating whether this is connected. + /// + /// + /// true if connected; otherwise, false. + /// + bool Connected { get; } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Message/MpdMessage.cs b/Sources/MpcNET/Message/MpdMessage.cs new file mode 100644 index 0000000..20e49ab --- /dev/null +++ b/Sources/MpcNET/Message/MpdMessage.cs @@ -0,0 +1,65 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Message +{ + using System.Collections.Generic; + using System.Linq; + using System.Text.RegularExpressions; + using Newtonsoft.Json; + + internal class MpdMessage : IMpdMessage + { + private readonly Regex linePattern = new Regex(@"^(?[\w-]*):[ ]{0,1}(?.*)$"); + private readonly IList rawResponse; + + public MpdMessage(IMpcCommand command, bool connected, IReadOnlyCollection response) + { + this.Request = new MpdRequest(command); + + var endLine = response.Skip(response.Count - 1).Single(); + this.rawResponse = response.Take(response.Count - 1).ToList(); + + var values = this.Request.Command.Deserialize(this.GetValuesFromResponse()); + this.Response = new MpdResponse(endLine, values, connected); + } + + public IMpdRequest Request { get; } + + public IMpdResponse Response { get; } + + public bool IsResponseValid => this.Response != null && this.Response.Result.Status == "OK"; + + public override string ToString() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + + private IReadOnlyList> GetValuesFromResponse() + { + var result = new List>(); + + foreach (var line in this.rawResponse) + { + var match = this.linePattern.Match(line); + if (match.Success) + { + var mpdKey = match.Result("${key}"); + if (!string.IsNullOrEmpty(mpdKey)) + { + var mpdValue = match.Result("${value}"); + if (!string.IsNullOrEmpty(mpdValue)) + { + result.Add(new KeyValuePair(mpdKey, mpdValue)); + } + } + } + } + + return result; + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Message/MpdRequest.cs b/Sources/MpcNET/Message/MpdRequest.cs new file mode 100644 index 0000000..3c4063e --- /dev/null +++ b/Sources/MpcNET/Message/MpdRequest.cs @@ -0,0 +1,33 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Message +{ + /// + /// MPD request containing the command. + /// + /// The content of the reponse. + /// + public class MpdRequest : IMpdRequest + { + /// + /// Initializes a new instance of the class. + /// + /// The command. + public MpdRequest(IMpcCommand command) + { + this.Command = command; + } + + /// + /// Gets the command. + /// + /// + /// The command. + /// + public IMpcCommand Command { get; } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Message/MpdResponse.cs b/Sources/MpcNET/Message/MpdResponse.cs new file mode 100644 index 0000000..8da3192 --- /dev/null +++ b/Sources/MpcNET/Message/MpdResponse.cs @@ -0,0 +1,44 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Message +{ + /// + /// Represents a response to a . + /// + /// The content type. + /// + public class MpdResponse : IMpdResponse + { + /// + /// Initializes a new instance of the class. + /// + /// The end line. + /// The content. + /// if set to true [connected]. + public MpdResponse(string endLine, TContent content, bool connected) + { + this.Result = new MpdResponseResult(endLine, connected, null); + this.Content = content; + } + + /// + /// Gets the state. + /// + /// + /// The state. + /// + public IMpdResponseResult Result { get; } + + /// + /// Gets the content. + /// + /// + /// The content. + /// + public TContent Content { get; } + } +} diff --git a/Sources/MpcNET/Message/MpdResponseResult.cs b/Sources/MpcNET/Message/MpdResponseResult.cs new file mode 100644 index 0000000..f0f9a39 --- /dev/null +++ b/Sources/MpcNET/Message/MpdResponseResult.cs @@ -0,0 +1,75 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Message +{ + using System; + using System.Text.RegularExpressions; + + internal class MpdResponseResult : IMpdResponseResult + { + private static readonly Regex ErrorPattern = new Regex("^ACK \\[(?[0-9]*)@(?[0-9]*)] \\{(?[a-z]*)} (?.*)$"); + + private readonly string endLine; + + public MpdResponseResult(string endLine, bool connected, Exception exception) + { + this.endLine = endLine; + this.Connected = connected; + this.Exception = exception; + if (this.Exception != null) + { + this.Status = "EXCEPTION"; + } + + if (!string.IsNullOrEmpty(this.endLine)) + { + if (this.endLine.Equals(Constants.Ok)) + { + this.Status = this.endLine; + this.Error = false; + } + else + { + this.ParseErrorResponse(); + } + } + } + + public bool Connected { get; } = false; + + public bool Error { get; } = true; + + public string Status { get; private set; } = "UNKNOWN"; + + public string ErrorMessage { get; private set; } = string.Empty; + + public string MpdError { get; private set; } = string.Empty; + + public Exception Exception { get; } + + private void ParseErrorResponse() + { + this.Status = "ERROR"; + this.MpdError = this.endLine; + + var match = ErrorPattern.Match(this.endLine); + + if (match.Groups.Count != 5) + { + this.ErrorMessage = "Unexpected response from server."; + } + else + { + var errorCode = match.Result("${code}"); + var commandListItem = match.Result("${nr}"); + var commandFailed = match.Result("${command}"); + var errorMessage = match.Result("${message}"); + this.ErrorMessage = $"ErrorCode: {errorCode}, CommandListItem: {commandListItem}, CommandFailed: {commandFailed}, ErrorMessage: {errorMessage}"; + } + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/MpcConnection.cs b/Sources/MpcNET/MpcConnection.cs new file mode 100644 index 0000000..9e5a749 --- /dev/null +++ b/Sources/MpcNET/MpcConnection.cs @@ -0,0 +1,261 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Net; + using System.Net.Sockets; + using System.Text; + using System.Threading.Tasks; + using MpcNET.Commands; + using MpcNET.Exceptions; + using MpcNET.Message; + using Sundew.Base.ControlFlow; + + /// + /// Keeps the connection to the MPD server and handels the most basic structure of the MPD protocol. + /// class. + /// + public class MpcConnection : IMpcConnection + { + private static readonly Encoding Encoding = new UTF8Encoding(); + private readonly ICommandFactory commandFactory; + private readonly IMpcConnectionObserver mpcConnectionObserver; + private readonly IPEndPoint server; + + private TcpClient tcpClient; + private NetworkStream networkStream; + + private string version; + + /// + /// Initializes a new instance of the class. + /// + /// The server. + /// The command factory. + /// The MPC connection logger. + public MpcConnection(IPEndPoint server, ICommandFactory commandFactory = null, IMpcConnectionObserver mpcConnectionObserver = null) + { + this.commandFactory = commandFactory ?? new CommandFactory(); + this.mpcConnectionObserver = mpcConnectionObserver; + this.ClearConnectionFields(); + this.server = server ?? throw new ArgumentNullException("Server IPEndPoint not set.", nameof(server)); + } + + /// + /// Gets the version. + /// + public string Version => this.version; + + /// + /// Connects asynchronously. + /// + /// The connect task. + public async Task ConnectAsync() + { + if (this.tcpClient != null) + { + var pingResult = await this.PingAsync(); + if (pingResult) + { + return; + } + } + + await this.ReconnectAsync(false); + } + + /// + /// Disconnects asynchronously. + /// + /// The disconnect task. + public Task DisconnectAsync() + { + return this.DisconnectAsync(true); + } + + /// + /// Sends the command asynchronously. + /// + /// The response type. + /// The command selector. + /// + /// The send task. + /// + public async Task> SendAsync(Func> commandSelector) + { + if (this.tcpClient == null) + { + await this.ReconnectAsync(true); + } + + var command = commandSelector?.Invoke(this.commandFactory); + if (command == null) + { + throw new CommandNullException(); + } + + Exception lastException = null; + IReadOnlyList response = new List(); + var sendAttempter = new Attempter(3); + var commandText = command.Serialize(); + this.mpcConnectionObserver?.Sending(commandText); + while (sendAttempter.Attempt()) + { + try + { + using (var writer = new StreamWriter(this.networkStream, Encoding, 512, true) { NewLine = "\n" }) + { + await writer.WriteLineAsync(commandText); + await writer.FlushAsync(); + } + + response = await this.ReadResponseAsync(); + if (response.Any()) + { + lastException = null; + break; + } + + throw new EmptyResponseException(commandText); + } + catch (Exception exception) + { + lastException = exception; + this.mpcConnectionObserver?.SendException(commandText, sendAttempter.CurrentAttempt, exception); + await this.ReconnectAsync(true); + this.mpcConnectionObserver?.RetrySend(commandText, sendAttempter.CurrentAttempt); + } + } + + if (lastException != null) + { + try + { + await this.DisconnectAsync(false); + } + catch (Exception) + { + } + + return new ErrorMpdMessage(command, new ErrorMpdResponse(lastException)); + } + + return new MpdMessage(command, true, response); + } + + /// + /// Releases unmanaged and - optionally - managed resources. + /// + void IDisposable.Dispose() + { + this.DisconnectAsync().Wait(); + } + + private async Task PingAsync() + { + try + { + using (var writer = new StreamWriter(this.networkStream, Encoding, 512, true) { NewLine = "\n" }) + { + await writer.WriteLineAsync("ping"); + await writer.FlushAsync(); + } + + using (var reader = new StreamReader(this.networkStream, Encoding, true, 512, true)) + { + var responseLine = await reader.ReadLineAsync(); + return responseLine == "OK"; + } + } + catch (Exception) + { + return false; + } + } + + private async Task ReconnectAsync(bool isReconnect) + { + var connectAttempter = new Attempter(3); + while (connectAttempter.Attempt()) + { + this.mpcConnectionObserver?.Connecting(isReconnect, connectAttempter.CurrentAttempt); + await this.DisconnectAsync(false); + + this.tcpClient = new TcpClient(); + await this.tcpClient.ConnectAsync(this.server.Address, this.server.Port); + if (this.tcpClient.Connected) + { + this.mpcConnectionObserver?.ConnectionAccepted(isReconnect, connectAttempter.CurrentAttempt); + break; + } + } + + this.networkStream = this.tcpClient.GetStream(); + using (var reader = new StreamReader(this.networkStream, Encoding, true, 512, true)) + { + var firstLine = await reader.ReadLineAsync(); + if (!firstLine.StartsWith(Constants.FirstLinePrefix)) + { + await this.DisconnectAsync(false); + throw new MpcConnectException("Response of mpd does not start with \"" + Constants.FirstLinePrefix + "\"."); + } + + this.version = firstLine.Substring(Constants.FirstLinePrefix.Length); + this.mpcConnectionObserver?.Connected(isReconnect, connectAttempter.CurrentAttempt, firstLine); + } + } + + private async Task> ReadResponseAsync() + { + var response = new List(); + using (var reader = new StreamReader(this.networkStream, Encoding, true, 512, true)) + { + string responseLine; + do + { + responseLine = await reader.ReadLineAsync(); + this.mpcConnectionObserver.ReadResponse(responseLine); + if (responseLine == null) + { + break; + } + + response.Add(responseLine); + } + while (!(responseLine.Equals(Constants.Ok) || responseLine.StartsWith(Constants.Ack))); + } + + return response; + } + + private Task DisconnectAsync(bool isExplicitDisconnect) + { + this.mpcConnectionObserver?.Disconnecting(isExplicitDisconnect); + if (this.tcpClient == null) + { + return Task.CompletedTask; + } + + this.ClearConnectionFields(); + this.mpcConnectionObserver?.Disconnected(isExplicitDisconnect); + return Task.CompletedTask; + } + + private void ClearConnectionFields() + { + this.networkStream?.Dispose(); + this.tcpClient?.Dispose(); + this.version = string.Empty; + this.tcpClient = null; + this.networkStream = null; + } + } +} diff --git a/src/MpcNET/MpcNET.csproj b/Sources/MpcNET/MpcNET.csproj similarity index 50% rename from src/MpcNET/MpcNET.csproj rename to Sources/MpcNET/MpcNET.csproj index ddcf769..cf73e33 100644 --- a/src/MpcNET/MpcNET.csproj +++ b/Sources/MpcNET/MpcNET.csproj @@ -4,23 +4,40 @@ netstandard2.0 MpcNET MpcNET - $(PackageTargetFallback);dnxcore50 false false false MpcNET + + bin\Debug\netstandard2.0\MpcNET.xml + true + + + + + bin\Release\netstandard2.0\MpcNET.xml + true + + + + - + + + + + + diff --git a/Sources/MpcNET/MpdDirectoryListing.cs b/Sources/MpcNET/MpdDirectoryListing.cs new file mode 100644 index 0000000..242362e --- /dev/null +++ b/Sources/MpcNET/MpdDirectoryListing.cs @@ -0,0 +1,46 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET +{ + using System; + using System.Collections.Generic; + using MpcNET.Types; + + /// + /// The MpdDirectoryListing class contains the response of a MPD server to a list command. + /// + public class MpdDirectoryListing + { + /// + /// Initializes a new instance of the class. + /// + /// The file. + /// The directory. + /// The playlist. + public MpdDirectoryListing(List file, List directory, List playlist) + { + this.FileListList = file ?? throw new ArgumentNullException("file"); + this.DirectoryList = directory ?? throw new ArgumentNullException("directory"); + this.PlaylistList = playlist ?? throw new ArgumentNullException("playlist"); + } + + /// + /// Gets the list of files in the directory. + /// + public IReadOnlyList FileListList { get; } + + /// + /// Gets the list of subdirectories in the directory. + /// + public IReadOnlyList DirectoryList { get; } + + /// + /// Gets the list of playlists in the directory. + /// + public IReadOnlyList PlaylistList { get; } + } +} diff --git a/src/MpcNET/MpdState.cs b/Sources/MpcNET/MpdState.cs similarity index 54% rename from src/MpcNET/MpdState.cs rename to Sources/MpcNET/MpdState.cs index 8eeb48c..05c0cec 100644 --- a/src/MpcNET/MpdState.cs +++ b/Sources/MpcNET/MpdState.cs @@ -1,4 +1,10 @@ -namespace MpcNET +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET { /// /// The possible states of the MPD. @@ -9,14 +15,17 @@ /// The state of the MPD could not be translated into this enumeration. /// Unknown, + /// /// The MPD is playing a track. /// Play, + /// /// The MPD is not playing a track. /// Stop, + /// /// The playback of the MPD is currently paused. /// diff --git a/Sources/MpcNET/MpdStatistics.cs b/Sources/MpcNET/MpdStatistics.cs new file mode 100644 index 0000000..b610837 --- /dev/null +++ b/Sources/MpcNET/MpdStatistics.cs @@ -0,0 +1,130 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET +{ + using System.Text; + + /// + /// The MpdStatistics class contains statistics of the MPD file database. + /// + public class MpdStatistics + { + private const string ArtistsText = "artists"; + private const string SongsText = "songs"; + private const string UptimeText = "uptime"; + private const string PlaytimeText = "playtime"; + private const string DbPlaytimeText = "db_playtime"; + private const string DbUpdateText = "db_update"; + + /// + /// Initializes a new instance of the class. + /// + /// The number of artists in the MPD database. + /// The number of albums in the MPD database. + /// The number of songs in the MPD database. + /// The time the MPD server is running in seconds. + /// The number of seconds the MPD played so far. + /// The total playtime of all songs in the MPD database. + /// The timestamp of the last MPD database update. + public MpdStatistics( + int artists, + int albums, + int songs, + int uptime, + int playtime, + int dbPlaytime, + long dbUpdate) + { + this.Artists = artists; + this.Albums = albums; + this.Songs = songs; + this.Uptime = uptime; + this.Playtime = playtime; + this.DbPlaytime = dbPlaytime; + this.DbUpdate = dbUpdate; + } + + /// + /// Gets the number of artists in the MPD database. + /// + public int Artists { get; } + + /// + /// Gets the number of albums in the MPD database. + /// + public int Albums { get; } + + /// + /// Gets the number of songs in the MPD database. + /// + public int Songs { get; } + + /// + /// Gets the time the MPD server is running in seconds. + /// + public int Uptime { get; } + + /// + /// Gets the number of seconds the MPD played so far. + /// + public int Playtime { get; } + + /// + /// Gets the total playtime of all songs in the MPD database. + /// + public int DbPlaytime { get; } + + /// + /// Gets the timestamp of the last MPD database update. + /// + public long DbUpdate { get; } + + /// + /// Returns a string representation of the object mainly for debugging purpuse. + /// + /// A string representation of the object. + public override string ToString() + { + var builder = new StringBuilder(); + + AppendInt(builder, ArtistsText, this.Artists); + AppendInt(builder, SongsText, this.Songs); + AppendInt(builder, UptimeText, this.Uptime); + AppendInt(builder, PlaytimeText, this.Playtime); + AppendInt(builder, DbPlaytimeText, this.DbPlaytime); + AppendLong(builder, DbUpdateText, this.DbUpdate); + + return builder.ToString(); + } + + private static void AppendInt(StringBuilder builder, string name, int value) + { + if (value < 0) + { + return; + } + + builder.Append(name); + builder.Append(": "); + builder.Append(value); + builder.AppendLine(); + } + + private static void AppendLong(StringBuilder builder, string name, long value) + { + if (value < 0) + { + return; + } + + builder.Append(name); + builder.Append(": "); + builder.Append(value); + builder.AppendLine(); + } + } +} diff --git a/src/MpcNET/MpdStatus.cs b/Sources/MpcNET/MpdStatus.cs similarity index 61% rename from src/MpcNET/MpdStatus.cs rename to Sources/MpcNET/MpdStatus.cs index 69d9c6c..46875bf 100644 --- a/src/MpcNET/MpdStatus.cs +++ b/Sources/MpcNET/MpdStatus.cs @@ -1,46 +1,56 @@ -using System; -using System.Text; - +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- namespace MpcNET { + using System; + using System.Text; + /// /// The MpdStatus class contains all values describing the current status of the MPD. /// public class MpdStatus { /// - /// Creates a new MpdStatus object. + /// Initializes a new instance of the class. /// - /// The current volume of the output. - /// If the playlist is repeated after finish. - /// If the playlist is played in random order. - /// The version number of the playlist. - /// The length of the playlist. - /// The number of seconds crossfaded between song changes. - /// The state of the MPD. - /// The index of the currently played song in the playlist. - /// The id of the song currently played. + /// The volume. + /// if set to true [repeat]. + /// if set to true [random]. + /// if set to true [consume]. + /// if set to true [single]. + /// The playlist. + /// Length of the playlist. + /// The x fade. + /// The state. + /// The song. + /// The song identifier. /// The next song. /// The next song identifier. /// The elapsed. /// The duration. - /// The bitrate of the current song. - /// The audio sample rate of the current song. - /// The audio bits of the current song. - /// The number of audio channels of the current song. - /// The number of the update on the MPD database currently running. - /// An error message, if there is an error. + /// The bitrate. + /// The audio sample rate. + /// The audio bits. + /// The audio channels. + /// The updating database. + /// The error. public MpdStatus( int volume, bool repeat, bool random, + bool consume, + bool single, int playlist, int playlistLength, int xFade, MpdState state, int song, int songId, - int nextSong, + int nextSong, int nextSongId, TimeSpan elapsed, TimeSpan duration, @@ -54,14 +64,16 @@ namespace MpcNET this.Volume = volume; this.Repeat = repeat; this.Random = random; + this.Consume = consume; + this.Single = single; this.Playlist = playlist; this.PlaylistLength = playlistLength; this.XFade = xFade; this.State = state; this.Song = song; this.SongId = songId; - NextSong = nextSong; - NextSongId = nextSongId; + this.NextSong = nextSong; + this.NextSongId = nextSongId; this.Elapsed = elapsed; this.Duration = duration; this.Bitrate = bitrate; @@ -73,90 +85,107 @@ namespace MpcNET } /// - /// The current volume of the output. + /// Gets the current volume of the output. /// public int Volume { get; } /// - /// If the playlist is repeated after finish. + /// Gets a value indicating whether the playlist is repeated after finish. /// public bool Repeat { get; } /// - /// If the playlist is played in random order. + /// Gets a value indicating whether the playlist is played in random order. /// public bool Random { get; } /// - /// The version number of the playlist. + /// Gets a value indicating whether the playlist is consumed. + /// + public bool Consume { get; } + + /// + /// Gets a value indicating whether the playlist only plays a song once when random is enabled. + /// + public bool Single { get; } + + /// + /// Gets the version number of the playlist. /// public int Playlist { get; } /// - /// The length of the playlist. + /// Gets the length of the playlist. /// public int PlaylistLength { get; } /// - /// The number of seconds crossfaded between song changes. + /// Gets the number of seconds crossfaded between song changes. /// public int XFade { get; } /// - /// The state of the MPD. + /// Gets the state of the MPD. /// public MpdState State { get; } /// - /// The index of the currently played song in the playlist. + /// Gets the index of the currently played song in the playlist. /// public int Song { get; } /// - /// The id of the song currently played. + /// Gets the id of the song currently played. /// public int SongId { get; } + /// + /// Gets the next song. + /// public int NextSong { get; } + + /// + /// Gets the next song identifier. + /// public int NextSongId { get; } /// - /// The number of seconds already played of the current song. + /// Gets the number of seconds already played of the current song. /// public TimeSpan Elapsed { get; } /// - /// The length of the current song in seconds. + /// Gets the length of the current song in seconds. /// public TimeSpan Duration { get; } /// - /// The bitrate of the current song. + /// Gets the bitrate of the current song. /// public int Bitrate { get; } /// - /// The audio sample rate of the current song. + /// Gets the audio sample rate of the current song. /// public int AudioSampleRate { get; } /// - /// The audio bits of the current song. + /// Gets the audio bits of the current song. /// public int AudioBits { get; } /// - /// The number of audio channels of the current song. + /// Gets the number of audio channels of the current song. /// public int AudioChannels { get; } /// - /// The number of the update on the MPD database currently running. + /// Gets the number of the update on the MPD database currently running. /// public int UpdatingDb { get; } /// - /// An error message, if there is an error. + /// Gets the error message, if there is an error. /// public string Error { get; } @@ -166,7 +195,7 @@ namespace MpcNET /// A string representation of the object. public override string ToString() { - StringBuilder builder = new StringBuilder(); + var builder = new StringBuilder(); AppendInt(builder, "volume", this.Volume); AppendBool(builder, "repeat", this.Repeat); @@ -197,8 +226,9 @@ namespace MpcNET builder.Append(this.Duration); builder.AppendLine(); } + AppendInt(builder, "bitrate", this.Bitrate); - if ((AudioSampleRate >= 0) || (this.AudioBits >= 0) || (this.AudioChannels >= 0)) + if ((this.AudioSampleRate >= 0) || (this.AudioBits >= 0) || (this.AudioChannels >= 0)) { builder.Append("audio: "); builder.Append(this.AudioSampleRate); @@ -208,6 +238,7 @@ namespace MpcNET builder.Append(this.AudioChannels); builder.AppendLine(); } + AppendInt(builder, "updating_db", this.UpdatingDb); if (this.Error != null) { @@ -221,7 +252,9 @@ namespace MpcNET private static void AppendInt(StringBuilder builder, string name, int value) { if (value < 0) + { return; + } builder.Append(name); builder.Append(": "); diff --git a/src/MpcNET/Properties/AssemblyInfo.cs b/Sources/MpcNET/Properties/AssemblyInfo.cs similarity index 60% rename from src/MpcNET/Properties/AssemblyInfo.cs rename to Sources/MpcNET/Properties/AssemblyInfo.cs index 7d6f01f..68712a3 100644 --- a/src/MpcNET/Properties/AssemblyInfo.cs +++ b/Sources/MpcNET/Properties/AssemblyInfo.cs @@ -1,4 +1,10 @@ -using System.Reflection; +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +using System.Reflection; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/Sources/MpcNET/Tags/FindTags.cs b/Sources/MpcNET/Tags/FindTags.cs new file mode 100644 index 0000000..18dfeff --- /dev/null +++ b/Sources/MpcNET/Tags/FindTags.cs @@ -0,0 +1,46 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Tags +{ + /// + /// https://www.musicpd.org/doc/protocol/database.html : find {TYPE} {WHAT} [...] [window START:END] + /// + public class FindTags + { + /// + /// Gets the any tag. + /// + /// + /// Any. + /// + public static ITag Any { get; } = new Tag("any"); + + /// + /// Gets the file tag. + /// + /// + /// The file. + /// + public static ITag File { get; } = new Tag("file"); + + /// + /// Gets the base tag. + /// + /// + /// The base. + /// + public static ITag Base { get; } = new Tag("base"); + + /// + /// Gets the modified since tag. + /// + /// + /// The modified since. + /// + public static ITag ModifiedSince { get; } = new Tag("modified-since"); + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Tags/ITag.cs b/Sources/MpcNET/Tags/ITag.cs new file mode 100644 index 0000000..97b2b28 --- /dev/null +++ b/Sources/MpcNET/Tags/ITag.cs @@ -0,0 +1,22 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Tags +{ + /// + /// Interface for representing a tag. + /// + public interface ITag + { + /// + /// Gets the value. + /// + /// + /// The value. + /// + string Value { get; } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Tags/MpdTags.cs b/Sources/MpcNET/Tags/MpdTags.cs new file mode 100644 index 0000000..3b6a56f --- /dev/null +++ b/Sources/MpcNET/Tags/MpdTags.cs @@ -0,0 +1,134 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Tags +{ + /// + /// https://www.musicpd.org/doc/protocol/tags.html + /// + public class MpdTags + { + /// + /// Gets the artist. + /// + /// + /// The artist. + /// + public static ITag Artist { get; } = new Tag("artist"); + + /// + /// Gets the artist sort. + /// + /// + /// The artist sort. + /// + public static ITag ArtistSort { get; } = new Tag("artistsort"); + + /// + /// Gets the album. + /// + /// + /// The album. + /// + public static ITag Album { get; } = new Tag("album"); + + /// + /// Gets the album sort. + /// + /// + /// The album sort. + /// + public static ITag AlbumSort { get; } = new Tag("albumsort"); + + /// + /// Gets the album artist. + /// + /// + /// The album artist. + /// + public static ITag AlbumArtist { get; } = new Tag("albumartist"); + + /// + /// Gets the album artist sort. + /// + /// + /// The album artist sort. + /// + public static ITag AlbumArtistSort { get; } = new Tag("albumartistsort"); + + /// + /// Gets the title. + /// + /// + /// The title. + /// + public static ITag Title { get; } = new Tag("title"); + + /// + /// Gets the track. + /// + /// + /// The track. + /// + public static ITag Track { get; } = new Tag("track"); + + /// + /// Gets the name. + /// + /// + /// The name. + /// + public static ITag Name { get; } = new Tag("name"); + + /// + /// Gets the genre. + /// + /// + /// The genre. + /// + public static ITag Genre { get; } = new Tag("genre"); + + /// + /// Gets the date. + /// + /// + /// The date. + /// + public static ITag Date { get; } = new Tag("date"); + + /// + /// Gets the composer. + /// + /// + /// The composer. + /// + public static ITag Composer { get; } = new Tag("composer"); + + /// + /// Gets the performer. + /// + /// + /// The performer. + /// + public static ITag Performer { get; } = new Tag("performer"); + + /// + /// Gets the comment. + /// + /// + /// The comment. + /// + public static ITag Comment { get; } = new Tag("comment"); + + /// + /// Gets the disc. + /// + /// + /// The disc. + /// + public static ITag Disc { get; } = new Tag("disc"); + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Tags/Tag.cs b/Sources/MpcNET/Tags/Tag.cs new file mode 100644 index 0000000..0a20058 --- /dev/null +++ b/Sources/MpcNET/Tags/Tag.cs @@ -0,0 +1,18 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Tags +{ + internal class Tag : ITag + { + internal Tag(string value) + { + this.Value = value; + } + + public string Value { get; } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Types/IMpdFile.cs b/Sources/MpcNET/Types/IMpdFile.cs new file mode 100644 index 0000000..8aba05a --- /dev/null +++ b/Sources/MpcNET/Types/IMpdFile.cs @@ -0,0 +1,207 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Types +{ + using System.Collections.Generic; + + /// + /// Interface for representing MPD files. + /// + /// + public interface IMpdFile : IMpdFilePath + { + /// + /// Gets the time. + /// + /// + /// The time. + /// + int Time { get; } + + /// + /// Gets the album. + /// + /// + /// The album. + /// + string Album { get; } + + /// + /// Gets the artist. + /// + /// + /// The artist. + /// + string Artist { get; } + + /// + /// Gets the title. + /// + /// + /// The title. + /// + string Title { get; } + + /// + /// Gets the track. + /// + /// + /// The track. + /// + string Track { get; } + + /// + /// Gets the name. + /// + /// + /// The name. + /// + string Name { get; } + + /// + /// Gets the genre. + /// + /// + /// The genre. + /// + string Genre { get; } + + /// + /// Gets the date. + /// + /// + /// The date. + /// + string Date { get; } + + /// + /// Gets the composer. + /// + /// + /// The composer. + /// + string Composer { get; } + + /// + /// Gets the performer. + /// + /// + /// The performer. + /// + string Performer { get; } + + /// + /// Gets the comment. + /// + /// + /// The comment. + /// + string Comment { get; } + + /// + /// Gets the disc. + /// + /// + /// The disc. + /// + int Disc { get; } + + /// + /// Gets the position. + /// + /// + /// The position. + /// + int Position { get; } + + /// + /// Gets the identifier. + /// + /// + /// The identifier. + /// + int Id { get; } + + /// + /// Gets the unknown metadata. + /// + /// + /// The unknown metadata. + /// + IReadOnlyDictionary UnknownMetadata { get; } + + /// + /// Gets a value indicating whether the MpdFile has the property set. + /// + bool HasTime { get; } + + /// + /// Gets a value indicating whether the MpdFile has the property set. + /// + bool HasAlbum { get; } + + /// + /// Gets a value indicating whether the MpdFile has the property set. + /// + bool HasArtist { get; } + + /// + /// Gets a value indicating whether the MpdFile has the property set. + /// + bool HasTitle { get; } + + /// + /// Gets a value indicating whether the MpdFile has the property set. + /// + bool HasTrack { get; } + + /// + /// Gets a value indicating whether the MpdFile has the property set. + /// + bool HasName { get; } + + /// + /// Gets a value indicating whether the MpdFile has the property set. + /// + bool HasGenre { get; } + + /// + /// Gets a value indicating whether the MpdFile has the property set. + /// + bool HasDate { get; } + + /// + /// Gets a value indicating whether the MpdFile has the property set. + /// + bool HasComposer { get; } + + /// + /// Gets a value indicating whether the MpdFile has the property set. + /// + bool HasPerformer { get; } + + /// + /// Gets a value indicating whether the MpdFile has the property set. + /// + bool HasComment { get; } + + /// + /// Gets a value indicating whether the MpdFile has the property set. + /// + bool HasDisc { get; } + + /// + /// Gets a value indicating whether the MpdFile has the property set. + /// + bool HasPos { get; } + + /// + /// Gets a value indicating whether the MpdFile has the property set. + /// + bool HasId { get; } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Types/IMpdFilePath.cs b/Sources/MpcNET/Types/IMpdFilePath.cs new file mode 100644 index 0000000..f86f01a --- /dev/null +++ b/Sources/MpcNET/Types/IMpdFilePath.cs @@ -0,0 +1,22 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Types +{ + /// + /// Interface for representing a MPD file path. + /// + public interface IMpdFilePath + { + /// + /// Gets the path. + /// + /// + /// The path. + /// + string Path { get; } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Types/MpdDecoderPlugin.cs b/Sources/MpcNET/Types/MpdDecoderPlugin.cs new file mode 100644 index 0000000..5d424d5 --- /dev/null +++ b/Sources/MpcNET/Types/MpdDecoderPlugin.cs @@ -0,0 +1,70 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Types +{ + using System.Collections.Generic; + + /// + /// Represents a MPD decoder plugin. + /// + public class MpdDecoderPlugin + { + /// + /// The empty plugiun. + /// + public static readonly MpdDecoderPlugin Empty = new MpdDecoderPlugin(string.Empty); + + private readonly List suffixes = new List(); + private readonly List mediaTypes = new List(); + + /// + /// Initializes a new instance of the class. + /// + /// The name. + public MpdDecoderPlugin(string name) + { + this.Name = name; + this.IsInitialized = !string.IsNullOrEmpty(name); + } + + /// + /// Gets the name. + /// + /// + /// The name. + /// + public string Name { get; } + + /// + /// Gets the suffixes. + /// + /// + /// The suffixes. + /// + public IReadOnlyList Suffixes => this.suffixes; + + /// + /// Gets the media types. + /// + /// + /// The media types. + /// + public IReadOnlyList MediaTypes => this.mediaTypes; + + internal bool IsInitialized { get; } + + internal void AddSuffix(string suffix) + { + this.suffixes.Add(suffix); + } + + internal void AddMediaType(string type) + { + this.mediaTypes.Add(type); + } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Types/MpdDirectory.cs b/Sources/MpcNET/Types/MpdDirectory.cs new file mode 100644 index 0000000..21ddc54 --- /dev/null +++ b/Sources/MpcNET/Types/MpdDirectory.cs @@ -0,0 +1,60 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Types +{ + using System.Collections.Generic; + using System.Linq; + + /// + /// Represents a MPD directory. + /// + public class MpdDirectory + { + private readonly List files = new List(); + + /// + /// Initializes a new instance of the class. + /// + /// The path. + public MpdDirectory(string path) + { + this.Path = path; + + var name = path.Split('/').Last(); + this.Name = string.IsNullOrEmpty(name) ? "root" : name; + } + + /// + /// Gets the path. + /// + /// + /// The path. + /// + public string Path { get; } + + /// + /// Gets the name. + /// + /// + /// The name. + /// + public string Name { get; } + + /// + /// Gets the files. + /// + /// + /// The files. + /// + public IReadOnlyList Files => this.files; + + internal void AddFile(string file) + { + this.files.Add(new MpdFile(file)); + } + } +} \ No newline at end of file diff --git a/src/MpcNET/Types/MpdFile.cs b/Sources/MpcNET/Types/MpdFile.cs similarity index 81% rename from src/MpcNET/Types/MpdFile.cs rename to Sources/MpcNET/Types/MpdFile.cs index 6944364..2b4a24e 100644 --- a/src/MpcNET/Types/MpdFile.cs +++ b/Sources/MpcNET/Types/MpdFile.cs @@ -1,7 +1,13 @@ -using System.Collections.Generic; - +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- namespace MpcNET.Types { + using System.Collections.Generic; + /// /// The MpdFile class contains all meta data for a file of the MPD. /// @@ -69,96 +75,110 @@ namespace MpcNET.Types this.Performer = performer; this.Comment = comment; this.Disc = disc; - this.Pos = pos; + this.Position = pos; this.Id = id; this.UnknownMetadata = unknownMetadata ?? new Dictionary(); } public string Path { get; } + public int Time { get; } + public string Album { get; } + public string Artist { get; } + public string Title { get; } + public string Track { get; } + public string Name { get; } + public string Genre { get; } + public string Date { get; } + public string Composer { get; } + public string Performer { get; } + public string Comment { get; } + public int Disc { get; } - public int Pos { get; set; } + + public int Position { get; set; } + public int Id { get; } + public IReadOnlyDictionary UnknownMetadata { get; } - /// - /// If the MpdFile has the property set. + /// Gets a value indicating whether the MpdFile has the property set. /// public bool HasTime => this.Time != NoTime; /// - /// If the MpdFile has the property set. + /// Gets a value indicating whether the MpdFile has the property set. /// public bool HasAlbum => this.Album != NoAlbum; /// - /// If the MpdFile has the property set. + /// Gets a value indicating whether the MpdFile has the property set. /// public bool HasArtist => this.Artist != NoArtist; /// - /// If the MpdFile has the property set. + /// Gets a value indicating whether the MpdFile has the property set. /// public bool HasTitle => this.Title != NoTitle; /// - /// If the MpdFile has the property set. + /// Gets a value indicating whether the MpdFile has the property set. /// public bool HasTrack => this.Track != NoTrack; /// - /// If the MpdFile has the property set. + /// Gets a value indicating whether the MpdFile has the property set. /// public bool HasName => this.Name != NoName; /// - /// If the MpdFile has the property set. + /// Gets a value indicating whether the MpdFile has the property set. /// public bool HasGenre => this.Genre != NoGenre; /// - /// If the MpdFile has the property set. + /// Gets a value indicating whether the MpdFile has the property set. /// public bool HasDate => this.Date != NoDate; /// - /// If the MpdFile has the property set. + /// Gets a value indicating whether the MpdFile has the property set. /// public bool HasComposer => this.Composer != NoComposer; /// - /// If the MpdFile has the property set. + /// Gets a value indicating whether the MpdFile has the property set. /// public bool HasPerformer => this.Performer != NoPerformer; /// - /// If the MpdFile has the property set. + /// Gets a value indicating whether the MpdFile has the property set. /// public bool HasComment => this.Comment != NoComment; /// - /// If the MpdFile has the property set. + /// Gets a value indicating whether the MpdFile has the property set. /// public bool HasDisc => this.Disc != NoDisc; /// - /// If the MpdFile has the property set. + /// Gets a value indicating whether the MpdFile has the property set. /// - public bool HasPos => this.Pos != NoPos; + public bool HasPos => this.Position != NoPos; /// - /// If the MpdFile has the property set. + /// Gets a value indicating whether the MpdFile has the property set. /// public bool HasId => this.Id != NoId; @@ -167,7 +187,9 @@ namespace MpcNET.Types return new MpdFile(path, pos: pos); } - internal static (IMpdFile mpdFile, int index) Create(IList> response, int startIndex) + internal static(IMpdFile mpdFile, int index) Create( + IReadOnlyList> response, + int startIndex) { string file; if (response.Count <= startIndex) @@ -229,6 +251,7 @@ namespace MpcNET.Types { time = tryTime; } + break; case TagAlbum: album = line.Value; @@ -306,12 +329,12 @@ namespace MpcNET.Types id), response.Count - 1); } - public static IEnumerable CreateList(IList> response) + internal static IEnumerable CreateList(IReadOnlyList> response) { var mpdFiles = new List(); for (var index = 0; index < response.Count; index++) { - var (mpdFile, lastIndex) = Create(response, index); + var(mpdFile, lastIndex) = Create(response, index); if (mpdFile != null) { mpdFiles.Add(mpdFile); @@ -326,5 +349,4 @@ namespace MpcNET.Types return mpdFiles; } } -} - +} \ No newline at end of file diff --git a/Sources/MpcNET/Types/MpdOutput.cs b/Sources/MpcNET/Types/MpdOutput.cs new file mode 100644 index 0000000..3fffe27 --- /dev/null +++ b/Sources/MpcNET/Types/MpdOutput.cs @@ -0,0 +1,51 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Types +{ + /// + /// Represents a MPD output. + /// + public class MpdOutput + { + /// + /// Initializes a new instance of the class. + /// + /// The identifier. + /// The name. + /// if set to true [enabled]. + public MpdOutput(int id, string name, bool enabled) + { + this.Id = id; + this.Name = name; + this.IsEnabled = enabled; + } + + /// + /// Gets the identifier. + /// + /// + /// The identifier. + /// + public int Id { get; } + + /// + /// Gets the name. + /// + /// + /// The name. + /// + public string Name { get; } + + /// + /// Gets a value indicating whether this instance is enabled. + /// + /// + /// true if this instance is enabled; otherwise, false. + /// + public bool IsEnabled { get; } + } +} \ No newline at end of file diff --git a/Sources/MpcNET/Types/MpdPlaylist.cs b/Sources/MpcNET/Types/MpdPlaylist.cs new file mode 100644 index 0000000..d1d7041 --- /dev/null +++ b/Sources/MpcNET/Types/MpdPlaylist.cs @@ -0,0 +1,47 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Hukano. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace MpcNET.Types +{ + using System; + using System.Globalization; + + /// + /// Represents a MPD playlist. + /// + public class MpdPlaylist + { + /// + /// Initializes a new instance of the class. + /// + /// The name. + public MpdPlaylist(string name) + { + this.Name = name; + } + + /// + /// Gets the name. + /// + /// + /// The name. + /// + public string Name { get; } + + /// + /// Gets the last modified. + /// + /// + /// The last modified. + /// + public DateTime LastModified { get; private set; } + + internal void AddLastModified(string lastModified) + { + this.LastModified = DateTime.Parse(lastModified, CultureInfo.InvariantCulture); + } + } +} diff --git a/Sources/MpcNET/stylecop.json b/Sources/MpcNET/stylecop.json new file mode 100644 index 0000000..5b65886 --- /dev/null +++ b/Sources/MpcNET/stylecop.json @@ -0,0 +1,24 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "companyName": "Hukano", + "xmlHeader": true, + "copyrightText": "Copyright (c) {companyName}. All rights reserved.\nLicensed under the {licenseName} license. See {licenseFile} file in the project root for full license information.", + "headerDecoration": "--------------------------------------------------------------------------------------------------------------------", + "variables": { + "licenseName": "MIT", + "licenseFile": "LICENSE" + }, + "documentExposedElements": false, + "documentInternalElements": false, + "documentInterfaces": false + } + } +} diff --git a/src/MpcNET/Commands/Commands.Database.cs b/src/MpcNET/Commands/Commands.Database.cs deleted file mode 100644 index 23a93b1..0000000 --- a/src/MpcNET/Commands/Commands.Database.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections.Generic; -using MpcNET.Commands.Database; -using MpcNET.Tags; -using MpcNET.Types; - -namespace MpcNET.Commands -{ - public static partial class Command - { - /// - /// https://www.musicpd.org/doc/protocol/database.html - /// - public static class Database - { - public static IMpcCommand> Find(ITag tag, string searchText) - { - return new FindCommand(tag, searchText); - } - - public static IMpcCommand Update(string uri = null) - { - return new UpdateCommand(uri); - } - - // TODO: count - // TODO: rescan - public static IMpcCommand> ListAll() - { - return new ListAllCommand(); - } - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Commands.Output.cs b/src/MpcNET/Commands/Commands.Output.cs deleted file mode 100644 index 595c157..0000000 --- a/src/MpcNET/Commands/Commands.Output.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Generic; -using MpcNET.Commands.Output; -using MpcNET.Types; - -namespace MpcNET.Commands -{ - public static partial class Command - { - /// - /// https://www.musicpd.org/doc/protocol/output_commands.html - /// - public class Output - { - public static IMpcCommand> Outputs() - { - return new OutputsCommand(); - } - - public static IMpcCommand DisableOutput(int outputId) - { - return new DisableOutputCommand(outputId); - } - - public static IMpcCommand EnableOutput(int outputId) - { - return new EnableOutputCommand(outputId); - } - - public static IMpcCommand ToggleOutput(int outputId) - { - return new ToggleOutputCommand(outputId); - } - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Commands.Playback.cs b/src/MpcNET/Commands/Commands.Playback.cs deleted file mode 100644 index c0a04b9..0000000 --- a/src/MpcNET/Commands/Commands.Playback.cs +++ /dev/null @@ -1,24 +0,0 @@ -using MpcNET.Commands.Playback; -using MpcNET.Types; - -namespace MpcNET.Commands -{ - public partial class Command - { - /// - /// https://www.musicpd.org/doc/protocol/playback_commands.html - /// - public static class Playback - { - public static IMpcCommand Next() => new NextCommand(); - - public static IMpcCommand Previous() => new PreviousCommand(); - - public static IMpcCommand PlayPause() => new PlayPauseCommand(); - - public static IMpcCommand Play(IMpdFile mpdFile) => new PlayCommand(mpdFile); - - public static IMpcCommand Stop() => new StopCommand(); - } - } -} diff --git a/src/MpcNET/Commands/Commands.Playlists.cs b/src/MpcNET/Commands/Commands.Playlists.cs deleted file mode 100644 index aa138a7..0000000 --- a/src/MpcNET/Commands/Commands.Playlists.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System.Collections.Generic; -using MpcNET.Commands.Playlist; -using MpcNET.Types; - -namespace MpcNET.Commands -{ - public static partial class Command - { - public static class Playlists - { - /// - /// https://www.musicpd.org/doc/protocol/queue.html - /// - public static class Current - { - /// - /// Command: add - /// - public static IMpcCommand AddDirectory(string directory) { return new AddCommand(directory); } - - /// - /// Command: addid - /// - public static IMpcCommand AddSong(string songPath) { return new AddIdCommand(songPath); } - - /// - /// Command: clear - /// - public static IMpcCommand Clear() { return new ClearCommand(); } - - /// - /// Command: playlist - /// - public static IMpcCommand> GetAllSongsInfo() { return new PlaylistCommand(); } - - /// - /// Command: delete - /// - public static IMpcCommand RemoveSongByPosition(int position) { return new DeleteCommand(position); } - - /// - /// Command: deleteid - /// - public static IMpcCommand RemoveSongById(int songId) { return new DeleteIdCommand(songId); } - - /// - /// Command: playlistid - /// - public static IMpcCommand> GetSongMetadata(int songId) { return new PlaylistIdCommand(songId); } - - /// - /// Command: playlistinfo - /// - public static IMpcCommand> GetAllSongMetadata() { return new PlaylistInfoCommand(); } - } - - /// - /// https://www.musicpd.org/doc/protocol/playlist_files.html - /// - public static class Stored - { - - /// - /// Command: load - /// - public static IMpcCommand Load(string playlistName) { return new LoadCommand(playlistName); } - - /// - /// Command: listplaylist - /// - public static IMpcCommand> GetContent(string playlistName) { return new ListPlaylistCommand(playlistName); } - - /// - /// Command: listplaylistinfo - /// - public static IMpcCommand> GetContentWithMetadata(string playlistName) { return new ListPlaylistInfoCommand(playlistName); } - - /// - /// Command: listplaylists - /// - public static IMpcCommand> GetAll() { return new ListPlaylistsCommand(); } - } - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Commands.Reflection.cs b/src/MpcNET/Commands/Commands.Reflection.cs deleted file mode 100644 index d8c3257..0000000 --- a/src/MpcNET/Commands/Commands.Reflection.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Generic; -using MpcNET.Commands.Reflection; -using MpcNET.Types; - -namespace MpcNET.Commands -{ - public static partial class Command - { - /// - /// https://www.musicpd.org/doc/protocol/reflection_commands.html - /// - public static class Reflection - { - public static IMpcCommand> Commands() - { - return new CommandsCommand(); - } - - public static IMpcCommand> TagTypes() - { - return new TagTypesCommand(); - } - - public static IMpcCommand> UrlHandlers() - { - return new UrlHandlersCommand(); - } - - public static IMpcCommand> Decoders() - { - return new DecodersCommand(); - } - } - } -} diff --git a/src/MpcNET/Commands/Commands.Status.cs b/src/MpcNET/Commands/Commands.Status.cs deleted file mode 100644 index aaa74b8..0000000 --- a/src/MpcNET/Commands/Commands.Status.cs +++ /dev/null @@ -1,24 +0,0 @@ -using MpcNET.Commands.Status; -using MpcNET.Types; - -namespace MpcNET.Commands -{ - public static partial class Command - { - /// - /// https://www.musicpd.org/doc/protocol/command_reference.html#status_commands - /// - public static class Status - { - public static IMpcCommand GetStatus() - { - return new StatusCommand(); - } - - public static IMpcCommand GetCurrentSong() - { - return new CurrentSongCommand(); - } - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Database/FindCommand.cs b/src/MpcNET/Commands/Database/FindCommand.cs deleted file mode 100644 index c4974c8..0000000 --- a/src/MpcNET/Commands/Database/FindCommand.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Collections.Generic; -using MpcNET.Tags; -using MpcNET.Types; - -namespace MpcNET.Commands.Database -{ - /// - /// Finds songs in the database that is exactly "searchText". - /// - internal class FindCommand : IMpcCommand> - { - private readonly ITag _tag; - private readonly string _searchText; - - public FindCommand(ITag tag, string searchText) - { - _tag = tag; - _searchText = searchText; - } - - public string Value => string.Join(" ", "find", _tag.Value, _searchText); - - public IEnumerable FormatResponse(IList> response) - { - return MpdFile.CreateList(response); - } - } - - // TODO: rescan -} diff --git a/src/MpcNET/Commands/Database/ListCommand.cs b/src/MpcNET/Commands/Database/ListCommand.cs deleted file mode 100644 index 6301773..0000000 --- a/src/MpcNET/Commands/Database/ListCommand.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Generic; -using MpcNET.Tags; - -namespace MpcNET.Commands.Database -{ - internal class ListCommand : IMpcCommand - { - private readonly ITag _tag; - - public ListCommand(ITag tag) - { - _tag = tag; - } - - public string Value => string.Join(" ", "list", _tag); - - public string FormatResponse(IList> response) - { - // TODO: - return response.ToString(); - } - } - - // TODO: rescan -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Database/UpdateCommand.cs b/src/MpcNET/Commands/Database/UpdateCommand.cs deleted file mode 100644 index ad676d2..0000000 --- a/src/MpcNET/Commands/Database/UpdateCommand.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Collections.Generic; - -namespace MpcNET.Commands.Database -{ - // TODO: listallinfo - // TODO: listfiles - // TODO: lsinfo - // TODO: readcomments - // TODO: search - // TODO: searchadd - // TODO: searchaddpl - - public class UpdateCommand : IMpcCommand - { - private readonly string uri; - - public UpdateCommand(string uri) - { - this.uri = uri; - } - - // TODO: Extend command: < update [URI] > - public string Value - { - get - { - if (string.IsNullOrEmpty(this.uri)) - { - return "update"; - } - - var newUri = this.uri; - if (this.uri.StartsWith(@"""")) - { - newUri = @"""" + this.uri; - } - - if (this.uri.EndsWith(@"""")) - { - newUri = this.uri + @""""; - } - - return string.Join(" ", "update", newUri); - } - } - - public string FormatResponse(IList> response) - { - return string.Join(", ", response); - } - } - - // TODO: rescan -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Output/DisableOutputCommand.cs b/src/MpcNET/Commands/Output/DisableOutputCommand.cs deleted file mode 100644 index 5bcca23..0000000 --- a/src/MpcNET/Commands/Output/DisableOutputCommand.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Generic; - -namespace MpcNET.Commands.Output -{ - /// - /// Turns an output off. - /// - public class DisableOutputCommand : IMpcCommand - { - private readonly int outputId; - - public DisableOutputCommand(int outputId) - { - this.outputId = outputId; - } - - public string Value => string.Join(" ", "disableoutput", this.outputId); - - public string FormatResponse(IList> response) - { - // Response should be empty. - return string.Join(", ", response); - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Output/EnableOutputCommand.cs b/src/MpcNET/Commands/Output/EnableOutputCommand.cs deleted file mode 100644 index bffdf1f..0000000 --- a/src/MpcNET/Commands/Output/EnableOutputCommand.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Generic; - -namespace MpcNET.Commands.Output -{ - /// - /// Turns an output on. - /// - internal class EnableOutputCommand : IMpcCommand - { - private readonly int _outputId; - - public EnableOutputCommand(int outputId) - { - _outputId = outputId; - } - - public string Value => string.Join(" ", "enableoutput", _outputId); - - public string FormatResponse(IList> response) - { - // Response should be empty. - return string.Join(", ", response); - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Output/OutputsCommand.cs b/src/MpcNET/Commands/Output/OutputsCommand.cs deleted file mode 100644 index 41b9e6d..0000000 --- a/src/MpcNET/Commands/Output/OutputsCommand.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Collections.Generic; -using MpcNET.Types; - -namespace MpcNET.Commands.Output -{ - /// - /// Shows information about all outputs. - /// - public class OutputsCommand : IMpcCommand> - { - public string Value => "outputs"; - - public IEnumerable FormatResponse(IList> response) - { - var result = new List(); - - for (var i = 0; i < response.Count; i += 3) - { - var outputId = int.Parse(response[i].Value); - var outputName = response[i + 1].Value; - var outputEnabled = response[i + 2].Value == "1"; - - result.Add(new MpdOutput(outputId, outputName, outputEnabled)); - } - - return result; - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Output/ToggleOutputCommand.cs b/src/MpcNET/Commands/Output/ToggleOutputCommand.cs deleted file mode 100644 index f4092e5..0000000 --- a/src/MpcNET/Commands/Output/ToggleOutputCommand.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections.Generic; - -namespace MpcNET.Commands.Output -{ - /// - /// Turns an output on or off, depending on the current state. - /// - internal class ToggleOutputCommand : IMpcCommand - { - private readonly int outputId; - - public ToggleOutputCommand(int outputId) - { - this.outputId = outputId; - } - - public string Value => string.Join(" ", "toggleoutput", outputId); - - public string FormatResponse(IList> response) - { - return string.Join(", ", response); - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Playback/NextCommand.cs b/src/MpcNET/Commands/Playback/NextCommand.cs deleted file mode 100644 index 4ad35b6..0000000 --- a/src/MpcNET/Commands/Playback/NextCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; - -namespace MpcNET.Commands.Playback -{ - internal class NextCommand : IMpcCommand - { - public string Value => string.Join(" ", "next"); - - public string FormatResponse(IList> response) - { - return string.Join(", ", response); - } - } -} diff --git a/src/MpcNET/Commands/Playback/PlayCommand.cs b/src/MpcNET/Commands/Playback/PlayCommand.cs deleted file mode 100644 index f2fd397..0000000 --- a/src/MpcNET/Commands/Playback/PlayCommand.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections.Generic; -using MpcNET.Types; - -namespace MpcNET.Commands.Playback -{ - internal class PlayCommand : IMpcCommand - { - private readonly IMpdFile mpdFile; - - public PlayCommand(IMpdFile mpdFile) - { - this.mpdFile = mpdFile; - } - - public string Value - { - get - { - if (this.mpdFile.HasId) - { - return string.Join(" ", "playid", this.mpdFile.Id); - } - - return string.Join(" ", "play", this.mpdFile.Pos); - } - } - - public string FormatResponse(IList> response) - { - return string.Join(", ", response); - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Playback/PlayPauseCommand.cs b/src/MpcNET/Commands/Playback/PlayPauseCommand.cs deleted file mode 100644 index 608fcd5..0000000 --- a/src/MpcNET/Commands/Playback/PlayPauseCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; - -namespace MpcNET.Commands.Playback -{ - internal class PlayPauseCommand : IMpcCommand - { - public string Value => string.Join(" ", "pause"); - - public string FormatResponse(IList> response) - { - return string.Join(", ", response); - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Playback/PreviousCommand.cs b/src/MpcNET/Commands/Playback/PreviousCommand.cs deleted file mode 100644 index eca70ae..0000000 --- a/src/MpcNET/Commands/Playback/PreviousCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; - -namespace MpcNET.Commands.Playback -{ - internal class PreviousCommand : IMpcCommand - { - public string Value => string.Join(" ", "previous"); - - public string FormatResponse(IList> response) - { - return string.Join(", ", response); - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Playback/StopCommand.cs b/src/MpcNET/Commands/Playback/StopCommand.cs deleted file mode 100644 index 71105a6..0000000 --- a/src/MpcNET/Commands/Playback/StopCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; - -namespace MpcNET.Commands.Playback -{ - internal class StopCommand : IMpcCommand - { - public string Value => string.Join(" ", "stop"); - - public string FormatResponse(IList> response) - { - return string.Join(", ", response); - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Playlist/AddCommand.cs b/src/MpcNET/Commands/Playlist/AddCommand.cs deleted file mode 100644 index 3a7d220..0000000 --- a/src/MpcNET/Commands/Playlist/AddCommand.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections.Generic; - -namespace MpcNET.Commands.Playlist -{ - /// - /// Adds the file URI to the playlist (directories add recursively). URI can also be a single file. - /// - internal class AddCommand : IMpcCommand - { - private readonly string _uri; - - public AddCommand(string uri) - { - _uri = uri; - } - - public string Value => string.Join(" ", "add", $"\"{_uri}\""); - - public string FormatResponse(IList> response) - { - return string.Join(", ", response); - } - } -} diff --git a/src/MpcNET/Commands/Playlist/AddIdCommand.cs b/src/MpcNET/Commands/Playlist/AddIdCommand.cs deleted file mode 100644 index 522bfb6..0000000 --- a/src/MpcNET/Commands/Playlist/AddIdCommand.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections.Generic; - -namespace MpcNET.Commands.Playlist -{ - /// - /// Adds a song to the playlist (non-recursive) and returns the song id. - /// - internal class AddIdCommand : IMpcCommand - { - private readonly string _uri; - - public AddIdCommand(string uri) - { - _uri = uri; - } - - public string Value => string.Join(" ", "addid", $"\"{_uri}\""); - - public string FormatResponse(IList> response) - { - return string.Join(", ", response); - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Playlist/ClearCommand.cs b/src/MpcNET/Commands/Playlist/ClearCommand.cs deleted file mode 100644 index 17ffa94..0000000 --- a/src/MpcNET/Commands/Playlist/ClearCommand.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections.Generic; - -namespace MpcNET.Commands.Playlist -{ - /// - /// Clears the current playlist. - /// - internal class ClearCommand : IMpcCommand - { - public string Value => "clear"; - - public string FormatResponse(IList> response) - { - return string.Join(", ", response); - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Playlist/DeleteCommand.cs b/src/MpcNET/Commands/Playlist/DeleteCommand.cs deleted file mode 100644 index 3dac0c6..0000000 --- a/src/MpcNET/Commands/Playlist/DeleteCommand.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections.Generic; - -namespace MpcNET.Commands.Playlist -{ - /// - /// Deletes a song from the playlist. - /// - internal class DeleteCommand : IMpcCommand - { - private readonly int position; - - public DeleteCommand(int position) - { - this.position = position; - } - - public string Value => string.Join(" ", "delete", this.position); - - public string FormatResponse(IList> response) - { - return string.Join(", ", response); - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Playlist/DeleteIdCommand.cs b/src/MpcNET/Commands/Playlist/DeleteIdCommand.cs deleted file mode 100644 index 19a3048..0000000 --- a/src/MpcNET/Commands/Playlist/DeleteIdCommand.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections.Generic; - -namespace MpcNET.Commands.Playlist -{ - /// - /// Deletes the song SONGID from the playlist - /// - internal class DeleteIdCommand : IMpcCommand - { - private readonly int songId; - - public DeleteIdCommand(int songId) - { - this.songId = songId; - } - - public string Value => string.Join(" ", "deleteid", this.songId); - - public string FormatResponse(IList> response) - { - return string.Join(", ", response); - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Playlist/ListPlaylistCommand.cs b/src/MpcNET/Commands/Playlist/ListPlaylistCommand.cs deleted file mode 100644 index 79a1c88..0000000 --- a/src/MpcNET/Commands/Playlist/ListPlaylistCommand.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using MpcNET.Types; - -namespace MpcNET.Commands.Playlist -{ - /// - /// Lists the songs in the playlist. - /// - internal class ListPlaylistCommand : IMpcCommand> - { - private readonly string _playlistName; - - public ListPlaylistCommand(string playlistName) - { - _playlistName = playlistName; - } - - public string Value => string.Join(" ", "listplaylist", $"\"{_playlistName}\""); - - public IEnumerable FormatResponse(IList> response) - { - var results = response.Where(line => line.Key.Equals("file")).Select(line => new MpdFile(line.Value)); - - return results; - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Playlist/ListPlaylistInfoCommand.cs b/src/MpcNET/Commands/Playlist/ListPlaylistInfoCommand.cs deleted file mode 100644 index 583162b..0000000 --- a/src/MpcNET/Commands/Playlist/ListPlaylistInfoCommand.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Generic; -using MpcNET.Types; - -namespace MpcNET.Commands.Playlist -{ - /// - /// Lists the songs with metadata in the playlist. - /// - internal class ListPlaylistInfoCommand : IMpcCommand> - { - private readonly string _playlistName; - - public ListPlaylistInfoCommand(string playlistName) - { - _playlistName = playlistName; - } - - public string Value => string.Join(" ", "listplaylistinfo", $"\"{_playlistName}\""); - - public IEnumerable FormatResponse(IList> response) - { - return MpdFile.CreateList(response); - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Playlist/ListPlaylistsCommand.cs b/src/MpcNET/Commands/Playlist/ListPlaylistsCommand.cs deleted file mode 100644 index 93b7465..0000000 --- a/src/MpcNET/Commands/Playlist/ListPlaylistsCommand.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using MpcNET.Types; - -namespace MpcNET.Commands.Playlist -{ - /// - /// Prints a list of the playlist directory. - /// - internal class ListPlaylistsCommand : IMpcCommand> - { - public string Value => "listplaylists"; - - public IEnumerable FormatResponse(IList> response) - { - var result = new List(); - - foreach (var line in response) - { - if (line.Key.Equals("playlist")) - { - result.Add(new MpdPlaylist(line.Value)); - } - else if (line.Key.Equals("Last-Modified")) - { - result.Last().AddLastModified(line.Value); - } - } - - return result; - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Playlist/LoadCommand.cs b/src/MpcNET/Commands/Playlist/LoadCommand.cs deleted file mode 100644 index 0769107..0000000 --- a/src/MpcNET/Commands/Playlist/LoadCommand.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections.Generic; - -namespace MpcNET.Commands.Playlist -{ - /// - /// Loads the playlist into the current queue. - /// - internal class LoadCommand : IMpcCommand - { - private readonly string _playlistName; - - public LoadCommand(string playlistName) - { - _playlistName = playlistName; - } - - public string Value => string.Join(" ", "load", $"\"{_playlistName}\""); - - public string FormatResponse(IList> response) - { - return string.Join(", ", response); - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Playlist/PlaylistCommand.cs b/src/MpcNET/Commands/Playlist/PlaylistCommand.cs deleted file mode 100644 index 65932fd..0000000 --- a/src/MpcNET/Commands/Playlist/PlaylistCommand.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using MpcNET.Types; - -namespace MpcNET.Commands.Playlist -{ - /// - /// Displays the current playlist. - /// - internal class PlaylistCommand : IMpcCommand> - { - public string Value => "playlist"; - - public IEnumerable FormatResponse(IList> response) - { - var results = response.Select(line => MpdFile.Create(line.Value, int.Parse(line.Key))); - - return results; - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Playlist/PlaylistIdCommand.cs b/src/MpcNET/Commands/Playlist/PlaylistIdCommand.cs deleted file mode 100644 index 992ea33..0000000 --- a/src/MpcNET/Commands/Playlist/PlaylistIdCommand.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Generic; -using MpcNET.Types; - -namespace MpcNET.Commands.Playlist -{ - /// - /// Displays song ID in the playlist. - /// - internal class PlaylistIdCommand : IMpcCommand> - { - private readonly int _songId; - - public PlaylistIdCommand(int songId) - { - _songId = songId; - } - - public string Value => string.Join((string) " ", new[] {"playlistid"}, _songId); - - public IEnumerable FormatResponse(IList> response) - { - return MpdFile.CreateList(response); - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Playlist/PlaylistInfoCommand.cs b/src/MpcNET/Commands/Playlist/PlaylistInfoCommand.cs deleted file mode 100644 index 9e48776..0000000 --- a/src/MpcNET/Commands/Playlist/PlaylistInfoCommand.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Collections.Generic; -using MpcNET.Types; - -namespace MpcNET.Commands.Playlist -{ - /// - /// Displays a list of all songs in the playlist, - /// - internal class PlaylistInfoCommand : IMpcCommand> - { - public string Value => "playlistinfo"; - - public IEnumerable FormatResponse(IList> response) - { - return MpdFile.CreateList(response); - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Reflection/CommandsCommand.cs b/src/MpcNET/Commands/Reflection/CommandsCommand.cs deleted file mode 100644 index 1fbb007..0000000 --- a/src/MpcNET/Commands/Reflection/CommandsCommand.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -namespace MpcNET.Commands.Reflection -{ - // config : This command is only permitted to "local" clients (connected via UNIX domain socket). - - /// - /// Shows which commands the current user has access to. - /// - public class CommandsCommand : IMpcCommand> - { - public string Value => "commands"; - - public IEnumerable FormatResponse(IList> response) - { - var result = response.Where(item => item.Key.Equals("command")).Select(item => item.Value); - - return result; - } - } -} diff --git a/src/MpcNET/Commands/Reflection/TagTypesCommand.cs b/src/MpcNET/Commands/Reflection/TagTypesCommand.cs deleted file mode 100644 index ab67f3e..0000000 --- a/src/MpcNET/Commands/Reflection/TagTypesCommand.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -namespace MpcNET.Commands.Reflection -{ - // TODO: notcommands : Shows which commands the current user does not have access to. - - /// - /// Shows a list of available song metadata. - /// - public class TagTypesCommand : IMpcCommand> - { - public string Value => "tagtypes"; - - public IEnumerable FormatResponse(IList> response) - { - var result = response.Where(item => item.Key.Equals("tagtype")).Select(item => item.Value); - - return result; - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Reflection/UrlHandlersCommand.cs b/src/MpcNET/Commands/Reflection/UrlHandlersCommand.cs deleted file mode 100644 index f329fd4..0000000 --- a/src/MpcNET/Commands/Reflection/UrlHandlersCommand.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -namespace MpcNET.Commands.Reflection -{ - /// - /// Gets a list of available URL handlers. - /// - public class UrlHandlersCommand : IMpcCommand> - { - public string Value => "urlhandlers"; - - public IEnumerable FormatResponse(IList> response) - { - var result = response.Where(item => item.Key.Equals("handler")).Select(item => item.Value); - - return result; - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Commands/Status/CurrentSongCommand.cs b/src/MpcNET/Commands/Status/CurrentSongCommand.cs deleted file mode 100644 index e0cd7a2..0000000 --- a/src/MpcNET/Commands/Status/CurrentSongCommand.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using MpcNET.Types; - -namespace MpcNET.Commands.Status -{ - internal class CurrentSongCommand : IMpcCommand - { - public string Value => "currentsong"; - - public IMpdFile FormatResponse(IList> response) - { - return MpdFile.Create(response, 0).mpdFile; - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Constants.cs b/src/MpcNET/Constants.cs deleted file mode 100644 index de5681e..0000000 --- a/src/MpcNET/Constants.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace MpcNET -{ - public class Constants - { - public static readonly string Ok = "OK"; - public static readonly string Ack = "ACK"; - - public static readonly string FirstLinePrefix = "OK MPD "; - } -} diff --git a/src/MpcNET/Exception.cs b/src/MpcNET/Exception.cs deleted file mode 100644 index fddbad9..0000000 --- a/src/MpcNET/Exception.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; - -namespace MpcNET -{ - /// - /// Is thrown when a command is to be executed on a disconnected - /// where the property is set to false. - /// - public class NotConnectedException : InvalidOperationException - { - /// - /// Creates a new NotConnectedException. - /// - public NotConnectedException() : base("Not connected.") {} - } - /// - /// Is thrown when the connect method is invoked on an already connected . - /// - public class AlreadyConnectedException : InvalidOperationException - { - /// - /// Creates a new AlreadyConnectedException. - /// - public AlreadyConnectedException() : base("Connected already established.") { } - } - /// - /// Is thrown if the response from a MPD server is not as expected. This should never happen when - /// working with a tested version of the MPD server. - /// - public class InvalidMpdResponseException : Exception - { - /// - /// Creates a new InvalidMpdResponseException. - /// - public InvalidMpdResponseException() : base( "Invalid Mpd Response." ) {} - /// - /// Creates a new InvalidMpdResponseException. - /// - /// A message describing the error. - public InvalidMpdResponseException(string message) : base("Invalid Mpd Response: " + message) { } - } - /// - /// Is thrown when the MPD server returns an error to a command. - /// - public class MpdResponseException : Exception - { - private int errorCode; - private string errorMessage; - /// - /// The error code of the mpd server. - /// - public int ErrorCode { get { return this.errorCode; } } - /// - /// A message describing what went wrong. - /// - public string ErrorMessage { get { return this.errorMessage; } } - /// - /// Creates a new MpdResponseException. - /// - /// The error code of the mpd server. - /// A message describing what went wrong. - public MpdResponseException(int errorCode, string errorMessage) - : base("MPD" + errorCode + " " + errorMessage) - { - this.errorCode = errorCode; - this.errorMessage = errorMessage; - } - } -} diff --git a/src/MpcNET/IMpcCommand.cs b/src/MpcNET/IMpcCommand.cs deleted file mode 100644 index f374832..0000000 --- a/src/MpcNET/IMpcCommand.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; - -namespace MpcNET -{ - public interface IMpcCommand - { - string Value { get; } - - T FormatResponse(IList> response); - } -} \ No newline at end of file diff --git a/src/MpcNET/Message/IMpdMessage.cs b/src/MpcNET/Message/IMpdMessage.cs deleted file mode 100644 index daa8e38..0000000 --- a/src/MpcNET/Message/IMpdMessage.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace MpcNET.Message -{ - public interface IMpdMessage - { - IMpdRequest Request { get; } - IMpdResponse Response { get; } - - bool IsResponseValid { get; } - } -} \ No newline at end of file diff --git a/src/MpcNET/Message/MpdMessage.cs b/src/MpcNET/Message/MpdMessage.cs deleted file mode 100644 index 9adff0b..0000000 --- a/src/MpcNET/Message/MpdMessage.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text.RegularExpressions; -using Newtonsoft.Json; - -namespace MpcNET.Message -{ - [DebuggerDisplay("Request: {Request.Command.Value} | Response Status: {Response.State.Status}")] - public class MpdMessage : IMpdMessage - { - private readonly Regex _linePattern = new Regex(@"^(?[\w-]*):[ ]{0,1}(?.*)$"); - private readonly IList _rawResponse; - - public MpdMessage(IMpcCommand command, bool connected, IReadOnlyCollection response) - { - Request = new MpdRequest(command); - - var endLine = response.Skip(response.Count - 1).Single(); - _rawResponse = response.Take(response.Count - 1).ToList(); - - var values = Request.Command.FormatResponse(GetValuesFromResponse()); - Response = new MpdResponse(endLine, values, connected); - } - - public IMpdRequest Request { get; } - - public IMpdResponse Response { get; } - - public bool IsResponseValid => this.Response.State.Status == "OK"; - - private IList> GetValuesFromResponse() - { - var result = new List>(); - - foreach (var line in _rawResponse) - { - var match = _linePattern.Match(line); - if (match.Success) - { - var mpdKey = match.Result("${key}"); - if (!string.IsNullOrEmpty(mpdKey)) - { - var mpdValue = match.Result("${value}"); - if (!string.IsNullOrEmpty(mpdValue)) - { - result.Add(new KeyValuePair(mpdKey, mpdValue)); - } - } - } - } - - return result; - } - - public override string ToString() - { - return JsonConvert.SerializeObject(this, Formatting.Indented); - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Message/MpdRequest.cs b/src/MpcNET/Message/MpdRequest.cs deleted file mode 100644 index f864252..0000000 --- a/src/MpcNET/Message/MpdRequest.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace MpcNET.Message -{ - public interface IMpdRequest - { - IMpcCommand Command { get; } - } - - public class MpdRequest : IMpdRequest - { - public MpdRequest(IMpcCommand command) - { - Command = command; - } - - public IMpcCommand Command { get; } - } -} \ No newline at end of file diff --git a/src/MpcNET/Message/MpdResponse.cs b/src/MpcNET/Message/MpdResponse.cs deleted file mode 100644 index 5df8990..0000000 --- a/src/MpcNET/Message/MpdResponse.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace MpcNET.Message -{ - public interface IMpdResponse - { - IMpdResponseState State { get; } - T Body { get; } - } - - public class MpdResponse : IMpdResponse - { - public MpdResponse(string endLine, T body, bool connected) - { - State = new MpdResponseState(endLine, connected); - Body = body; - } - - public IMpdResponseState State { get; } - public T Body { get; } - } -} diff --git a/src/MpcNET/Message/MpdResponseState.cs b/src/MpcNET/Message/MpdResponseState.cs deleted file mode 100644 index e2c7668..0000000 --- a/src/MpcNET/Message/MpdResponseState.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System.Text.RegularExpressions; - -namespace MpcNET.Message -{ - public interface IMpdResponseState - { - string Status { get; } - string ErrorMessage { get; } - string MpdError { get; } - bool Error { get; } - bool Connected { get; } - } - - public class MpdResponseState : IMpdResponseState - { - private static readonly Regex ErrorPattern = new Regex("^ACK \\[(?[0-9]*)@(?[0-9]*)] \\{(?[a-z]*)} (?.*)$"); - - private readonly string _endLine; - - public MpdResponseState(string endLine, bool connected) - { - _endLine = endLine; - Connected = connected; - - if (!string.IsNullOrEmpty(_endLine)) - { - if (_endLine.Equals(Constants.Ok)) - { - Status = _endLine; - Error = false; - } - else - { - ParseErrorResponse(); - } - } - } - - public bool Connected { get; } = false; - public bool Error { get; } = true; - public string Status { get; private set; } = "UNKNOWN"; - public string ErrorMessage { get; private set; } = string.Empty; - public string MpdError { get; private set; } = string.Empty; - - private void ParseErrorResponse() - { - Status = "ERROR"; - MpdError = _endLine; - - var match = ErrorPattern.Match(_endLine); - - if (match.Groups.Count != 5) - { - ErrorMessage = "Unexpected response from server."; - } - else - { - var errorCode = match.Result("${code}"); - var commandListItem = match.Result("${nr}"); - var commandFailed = match.Result("${command}"); - var errorMessage = match.Result("${message}"); - ErrorMessage = $"ErrorCode: { errorCode }, CommandListItem: { commandListItem }, CommandFailed: { commandFailed }, ErrorMessage: { errorMessage }"; - } - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Mpc.cs b/src/MpcNET/Mpc.cs deleted file mode 100644 index 588a5a8..0000000 --- a/src/MpcNET/Mpc.cs +++ /dev/null @@ -1,1114 +0,0 @@ -using System.Net; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; -using MpcNET.Message; - -namespace MpcNET -{ - /// - /// The Mpc class implements all commands for the MPD. It takes care of command building - /// and parsing the response into .net objects. - /// - public class Mpc - { - private static readonly Regex STATUS_AUDIO_REGEX = new Regex("^(?[0-9]*):(?[0-9]*):(?[0-9]*)$"); - - private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); - private readonly IPEndPoint _server; - private MpcConnection _connection; - - public Mpc(IPEndPoint server) - { - _server = server; - } - - public bool IsConnected => _connection?.IsConnected ?? false; - public string Version => _connection?.Version ?? "Unknown"; - - public async Task ConnectAsync() - { - if (_connection == null) - { - _connection = new MpcConnection(_server); - } - - if (!_connection.IsConnected) - { - await _connection.ConnectAsync(); - } - - return _connection.IsConnected; - } - - public async Task DisconnectAsync() - { - if (_connection == null) - { - return; - } - - if (_connection.IsConnected) - { - await _connection?.DisconnectAsync(); - } - } - - public async Task> SendAsync(IMpcCommand command) - { - await _semaphore.WaitAsync(); - try - { - return await _connection.SendAsync(command); - } - finally - { - _semaphore.Release(); - } - } - - /* - #region Database Commands - - /// - /// Returns all values found in files of the MPD for the given attribute. - /// - /// The attribute who's values are requested. - /// All values found in files of the MPD for the given attribute. - public async Task> ListAsync(ITag tag) - { - MpdResponse response = await _connection.SendAsync("list", new string[] { tag.Value }); - - if (response.State.Error) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - return response.getValueList(); - } - /// - /// Returns all values for the given attribute found in files of the MPD where another attribute matches a given value. - /// - /// The attribute whos values are returns. - /// The attribute whos value should match a given value for the file to be included in the result. - /// The value the searchTag attribute must match for the file to be included in the result. - /// All values found in files of the MPD for the given attribute. - public async Task> ListAsync(ITag resultTag, ITag searchTag, string searchValue) - { - if (searchValue == null) - throw new ArgumentNullException("searchValue"); - - MpdResponse response = await _connection.SendAsync("list", new string[] { resultTag.Value, searchTag.Value, searchValue }); - - if (response.State.Error) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - return response.getValueList(); - } - /// - /// Returns the names of all files and directory found under the given path. - /// - /// The path whos subdirectories and their files are requested. - /// The names of all files and directory found under the given path. - public async Task> ListAllAsync(string path) - { - if (path == null) - throw new ArgumentNullException("path"); - - MpdResponse response = await _connection.SendAsync("listall", new string[] { path }); - - if (response.State.Error) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - return response.getValueList(); - } - /// - /// Returns the information of all files found in the given path and its subdirectories. - /// - /// The path of which the file information is requested. - /// The information of all files found in the given path and its subdirectories. - public async Task> ListAllInfoAsync(string path) - { - if (path == null) - throw new ArgumentNullException("path"); - - MpdResponse response = await _connection.SendAsync("listallinfo", new string[] { path }); - - if (response.State.Error) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - return MpdFile.buildList(response); - } - /// - /// Returns the directory listing of the root directory. - /// - /// The listing of the root directory. - public async Task LsInfoAsync() - { - return await LsInfoAsync(null); - } - /// - /// Returns the directory listing of the given path. - /// - /// The path whos listing is requested. - /// The directory listing of the given path. - public async Task LsInfoAsync(string path) - { - MpdResponse response; - if (path == null) - response = await _connection.SendAsync("lsinfo"); - else - response = await _connection.SendAsync("lsinfo", new string[] { path }); - - if (response.State.Error) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - return new MpdDirectoryListing( - MpdFile.buildList(response), - response.getAttributeValueList("directory"), - response.getAttributeValueList("playlist")); - } - /// - /// Returns all files in the database who's attribute matches the given token. Works like the Find command but is case insensitive. - /// - /// Specifies the attribute to search for. - /// The value the files attribute must have to be included in the result. - /// All files in the database who's attribute matches the given token. - public async Task> SearchAsync(ITag tag, string token) - { - if (token == null) - throw new ArgumentNullException("token"); - - MpdResponse response = await _connection.SendAsync("search", new string[] { tag.Value, token }); - - if (response.State.Error) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - return MpdFile.buildList(response); - } - - #endregion - - #region Playlist Commands - /// - /// Adds a file to the playlist. - /// - /// The name and path of the file to add. - public async Task AddAsync(string filename) - { - if (filename == null) - throw new ArgumentNullException("filename"); - - MpdResponse response = await _connection.SendAsync("add", new string[] { filename }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Adds a file to the playlist and returns the id. - /// - /// The name and path of the file to add. - /// The id of the file in the playlist. - public async Task AddIdAsync(string filename) - { - if (filename == null) - throw new ArgumentNullException("filename"); - - MpdResponse response = await _connection.SendAsync("add", new string[] { filename }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - if (response.Count != 1) - throw new InvalidMpdResponseException("Returned more than one line for command addid."); - - string id = response["Id"]; - if (id == null) - throw new InvalidMpdResponseException("Tag Id missing in response to command addid."); - int tryId = -1; - if (!int.TryParse(id, out tryId)) - throw new InvalidMpdResponseException("Tag Id in response to command addid does not contain an number."); - - return tryId; - } - /// - /// Clears the playlist. - /// - public async Task ClearAsync() - { - MpdResponse response = await _connection.SendAsync("clear"); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Returns the information of the current song. - /// - /// The information of the current song. - public async Task CurrentSongAsync() - { - MpdResponse response = await _connection.SendAsync("currentsong"); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - return MpdFile.build(response); - } - /// - /// Deletes the track with the given index from the current playlist. - /// - /// The index of the track to remove from the playlist. - public async Task DeleteAsync(int nr) - { - MpdResponse response = await _connection.SendAsync("delete", new string[] { nr.ToString() }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Deletes the track with the given id from the current playlist. - /// - /// The id of the track to remove from the playlist. - public async Task DeleteIdAsync(int id) - { - MpdResponse response = await _connection.SendAsync("deleteid", new string[] { id.ToString() }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Loads the playlist with the given name. - /// - /// The name of the playlist to load. - public async Task LoadAsync(string name) - { - if (name == null) - throw new ArgumentNullException("name"); - - MpdResponse response = await _connection.SendAsync("load", new string[] { name }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Renames a playlist. - /// - /// The old name of the playlist. - /// The new name of the playlist. - public async Task RenameAsync(string oldName, string newName) - { - if (oldName == null) - throw new ArgumentNullException("oldName"); - if (newName == null) - throw new ArgumentNullException("newName"); - - MpdResponse response = await _connection.SendAsync("rename", new string[] { oldName, newName }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Moves a track within the playlist. - /// - /// The old index of the track in the playlist. - /// The new index of the track in the playlist. - public async Task MoveAsync(int oldNr, int newNr) - { - MpdResponse response = await _connection.SendAsync("move", new string[] { oldNr.ToString(), newNr.ToString() }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Moves a track within the playlist. - /// - /// The id of the track to move. - /// The new index of the track in the playlist. - public async Task MoveIdAsync(int id, int nr) - { - MpdResponse response = await _connection.SendAsync("moveid", new string[] { id.ToString(), nr.ToString() }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Returns the meta data of the items in the current playlist. - /// - /// The meta data of the items in the current playlist. - public async Task> PlaylistInfoAsync() - { - MpdResponse response = await _connection.SendAsync("playlistinfo"); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - return MpdFile.buildList(response); - } - /// - /// Returns the meta data of a track in the current playlist. - /// - /// The index of the track in the playlist. - /// The meta data of the track in the current playlist. - public async Task PlaylistInfoAsync(int nr) - { - MpdResponse response = await _connection.SendAsync("playlistinfo", new string[] { nr.ToString() }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - return MpdFile.build(response); - } - /// - /// Returns the meta data of the items in the current playlist. - /// - /// The meta data of the items in the current playlist. - public async Task> PlaylistIdAsync() - { - MpdResponse response = await _connection.SendAsync("playlistid"); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - return MpdFile.buildList(response); - } - /// - /// Returns the meta data of a track in the current playlist. - /// - /// The id of the track in the playlist. - /// The meta data of the track in the current playlist. - public async Task PlaylistIdAsync(int id) - { - MpdResponse response = await _connection.SendAsync("playlistid", new string[] { id.ToString() }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - return MpdFile.build(response); - } - /// - /// Returns all changed tracks in the playlist since the given version. - /// - /// The version number. - /// All changed songs in the playlist since the given version. - public async Task> PlchangesAsync(int version) - { - MpdResponse response = await _connection.SendAsync("plchanges", new string[] { version.ToString() }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - return MpdFile.buildList(response); - } - /// - /// Returns the ids and positions of the changed tracks in the playlist since the given version. - /// - /// - /// - /// The ids and positions of the changed tracks in the playlist since the given version as KeyValuePairs. - /// The key is the index and the id is the value. - /// - public async Task>> PlChangesPosIdAsync(int version) - { - MpdResponse response = await _connection.SendAsync("plchangesposid", new string[] { version.ToString() }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - if (response.Count % 2 != 0) - throw new InvalidMpdResponseException("Response to command plchangesposid contains an odd number of lines!"); - - List> ret = new List>(); - - for (int i = 0; i < response.Count; i += 2) - { - KeyValuePair posLine = response[i]; - KeyValuePair idLine = response[i + 1]; - - if ((posLine.Key == null) || (posLine.Value == null)) - throw new InvalidMpdResponseException("Invalid format of line " + i + "!"); - if ((idLine.Key == null) || (idLine.Value == null)) - throw new InvalidMpdResponseException("Invalid format of line " + (i + 1) + "!"); - - if (!posLine.Key.Equals("cpos")) - throw new InvalidMpdResponseException("Line " + i + " does not start with \"cpos\"!"); - if (!idLine.Key.Equals("Id")) - throw new InvalidMpdResponseException("Line " + (i + 1) + " does not start with \"Id\"!"); - - int tryPos = -1; - if (!int.TryParse(posLine.Value, out tryPos)) - throw new InvalidMpdResponseException("Tag value on line " + i + " is not a number."); - int tryId = -1; - if (!int.TryParse(idLine.Value, out tryId)) - throw new InvalidMpdResponseException("Tag value on line " + (i + 1) + " is not a number."); - - ret.Add(new KeyValuePair(tryPos, tryId)); - } - - - return ret; - } - /// - /// Removes the playlist with the given name. - /// - /// The name of the playlist to remove. - public async Task RmAsync(string name) - { - if (name == null) - throw new ArgumentNullException("name"); - - MpdResponse response = await _connection.SendAsync("rm", new string[] { name }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Saves the current playlist with the given name. - /// - /// The name to the save the currenty playlist. - public async Task SaveAsync(string name) - { - if (name == null) - throw new ArgumentNullException("name"); - - MpdResponse response = await _connection.SendAsync("save", new string[] { name }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Shuffles the current playlist. - /// - public async Task ShuffleAsync() - { - MpdResponse response = await _connection.SendAsync("shuffle"); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Swaps the to tracks in the current playlist. - /// - /// The index of the first track. - /// The index of the second track. - public async Task SwapAsync(int nr1, int nr2) - { - MpdResponse response = await _connection.SendAsync("swap", new string[] { nr1.ToString(), nr2.ToString() }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Swaps the to tracks in the current playlist. - /// - /// The id of the first track. - /// The id of the second track. - public async Task SwapIdAsync(int id1, int id2) - { - MpdResponse response = await _connection.SendAsync("swapid", new string[] { id1.ToString(), id2.ToString() }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Returns the filenames of the tracks in the given playlist. - /// - /// The playlist whos filename are requested. - /// The filenames of the tracks in the given playlist. - public async Task> ListPlaylistAsync(string name) - { - if (name == null) - throw new ArgumentNullException("name"); - - MpdResponse response = await _connection.SendAsync("listplaylist", new string[] { name }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - return response.getValueList(); - } - /// - /// Return the meta data of the tracks in the given playlist. - /// - /// The playlist whos files meta data are requested. - /// The meta data of the tracks in the given playlist. - public async Task> ListPlaylistInfoAsync(string name) - { - if (name == null) - throw new ArgumentNullException("name"); - - MpdResponse response = await _connection.SendAsync("listplaylistinfo", new string[] { name }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - return MpdFile.buildList(response); - } - /// - /// Add a file to a playlist. - /// - /// The name of the playlist. - /// The path and name of the file to add. - public async Task PlaylistAddAsync(string name, string file) - { - if (name == null) - throw new ArgumentNullException("name"); - if (file == null) - throw new ArgumentNullException("file"); - - MpdResponse response = await _connection.SendAsync("playlistadd", new string[] { name, file }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Clears all tracks from a playlist. - /// - /// The name of the playlist to clear. - public async Task PlaylistClearAsync(string name) - { - if (name == null) - throw new ArgumentNullException("name"); - - MpdResponse response = await _connection.SendAsync("playlistclear", new string[] { name }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Delete a file from a playlist. - /// - /// The name of the playlist - /// The id of the track to delete. - public async Task PlaylistDeleteAsync(string name, int id) - { - if (name == null) - throw new ArgumentNullException("name"); - - MpdResponse response = await _connection.SendAsync("playlistdelete", new string[] { name, id.ToString() }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Moves a track in a playlist. - /// - /// The name of the playlist. - /// The id of the track to move. - /// The position to move the track to. - public async Task PlaylistMoveAsync(string name, int id, int nr) - { - if (name == null) - throw new ArgumentNullException("name"); - - MpdResponse response = await _connection.SendAsync("playlistmove", new string[] { id.ToString(), nr.ToString() }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Returns the meta data for all tracks in the current playlist whos attribute equals the given value. - /// - /// The attribute to search for the given value. - /// The value to search for in the given attribute. - /// The meta data for all tracks in the current playlist whos attribute equals the given value. - public async Task> PlaylistFindAsync(ITag tag, string token) - { - if (token == null) - throw new ArgumentNullException("token"); - - MpdResponse response = await _connection.SendAsync("playlistfind", new string[] { tag.Value, token }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - return MpdFile.buildList(response); - } - /// - /// Returns the meta data for all tracks in the current playlist whos attribute contains the given value. - /// - /// The attribute to search for the given value. - /// The value to search for in the given attribute. - /// The meta data for all tracks in the current playlist whos attribute contains the given value. - public async Task> PlaylistSearchAsync(ITag tag, string token) - { - if (token == null) - throw new ArgumentNullException("token"); - - MpdResponse response = await _connection.SendAsync("playlistsearch", new string[] { tag.Value, token }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - return MpdFile.buildList(response); - } - #endregion - - #region Playback Commands - /// - /// Sets the seconds to crossfade between songs. - /// - /// The seconds to crossfade between songs. - public async Task CrossfadeAsync(int seconds) - { - MpdResponse response = await _connection.SendAsync("crossfade", new string[] { seconds.ToString() }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Starts the playback of the next song in the playlist- - /// - public async Task NextAsync() - { - MpdResponse response = await _connection.SendAsync("next"); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Sets the MPD to pause or resume the playback. - /// - /// If the playback should be paused or resumed. - public async Task PauseAsync(bool pause) - { - MpdResponse response = await _connection.SendAsync("pause", new string[] { pause ? "1" : "0" }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Starts the playback of the current item in the playlist. - /// - public async Task PlayAsync() - { - MpdResponse response = await _connection.SendAsync("play"); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Starts the playback of the item with the given index in the playlist. - /// - /// The index of the track in the playlist to start playing. - public async Task PlayAsync(int nr) - { - MpdResponse response = await _connection.SendAsync("play", new string[] { nr.ToString() }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Starts the playback of the track in the playlist with the id 0. - /// - public async Task PlayIdAsync() - { - MpdResponse response = await _connection.SendAsync("playid"); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Starts the playback of the track in the playlist with the given id. - /// - /// The id of the track to start playing. - public async Task PlayIdAsync(int id) - { - MpdResponse response = await _connection.SendAsync("playid", new string[] { id.ToString() }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Starts the playback of the previous track in the playlist. - /// - public async Task PreviousAsync() - { - MpdResponse response = await _connection.SendAsync("previous"); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Sets the MPD to random or sequential playback. - /// - /// If the MPD playlist should be played randomly. - public async Task RandomAsync(bool random) - { - MpdResponse response = await _connection.SendAsync("random", new string[] { random ? "1" : "0" }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Sets if the MPD should repeat the playlist. - /// - /// If the MPD should repeat the playlist. - public async Task RepeatAsync(bool repeat) - { - MpdResponse response = await _connection.SendAsync("repeat", new string[] { repeat ? "1" : "0" }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Starts playback of a given song at the give position. - /// - /// The index of the song in the playlist. - /// The number of seconds to start playback on. - public async Task SeekAsync(int nr, int time) - { - MpdResponse response = await _connection.SendAsync("seek", new string[] { nr.ToString(), time.ToString() }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Starts playback of a given song at the give position. - /// - /// The id of the song in the playlist. - /// The number of seconds to start playback on. - public async Task SeekIdAsync(int id, int time) - { - MpdResponse response = await _connection.SendAsync("seekid", new string[] { id.ToString(), time.ToString() }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Sets the output volume of the MPD. - /// - /// The output volume of the MPD between 0 and 100. - public async Task SetVolAsync(int vol) - { - if (vol < 0) - throw new ArgumentException("vol < 0"); - if (vol > 100) - throw new ArgumentException("vol > 100"); - - MpdResponse response = await _connection.SendAsync("setvol", new string[] { vol.ToString() }); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - /// - /// Stops the playback of the MPD. - /// - public async Task StopAsync() - { - MpdResponse response = await _connection.SendAsync("stop"); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - } - - #endregion - - #region Misc Commands - /// - /// Clears the error message set in the MPD. - /// - public async Task ClearErrorAsync() - { - await _connection.SendAsync("clearerror"); - } - /// - /// Returns which commands the current user has access to. - /// - /// The commands the current user has access to. - public async Task> CommandsAsync() - { - MpdResponse response = await _connection.SendAsync("commands"); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - return response.getValueList(); - } - /// - /// Returns which commands the current user does has access to. - /// - /// The commands the current user does has access to. - public async Task> NotCommandsAsync() - { - MpdResponse response = await _connection.SendAsync("notcommands"); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - return response.getValueList(); - } - /// - /// Send the password to the server allow access to the server if enabled in the MPD. - /// - /// The password to authorize to the server. - /// If the password is valid. - public async Task PasswordAsync(string password) - { - if (password == null) - throw new ArgumentNullException("password"); - - var mpdResponse = await _connection.SendAsync("password", new string[] { password }); - return mpdResponse.IsError; - } - /// - /// Sends a ping command to the server and waits for the response. - /// - public async Task PingAsync() - { - await _connection.SendAsync("ping"); - } - /// - /// Requests the current statistics from the MPD, - /// - /// The current statistics fromt the MPD. - public async Task StatsAsync() - { - MpdResponse response = await _connection.SendAsync("stats"); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - int artists = -1; - int albums = -1; - int songs = -1; - int uptime = -1; - int playtime = -1; - int db_playtime = -1; - int db_update = -1; - - foreach (KeyValuePair line in response) - { - if ((line.Key != null) && (line.Value != null)) - switch (line.Key) - { - case "artists": - { - int tryValue; - if (int.TryParse(line.Value, out tryValue)) - artists = tryValue; - } - break; - case "albums": - { - int tryValue; - if (int.TryParse(line.Value, out tryValue)) - albums = tryValue; - } - break; - case "songs": - { - int tryValue; - if (int.TryParse(line.Value, out tryValue)) - songs = tryValue; - } - break; - case "uptime": - { - int tryValue; - if (int.TryParse(line.Value, out tryValue)) - uptime = tryValue; - } - break; - case "playtime": - { - int tryValue; - if (int.TryParse(line.Value, out tryValue)) - playtime = tryValue; - } - break; - case "db_playtime": - { - int tryValue; - if (int.TryParse(line.Value, out tryValue)) - db_playtime = tryValue; - } - break; - case "db_update": - { - int tryValue; - if (int.TryParse(line.Value, out tryValue)) - db_update = tryValue; - } - break; - } - } - - return new MpdStatistics(artists, albums, songs, uptime, playtime, db_playtime, db_update); - } - /// - /// Returns the current status of the MPD. - /// - /// The current status of the MPD. - public async Task StatusAsync() - { - MpdResponse response = await _connection.SendAsync("status"); - - if (response.IsError) - throw new MpdResponseException(response.ErrorCode, response.ErrorMessage); - - int volume = -1; - bool repeat = false; - bool random = false; - int playlist = -1; - int playlistLength = -1; - int playlistQueue = -1; - int xFade = -1; - MpdState state = MpdState.Unknown; - int song = -1; - int songId = -1; - int timeElapsed = -1; - int timeTotal = -1; - int bitrate = -1; - int audioSampleRate = -1; - int audioBits = -1; - int audioChannels = -1; - int updatingDb = -1; - string error = null; - - foreach (KeyValuePair line in response) - { - if ((line.Key != null) && (line.Value != null)) - switch (line.Key) - { - case "volume": - { - int tryValue; - if (int.TryParse(line.Value, out tryValue)) - { - volume = tryValue; - if (volume < 0) - volume = 0; - if (volume > 100) - volume = 100; - } - } - break; - case "repeat": - repeat = (line.Value != null) && (line.Value.Equals("1")); - break; - case "random": - random = (line.Value != null) && (line.Value.Equals("1")); - break; - case "playlist": - { - int tryValue; - if (int.TryParse(line.Value, out tryValue)) - playlist = tryValue; - } - break; - case "playlistlength": - { - int tryValue; - if (int.TryParse(line.Value, out tryValue)) - playlistLength = tryValue; - } - break; - case "playlistqueue": - { - int tryValue; - if (int.TryParse(line.Value, out tryValue)) - playlistQueue = tryValue; - } - break; - case "xfade": - { - int tryValue; - if (int.TryParse(line.Value, out tryValue)) - xFade = tryValue; - } - break; - case "state": - switch (line.Value) - { - case "play": - state = MpdState.Play; - break; - case "pause": - state = MpdState.Pause; - break; - case "stop": - state = MpdState.Stop; - break; - } - break; - case "song": - { - int tryValue; - if (int.TryParse(line.Value, out tryValue)) - song = tryValue; - } - break; - case "songid": - { - int tryValue; - if (int.TryParse(line.Value, out tryValue)) - songId = tryValue; - } - break; - case "time": - int index = line.Value.IndexOf(':'); - if (index >= 0) - { - int tryValue; - if (int.TryParse(line.Value.Substring(0, index), out tryValue)) - timeElapsed = tryValue; - if (int.TryParse(line.Value.Substring(index + 1), out tryValue)) - timeTotal = tryValue; - } - break; - case "bitrate": - { - int tryValue; - if (int.TryParse(line.Value, out tryValue)) - bitrate = tryValue; - } - break; - case "audio": - Match match = STATUS_AUDIO_REGEX.Match(line.Value); - if (match.Success) - { - int tryValue; - if (int.TryParse(match.Result("$sampleRate"), out tryValue)) - audioSampleRate = tryValue; - if (int.TryParse(match.Result("$bits"), out tryValue)) - audioBits = tryValue; - if (int.TryParse(match.Result("$channels"), out tryValue)) - audioChannels = tryValue; - } - break; - case "updating_db": - { - int tryValue; - if (int.TryParse(line.Value, out tryValue)) - updatingDb = tryValue; - } - break; - case "error": - error = line.Value; - break; - } - } - - return new MpdStatus( - volume, - repeat, - random, - playlist, - playlistLength, - xFade, - state, - song, - songId, - timeElapsed, - timeTotal, - bitrate, - audioSampleRate, - audioBits, - audioChannels, - updatingDb, - error - ); - } - - #endregion - */ - } -} diff --git a/src/MpcNET/MpcConnection.cs b/src/MpcNET/MpcConnection.cs deleted file mode 100644 index a4c6e33..0000000 --- a/src/MpcNET/MpcConnection.cs +++ /dev/null @@ -1,164 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading.Tasks; -using MpcNET.Message; -using MpcNET.Utils; - -namespace MpcNET -{ - /// - /// Keeps the connection to the MPD server and handels the most basic structure of the - /// MPD protocol. The high level commands are handeled in the - /// class. - /// - public class MpcConnection - { - private readonly Encoding encoding = new UTF8Encoding(); - private readonly IPEndPoint _server; - - private TcpClient _tcpClient; - private NetworkStream _networkStream; - - private string _version; - - public MpcConnection(IPEndPoint server) - { - if (this.IsConnected) - { - return; - } - - ClearConnectionFields(); - _server = server; - } - - public bool IsConnected => (_tcpClient != null) && _tcpClient.Connected; - public string Version => _version; - - public async Task ConnectAsync() - { - if (_server == null) - throw new InvalidOperationException("Server IPEndPoint not set."); - - if (IsConnected) - throw new AlreadyConnectedException(); - - - _tcpClient = new TcpClient(); - await _tcpClient.ConnectAsync(_server.Address, _server.Port); - - _networkStream = _tcpClient.GetStream(); - - // Encoding UTF8 has some problems with TcpClient: https://bugs.musicpd.org/view.php?id=4501 - using (var reader = new StreamReader(_networkStream, this.encoding, true, 512, true)) - { - var firstLine = await reader.ReadLineAsync(); - if (!firstLine.StartsWith(Constants.FirstLinePrefix)) - { - await DisconnectAsync(); - throw new InvalidDataException("Response of mpd does not start with \"" + Constants.FirstLinePrefix + "\"."); - } - - _version = firstLine.Substring(Constants.FirstLinePrefix.Length); - } - } - - public Task DisconnectAsync() - { - if (_tcpClient == null) - { - return Task.CompletedTask; - } - - _networkStream.Dispose(); - ClearConnectionFields(); - - return Task.CompletedTask; - } - - - public async Task> SendAsync(IMpcCommand command) - { - command.CheckNotNull(); - - var connected = await CheckConnectionAsync(); - string[] response; - - try - { - Console.WriteLine("Command: " + command.Value); - // Encoding UTF8 has some problems with TcpClient: https://bugs.musicpd.org/view.php?id=4501 - - using (var writer = new StreamWriter(_networkStream, this.encoding, 512, true) { NewLine = "\n" }) - { - writer.WriteLine(command.Value); - writer.Flush(); - } - - response = await ReadResponseAsync(); - } - catch (Exception exception) - { - Console.WriteLine("Exception:" + exception); - try - { - await DisconnectAsync(); - } - catch (Exception) - { - } - - return null; // TODO: Create Null Object for MpdResponse - } - - return new MpdMessage(command, connected, response); - } - - private async Task CheckConnectionAsync() - { - if (!IsConnected) - { - await ConnectAsync(); - } - - return IsConnected; - } - - private async Task ReadResponseAsync() - { - var response = new List(); - - // Read response untli reach end token (OK or ACK) - using (var reader = new StreamReader(_networkStream, this.encoding, true, 512, true)) - { - string responseLine; - do - { - responseLine = await reader.ReadLineAsync(); - Console.WriteLine("ReadLine:|" + responseLine + "|"); - if (responseLine == null) - { - Console.WriteLine("Received null"); - responseLine = string.Empty; - continue; - } - response.Add(responseLine); - } while (!(responseLine.Equals(Constants.Ok) || responseLine.StartsWith(Constants.Ack))); - } - - return response.Where(line => !string.IsNullOrEmpty(line)).ToArray(); - } - - private void ClearConnectionFields() - { - _networkStream?.Dispose(); - _tcpClient?.Dispose(); - _version = string.Empty; - } - } -} diff --git a/src/MpcNET/MpdDirectoryListing.cs b/src/MpcNET/MpdDirectoryListing.cs deleted file mode 100644 index c295f74..0000000 --- a/src/MpcNET/MpdDirectoryListing.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using MpcNET.Types; - -namespace MpcNET -{ - /// - /// The MpdDirectoryListing class contains the response of a MPD server to a list command. - /// - public class MpdDirectoryListing - { - private readonly ReadOnlyCollection file; - private readonly ReadOnlyCollection directory; - private readonly ReadOnlyCollection playlist; - /// - /// The list of files in the directory. - /// - public ReadOnlyCollection FileList { get { return this.file; } } - /// - /// The list of subdirectories in the directory. - /// - public ReadOnlyCollection DirectoryList { get { return this.directory; } } - /// - /// The list of playlists in the directory. - /// - public ReadOnlyCollection PlaylistList { get { return this.playlist; } } - /// - /// Creates a new MpdDirectoryListing. - /// - /// The list of files in the directory. - /// The list of subdirectories in the directory. - /// The list of playlists in the directory. - public MpdDirectoryListing(List file, List directory, List playlist) - { - if (file == null) - throw new ArgumentNullException("file"); - if (directory == null) - throw new ArgumentNullException("directory"); - if (playlist == null) - throw new ArgumentNullException("playlist"); - - this.file = new ReadOnlyCollection(file); - this.directory = new ReadOnlyCollection(directory); - this.playlist = new ReadOnlyCollection(playlist); - } - /// - /// Creates a new MpdDirectoryListing. - /// - /// The list of files in the directory. - /// The list of subdirectories in the directory. - /// The list of playlists in the directory. - public MpdDirectoryListing(ReadOnlyCollection file, ReadOnlyCollection directory, ReadOnlyCollection playlist) - { - if (file == null) - throw new ArgumentNullException("file"); - if (directory == null) - throw new ArgumentNullException("directory"); - if (playlist == null) - throw new ArgumentNullException("playlist"); - - this.file = file; - this.directory = directory; - this.playlist = playlist; - } - } -} diff --git a/src/MpcNET/MpdStatistics.cs b/src/MpcNET/MpdStatistics.cs deleted file mode 100644 index 42c4371..0000000 --- a/src/MpcNET/MpdStatistics.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System.Text; - -namespace MpcNET -{ - /// - /// The MpdStatistics class contains statistics of the MPD file database. - /// - public class MpdStatistics - { - private readonly int artists; - private readonly int albums; - private readonly int songs; - private readonly int uptime; - private readonly int playtime; - private readonly int db_playtime; - private readonly long db_update; - /// - /// The number of artists in the MPD database. - /// - public int Artists { get { return this.artists; } } - /// - /// The number of albums in the MPD database. - /// - public int Albums { get { return this.albums; } } - /// - /// The number of songs in the MPD database. - /// - public int Songs { get { return this.songs; } } - /// - /// The time the MPD server is running in seconds. - /// - public int Uptime { get { return this.uptime; } } - /// - /// The number of seconds the MPD played so far. - /// - public int Playtime { get { return this.playtime; } } - /// - /// The total playtime of all songs in the MPD database. - /// - public int DbPlaytime { get { return this.db_playtime; } } - /// - /// The timestamp of the last MPD database update. - /// - public long DbUpdate { get { return this.db_update; } } - /// - /// Creates a new MpdStatistics object. - /// - /// The number of artists in the MPD database. - /// The number of albums in the MPD database. - /// The number of songs in the MPD database. - /// The time the MPD server is running in seconds. - /// The number of seconds the MPD played so far. - /// The total playtime of all songs in the MPD database. - /// The timestamp of the last MPD database update. - public MpdStatistics( - int artists, - int albums, - int songs, - int uptime, - int playtime, - int db_playtime, - long db_update - ) - { - this.artists = artists; - this.albums = albums; - this.songs = songs; - this.uptime = uptime; - this.playtime = playtime; - this.db_playtime = db_playtime; - this.db_update = db_update; - } - /// - /// Returns a string representation of the object mainly for debugging purpuse. - /// - /// A string representation of the object. - public override string ToString() - { - StringBuilder builder = new StringBuilder(); - - appendInt(builder, "artists", this.artists); - appendInt(builder, "songs", this.songs); - appendInt(builder, "uptime", this.uptime); - appendInt(builder, "playtime", this.playtime); - appendInt(builder, "db_playtime", this.db_playtime); - appendLong(builder, "db_update", this.db_update); - - return builder.ToString(); - } - - private static void appendInt(StringBuilder builder, string name, int value) - { - if (value < 0) - return; - - builder.Append(name); - builder.Append(": "); - builder.Append(value); - builder.AppendLine(); - } - - private static void appendLong(StringBuilder builder, string name, long value) - { - if (value < 0) - return; - - builder.Append(name); - builder.Append(": "); - builder.Append(value); - builder.AppendLine(); - } - - } -} diff --git a/src/MpcNET/Tags/FindTags.cs b/src/MpcNET/Tags/FindTags.cs deleted file mode 100644 index 51f84c6..0000000 --- a/src/MpcNET/Tags/FindTags.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace MpcNET.Tags -{ - /// - /// https://www.musicpd.org/doc/protocol/database.html : find {TYPE} {WHAT} [...] [window START:END] - /// - public class FindTags - { - public static ITag Any { get; } = new Tag("any"); - public static ITag File { get; } = new Tag("file"); - public static ITag Base { get; } = new Tag("base"); - public static ITag ModifiedSince { get; } = new Tag("modified-since"); - } -} \ No newline at end of file diff --git a/src/MpcNET/Tags/MpdTags.cs b/src/MpcNET/Tags/MpdTags.cs deleted file mode 100644 index 5d96fe3..0000000 --- a/src/MpcNET/Tags/MpdTags.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace MpcNET.Tags -{ - /// - /// https://www.musicpd.org/doc/protocol/tags.html - /// - public class MpdTags - { - public static ITag Artist { get; } = new Tag("artist"); - public static ITag ArtistSort { get; } = new Tag("artistsort"); - public static ITag Album { get; } = new Tag("album"); - public static ITag AlbumSort { get; } = new Tag("albumsort"); - public static ITag AlbumArtist { get; } = new Tag("albumartist"); - public static ITag AlbumArtistSort { get; } = new Tag("albumartistsort"); - public static ITag Title { get; } = new Tag("title"); - public static ITag Track { get; } = new Tag("track"); - public static ITag Name { get; } = new Tag("name"); - public static ITag Genre { get; } = new Tag("genre"); - public static ITag Date { get; } = new Tag("date"); - public static ITag Composer { get; } = new Tag("composer"); - public static ITag Performer { get; } = new Tag("performer"); - public static ITag Comment { get; } = new Tag("comment"); - public static ITag Disc { get; } = new Tag("disc"); - } -} \ No newline at end of file diff --git a/src/MpcNET/Tags/Tag.cs b/src/MpcNET/Tags/Tag.cs deleted file mode 100644 index 83fd690..0000000 --- a/src/MpcNET/Tags/Tag.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace MpcNET.Tags -{ - public interface ITag - { - string Value { get; } - } - - - internal class Tag : ITag - { - internal Tag(string value) - { - Value = value; - } - - public string Value { get; } - } -} \ No newline at end of file diff --git a/src/MpcNET/Types/IMpdFile.cs b/src/MpcNET/Types/IMpdFile.cs deleted file mode 100644 index 5876e76..0000000 --- a/src/MpcNET/Types/IMpdFile.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Collections.Generic; - -namespace MpcNET.Types -{ - public interface IMpdFile : IMpdFilePath - { - int Time { get; } - string Album { get; } - string Artist { get; } - string Title { get; } - string Track { get; } - string Name { get; } - string Genre { get; } - string Date { get; } - string Composer { get; } - string Performer { get; } - string Comment { get; } - int Disc { get; } - int Pos { get; } - int Id { get; } - IReadOnlyDictionary UnknownMetadata { get; } - - /// - /// If the MpdFile has the property set. - /// - bool HasTime { get; } - - /// - /// If the MpdFile has the property set. - /// - bool HasAlbum { get; } - - /// - /// If the MpdFile has the property set. - /// - bool HasArtist { get; } - - /// - /// If the MpdFile has the property set. - /// - bool HasTitle { get; } - - /// - /// If the MpdFile has the property set. - /// - bool HasTrack { get; } - - /// - /// If the MpdFile has the property set. - /// - bool HasName { get; } - - /// - /// If the MpdFile has the property set. - /// - bool HasGenre { get; } - - /// - /// If the MpdFile has the property set. - /// - bool HasDate { get; } - - /// - /// If the MpdFile has the property set. - /// - bool HasComposer { get; } - - /// - /// If the MpdFile has the property set. - /// - bool HasPerformer { get; } - - /// - /// If the MpdFile has the property set. - /// - bool HasComment { get; } - - /// - /// If the MpdFile has the property set. - /// - bool HasDisc { get; } - - /// - /// If the MpdFile has the property set. - /// - bool HasPos { get; } - - /// - /// If the MpdFile has the property set. - /// - bool HasId { get; } - } -} \ No newline at end of file diff --git a/src/MpcNET/Types/IMpdFilePath.cs b/src/MpcNET/Types/IMpdFilePath.cs deleted file mode 100644 index 81bd28e..0000000 --- a/src/MpcNET/Types/IMpdFilePath.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace MpcNET.Types -{ - public interface IMpdFilePath - { - string Path { get; } - } -} \ No newline at end of file diff --git a/src/MpcNET/Types/MpdDecoderPlugin.cs b/src/MpcNET/Types/MpdDecoderPlugin.cs deleted file mode 100644 index 3eda867..0000000 --- a/src/MpcNET/Types/MpdDecoderPlugin.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections.Generic; -using MpcNET.Utils; - -namespace MpcNET.Types -{ - public class MpdDecoderPlugin - { - public static readonly MpdDecoderPlugin Empty = new MpdDecoderPlugin(string.Empty); - - private readonly IList _suffixes = new List(); - private readonly IList _mediaTypes = new List(); - - public MpdDecoderPlugin(string name) - { - name.CheckNotNull(); - - Name = name; - IsInitialized = !string.IsNullOrEmpty(name); - } - - public string Name { get; } - public IEnumerable Suffixes => _suffixes; - public IEnumerable MediaTypes => _mediaTypes; - - internal bool IsInitialized { get; } - - internal void AddSuffix(string suffix) - { - _suffixes.Add(suffix); - } - - internal void AddMediaType(string type) - { - _mediaTypes.Add(type); - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Types/MpdDirectory.cs b/src/MpcNET/Types/MpdDirectory.cs deleted file mode 100644 index 1170fd5..0000000 --- a/src/MpcNET/Types/MpdDirectory.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using MpcNET.Utils; - -namespace MpcNET.Types -{ - public class MpdDirectory - { - private readonly IList _files = new List(); - - public MpdDirectory(string path) - { - path.CheckNotNull(); - - Path = path; - - var name = path.Split('/').Last(); - Name = string.IsNullOrEmpty(name) ? "root" : name; - } - - public string Path { get; } - public string Name { get; } - public IEnumerable Files => _files; - - internal void AddFile(string file) - { - _files.Add(new MpdFile(file)); - } - } -} \ No newline at end of file diff --git a/src/MpcNET/Types/MpdOutput.cs b/src/MpcNET/Types/MpdOutput.cs deleted file mode 100644 index 3321e0c..0000000 --- a/src/MpcNET/Types/MpdOutput.cs +++ /dev/null @@ -1,23 +0,0 @@ -using MpcNET.Utils; - -namespace MpcNET.Types -{ - /// - /// The MpdOutput class contains all attributes of an output device of the MPD. - /// - public class MpdOutput - { - public MpdOutput(int id, string name, bool enabled) - { - name.CheckNotNull(); - - Id = id; - Name = name; - IsEnabled = enabled; - } - - public int Id { get; } - public string Name { get; } - public bool IsEnabled { get; } - } -} \ No newline at end of file diff --git a/src/MpcNET/Types/MpdPlaylist.cs b/src/MpcNET/Types/MpdPlaylist.cs deleted file mode 100644 index 03c7a40..0000000 --- a/src/MpcNET/Types/MpdPlaylist.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Globalization; -using MpcNET.Utils; - -namespace MpcNET.Types -{ - public class MpdPlaylist - { - public MpdPlaylist(string name) - { - name.CheckNotNull(); - - Name = name; - } - - public string Name { get; } - public DateTime LastModified { get; private set; } - - internal void AddLastModified(string lastModified) - { - LastModified = DateTime.Parse(lastModified, CultureInfo.InvariantCulture); - } - } -} diff --git a/src/MpcNET/Utils/CheckNotNullExtension.cs b/src/MpcNET/Utils/CheckNotNullExtension.cs deleted file mode 100644 index 465da6d..0000000 --- a/src/MpcNET/Utils/CheckNotNullExtension.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace MpcNET.Utils -{ - public static class CheckNotNullExtension - { - public static void CheckNotNull(this object toBeChecked) - { - if (toBeChecked == null) - { - throw new ArgumentNullException(nameof(toBeChecked)); - } - } - } -} \ No newline at end of file