1
0
mirror of https://github.com/ZetaKebab/MpcNET.git synced 2024-09-16 05:30:09 +00:00

Rewrote most of the library

This commit is contained in:
Kim Hugener-Ohlsen 2018-03-02 12:14:26 +01:00
parent a2c012dd7e
commit 245efd6477
181 changed files with 3927 additions and 3020 deletions

4
.gitignore vendored
View File

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

View File

@ -0,0 +1,74 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CommandFactory.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET
{
using MpcNET.Commands;
/// <summary>
/// Provides MPD commands.
/// </summary>
/// <seealso cref="MpcNET.ICommandFactory" />
public class CommandFactory : ICommandFactory
{
/// <summary>
/// Gets the status command factory.
/// </summary>
/// <value>
/// The status.
/// </value>
public IStatusCommandFactory Status { get; } = new StatusCommandFactory();
/// <summary>
/// Gets the database command factory.
/// </summary>
/// <value>
/// The database.
/// </value>
public IDatabaseCommandFactory Database { get; } = new DatabaseCommandFactory();
/// <summary>
/// Gets the reflection command factory.
/// </summary>
/// <value>
/// The reflection.
/// </value>
public IReflectionCommandFactory Reflection { get; } = new ReflectionCommandFactory();
/// <summary>
/// Gets the stored playlist command factory.
/// </summary>
/// <value>
/// The stored playlist.
/// </value>
public IStoredPlaylistCommandFactory StoredPlaylist { get; } = new StoredPlaylistCommandFactory();
/// <summary>
/// Gets the current playlist command factory.
/// </summary>
/// <value>
/// The current playlist.
/// </value>
public ICurrentPlaylistCommandFactory CurrentPlaylist { get; } = new CurrentPlaylistCommandFactory();
/// <summary>
/// Gets the playback command factory.
/// </summary>
/// <value>
/// The playback.
/// </value>
public IPlaybackCommandFactory Playback { get; } = new PlaybackCommandFactory();
/// <summary>
/// Gets the output command factory.
/// </summary>
/// <value>
/// The output.
/// </value>
public IOutputCommandFactory Output { get; } = new OutputCommandFactory();
}
}

View File

@ -0,0 +1,95 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CurrentPlaylistCommandFactory.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands
{
using System.Collections.Generic;
using MpcNET.Commands.Playlist;
using MpcNET.Types;
/// <summary>
/// https://www.musicpd.org/doc/protocol/queue.html
/// </summary>
public class CurrentPlaylistCommandFactory : ICurrentPlaylistCommandFactory
{
/// <summary>
/// Command: add
/// </summary>
/// <param name="directory">The directory.</param>
/// <returns>An <see cref="AddCommand"/>.</returns>
public IMpcCommand<string> AddDirectory(string directory)
{
return new AddCommand(directory);
}
/// <summary>
/// Command: addid
/// </summary>
/// <param name="songPath">The song path.</param>
/// <returns>An <see cref="AddIdCommand"/>.</returns>
public IMpcCommand<string> AddSong(string songPath)
{
return new AddIdCommand(songPath);
}
/// <summary>
/// Command: clear
/// </summary>
/// <returns>An <see cref="ClearCommand"/>.</returns>
public IMpcCommand<string> Clear()
{
return new ClearCommand();
}
/// <summary>
/// Command: playlist
/// </summary>
/// <returns>A <see cref="PlaylistCommand"/>.</returns>
public IMpcCommand<IEnumerable<IMpdFile>> GetAllSongsInfo()
{
return new PlaylistCommand();
}
/// <summary>
/// Command: delete
/// </summary>
/// <param name="position">The position.</param>
/// <returns>A <see cref="DeleteCommand" />.</returns>
public IMpcCommand<string> RemoveSongByPosition(int position)
{
return new DeleteCommand(position);
}
/// <summary>
/// Command: deleteid
/// </summary>
/// <param name="songId">The song identifier.</param>
/// <returns>A <see cref="DeleteIdCommand"/>.</returns>
public IMpcCommand<string> RemoveSongById(int songId)
{
return new DeleteIdCommand(songId);
}
/// <summary>
/// Command: playlistid
/// </summary>
/// <param name="songId">The song identifier.</param>
/// <returns>A <see cref="PlaylistIdCommand" />.</returns>
public IMpcCommand<IEnumerable<IMpdFile>> GetSongMetadata(int songId)
{
return new PlaylistIdCommand(songId);
}
/// <summary>
/// Command: playlistinfo
/// </summary>
/// <returns>A <see cref="PlaylistInfoCommand" />.</returns>
public IMpcCommand<IEnumerable<IMpdFile>> GetAllSongMetadata()
{
return new PlaylistInfoCommand();
}
}
}

View File

@ -0,0 +1,36 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="FindCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Database
{
using System.Collections.Generic;
using MpcNET.Tags;
using MpcNET.Types;
/// <summary>
/// Finds songs in the database that is exactly "searchText".
/// </summary>
internal class FindCommand : IMpcCommand<IEnumerable<IMpdFile>>
{
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<IMpdFile> Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
return MpdFile.CreateList(response);
}
}
// TODO: rescan
}

View File

