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

Each command can format the mpd response. User response is a MpdMessage which conatins the requested command and the formatted response.

This commit is contained in:
glucaci 2016-12-06 18:01:28 +01:00
parent 9212021be6
commit 53325604e8
13 changed files with 250 additions and 270 deletions

View File

@ -1,4 +1,4 @@
using System;
using System.Collections.Generic;
namespace LibMpc
{
@ -11,7 +11,7 @@ namespace LibMpc
{
// TODO: count
public class Find : IMpcCommand
public class Find : IMpcCommand<string>
{
private readonly ITag _tag;
private readonly string _searchText;
@ -24,13 +24,13 @@ namespace LibMpc
public string Value => string.Join(" ", "find", _tag.Value, _searchText);
public object ParseResponse(object response)
public IReadOnlyDictionary<string, IList<string>> FormatResponse(IReadOnlyDictionary<string, IList<string>> response)
{
throw new NotImplementedException();
return response;
}
}
public class List : IMpcCommand
public class List : IMpcCommand<string>
{
private readonly ITag _tag;
@ -41,15 +41,15 @@ namespace LibMpc
public string Value => string.Join(" ", "list", _tag);
public object ParseResponse(object response)
public IReadOnlyDictionary<string, IList<string>> FormatResponse(IReadOnlyDictionary<string, IList<string>> response)
{
throw new NotImplementedException();
return response;
}
}
// TODO: findadd
public class ListAll : IMpcCommand
public class ListAll : IMpcCommand<string>
{
private readonly string _path;
@ -60,9 +60,9 @@ namespace LibMpc
public string Value => string.Join(" ", "listall", _path);
public object ParseResponse(object response)
public IReadOnlyDictionary<string, IList<string>> FormatResponse(IReadOnlyDictionary<string, IList<string>> response)
{
throw new NotImplementedException();
return response;
}
}
@ -74,13 +74,13 @@ namespace LibMpc
// TODO: searchadd
// TODO: searchaddpl
public class Update : IMpcCommand
public class Update : IMpcCommand<string>
{
public string Value => "update";
public object ParseResponse(object response)
public IReadOnlyDictionary<string, IList<string>> FormatResponse(IReadOnlyDictionary<string, IList<string>> response)
{
throw new NotImplementedException();
return response;
}
}

View File

@ -1,4 +1,6 @@
namespace LibMpc
using System.Collections.Generic;
namespace LibMpc
{
public partial class Commands
{
@ -10,7 +12,7 @@
/// <summary>
/// Turns an output off.
/// </summary>
public class DisableOutput : IMpcCommand
public class DisableOutput : IMpcCommand<string>
{
private readonly int _outputId;
@ -21,16 +23,16 @@
public string Value => string.Join(" ", "disableoutput", _outputId);
public object ParseResponse(object response)
public IReadOnlyDictionary<string, IList<string>> FormatResponse(IReadOnlyDictionary<string, IList<string>> response)
{
throw new System.NotImplementedException();
return response;
}
}
/// <summary>
/// Turns an output on.
/// </summary>
public class EnableOutput : IMpcCommand
public class EnableOutput : IMpcCommand<string>
{
private readonly int _outputId;
@ -41,9 +43,9 @@
public string Value => string.Join(" ", "enableoutput", _outputId);
public object ParseResponse(object response)
public IReadOnlyDictionary<string, IList<string>> FormatResponse(IReadOnlyDictionary<string, IList<string>> response)
{
throw new System.NotImplementedException();
return response;
}
}
@ -52,13 +54,27 @@
/// <summary>
/// Shows information about all outputs.
/// </summary>
public class Outputs : IMpcCommand
public class Outputs : IMpcCommand<Dictionary<string, string>>
{
public string Value => "outputs";
public object ParseResponse(object response)
public IReadOnlyDictionary<string, IList<Dictionary<string, string>>> FormatResponse(IReadOnlyDictionary<string, IList<string>> response)
{
throw new System.NotImplementedException();
var result = new Dictionary<string, IList<Dictionary<string, string>>>
{
{"outputs", new List<Dictionary<string, string>>()}
};
for (var i = 0; i < response["outputid"].Count; i++)
{
result["outputs"].Add(new Dictionary<string, string>
{
{ "id", response["outputid"][i] },
{ "name", response["outputname"][i] },
{ "enabled", response["outputenabled"][i] }
});
}
return result;
}
}
}

View File

@ -1,4 +1,6 @@
namespace LibMpc
using System.Collections.Generic;
namespace LibMpc
{
public partial class Commands
{
@ -11,13 +13,13 @@
// TODO: commands
// TODO: notcommands
public class TagTypes : IMpcCommand
public class TagTypes : IMpcCommand<string>
{
public string Value => "tagtypes";
public object ParseResponse(object response)
public IReadOnlyDictionary<string, IList<string>> FormatResponse(IReadOnlyDictionary<string, IList<string>> response)
{
throw new System.NotImplementedException();
return response;
}
}

View File

@ -1,10 +1,11 @@
using System.Collections.Generic;
namespace LibMpc
{
public interface IMpcCommand
public interface IMpcCommand<T>
{
string Value { get; }
// TODO: Return IMpdResponse and create type-safe input.
object ParseResponse(object response);
IReadOnlyDictionary<string, IList<T>> FormatResponse(IReadOnlyDictionary<string, IList<string>> response);
}
}

View File

@ -1,24 +1,69 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
namespace LibMpc
{
public interface IMpdMessage
public interface IMpdMessage<T>
{
IMpdRequest Request { get; }
IMpdResponse Response { get; }
IMpdRequest<T> Request { get; }
IMpdResponse<T> Response { get; }
}
public class MpdMessage : IMpdMessage
public class MpdMessage<T> : IMpdMessage<T>
{
public MpdMessage(IMpcCommand command)
private readonly Regex _linePattern = new Regex("^(?<key>[A-Za-z]*):[ ]{0,1}(?<value>.*)$");
private readonly IList<string> _rawResponse;
public MpdMessage(IMpcCommand<T> command, bool connected, IReadOnlyCollection<string> response)
{
Request = new MpdRequest(command);
Request = new MpdRequest<T>(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<T>(endLine, values, connected);
}
public void AddResponse(IMpdResponse response)
public IMpdRequest<T> Request { get; }
public IMpdResponse<T> Response { get; }
private IReadOnlyDictionary<string, IList<string>> GetValuesFromResponse()
{
Response = response;
var result = new Dictionary<string, IList<string>>();
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))
{
if (!result.ContainsKey(mpdKey))
{
result.Add(mpdKey, new List<string>() { mpdValue });
}
else
{
result[mpdKey].Add(mpdValue);
}
}
}
}
}
public IMpdRequest Request { get; }
public IMpdResponse Response { get; private set; }
return result;
}
public override string ToString()
{
return JsonConvert.SerializeObject(this, Formatting.Indented);
}
}
}

View File

@ -1,17 +1,17 @@
namespace LibMpc
{
public interface IMpdRequest
public interface IMpdRequest<T>
{
IMpcCommand Command { get; }
IMpcCommand<T> Command { get; }
}
public class MpdRequest : IMpdRequest
public class MpdRequest<T> : IMpdRequest<T>
{
public MpdRequest(IMpcCommand command)
public MpdRequest(IMpcCommand<T> command)
{
Command = command;
}
public IMpcCommand Command { get; }
public IMpcCommand<T> Command { get; }
}
}

View File

@ -1,63 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace LibMpc
{
public interface IMpdResponse
public interface IMpdResponse<T>
{
IEnumerable<string> Response { get; }
IReadOnlyDictionary<string, string> Values { get; }
IMpdResponseState State { get; }
IReadOnlyDictionary<string, IList<T>> Body { get; }
}
public class MpdResponse : IMpdResponse
public class MpdResponse<T> : IMpdResponse<T>
{
private static readonly Regex LinePattern = new Regex("^(?<key>[A-Za-z]*):[ ]{0,1}(?<value>.*)$");
public MpdResponse(ICollection<string> response)
public MpdResponse(string endLine, IReadOnlyDictionary<string, IList<T>> body, bool connected)
{
response.CheckNotNull();
var endLine = response.Take(response.Count - 2).Single();
Response = response.Take(response.Count - 2).ToList();
State = new MpdResponseState(endLine);
Values = GetValuesFromResponse();
State = new MpdResponseState(endLine, connected);
Body = body;
}
public IMpdResponseState State { get; }
public IEnumerable<string> Response { get; }
public IReadOnlyDictionary<string, string> Values { get; }
private IReadOnlyDictionary<string, string> GetValuesFromResponse()
{
var result = new Dictionary<string, string>();
foreach (var line in Response)
{
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(mpdKey, mpdValue);
}
}
}
}
return result;
}
public IReadOnlyDictionary<string, IList<T>> Body { get; }
}
public static class CheckNotNullExtension

