From 53325604e8f8e6aae6c4b4f1d2cbe993496aa986 Mon Sep 17 00:00:00 2001 From: glucaci Date: Tue, 6 Dec 2016 18:01:28 +0100 Subject: [PATCH] Each command can format the mpd response. User response is a MpdMessage which conatins the requested command and the formatted response. --- LibMpc/Commands/Commands.Database.cs | 30 ++--- LibMpc/Commands/Commands.Output.cs | 38 +++++-- LibMpc/Commands/Commands.Reflection.cs | 10 +- LibMpc/Commands/IMpcCommand.cs | 7 +- LibMpc/Message/MpdMessage.cs | 67 +++++++++-- LibMpc/Message/MpdRequest.cs | 10 +- LibMpc/Message/MpdResponse.cs | 53 ++------- LibMpc/Message/MpdResponseState.cs | 11 +- LibMpc/Mpc.cs | 150 ++++++++++++------------- LibMpc/MpcConnection.cs | 94 ++-------------- LibMpc/MpdFile.cs | 7 +- LibMpc/project.json | 5 +- LibMpcApp/Program.cs | 38 +++++-- 13 files changed, 250 insertions(+), 270 deletions(-) diff --git a/LibMpc/Commands/Commands.Database.cs b/LibMpc/Commands/Commands.Database.cs index f09c4a7..a35195c 100644 --- a/LibMpc/Commands/Commands.Database.cs +++ b/LibMpc/Commands/Commands.Database.cs @@ -1,4 +1,4 @@ -using System; +using System.Collections.Generic; namespace LibMpc { @@ -10,8 +10,8 @@ namespace LibMpc public class Database { // TODO: count - - public class Find : IMpcCommand + + public class Find : IMpcCommand { 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> FormatResponse(IReadOnlyDictionary> response) { - throw new NotImplementedException(); + return response; } } - public class List : IMpcCommand + public class List : IMpcCommand { private readonly ITag _tag; @@ -41,15 +41,15 @@ namespace LibMpc public string Value => string.Join(" ", "list", _tag); - public object ParseResponse(object response) + public IReadOnlyDictionary> FormatResponse(IReadOnlyDictionary> response) { - throw new NotImplementedException(); + return response; } } // TODO: findadd - public class ListAll : IMpcCommand + public class ListAll : IMpcCommand { private readonly string _path; @@ -60,9 +60,9 @@ namespace LibMpc public string Value => string.Join(" ", "listall", _path); - public object ParseResponse(object response) + public IReadOnlyDictionary> FormatResponse(IReadOnlyDictionary> response) { - throw new NotImplementedException(); + return response; } } @@ -74,16 +74,16 @@ namespace LibMpc // TODO: searchadd // TODO: searchaddpl - public class Update : IMpcCommand + public class Update : IMpcCommand { public string Value => "update"; - public object ParseResponse(object response) + public IReadOnlyDictionary> FormatResponse(IReadOnlyDictionary> response) { - throw new NotImplementedException(); + return response; } } - + // TODO: rescan } } diff --git a/LibMpc/Commands/Commands.Output.cs b/LibMpc/Commands/Commands.Output.cs index c644aea..203f234 100644 --- a/LibMpc/Commands/Commands.Output.cs +++ b/LibMpc/Commands/Commands.Output.cs @@ -1,4 +1,6 @@ -namespace LibMpc +using System.Collections.Generic; + +namespace LibMpc { public partial class Commands { @@ -10,7 +12,7 @@ /// /// Turns an output off. /// - public class DisableOutput : IMpcCommand + public class DisableOutput : IMpcCommand { private readonly int _outputId; @@ -21,16 +23,16 @@ public string Value => string.Join(" ", "disableoutput", _outputId); - public object ParseResponse(object response) + public IReadOnlyDictionary> FormatResponse(IReadOnlyDictionary> response) { - throw new System.NotImplementedException(); + return response; } } /// /// Turns an output on. /// - public class EnableOutput : IMpcCommand + public class EnableOutput : IMpcCommand { private readonly int _outputId; @@ -41,9 +43,9 @@ public string Value => string.Join(" ", "enableoutput", _outputId); - public object ParseResponse(object response) + public IReadOnlyDictionary> FormatResponse(IReadOnlyDictionary> response) { - throw new System.NotImplementedException(); + return response; } } @@ -52,13 +54,27 @@ /// /// Shows information about all outputs. /// - public class Outputs : IMpcCommand + public class Outputs : IMpcCommand> { public string Value => "outputs"; - - public object ParseResponse(object response) + public IReadOnlyDictionary>> FormatResponse(IReadOnlyDictionary> response) { - throw new System.NotImplementedException(); + var result = new Dictionary>> + { + {"outputs", new List>()} + }; + + for (var i = 0; i < response["outputid"].Count; i++) + { + result["outputs"].Add(new Dictionary + { + { "id", response["outputid"][i] }, + { "name", response["outputname"][i] }, + { "enabled", response["outputenabled"][i] } + }); + } + + return result; } } } diff --git a/LibMpc/Commands/Commands.Reflection.cs b/LibMpc/Commands/Commands.Reflection.cs index 45def98..f05dc17 100644 --- a/LibMpc/Commands/Commands.Reflection.cs +++ b/LibMpc/Commands/Commands.Reflection.cs @@ -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 { public string Value => "tagtypes"; - public object ParseResponse(object response) + public IReadOnlyDictionary> FormatResponse(IReadOnlyDictionary> response) { - throw new System.NotImplementedException(); + return response; } } diff --git a/LibMpc/Commands/IMpcCommand.cs b/LibMpc/Commands/IMpcCommand.cs index e15db91..0db8d55 100644 --- a/LibMpc/Commands/IMpcCommand.cs +++ b/LibMpc/Commands/IMpcCommand.cs @@ -1,10 +1,11 @@ +using System.Collections.Generic; + namespace LibMpc { - public interface IMpcCommand + public interface IMpcCommand { string Value { get; } - // TODO: Return IMpdResponse and create type-safe input. - object ParseResponse(object response); + IReadOnlyDictionary> FormatResponse(IReadOnlyDictionary> response); } } \ No newline at end of file diff --git a/LibMpc/Message/MpdMessage.cs b/LibMpc/Message/MpdMessage.cs index 5d3da1b..e7061f4 100644 --- a/LibMpc/Message/MpdMessage.cs +++ b/LibMpc/Message/MpdMessage.cs @@ -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 { - IMpdRequest Request { get; } - IMpdResponse Response { get; } + IMpdRequest Request { get; } + IMpdResponse Response { get; } } - public class MpdMessage : IMpdMessage + public class MpdMessage : IMpdMessage { - public MpdMessage(IMpcCommand command) + private readonly Regex _linePattern = new Regex("^(?[A-Za-z]*):[ ]{0,1}(?.*)$"); + private readonly IList _rawResponse; + + public MpdMessage(IMpcCommand command, bool connected, IReadOnlyCollection response) { - Request = new MpdRequest(command); + Request = new MpdRequest(command); + + var endLine = response.Skip(response.Count - 1).Single(); + _rawResponse = response.Take(response.Count - 1).ToList(); + + var values = Request.Command.FormatResponse(GetValuesFromResponse()); + Response = new MpdResponse(endLine, values, connected); } - public void AddResponse(IMpdResponse response) - { - Response = response; + public IMpdRequest Request { get; } + public IMpdResponse Response { get; } + + private IReadOnlyDictionary> GetValuesFromResponse() + { + var result = new Dictionary>(); + + 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() { mpdValue }); + } + else + { + result[mpdKey].Add(mpdValue); + } + } + } + } + } + + return result; } - public IMpdRequest Request { get; } - public IMpdResponse Response { get; private set; } + public override string ToString() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } } } \ No newline at end of file diff --git a/LibMpc/Message/MpdRequest.cs b/LibMpc/Message/MpdRequest.cs index c078f38..b769b5e 100644 --- a/LibMpc/Message/MpdRequest.cs +++ b/LibMpc/Message/MpdRequest.cs @@ -1,17 +1,17 @@ namespace LibMpc { - public interface IMpdRequest + public interface IMpdRequest { - IMpcCommand Command { get; } + IMpcCommand Command { get; } } - public class MpdRequest : IMpdRequest + public class MpdRequest : IMpdRequest { - public MpdRequest(IMpcCommand command) + public MpdRequest(IMpcCommand command) { Command = command; } - public IMpcCommand Command { get; } + public IMpcCommand Command { get; } } } \ No newline at end of file diff --git a/LibMpc/Message/MpdResponse.cs b/LibMpc/Message/MpdResponse.cs index dacf15b..9ae53aa 100644 --- a/LibMpc/Message/MpdResponse.cs +++ b/LibMpc/Message/MpdResponse.cs @@ -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 { - IEnumerable Response { get; } - IReadOnlyDictionary Values { get; } IMpdResponseState State { get; } + IReadOnlyDictionary> Body { get; } } - public class MpdResponse : IMpdResponse + public class MpdResponse : IMpdResponse { - private static readonly Regex LinePattern = new Regex("^(?[A-Za-z]*):[ ]{0,1}(?.*)$"); - - public MpdResponse(ICollection response) + public MpdResponse(string endLine, IReadOnlyDictionary> 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 Response { get; } - - public IReadOnlyDictionary Values { get; } - - - private IReadOnlyDictionary GetValuesFromResponse() - { - var result = new Dictionary(); - - 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> Body { get; } } public static class CheckNotNullExtension diff --git a/LibMpc/Message/MpdResponseState.cs b/LibMpc/Message/MpdResponseState.cs index e1043e4..447c87d 100644 --- a/LibMpc/Message/MpdResponseState.cs +++ b/LibMpc/Message/MpdResponseState.cs @@ -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; diff --git a/LibMpc/Mpc.cs b/LibMpc/Mpc.cs index a56e0b8..8772d4d 100644 --- a/LibMpc/Mpc.cs +++ b/LibMpc/Mpc.cs @@ -53,15 +53,14 @@ namespace LibMpc } // TODO: create response type - public async Task SendAsync(IMpcCommand command) + public async Task SendAsync(IMpcCommand 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 /// /// Disables an MPD output. @@ -84,18 +83,18 @@ namespace LibMpc var mpdResponse = await _connection.Exec("enableoutput", new string[] { id.ToString() }); return !mpdResponse.IsError; } - + /// /// Lists all outputs of the MPD. /// /// The list of all MPD outputs. public async Task 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 /// The list of tag types the MPD supports. public async Task 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 /// An sequential number of the update process. public async Task 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 /// All values found in files of the MPD for the given attribute. public async Task> 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 /// 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 /// The information of the current song. public async Task 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 /// The index of the track to remove from the playlist. 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 /// The id of the track to remove from the playlist. 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 /// The new index of the track in the playlist. 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 /// The new index of the track in the playlist. 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 /// The meta data of the items in the current playlist. public async Task> 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 /// The meta data of the track in the current playlist. public async Task 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 /// The meta data of the items in the current playlist. public async Task> 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 /// The meta data of the track in the current playlist. public async Task 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 /// All changed songs in the playlist since the given version. public async Task> 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 /// public async Task>> 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 /// 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 /// The index of the second track. 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 /// The id of the second track. 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 /// The seconds to crossfade between songs. 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 /// 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 /// If the playback should be paused or resumed. 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 /// 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 /// The index of the track in the playlist to start playing. 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 /// 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 /// The id of the track to start playing. 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 /// 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 /// If the MPD playlist should be played randomly. 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 /// If the MPD should repeat the playlist. 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 /// The number of seconds to start playback on. 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 /// The number of seconds to start playback on. 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 /// 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 /// public async Task ClearErrorAsync() { - await _connection.Exec("clearerror"); + await _connection.SendAsync("clearerror"); } /// /// Returns which commands the current user has access to. @@ -939,7 +938,7 @@ namespace LibMpc /// The commands the current user has access to. public async Task> 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 /// The commands the current user does has access to. public async Task> 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; } /// @@ -977,7 +976,7 @@ namespace LibMpc /// public async Task PingAsync() { - await _connection.Exec("ping"); + await _connection.SendAsync("ping"); } /// /// Requests the current statistics from the MPD, @@ -985,7 +984,7 @@ namespace LibMpc /// The current statistics fromt the MPD. public async Task 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 /// The current status of the MPD. public async Task 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 + */ } } diff --git a/LibMpc/MpcConnection.cs b/LibMpc/MpcConnection.cs index 6740dd0..5eb067f 100644 --- a/LibMpc/MpcConnection.cs +++ b/LibMpc/MpcConnection.cs @@ -78,84 +78,29 @@ namespace LibMpc return Task.CompletedTask; } - /// - /// Executes a simple command without arguments on the MPD server and returns the response. - /// - /// The command to execute. - /// The MPD server response parsed into a basic object. - /// If the command contains a space of a newline charakter. - public async Task 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> SendAsync(IMpcCommand 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 } - } - /// - /// Executes a MPD command with arguments on the MPD server. - /// - /// The command to execute. - /// The arguments of the command. - /// The MPD server response parsed into a basic object. - /// If the command contains a space of a newline charakter. - public async Task 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(command, connected, response); } private async Task 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 ReadResponseAsync() + private async Task ReadResponseAsync() { var response = new List(); @@ -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() diff --git a/LibMpc/MpdFile.cs b/LibMpc/MpdFile.cs index 28e93cf..7809ad5 100644 --- a/LibMpc/MpdFile.cs +++ b/LibMpc/MpdFile.cs @@ -280,6 +280,7 @@ namespace LibMpc builder.Append(value); builder.AppendLine(); } + /* /// /// Returns a MpdFile object from a MpdResponse object. /// @@ -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; } + */ } } diff --git a/LibMpc/project.json b/LibMpc/project.json index 864b9a5..ba4e60a 100644 --- a/LibMpc/project.json +++ b/LibMpc/project.json @@ -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": { diff --git a/LibMpcApp/Program.cs b/LibMpcApp/Program.cs index 7a54497..cb43c88 100644 --- a/LibMpcApp/Program.cs +++ b/LibMpcApp/Program.cs @@ -1,7 +1,6 @@ using System; using System.Net; using LibMpc; -using System.Collections.Generic; namespace LibMpcApp { @@ -10,11 +9,6 @@ namespace LibMpcApp /// public class Program { - private static readonly Dictionary> _commands = new Dictionary> - { - { 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 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();