@ -1,18 +1,23 @@
using System.Collections.Generic;
using System.Linq;
using MpcNET.Types;
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ListAllCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Database
{
using System.Collections.Generic;
using System.Linq;
using MpcNET.Types;
/// <summary>
/// Lists all songs and directories in URI.
/// </summary>
internal class ListAllCommand : IMpcCommand<IEnumerable<MpdDirectory>>
{
public string Value => "listall";
public string Serialize() => "listall";
public IEnumerable<MpdDirectory> FormatResponse(IList<KeyValuePair<string, string>> response)
public IEnumerable<MpdDirectory> Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
var rootDirectory = new List<MpdDirectory>
{

View File

@ -0,0 +1,31 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ListCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Database
{
using System.Collections.Generic;
using MpcNET.Tags;
internal class ListCommand : IMpcCommand<string>
{
private readonly ITag tag;
public ListCommand(ITag tag)
{
this.tag = tag;
}
public string Serialize() => string.Join(" ", "list", this.tag);
public string Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
// TODO:
return response.ToString();
}
}
// TODO: rescan
}

View File

@ -0,0 +1,46 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UpdateCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Database
{
using System.Collections.Generic;
internal class UpdateCommand : IMpcCommand<string>
{
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<KeyValuePair<string, string>> response)
{
return string.Join(", ", response);
}
}
}

View File

@ -0,0 +1,52 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="DatabaseCommandFactory.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands
{
using System.Collections.Generic;
using MpcNET.Commands.Database;
using MpcNET.Tags;
using MpcNET.Types;
/// <summary>
/// https://www.musicpd.org/doc/protocol/database.html
/// </summary>
public class DatabaseCommandFactory : IDatabaseCommandFactory
{
/// <summary>
/// Finds the specified tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <param name="searchText">The search text.</param>
/// <returns>An <see cref="FindCommand"/>.</returns>
public IMpcCommand<IEnumerable<IMpdFile>> Find(ITag tag, string searchText)
{
return new FindCommand(tag, searchText);
}
/// <summary>
/// Updates the specified URI.
/// </summary>
/// <param name="uri">The URI.</param>
/// <returns>An <see cref="UpdateCommand"/>.</returns>
public IMpcCommand<string> Update(string uri = null)
{
return new UpdateCommand(uri);
}
/// <summary>
/// Lists all.
/// </summary>
/// <returns>A <see cref="ListAllCommand"/>.</returns>
public IMpcCommand<IEnumerable<MpdDirectory>> ListAll()
{
return new ListAllCommand();
}
// TODO: count
// TODO: rescan
}
}

View File

@ -0,0 +1,71 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ICurrentPlaylistCommandFactory.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands
{
using System.Collections.Generic;
using MpcNET.Commands.Playlist;
using MpcNET.Types;
/// <summary>
/// Provides current playlist commands.
/// </summary>
public interface ICurrentPlaylistCommandFactory
{
/// <summary>
/// Command: add
/// </summary>
/// <param name="directory">The directory.</param>
/// <returns>An <see cref="AddCommand"/>.</returns>
IMpcCommand<string> AddDirectory(string directory);
/// <summary>
/// Command: addid
/// </summary>
/// <param name="songPath">The song path.</param>
/// <returns>An <see cref="AddIdCommand"/>.</returns>
IMpcCommand<string> AddSong(string songPath);
/// <summary>
/// Command: clear
/// </summary>
/// <returns>An <see cref="ClearCommand"/>.</returns>
IMpcCommand<string> Clear();
/// <summary>
/// Command: playlist
/// </summary>
/// <returns>A <see cref="PlaylistCommand"/>.</returns>
IMpcCommand<IEnumerable<IMpdFile>> GetAllSongsInfo();
/// <summary>
/// Command: delete
/// </summary>
/// <param name="position">The position.</param>
/// <returns>A <see cref="DeleteCommand" />.</returns>
IMpcCommand<string> RemoveSongByPosition(int position);
/// <summary>
/// Command: deleteid
/// </summary>
/// <param name="songId">The song identifier.</param>
/// <returns>A <see cref="DeleteIdCommand"/>.</returns>
IMpcCommand<string> RemoveSongById(int songId);
/// <summary>
/// Command: playlistid
/// </summary>
/// <param name="songId">The song identifier.</param>
/// <returns>A <see cref="PlaylistIdCommand" />.</returns>
IMpcCommand<IEnumerable<IMpdFile>> GetSongMetadata(int songId);
/// <summary>
/// Command: playlistinfo
/// </summary>
/// <returns>A <see cref="PlaylistInfoCommand" />.</returns>
IMpcCommand<IEnumerable<IMpdFile>> GetAllSongMetadata();
}
}

View File

@ -0,0 +1,40 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="IDatabaseCommandFactory.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands
{
using System.Collections.Generic;
using MpcNET.Commands.Database;
using MpcNET.Tags;
using MpcNET.Types;
/// <summary>
/// Provides database commands.
/// </summary>
public interface IDatabaseCommandFactory
{
/// <summary>
/// Finds the specified tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <param name="searchText">The search text.</param>
/// <returns>An <see cref="FindCommand"/>.</returns>
IMpcCommand<IEnumerable<IMpdFile>> Find(ITag tag, string searchText);
/// <summary>
/// Updates the specified URI.
/// </summary>
/// <param name="uri">The URI.</param>
/// <returns>An <see cref="UpdateCommand"/>.</returns>
IMpcCommand<string> Update(string uri = null);
/// <summary>
/// Lists all.
/// </summary>
/// <returns>A <see cref="ListAllCommand"/>.</returns>
IMpcCommand<IEnumerable<MpdDirectory>> ListAll();
}
}

View File

@ -0,0 +1,45 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="IOutputCommandFactory.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands
{
using System.Collections.Generic;
using MpcNET.Commands.Output;
using MpcNET.Types;
/// <summary>
/// Provides output commands.
/// </summary>
public interface IOutputCommandFactory
{
/// <summary>
/// Outputses this instance.
/// </summary>
/// <returns>An <see cref="OutputsCommand"/>.</returns>
IMpcCommand<IEnumerable<MpdOutput>> Outputs();
/// <summary>
/// Disables the output.
/// </summary>
/// <param name="outputId">The output identifier.</param>
/// <returns>A <see cref="DisableOutputCommand"/>.</returns>
IMpcCommand<string> DisableOutput(int outputId);
/// <summary>
/// Enables the output.
/// </summary>
/// <param name="outputId">The output identifier.</param>
/// <returns>A <see cref="EnableOutputCommand"/>.</returns>
IMpcCommand<string> EnableOutput(int outputId);
/// <summary>
/// Toggles the output.
/// </summary>
/// <param name="outputId">The output identifier.</param>
/// <returns>A <see cref="ToggleOutputCommand"/>.</returns>
IMpcCommand<string> ToggleOutput(int outputId);
}
}

View File

@ -0,0 +1,71 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="IPlaybackCommandFactory.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands
{
using MpcNET.Commands.Playback;
using MpcNET.Types;
/// <summary>
/// Provides playback commands.
/// </summary>
public interface IPlaybackCommandFactory
{
/// <summary>
/// Get a next command.
/// </summary>
/// <returns>A <see cref="NextCommand"/>.</returns>
IMpcCommand<string> Next();
/// <summary>
/// Get a previous command.
/// </summary>
/// <returns>A <see cref="StopCommand"/>.</returns>
IMpcCommand<string> Previous();
/// <summary>
/// Gets a play-pause command.
/// </summary>
/// <returns>A <see cref="PlayPauseCommand"/>.</returns>
IMpcCommand<string> PlayPause();
/// <summary>
/// Gets a play command.
/// </summary>
/// <param name="mpdFile">The MPD file.</param>
/// <returns>A <see cref="PlayCommand"/>.</returns>
IMpcCommand<string> Play(IMpdFile mpdFile);
/// <summary>
/// Gets a play command.
/// </summary>
/// <param name="position">The position.</param>
/// <returns>A <see cref="PlayCommand"/>.</returns>
IMpcCommand<string> Play(int position);
/// <summary>
/// Gets a play command.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>A <see cref="PlayCommand"/>.</returns>
IMpcCommand<string> PlayId(int id);
/// <summary>
/// Gets a stop command.
/// </summary>
/// <returns>A <see cref="StopCommand"/>.</returns>
IMpcCommand<string> Stop();
/// <summary>
/// Sets the volume.
/// </summary>
/// <param name="volume">The volume.</param>
/// <returns>
/// A <see cref="SetVolumeCommand" />.
/// </returns>
IMpcCommand<string> SetVolume(byte volume);
}
}

View File

@ -0,0 +1,42 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="IReflectionCommandFactory.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands
{
using System.Collections.Generic;
using MpcNET.Commands.Reflection;
using MpcNET.Types;
/// <summary>
/// Provides reflection commands.
/// </summary>
public interface IReflectionCommandFactory
{
/// <summary>
/// Gets a commands command.
/// </summary>
/// <returns>A <see cref="CommandsCommand"/>.</returns>
IMpcCommand<IEnumerable<string>> Commands();
/// <summary>
/// Gets a tag types command.
/// </summary>
/// <returns>A <see cref="TagTypesCommand"/>.</returns>
IMpcCommand<IEnumerable<string>> TagTypes();
/// <summary>
/// Gets URL handlers command.
/// </summary>
/// <returns>A <see cref="UrlHandlersCommand"/>.</returns>
IMpcCommand<IEnumerable<string>> UrlHandlers();
/// <summary>
/// Gets a decoders command.
/// </summary>
/// <returns>A <see cref="DecodersCommand"/>.</returns>
IMpcCommand<IEnumerable<MpdDecoderPlugin>> Decoders();
}
}

View File

@ -0,0 +1,29 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="IStatusCommandFactory.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands
{
using MpcNET.Commands.Status;
using MpcNET.Types;
/// <summary>
/// Provides status commands.
/// </summary>
public interface IStatusCommandFactory
{
/// <summary>
/// Gets a status command.
/// </summary>
/// <returns>A <see cref="StatusCommand"/>.</returns>
IMpcCommand<MpdStatus> GetStatus();
/// <summary>
/// Gets a current song command.
/// </summary>
/// <returns>A <see cref="CurrentSongCommand"/>.</returns>
IMpcCommand<IMpdFile> GetCurrentSong();
}
}

View File

@ -0,0 +1,45 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="IStoredPlaylistCommandFactory.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands
{
using System.Collections.Generic;
using MpcNET.Commands.Playlist;
using MpcNET.Types;
/// <summary>
/// Provides stored playlist commands.
/// </summary>
public interface IStoredPlaylistCommandFactory
{
/// <summary>
/// Command: load
/// </summary>
/// <param name="playlistName">Name of the playlist.</param>
/// <returns>A <see cref="LoadCommand" />.</returns>
IMpcCommand<string> Load(string playlistName);
/// <summary>
/// Command: listplaylist
/// </summary>
/// <param name="playlistName">Name of the playlist.</param>
/// <returns>A <see cref="ListPlaylistCommand" />.</returns>
IMpcCommand<IEnumerable<IMpdFilePath>> GetContent(string playlistName);
/// <summary>
/// Command: listplaylistinfo
/// </summary>
/// <param name="playlistName">Name of the playlist.</param>
/// <returns>A <see cref="ListPlaylistInfoCommand" />.</returns>
IMpcCommand<IEnumerable<IMpdFile>> GetContentWithMetadata(string playlistName);
/// <summary>
/// Command: listplaylists
/// </summary>
/// <returns>A <see cref="ListPlaylistsCommand" />.</returns>
IMpcCommand<IEnumerable<MpdPlaylist>> GetAll();
}
}

View File

@ -0,0 +1,31 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="DisableOutputCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Output
{
using System.Collections.Generic;
/// <summary>
/// Turns an output off.
/// </summary>
internal class DisableOutputCommand : IMpcCommand<string>
{
private readonly int outputId;
public DisableOutputCommand(int outputId)
{
this.outputId = outputId;
}
public string Serialize() => string.Join(" ", "disableoutput", this.outputId);
public string Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
// Response should be empty.
return string.Join(", ", response);
}
}
}