View File

@ -7,7 +7,8 @@ namespace LibMpc
string Status { get; }
string ErrorMessage { get; }
string MpdError { get; }
bool IsError { get; }
bool Error { get; }
bool Connected { get; }
}
public class MpdResponseState : IMpdResponseState
@ -16,16 +17,17 @@ namespace LibMpc
private readonly string _endLine;
public MpdResponseState(string endLine)
public MpdResponseState(string endLine, bool connected)
{
_endLine = endLine;
Connected = connected;
if (!string.IsNullOrEmpty(_endLine))
{
if (_endLine.Equals(Constants.Ok))
{
Status = _endLine;
IsError = false;
Error = false;
}
else
{
@ -34,7 +36,8 @@ namespace LibMpc
}
}
public bool IsError { get; private set; } = true;
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;

View File

@ -53,15 +53,14 @@ namespace LibMpc
}
// TODO: create response type
public async Task<object> SendAsync(IMpcCommand command)
public async Task<object> SendAsync<T>(IMpcCommand<T> command)
{
var mpdResponse = await _connection.Exec(command.Value);
var respose = command.ParseResponse(mpdResponse);
var mpdMessage = await _connection.SendAsync(command);
return respose;
return mpdMessage;
}
/*
#region Admin Commands
/// <summary>
/// Disables an MPD output.
@ -91,11 +90,11 @@ namespace LibMpc
/// <returns>The list of all MPD outputs.</returns>
public async Task<MpdOutput[]> OutputsAsync()
{
MpdResponse response = await _connection.Exec("outputs");
MpdResponse response = await _connection.SendAsync("outputs");
if (response.Message.Count % 3 != 0)
throw new InvalidMpdResponseException();
MpdOutput[] ret = new MpdOutput[response.Message.Count / 3];
MpdOutput[] ret = new MpdcountsOutput[response.Message.Count / 3];
for (int i = 0; i < ret.Length; i++)
{
@ -137,7 +136,7 @@ namespace LibMpc
/// <returns>The list of tag types the MPD supports.</returns>
public async Task<string[]> TagTypesAsync()
{
MpdResponse response = await _connection.Exec("tagtypes");
MpdResponse response = await _connection.SendAsync("tagtypes");
string[] ret = new string[response.Message.Count];
@ -157,7 +156,7 @@ namespace LibMpc
/// <returns>An sequential number of the update process.</returns>
public async Task<int> UpdateAsync()
{
MpdResponse response = await _connection.Exec("update");
MpdResponse response = await _connection.SendAsync("update");
if (response.Message.Count != 1)
throw new InvalidMpdResponseException("Respose message has more than one line.");
@ -187,9 +186,9 @@ namespace LibMpc
if (token == null)
throw new ArgumentNullException("token");
MpdResponse response = await _connection.Exec("find", new string[] { tag.Value, token });
MpdResponse response = await _connection.SendAsync("find", new string[] { tag.Value, token });
if (response.IsError)
if (response.State.Error)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
return MpdFile.buildList(response);
@ -201,9 +200,9 @@ namespace LibMpc
/// <returns>All values found in files of the MPD for the given attribute.</returns>
public async Task<List<string>> ListAsync(ITag tag)
{
MpdResponse response = await _connection.Exec("list", new string[] { tag.Value });
MpdResponse response = await _connection.SendAsync("list", new string[] { tag.Value });
if (response.IsError)
if (response.State.Error)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
return response.getValueList();
@ -220,9 +219,9 @@ namespace LibMpc
if (searchValue == null)
throw new ArgumentNullException("searchValue");
MpdResponse response = await _connection.Exec("list", new string[] { resultTag.Value, searchTag.Value, searchValue });
MpdResponse response = await _connection.SendAsync("list", new string[] { resultTag.Value, searchTag.Value, searchValue });
if (response.IsError)
if (response.State.Error)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
return response.getValueList();
@ -237,9 +236,9 @@ namespace LibMpc
if (path == null)
throw new ArgumentNullException("path");
MpdResponse response = await _connection.Exec("listall", new string[] { path });
MpdResponse response = await _connection.SendAsync("listall", new string[] { path });
if (response.IsError)
if (response.State.Error)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
return response.getValueList();
@ -254,9 +253,9 @@ namespace LibMpc
if (path == null)
throw new ArgumentNullException("path");
MpdResponse response = await _connection.Exec("listallinfo", new string[] { path });
MpdResponse response = await _connection.SendAsync("listallinfo", new string[] { path });
if (response.IsError)
if (response.State.Error)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
return MpdFile.buildList(response);
@ -278,11 +277,11 @@ namespace LibMpc
{
MpdResponse response;
if (path == null)
response = await _connection.Exec("lsinfo");
response = await _connection.SendAsync("lsinfo");
else
response = await _connection.Exec("lsinfo", new string[] { path });
response = await _connection.SendAsync("lsinfo", new string[] { path });
if (response.IsError)
if (response.State.Error)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
return new MpdDirectoryListing(
@ -301,9 +300,9 @@ namespace LibMpc
if (token == null)
throw new ArgumentNullException("token");
MpdResponse response = await _connection.Exec("search", new string[] { tag.Value, token });
MpdResponse response = await _connection.SendAsync("search", new string[] { tag.Value, token });
if (response.IsError)
if (response.State.Error)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
return MpdFile.buildList(response);
@ -321,7 +320,7 @@ namespace LibMpc
if (filename == null)
throw new ArgumentNullException("filename");
MpdResponse response = await _connection.Exec("add", new string[] { filename });
MpdResponse response = await _connection.SendAsync("add", new string[] { filename });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -336,7 +335,7 @@ namespace LibMpc
if (filename == null)
throw new ArgumentNullException("filename");
MpdResponse response = await _connection.Exec("add", new string[] { filename });
MpdResponse response = await _connection.SendAsync("add", new string[] { filename });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -358,7 +357,7 @@ namespace LibMpc
/// </summary>
public async Task ClearAsync()
{
MpdResponse response = await _connection.Exec("clear");
MpdResponse response = await _connection.SendAsync("clear");
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -369,7 +368,7 @@ namespace LibMpc
/// <returns>The information of the current song.</returns>
public async Task<MpdFile> CurrentSongAsync()
{
MpdResponse response = await _connection.Exec("currentsong");
MpdResponse response = await _connection.SendAsync("currentsong");
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -382,7 +381,7 @@ namespace LibMpc
/// <param name="nr">The index of the track to remove from the playlist.</param>
public async Task DeleteAsync(int nr)
{
MpdResponse response = await _connection.Exec("delete", new string[] { nr.ToString() });
MpdResponse response = await _connection.SendAsync("delete", new string[] { nr.ToString() });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -393,7 +392,7 @@ namespace LibMpc
/// <param name="id">The id of the track to remove from the playlist.</param>
public async Task DeleteIdAsync(int id)
{
MpdResponse response = await _connection.Exec("deleteid", new string[] { id.ToString() });
MpdResponse response = await _connection.SendAsync("deleteid", new string[] { id.ToString() });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -407,7 +406,7 @@ namespace LibMpc
if (name == null)
throw new ArgumentNullException("name");
MpdResponse response = await _connection.Exec("load", new string[] { name });
MpdResponse response = await _connection.SendAsync("load", new string[] { name });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -424,7 +423,7 @@ namespace LibMpc
if (newName == null)
throw new ArgumentNullException("newName");
MpdResponse response = await _connection.Exec("rename", new string[] { oldName, newName });
MpdResponse response = await _connection.SendAsync("rename", new string[] { oldName, newName });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -436,7 +435,7 @@ namespace LibMpc
/// <param name="newNr">The new index of the track in the playlist.</param>
public async Task MoveAsync(int oldNr, int newNr)
{
MpdResponse response = await _connection.Exec("move", new string[] { oldNr.ToString(), newNr.ToString() });
MpdResponse response = await _connection.SendAsync("move", new string[] { oldNr.ToString(), newNr.ToString() });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -448,7 +447,7 @@ namespace LibMpc
/// <param name="nr">The new index of the track in the playlist.</param>
public async Task MoveIdAsync(int id, int nr)
{
MpdResponse response = await _connection.Exec("moveid", new string[] { id.ToString(), nr.ToString() });
MpdResponse response = await _connection.SendAsync("moveid", new string[] { id.ToString(), nr.ToString() });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -459,7 +458,7 @@ namespace LibMpc
/// <returns>The meta data of the items in the current playlist.</returns>
public async Task<List<MpdFile>> PlaylistInfoAsync()
{
MpdResponse response = await _connection.Exec("playlistinfo");
MpdResponse response = await _connection.SendAsync("playlistinfo");
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -473,7 +472,7 @@ namespace LibMpc
/// <returns>The meta data of the track in the current playlist.</returns>
public async Task<MpdFile> PlaylistInfoAsync(int nr)
{
MpdResponse response = await _connection.Exec("playlistinfo", new string[] { nr.ToString() });
MpdResponse response = await _connection.SendAsync("playlistinfo", new string[] { nr.ToString() });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -486,7 +485,7 @@ namespace LibMpc
/// <returns>The meta data of the items in the current playlist.</returns>
public async Task<List<MpdFile>> PlaylistIdAsync()
{
MpdResponse response = await _connection.Exec("playlistid");
MpdResponse response = await _connection.SendAsync("playlistid");
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -500,7 +499,7 @@ namespace LibMpc
/// <returns>The meta data of the track in the current playlist.</returns>
public async Task<MpdFile> PlaylistIdAsync(int id)
{
MpdResponse response = await _connection.Exec("playlistid", new string[] { id.ToString() });
MpdResponse response = await _connection.SendAsync("playlistid", new string[] { id.ToString() });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -514,7 +513,7 @@ namespace LibMpc
/// <returns>All changed songs in the playlist since the given version.</returns>
public async Task<List<MpdFile>> PlchangesAsync(int version)
{
MpdResponse response = await _connection.Exec("plchanges", new string[] { version.ToString() });
MpdResponse response = await _connection.SendAsync("plchanges", new string[] { version.ToString() });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -531,7 +530,7 @@ namespace LibMpc
/// </returns>
public async Task<List<KeyValuePair<int, int>>> PlChangesPosIdAsync(int version)
{
MpdResponse response = await _connection.Exec("plchangesposid", new string[] { version.ToString() });
MpdResponse response = await _connection.SendAsync("plchangesposid", new string[] { version.ToString() });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -578,7 +577,7 @@ namespace LibMpc
if (name == null)
throw new ArgumentNullException("name");
MpdResponse response = await _connection.Exec("rm", new string[] { name });
MpdResponse response = await _connection.SendAsync("rm", new string[] { name });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -592,7 +591,7 @@ namespace LibMpc
if (name == null)
throw new ArgumentNullException("name");
MpdResponse response = await _connection.Exec("save", new string[] { name });
MpdResponse response = await _connection.SendAsync("save", new string[] { name });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -602,7 +601,7 @@ namespace LibMpc
/// </summary>
public async Task ShuffleAsync()
{
MpdResponse response = await _connection.Exec("shuffle");
MpdResponse response = await _connection.SendAsync("shuffle");
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -614,7 +613,7 @@ namespace LibMpc
/// <param name="nr2">The index of the second track.</param>
public async Task SwapAsync(int nr1, int nr2)
{
MpdResponse response = await _connection.Exec("swap", new string[] { nr1.ToString(), nr2.ToString() });
MpdResponse response = await _connection.SendAsync("swap", new string[] { nr1.ToString(), nr2.ToString() });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -626,7 +625,7 @@ namespace LibMpc
/// <param name="id2">The id of the second track.</param>
public async Task SwapIdAsync(int id1, int id2)
{
MpdResponse response = await _connection.Exec("swapid", new string[] { id1.ToString(), id2.ToString() });
MpdResponse response = await _connection.SendAsync("swapid", new string[] { id1.ToString(), id2.ToString() });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -641,7 +640,7 @@ namespace LibMpc
if (name == null)
throw new ArgumentNullException("name");
MpdResponse response = await _connection.Exec("listplaylist", new string[] { name });
MpdResponse response = await _connection.SendAsync("listplaylist", new string[] { name });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -658,7 +657,7 @@ namespace LibMpc
if (name == null)
throw new ArgumentNullException("name");
MpdResponse response = await _connection.Exec("listplaylistinfo", new string[] { name });
MpdResponse response = await _connection.SendAsync("listplaylistinfo", new string[] { name });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -677,7 +676,7 @@ namespace LibMpc
if (file == null)
throw new ArgumentNullException("file");
MpdResponse response = await _connection.Exec("playlistadd", new string[] { name, file });
MpdResponse response = await _connection.SendAsync("playlistadd", new string[] { name, file });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -691,7 +690,7 @@ namespace LibMpc
if (name == null)
throw new ArgumentNullException("name");
MpdResponse response = await _connection.Exec("playlistclear", new string[] { name });
MpdResponse response = await _connection.SendAsync("playlistclear", new string[] { name });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -706,7 +705,7 @@ namespace LibMpc
if (name == null)
throw new ArgumentNullException("name");
MpdResponse response = await _connection.Exec("playlistdelete", new string[] { name, id.ToString() });
MpdResponse response = await _connection.SendAsync("playlistdelete", new string[] { name, id.ToString() });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -722,7 +721,7 @@ namespace LibMpc
if (name == null)
throw new ArgumentNullException("name");
MpdResponse response = await _connection.Exec("playlistmove", new string[] { id.ToString(), nr.ToString() });
MpdResponse response = await _connection.SendAsync("playlistmove", new string[] { id.ToString(), nr.ToString() });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -738,7 +737,7 @@ namespace LibMpc
if (token == null)
throw new ArgumentNullException("token");
MpdResponse response = await _connection.Exec("playlistfind", new string[] { tag.Value, token });
MpdResponse response = await _connection.SendAsync("playlistfind", new string[] { tag.Value, token });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -756,7 +755,7 @@ namespace LibMpc
if (token == null)
throw new ArgumentNullException("token");
MpdResponse response = await _connection.Exec("playlistsearch", new string[] { tag.Value, token });
MpdResponse response = await _connection.SendAsync("playlistsearch", new string[] { tag.Value, token });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -772,7 +771,7 @@ namespace LibMpc
/// <param name="seconds">The seconds to crossfade between songs.</param>
public async Task CrossfadeAsync(int seconds)
{
MpdResponse response = await _connection.Exec("crossfade", new string[] { seconds.ToString() });
MpdResponse response = await _connection.SendAsync("crossfade", new string[] { seconds.ToString() });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -782,7 +781,7 @@ namespace LibMpc
/// </summary>
public async Task NextAsync()
{
MpdResponse response = await _connection.Exec("next");
MpdResponse response = await _connection.SendAsync("next");
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -793,7 +792,7 @@ namespace LibMpc
/// <param name="pause">If the playback should be paused or resumed.</param>
public async Task PauseAsync(bool pause)
{
MpdResponse response = await _connection.Exec("pause", new string[] { pause ? "1" : "0" });
MpdResponse response = await _connection.SendAsync("pause", new string[] { pause ? "1" : "0" });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -803,7 +802,7 @@ namespace LibMpc
/// </summary>
public async Task PlayAsync()
{
MpdResponse response = await _connection.Exec("play");
MpdResponse response = await _connection.SendAsync("play");
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -814,7 +813,7 @@ namespace LibMpc
/// <param name="nr">The index of the track in the playlist to start playing.</param>
public async Task PlayAsync(int nr)
{
MpdResponse response = await _connection.Exec("play", new string[] { nr.ToString() });
MpdResponse response = await _connection.SendAsync("play", new string[] { nr.ToString() });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -824,7 +823,7 @@ namespace LibMpc
/// </summary>
public async Task PlayIdAsync()
{
MpdResponse response = await _connection.Exec("playid");
MpdResponse response = await _connection.SendAsync("playid");
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -835,7 +834,7 @@ namespace LibMpc
/// <param name="id">The id of the track to start playing.</param>
public async Task PlayIdAsync(int id)
{
MpdResponse response = await _connection.Exec("playid", new string[] { id.ToString() });
MpdResponse response = await _connection.SendAsync("playid", new string[] { id.ToString() });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -845,7 +844,7 @@ namespace LibMpc
/// </summary>
public async Task PreviousAsync()
{
MpdResponse response = await _connection.Exec("previous");
MpdResponse response = await _connection.SendAsync("previous");
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -856,7 +855,7 @@ namespace LibMpc
/// <param name="random">If the MPD playlist should be played randomly.</param>
public async Task RandomAsync(bool random)
{
MpdResponse response = await _connection.Exec("random", new string[] { random ? "1" : "0" });
MpdResponse response = await _connection.SendAsync("random", new string[] { random ? "1" : "0" });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -867,7 +866,7 @@ namespace LibMpc
/// <param name="repeat">If the MPD should repeat the playlist.</param>
public async Task RepeatAsync(bool repeat)
{
MpdResponse response = await _connection.Exec("repeat", new string[] { repeat ? "1" : "0" });
MpdResponse response = await _connection.SendAsync("repeat", new string[] { repeat ? "1" : "0" });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -879,7 +878,7 @@ namespace LibMpc
/// <param name="time">The number of seconds to start playback on.</param>
public async Task SeekAsync(int nr, int time)
{
MpdResponse response = await _connection.Exec("seek", new string[] { nr.ToString(), time.ToString() });
MpdResponse response = await _connection.SendAsync("seek", new string[] { nr.ToString(), time.ToString() });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -891,7 +890,7 @@ namespace LibMpc
/// <param name="time">The number of seconds to start playback on.</param>
public async Task SeekIdAsync(int id, int time)
{
MpdResponse response = await _connection.Exec("seekid", new string[] { id.ToString(), time.ToString() });
MpdResponse response = await _connection.SendAsync("seekid", new string[] { id.ToString(), time.ToString() });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -907,7 +906,7 @@ namespace LibMpc
if (vol > 100)
throw new ArgumentException("vol > 100");
MpdResponse response = await _connection.Exec("setvol", new string[] { vol.ToString() });
MpdResponse response = await _connection.SendAsync("setvol", new string[] { vol.ToString() });
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -917,7 +916,7 @@ namespace LibMpc
/// </summary>
public async Task StopAsync()
{
MpdResponse response = await _connection.Exec("stop");
MpdResponse response = await _connection.SendAsync("stop");
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -931,7 +930,7 @@ namespace LibMpc
/// </summary>
public async Task ClearErrorAsync()
{
await _connection.Exec("clearerror");
await _connection.SendAsync("clearerror");
}
/// <summary>
/// Returns which commands the current user has access to.
@ -939,7 +938,7 @@ namespace LibMpc
/// <returns>The commands the current user has access to.</returns>
public async Task<List<string>> CommandsAsync()
{
MpdResponse response = await _connection.Exec("commands");
MpdResponse response = await _connection.SendAsync("commands");
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -952,7 +951,7 @@ namespace LibMpc
/// <returns>The commands the current user does has access to.</returns>
public async Task<List<string>> NotCommandsAsync()
{
MpdResponse response = await _connection.Exec("notcommands");
MpdResponse response = await _connection.SendAsync("notcommands");
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -969,7 +968,7 @@ namespace LibMpc
if (password == null)
throw new ArgumentNullException("password");
var mpdResponse = await _connection.Exec("password", new string[] { password });
var mpdResponse = await _connection.SendAsync("password", new string[] { password });
return mpdResponse.IsError;
}
/// <summary>
@ -977,7 +976,7 @@ namespace LibMpc
/// </summary>
public async Task PingAsync()
{
await _connection.Exec("ping");
await _connection.SendAsync("ping");
}
/// <summary>
/// Requests the current statistics from the MPD,
@ -985,7 +984,7 @@ namespace LibMpc
/// <returns>The current statistics fromt the MPD.</returns>
public async Task<MpdStatistics> StatsAsync()
{
MpdResponse response = await _connection.Exec("stats");
MpdResponse response = await _connection.SendAsync("stats");
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -1063,7 +1062,7 @@ namespace LibMpc
/// <returns>The current status of the MPD.</returns>
public async Task<MpdStatus> StatusAsync()
{
MpdResponse response = await _connection.Exec("status");
MpdResponse response = await _connection.SendAsync("status");
if (response.IsError)
throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
@ -1233,5 +1232,6 @@ namespace LibMpc
}
#endregion
*/
}
}

View File

@ -78,84 +78,29 @@ namespace LibMpc
return Task.CompletedTask;
}
/// <summary>
/// Executes a simple command without arguments on the MPD server and returns the response.
/// </summary>
/// <param name="command">The command to execute.</param>
/// <returns>The MPD server response parsed into a basic object.</returns>
/// <exception cref="ArgumentException">If the command contains a space of a newline charakter.</exception>
public async Task<MpdResponse> Exec(string command)
{
if (command == null)
throw new ArgumentNullException("command");
if (command.Contains(" "))
throw new ArgumentException("command contains space");
if (command.Contains("\n"))
throw new ArgumentException("command contains newline");
// TODO: Integrate connection status in MpdResponse
var connectionResult = await CheckConnectionAsync();
public async Task<IMpdMessage<T>> SendAsync<T>(IMpcCommand<T> command)
{
command.CheckNotNull();
var connected = await CheckConnectionAsync();
string[] response;
try
{
_writer.WriteLine(command);
_writer.WriteLine(command.Value);
_writer.Flush();
return await ReadResponseAsync();
response = await ReadResponseAsync();
}
catch (Exception)
{
try { await DisconnectAsync(); } catch (Exception) { }
return null; // TODO: Create Null Object for MpdResponse
}
}
/// <summary>
/// Executes a MPD command with arguments on the MPD server.
/// </summary>
/// <param name="command">The command to execute.</param>
/// <param name="argument">The arguments of the command.</param>
/// <returns>The MPD server response parsed into a basic object.</returns>
/// <exception cref="ArgumentException">If the command contains a space of a newline charakter.</exception>
public async Task<MpdResponse> Exec(string command, string[] argument)
{
if (command == null)
throw new ArgumentNullException("command");
if (command.Contains(" "))
throw new ArgumentException("command contains space");
if (command.Contains("\n"))
throw new ArgumentException("command contains newline");
if (argument == null)
throw new ArgumentNullException("argument");
for (int i = 0; i < argument.Length; i++)
{
if (argument[i] == null)
throw new ArgumentNullException("argument[" + i + "]");
if (argument[i].Contains("\n"))
throw new ArgumentException("argument[" + i + "] contains newline");
}
// TODO: Integrate connection status in MpdResponse
var connectionResult = await CheckConnectionAsync();
try
{
_writer.Write(command);
foreach (string arg in argument)
{
_writer.Write(' ');
WriteToken(arg);
}
_writer.WriteLine();
_writer.Flush();
return await ReadResponseAsync();
}
catch (Exception)
{
try { await DisconnectAsync(); } catch (Exception) { }
throw;
}
return new MpdMessage<T>(command, connected, response);
}
private async Task<bool> CheckConnectionAsync()
@ -168,22 +113,7 @@ namespace LibMpc
return IsConnected;
}
private void WriteToken(string token)
{
if (token.Contains(" "))
{
_writer.Write("\"");
foreach (char chr in token)
if (chr == '"')
_writer.Write("\\\"");
else
_writer.Write(chr);
}
else
_writer.Write(token);
}
private async Task<MpdResponse> ReadResponseAsync()
private async Task<string[]> ReadResponseAsync()
{
var response = new List<string>();
@ -195,7 +125,7 @@ namespace LibMpc
response.Add(responseLine);
} while (!(responseLine.Equals(Constants.Ok) || responseLine.StartsWith(Constants.Ack) || string.IsNullOrEmpty(responseLine)));
return new MpdResponse(response);
return response.ToArray();
}
private void ClearConnectionFields()