View File

@ -0,0 +1,31 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="EnableOutputCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Output
{
using System.Collections.Generic;
/// <summary>
/// Turns an output on.
/// </summary>
internal class EnableOutputCommand : IMpcCommand<string>
{
private readonly int outputId;
public EnableOutputCommand(int outputId)
{
this.outputId = outputId;
}
public string Serialize() => string.Join(" ", "enableoutput", this.outputId);
public string Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
// Response should be empty.
return string.Join(", ", response);
}
}
}

View File

@ -0,0 +1,35 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="OutputsCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Output
{
using System.Collections.Generic;
using MpcNET.Types;
/// <summary>
/// Shows information about all outputs.
/// </summary>
internal class OutputsCommand : IMpcCommand<IEnumerable<MpdOutput>>
{
public string Serialize() => "outputs";
public IEnumerable<MpdOutput> Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
var result = new List<MpdOutput>();
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;
}
}
}

View File

@ -0,0 +1,30 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ToggleOutputCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Output
{
using System.Collections.Generic;
/// <summary>
/// Turns an output on or off, depending on the current state.
/// </summary>
internal class ToggleOutputCommand : IMpcCommand<string>
{
private readonly int outputId;
public ToggleOutputCommand(int outputId)
{
this.outputId = outputId;
}
public string Serialize() => string.Join(" ", "toggleoutput", this.outputId);
public string Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
return string.Join(", ", response);
}
}
}