View File

@ -280,6 +280,7 @@ namespace LibMpc
builder.Append(value);
builder.AppendLine();
}
/*
/// <summary>
/// Returns a MpdFile object from a MpdResponse object.
/// </summary>
@ -475,11 +476,12 @@ namespace LibMpc
break;
case TAG_TRACK:
track = line.Value;
/*
// TODO:
int tryTrack;
if (int.TryParse(line.Value, out tryTrack))
track = tryTrack;
*/
break;
case TAG_NAME:
name = line.Value;
@ -537,5 +539,6 @@ namespace LibMpc
return ret;
}
*/
}
}

View File

@ -1,8 +1,9 @@
{
{
"version": "1.0.0-*",
"dependencies": {
"NETStandard.Library": "1.6.0"
"NETStandard.Library": "1.6.0",
"Newtonsoft.Json": "9.0.1"
},
"frameworks": {

View File

@ -1,7 +1,6 @@
using System;
using System.Net;
using LibMpc;
using System.Collections.Generic;
namespace LibMpcApp
{
@ -10,11 +9,6 @@ namespace LibMpcApp
/// </summary>
public class Program
{
private static readonly Dictionary<int, Func<object, IMpcCommand>> _commands = new Dictionary<int, Func<object, IMpcCommand>>
{
{ 1, input => new Commands.Reflection.TagTypes() }
};
public static void Main(string[] args)
{
var mpc = new Mpc(new IPEndPoint(IPAddress.Loopback, 6600));
@ -38,12 +32,23 @@ namespace LibMpcApp
int userInput = 0;
while ((userInput = DisplayMenu()) != 99)
{
Func<object, IMpcCommand> command;
var response = new object();
if (_commands.TryGetValue(userInput, out command))
switch (userInput)
{
response = mpc.SendAsync(command(null)).GetAwaiter().GetResult();
case 11:
response = mpc.SendAsync(new Commands.Output.DisableOutput(0)).GetAwaiter().GetResult();
break;
case 12:
response = mpc.SendAsync(new Commands.Output.EnableOutput(0)).GetAwaiter().GetResult();
break;
case 13:
response = mpc.SendAsync(new Commands.Output.Outputs()).GetAwaiter().GetResult();
break;
case 24:
response = mpc.SendAsync(new Commands.Reflection.TagTypes()).GetAwaiter().GetResult();
break;
}
Console.WriteLine("Response: ");
@ -55,7 +60,20 @@ namespace LibMpcApp
{
Console.WriteLine();
Console.WriteLine("Commands: ");
Console.WriteLine("1. tagtypes");
// Ouput
Console.WriteLine();
Console.WriteLine("11. disableoutput 0");
Console.WriteLine("12. enableoutput 0");
Console.WriteLine("13. outputs");
// Reflection
Console.WriteLine();
Console.WriteLine("24. tagtypes");
// Database
Console.WriteLine();
Console.WriteLine("99. Exit");
Console.WriteLine();
var result = Console.ReadLine();