View File

@ -0,0 +1,57 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="OutputCommandFactory.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands
{
using System.Collections.Generic;
using MpcNET.Commands.Output;
using MpcNET.Types;
/// <summary>
/// https://www.musicpd.org/doc/protocol/output_commands.html
/// </summary>
public class OutputCommandFactory : IOutputCommandFactory
{
/// <summary>
/// Outputses this instance.
/// </summary>
/// <returns>An <see cref="OutputsCommand"/>.</returns>
public IMpcCommand<IEnumerable<MpdOutput>> Outputs()
{
return new OutputsCommand();
}
/// <summary>
/// Disables the output.
/// </summary>
/// <param name="outputId">The output identifier.</param>
/// <returns>A <see cref="DisableOutputCommand"/>.</returns>
public IMpcCommand<string> DisableOutput(int outputId)
{
return new DisableOutputCommand(outputId);
}
/// <summary>
/// Enables the output.
/// </summary>
/// <param name="outputId">The output identifier.</param>
/// <returns>A <see cref="EnableOutputCommand"/>.</returns>
public IMpcCommand<string> EnableOutput(int outputId)
{
return new EnableOutputCommand(outputId);
}
/// <summary>
/// Toggles the output.
/// </summary>
/// <param name="outputId">The output identifier.</param>
/// <returns>A <see cref="ToggleOutputCommand"/>.</returns>
public IMpcCommand<string> ToggleOutput(int outputId)
{
return new ToggleOutputCommand(outputId);
}
}
}

View File

@ -0,0 +1,20 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="NextCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Playback
{
using System.Collections.Generic;
internal class NextCommand : IMpcCommand<string>
{
public string Serialize() => string.Join(" ", "next");
public string Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
return string.Join(", ", response);
}
}
}

View File

@ -0,0 +1,43 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="PlayCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Playback
{
using System;
using System.Collections.Generic;
using MpcNET.Types;
internal class PlayCommand : IMpcCommand<string>
{
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<KeyValuePair<string, string>> response)
{
return string.Join(", ", response);
}
}
}

View File

@ -0,0 +1,20 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="PlayPauseCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Playback
{
using System.Collections.Generic;
internal class PlayPauseCommand : IMpcCommand<string>
{
public string Serialize() => string.Join(" ", "pause");
public string Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
return string.Join(", ", response);
}
}
}

View File

@ -0,0 +1,20 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="PreviousCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Playback
{
using System.Collections.Generic;
internal class PreviousCommand : IMpcCommand<string>
{
public string Serialize() => string.Join(" ", "previous");
public string Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
return string.Join(", ", response);
}
}
}

View File

@ -0,0 +1,31 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="SetVolumeCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Playback
{
using System.Collections.Generic;
internal class SetVolumeCommand : IMpcCommand<string>
{
private readonly byte volume;
public SetVolumeCommand(byte volume)
{
this.volume = volume;
}
public string Serialize()
{
return string.Join(" ", "setvol", this.volume);
}
public string Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
return string.Join(", ", response);
}
}
}

View File

@ -0,0 +1,20 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="StopCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Playback
{
using System.Collections.Generic;
internal class StopCommand : IMpcCommand<string>
{
public string Serialize() => string.Join(" ", "stop");
public string Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
return string.Join(", ", response);
}
}
}

View File

@ -0,0 +1,95 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="PlaybackCommandFactory.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands
{
using MpcNET.Commands.Playback;
using MpcNET.Types;
/// <summary>
/// https://www.musicpd.org/doc/protocol/playback_commands.html
/// </summary>
public class PlaybackCommandFactory : IPlaybackCommandFactory
{
/// <summary>
/// Get a next command.
/// </summary>
/// <returns>A <see cref="NextCommand"/>.</returns>
public IMpcCommand<string> Next()
{
return new NextCommand();
}
/// <summary>
/// Get a previous command.
/// </summary>
/// <returns>A <see cref="StopCommand"/>.</returns>
public IMpcCommand<string> Previous()
{
return new PreviousCommand();
}
/// <summary>
/// Gets a play-pause command.
/// </summary>
/// <returns>A <see cref="PlayPauseCommand"/>.</returns>
public IMpcCommand<string> PlayPause()
{
return new PlayPauseCommand();
}
/// <summary>
/// Gets a play command.
/// </summary>
/// <param name="mpdFile">The MPD file.</param>
/// <returns>A <see cref="PlayCommand"/>.</returns>
public IMpcCommand<string> Play(IMpdFile mpdFile)
{
return new PlayCommand(mpdFile.Id, mpdFile.Position);
}
/// <summary>
/// Gets a play command.
/// </summary>
/// <param name="position">The position.</param>
/// <returns>A <see cref="PlayCommand"/>.</returns>
public IMpcCommand<string> Play(int position)
{
return new PlayCommand(position, MpdFile.NoId);
}
/// <summary>
/// Gets a play command.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>A <see cref="PlayCommand"/>.</returns>
public IMpcCommand<string> PlayId(int id)
{
return new PlayCommand(MpdFile.NoPos, id);
}
/// <summary>
/// Gets a stop command.
/// </summary>
/// <returns>A <see cref="StopCommand"/>.</returns>
public IMpcCommand<string> Stop()
{
return new StopCommand();
}
/// <summary>
/// Sets the volume.
/// </summary>
/// <param name="volume">The volume.</param>
/// <returns>
/// A <see cref="T:MpcNET.Commands.Playback.SetVolumeCommand" />.
/// </returns>
public IMpcCommand<string> SetVolume(byte volume)
{
return new SetVolumeCommand(volume);
}
}
}

View File

@ -0,0 +1,30 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="AddCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Playlist
{
using System.Collections.Generic;
/// <summary>
/// Adds the file URI to the playlist (directories add recursively). URI can also be a single file.
/// </summary>
internal class AddCommand : IMpcCommand<string>
{
private readonly string uri;
public AddCommand(string uri)
{
this.uri = uri;
}
public string Serialize() => string.Join(" ", "add", $"\"{this.uri}\"");
public string Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
return string.Join(", ", response);
}
}
}

View File

@ -0,0 +1,30 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="AddIdCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Playlist
{
using System.Collections.Generic;
/// <summary>
/// Adds a song to the playlist (non-recursive) and returns the song id.
/// </summary>
internal class AddIdCommand : IMpcCommand<string>
{
private readonly string uri;
public AddIdCommand(string uri)
{
this.uri = uri;
}
public string Serialize() => string.Join(" ", "addid", $"\"{this.uri}\"");
public string Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
return string.Join(", ", response);
}
}
}

View File

@ -0,0 +1,23 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ClearCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Playlist
{
using System.Collections.Generic;
/// <summary>
/// Clears the current playlist.
/// </summary>
internal class ClearCommand : IMpcCommand<string>
{
public string Serialize() => "clear";
public string Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
return string.Join(", ", response);
}
}
}

View File

@ -0,0 +1,30 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="DeleteCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Playlist
{
using System.Collections.Generic;
/// <summary>
/// Deletes a song from the playlist.
/// </summary>
internal class DeleteCommand : IMpcCommand<string>
{
private readonly int position;
public DeleteCommand(int position)
{
this.position = position;
}
public string Serialize() => string.Join(" ", "delete", this.position);
public string Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
return string.Join(", ", response);
}
}
}

View File

@ -0,0 +1,30 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="DeleteIdCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Playlist
{
using System.Collections.Generic;
/// <summary>
/// Deletes the song SONGID from the playlist
/// </summary>
internal class DeleteIdCommand : IMpcCommand<string>
{
private readonly int songId;
public DeleteIdCommand(int songId)
{
this.songId = songId;
}
public string Serialize() => string.Join(" ", "deleteid", this.songId);
public string Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
return string.Join(", ", response);
}
}
}

View File

@ -0,0 +1,34 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ListPlaylistCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Playlist
{
using System.Collections.Generic;
using System.Linq;
using MpcNET.Types;
/// <summary>
/// Lists the songs in the playlist.
/// </summary>
internal class ListPlaylistCommand : IMpcCommand<IEnumerable<IMpdFilePath>>
{
private readonly string playlistName;
public ListPlaylistCommand(string playlistName)
{
this.playlistName = playlistName;
}
public string Serialize() => string.Join(" ", "listplaylist", $"\"{this.playlistName}\"");
public IEnumerable<IMpdFilePath> Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
var results = response.Where(line => line.Key.Equals("file")).Select(line => new MpdFile(line.Value));
return results;
}
}
}

View File

@ -0,0 +1,31 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ListPlaylistInfoCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Playlist
{
using System.Collections.Generic;
using MpcNET.Types;
/// <summary>
/// Lists the songs with metadata in the playlist.
/// </summary>
internal class ListPlaylistInfoCommand : IMpcCommand<IEnumerable<IMpdFile>>
{
private readonly string playlistName;
public ListPlaylistInfoCommand(string playlistName)
{
this.playlistName = playlistName;
}
public string Serialize() => string.Join(" ", "listplaylistinfo", $"\"{this.playlistName}\"");
public IEnumerable<IMpdFile> Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
return MpdFile.CreateList(response);
}
}
}

View File

@ -0,0 +1,39 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ListPlaylistsCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Playlist
{
using System.Collections.Generic;
using System.Linq;
using MpcNET.Types;
/// <summary>
/// Prints a list of the playlist directory.
/// </summary>
internal class ListPlaylistsCommand : IMpcCommand<IEnumerable<MpdPlaylist>>
{
public string Serialize() => "listplaylists";
public IEnumerable<MpdPlaylist> Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
var result = new List<MpdPlaylist>();
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;
}
}
}

View File

@ -0,0 +1,30 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="LoadCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Playlist
{
using System.Collections.Generic;
/// <summary>
/// Loads the playlist into the current queue.
/// </summary>
internal class LoadCommand : IMpcCommand<string>
{
private readonly string playlistName;
public LoadCommand(string playlistName)
{
this.playlistName = playlistName;
}
public string Serialize() => string.Join(" ", "load", $"\"{this.playlistName}\"");
public string Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
return string.Join(", ", response);
}
}
}

View File

@ -0,0 +1,27 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="PlaylistCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Playlist
{
using System.Collections.Generic;
using System.Linq;
using MpcNET.Types;
/// <summary>
/// Displays the current playlist.
/// </summary>
internal class PlaylistCommand : IMpcCommand<IEnumerable<IMpdFile>>
{
public string Serialize() => "playlist";
public IEnumerable<IMpdFile> Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
var results = response.Select(line => MpdFile.Create(line.Value, int.Parse(line.Key)));
return results;
}
}
}

View File

@ -0,0 +1,31 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="PlaylistIdCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Playlist
{
using System.Collections.Generic;
using MpcNET.Types;
/// <summary>
/// Displays song ID in the playlist.
/// </summary>
internal class PlaylistIdCommand : IMpcCommand<IEnumerable<IMpdFile>>
{
private readonly int songId;
public PlaylistIdCommand(int songId)
{
this.songId = songId;
}
public string Serialize() => string.Join(" ", new[] { "playlistid" }, this.songId);
public IEnumerable<IMpdFile> Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
return MpdFile.CreateList(response);
}
}
}

View File

@ -0,0 +1,24 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="PlaylistInfoCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Playlist
{
using System.Collections.Generic;
using MpcNET.Types;
/// <summary>
/// Displays a list of all songs in the playlist,
/// </summary>
internal class PlaylistInfoCommand : IMpcCommand<IEnumerable<IMpdFile>>
{
public string Serialize() => "playlistinfo";
public IEnumerable<IMpdFile> Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
return MpdFile.CreateList(response);
}
}
}

View File

@ -0,0 +1,27 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CommandsCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Reflection
{
using System.Collections.Generic;
using System.Linq;
/// <summary>
/// Shows which commands the current user has access to.
/// config : This command is only permitted to "local" clients (connected via UNIX domain socket).
/// </summary>
internal class CommandsCommand : IMpcCommand<IEnumerable<string>>
{
public string Serialize() => "commands";
public IEnumerable<string> Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
var result = response.Where(item => item.Key.Equals("command")).Select(item => item.Value);
return result;
}
}
}

View File

@ -1,16 +1,22 @@
using System.Collections.Generic;
using MpcNET.Types;
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="DecodersCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Reflection
{
using System.Collections.Generic;
using MpcNET.Types;
/// <summary>
/// Print a list of decoder plugins, followed by their supported suffixes and MIME types.
/// </summary>
public class DecodersCommand : IMpcCommand<IEnumerable<MpdDecoderPlugin>>
internal class DecodersCommand : IMpcCommand<IEnumerable<MpdDecoderPlugin>>
{
public string Value => "decoders";
public string Serialize() => "decoders";
public IEnumerable<MpdDecoderPlugin> FormatResponse(IList<KeyValuePair<string, string>> response)
public IEnumerable<MpdDecoderPlugin> Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
var result = new List<MpdDecoderPlugin>();

View File

@ -0,0 +1,28 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="TagTypesCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Reflection
{
using System.Collections.Generic;
using System.Linq;
// TODO: notcommands : Shows which commands the current user does not have access to.
/// <summary>
/// Shows a list of available song metadata.
/// </summary>
internal class TagTypesCommand : IMpcCommand<IEnumerable<string>>
{
public string Serialize() => "tagtypes";
public IEnumerable<string> Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
var result = response.Where(item => item.Key.Equals("tagtype")).Select(item => item.Value);
return result;
}
}
}

View File

@ -0,0 +1,26 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UrlHandlersCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Reflection
{
using System.Collections.Generic;
using System.Linq;
/// <summary>
/// Gets a list of available URL handlers.
/// </summary>
internal class UrlHandlersCommand : IMpcCommand<IEnumerable<string>>
{
public string Serialize() => "urlhandlers";
public IEnumerable<string> Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
var result = response.Where(item => item.Key.Equals("handler")).Select(item => item.Value);
return result;
}
}
}

View File

@ -0,0 +1,54 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ReflectionCommandFactory.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands
{
using System.Collections.Generic;
using MpcNET.Commands.Reflection;
using MpcNET.Types;
/// <summary>
/// https://www.musicpd.org/doc/protocol/reflection_commands.html
/// </summary>
public class ReflectionCommandFactory : IReflectionCommandFactory
{
/// <summary>
/// Gets a commands command.
/// </summary>
/// <returns>A <see cref="CommandsCommand"/>.</returns>
public IMpcCommand<IEnumerable<string>> Commands()
{
return new CommandsCommand();
}
/// <summary>
/// Gets a tag types command.
/// </summary>
/// <returns>A <see cref="TagTypesCommand"/>.</returns>
public IMpcCommand<IEnumerable<string>> TagTypes()
{
return new TagTypesCommand();
}
/// <summary>
/// Gets URL handlers command.
/// </summary>
/// <returns>A <see cref="UrlHandlersCommand"/>.</returns>
public IMpcCommand<IEnumerable<string>> UrlHandlers()
{
return new UrlHandlersCommand();
}
/// <summary>
/// Gets a decoders command.
/// </summary>
/// <returns>A <see cref="DecodersCommand"/>.</returns>
public IMpcCommand<IEnumerable<MpdDecoderPlugin>> Decoders()
{
return new DecodersCommand();
}
}
}

View File

@ -0,0 +1,21 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CurrentSongCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Status
{
using System.Collections.Generic;
using MpcNET.Types;
internal class CurrentSongCommand : IMpcCommand<IMpdFile>
{
public string Serialize() => "currentsong";
public IMpdFile Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
return MpdFile.Create(response, 0).mpdFile;
}
}
}

View File

@ -0,0 +1,35 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="IdleCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Status
{
using System.Collections.Generic;
internal class IdleCommand : IMpcCommand<string>
{
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<KeyValuePair<string, string>> response)
{
return string.Join(", ", response);
}
}
}

View File

@ -0,0 +1,20 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="NoIdleCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Status
{
using System.Collections.Generic;
internal class NoIdleCommand : IMpcCommand<string>
{
public string Serialize() => "noidle";
public string Deserialize(IReadOnlyList<KeyValuePair<string, string>> response)
{
return string.Join(", ", response);
}
}
}

View File

@ -1,14 +1,41 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="StatusCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands.Status
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
internal class StatusCommand : IMpcCommand<MpdStatus>
{
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<KeyValuePair<string, string>> response)
public string Serialize() => "status";
public MpdStatus Deserialize(IReadOnlyList<KeyValuePair<string, string>> 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,

View File

@ -0,0 +1,35 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="StatusCommandFactory.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands
{
using MpcNET.Commands.Status;
using MpcNET.Types;
/// <summary>
/// https://www.musicpd.org/doc/protocol/command_reference.html#status_commands
/// </summary>
public class StatusCommandFactory : IStatusCommandFactory
{
/// <summary>
/// Gets a status command.
/// </summary>
/// <returns>A <see cref="StatusCommand"/>.</returns>
public IMpcCommand<MpdStatus> GetStatus()
{
return new StatusCommand();
}
/// <summary>
/// Gets a current song command.
/// </summary>
/// <returns>A <see cref="CurrentSongCommand"/>.</returns>
public IMpcCommand<IMpdFile> GetCurrentSong()
{
return new CurrentSongCommand();
}
}
}

View File

@ -0,0 +1,57 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="StoredPlaylistCommandFactory.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Commands
{
using System.Collections.Generic;
using MpcNET.Commands.Playlist;
using MpcNET.Types;
/// <summary>
/// https://www.musicpd.org/doc/protocol/playlist_files.html
/// </summary>
public class StoredPlaylistCommandFactory : IStoredPlaylistCommandFactory
{
/// <summary>
/// Command: load
/// </summary>
/// <param name="playlistName">Name of the playlist.</param>
/// <returns>A <see cref="LoadCommand" />.</returns>
public IMpcCommand<string> Load(string playlistName)
{
return new LoadCommand(playlistName);
}
/// <summary>
/// Command: listplaylist
/// </summary>
/// <param name="playlistName">Name of the playlist.</param>
/// <returns>A <see cref="ListPlaylistCommand" />.</returns>
public IMpcCommand<IEnumerable<IMpdFilePath>> GetContent(string playlistName)
{
return new ListPlaylistCommand(playlistName);
}
/// <summary>
/// Command: listplaylistinfo
/// </summary>
/// <param name="playlistName">Name of the playlist.</param>
/// <returns>A <see cref="ListPlaylistInfoCommand" />.</returns>
public IMpcCommand<IEnumerable<IMpdFile>> GetContentWithMetadata(string playlistName)
{
return new ListPlaylistInfoCommand(playlistName);
}
/// <summary>
/// Command: listplaylists
/// </summary>
/// <returns>A <see cref="ListPlaylistsCommand" />.</returns>
public IMpcCommand<IEnumerable<MpdPlaylist>> GetAll()
{
return new ListPlaylistsCommand();
}
}
}

View File

@ -0,0 +1,17 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Constants.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET
{
internal class Constants
{
public static readonly string Ok = "OK";
public static readonly string Ack = "ACK";
public static readonly string FirstLinePrefix = "OK MPD ";
}
}

View File

@ -0,0 +1,20 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CommandNullException.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Exceptions
{
/// <summary>
/// Thrown by <see cref="MpcConnection"/> when the command is null.
/// </summary>
/// <seealso cref="System.Exception" />
public class CommandNullException : MpcException
{
internal CommandNullException()
: base("No command was specified")
{
}
}
}

View File

@ -0,0 +1,26 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="EmptyResponseException.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Exceptions
{
using System;
/// <summary>
/// Exception throw when an empty response is received.
/// </summary>
/// <seealso cref="Exception" />
public class EmptyResponseException : MpcException
{
/// <summary>
/// Initializes a new instance of the <see cref="EmptyResponseException"/> class.
/// </summary>
/// <param name="command">The command.</param>
public EmptyResponseException(string command)
: base($"The command: {command} returned no response")
{
}
}
}

View File

@ -0,0 +1,26 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="MpcConnectException.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Exceptions
{
using System;
/// <summary>
/// Exception thrown when there are problems with the <see cref="MpcConnection"/>.
/// </summary>
/// <seealso cref="Exception" />
public class MpcConnectException : MpcException
{
/// <summary>
/// Initializes a new instance of the <see cref="MpcConnectException"/> class.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public MpcConnectException(string message)
: base(message)
{
}
}
}

View File

@ -0,0 +1,26 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="MpcException.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Exceptions
{
using System;
/// <summary>
/// Base class for all exceptions.
/// </summary>
/// <seealso cref="System.Exception" />
public class MpcException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="MpcException" /> class.
/// </summary>
/// <param name="message">The message.</param>
public MpcException(string message)
: base(message)
{
}
}
}

View File

@ -0,0 +1,72 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ICommandFactory.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET
{
using MpcNET.Commands;
/// <summary>
/// Interface for providing specific command factories.
/// </summary>
public interface ICommandFactory
{
/// <summary>
/// Gets the status command factory.
/// </summary>
/// <value>
/// The status.
/// </value>
IStatusCommandFactory Status { get; }
/// <summary>
/// Gets the database command factory.
/// </summary>
/// <value>
/// The database.
/// </value>
IDatabaseCommandFactory Database { get; }
/// <summary>
/// Gets the reflection command factory.
/// </summary>
/// <value>
/// The reflection.
/// </value>
IReflectionCommandFactory Reflection { get; }
/// <summary>
/// Gets the stored playlist command factory.
/// </summary>
/// <value>
/// The stored playlist.
/// </value>
IStoredPlaylistCommandFactory StoredPlaylist { get; }
/// <summary>
/// Gets the current playlist command factory.
/// </summary>
/// <value>
/// The current playlist.
/// </value>
ICurrentPlaylistCommandFactory CurrentPlaylist { get; }
/// <summary>
/// Gets the playback command factory.
/// </summary>
/// <value>
/// The playback.
/// </value>
IPlaybackCommandFactory Playback { get; }
/// <summary>
/// Gets the output command factory.
/// </summary>
/// <value>
/// The output.
/// </value>
IOutputCommandFactory Output { get; }
}
}

View File

@ -0,0 +1,30 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="IMpcCommand.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET
{
using System.Collections.Generic;
/// <summary>
/// Interface for implementing a MPD command.
/// </summary>
/// <typeparam name="TValue">The type of the value.</typeparam>
public interface IMpcCommand<out TValue>
{
/// <summary>
/// Serializes the command.
/// </summary>
/// <returns>The serialize command.</returns>
string Serialize();
/// <summary>
/// Deserializes the specified response text pairs.
/// </summary>
/// <param name="response">The response.</param>
/// <returns>The deserialized response.</returns>
TValue Deserialize(IReadOnlyList<KeyValuePair<string, string>> response);
}
}

View File

@ -0,0 +1,45 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="IMpcConnection.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET
{
using System;
using System.Threading.Tasks;
using MpcNET.Message;
/// <summary>
/// Interface for implementing an MPD connection.
/// </summary>
/// <seealso cref="System.IDisposable" />
public interface IMpcConnection : IDisposable
{
/// <summary>
/// Gets the version.
/// </summary>
string Version { get; }
/// <summary>
/// Connects asynchronously.
/// </summary>
/// <returns>The connect task.</returns>
Task ConnectAsync();
/// <summary>
/// Disconnects asynchronously.
/// </summary>
/// <returns>The disconnect task.</returns>
Task DisconnectAsync();
/// <summary>
/// Sends the command asynchronously.
/// </summary>
/// <typeparam name="TResponse">The response type.</typeparam>
/// <param name="commandSelector">The command selector.</param>
/// <returns>The send task.</returns>
Task<IMpdMessage<TResponse>> SendAsync<TResponse>(Func<ICommandFactory, IMpcCommand<TResponse>> commandSelector);
}
}

View File

@ -0,0 +1,77 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="IMpcConnectionObserver.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET
{
using System;
/// <summary>
/// Interface for implementing an observer for <see cref="MpcConnection"/>.
/// </summary>
public interface IMpcConnectionObserver
{
/// <summary>
/// Called when connecting.
/// </summary>
/// <param name="isReconnect">if set to <c>true</c> [is reconnect].</param>
/// <param name="connectAttempt">The connect attempt.</param>
void Connecting(bool isReconnect, int connectAttempt);
/// <summary>
/// Called when connection is accepted.
/// </summary>
/// <param name="isReconnect">if set to <c>true</c> [is reconnect].</param>
/// <param name="connectAttempt">The connect attempt.</param>
void ConnectionAccepted(bool isReconnect, int connectAttempt);
/// <summary>
/// Called when connected.
/// </summary>
/// <param name="isReconnect">if set to <c>true</c> [is reconnect].</param>
/// <param name="connectAttempt">The connect attempt.</param>
/// <param name="connectionInfo">The connection information.</param>
void Connected(bool isReconnect, int connectAttempt, string connectionInfo);
/// <summary>
/// Called when sending command.
/// </summary>
/// <param name="command">The command.</param>
void Sending(string command);
/// <summary>
/// Called when send exception occured.
/// </summary>
/// <param name="commandText">The command text.</param>
/// <param name="sendAttempt">The send attempt.</param>
/// <param name="exception">The exception.</param>
void SendException(string commandText, int sendAttempt, Exception exception);
/// <summary>
/// Called when send is retried.
/// </summary>
/// <param name="command">The command.</param>
/// <param name="sendAttempt">The send attempt.</param>
void RetrySend(string command, int sendAttempt);
/// <summary>
/// Called when response is read.
/// </summary>
/// <param name="responseLine">The response line.</param>
void ReadResponse(string responseLine);
/// <summary>
/// Called when disconnecting.
/// </summary>
/// <param name="isExplicitDisconnect">if set to <c>true</c> the disconnect was explicitly called.</param>
void Disconnecting(bool isExplicitDisconnect);
/// <summary>
/// Called when disconnected.
/// </summary>
/// <param name="isExplicitDisconnect">if set to <c>true</c> the disconnect was explicitly called.</param>
void Disconnected(bool isExplicitDisconnect);
}
}

View File

@ -0,0 +1,23 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ErrorMpdMessage.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Message
{
internal class ErrorMpdMessage<T> : IMpdMessage<T>
{
public ErrorMpdMessage(IMpcCommand<T> command, ErrorMpdResponse<T> errorResponse)
{
this.Request = new MpdRequest<T>(command);
this.Response = errorResponse;
}
public IMpdRequest<T> Request { get; }
public IMpdResponse<T> Response { get; }
public bool IsResponseValid => false;
}
}

View File

@ -0,0 +1,44 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ErrorMpdResponse.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Message
{
using System;
/// <summary>
/// Implementation of <see cref="IMpdResponse{TContent}"/> in case of an error.
/// </summary>
/// <typeparam name="TContent">The content type.</typeparam>
/// <seealso cref="MpcNET.Message.IMpdResponse{T}" />
public class ErrorMpdResponse<TContent> : IMpdResponse<TContent>
{
/// <summary>
/// Initializes a new instance of the <see cref="ErrorMpdResponse{TContent}"/> class.
/// </summary>
/// <param name="exception">The exception.</param>
public ErrorMpdResponse(Exception exception)
{
this.Result = new MpdResponseResult(null, false, exception);
this.Content = default(TContent);
}
/// <summary>
/// Gets the state.
/// </summary>
/// <value>
/// The state.
/// </value>
public IMpdResponseResult Result { get; }
/// <summary>
/// Gets the content.
/// </summary>
/// <value>
/// The content.
/// </value>
public TContent Content { get; }
}
}

View File

@ -0,0 +1,39 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="IMpdMessage.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Message
{
/// <summary>
/// Interface for implementing MPD message.
/// </summary>
/// <typeparam name="TContent">The type of the content.</typeparam>
public interface IMpdMessage<TContent>
{
/// <summary>
/// Gets the request.
/// </summary>
/// <value>
/// The request.
/// </value>
IMpdRequest<TContent> Request { get; }
/// <summary>
/// Gets the response.
/// </summary>
/// <value>
/// The response.
/// </value>
IMpdResponse<TContent> Response { get; }
/// <summary>
/// Gets a value indicating whether this instance is response valid.
/// </summary>
/// <value>
/// <c>true</c> if this instance is response valid; otherwise, <c>false</c>.
/// </value>
bool IsResponseValid { get; }
}
}

View File

@ -0,0 +1,23 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="IMpdRequest.cs" company="Hukano">
// Copyright (c) Hukano. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MpcNET.Message
{
/// <summary>
/// Interface for implementing a MPD request.
/// </summary>
/// <typeparam name="TContent">The response content.</typeparam>
public interface IMpdRequest<out TContent>
{
/// <summary>
/// Gets the command.
/// </summary>
/// <value>
/// The command.
/// </value>
IMpcCommand<TContent> Command { get; }
}
}

Some files were not shown because too many files have changed in this diff Show More