mirror of
				https://github.com/ZetaKebab/MpcNET.git
				synced 2025-11-03 20:09:49 +00:00 
			
		
		
		
	@@ -1,4 +1,5 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
 | 
			
		||||
namespace LibMpc
 | 
			
		||||
{
 | 
			
		||||
@@ -11,7 +12,7 @@ namespace LibMpc
 | 
			
		||||
        {
 | 
			
		||||
            // TODO: count
 | 
			
		||||
            
 | 
			
		||||
            public class Find : IMpcCommand
 | 
			
		||||
            public class Find : IMpcCommand<IList<IDictionary<string, string>>>
 | 
			
		||||
            {
 | 
			
		||||
                private readonly ITag _tag;
 | 
			
		||||
                private readonly string _searchText;
 | 
			
		||||
@@ -24,13 +25,30 @@ namespace LibMpc
 | 
			
		||||
 | 
			
		||||
                public string Value => string.Join(" ", "find", _tag.Value, _searchText);
 | 
			
		||||
 | 
			
		||||
                public object ParseResponse(object response)
 | 
			
		||||
                public IDictionary<string, IList<IDictionary<string, string>>> FormatResponse(IList<KeyValuePair<string, string>> response)
 | 
			
		||||
                {
 | 
			
		||||
                    throw new NotImplementedException();
 | 
			
		||||
                    var results = new Dictionary<string, IList<IDictionary<string, string>>>
 | 
			
		||||
                    {
 | 
			
		||||
                        { "files", new List<IDictionary<string, string>>() }
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                    foreach (var line in response)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (line.Key.Equals("file"))
 | 
			
		||||
                        {
 | 
			
		||||
                            results["files"].Add(new Dictionary<string, string> { { "file", line.Value } });
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            results["files"].Last().Add(line.Key, line.Value);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return results;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            public class List : IMpcCommand
 | 
			
		||||
            public class List : IMpcCommand<string>
 | 
			
		||||
            {
 | 
			
		||||
                private readonly ITag _tag;
 | 
			
		||||
 | 
			
		||||
@@ -41,15 +59,15 @@ namespace LibMpc
 | 
			
		||||
 | 
			
		||||
                public string Value => string.Join(" ", "list", _tag);
 | 
			
		||||
 | 
			
		||||
                public object ParseResponse(object response)
 | 
			
		||||
                public IDictionary<string, string> FormatResponse(IList<KeyValuePair<string, string>> response)
 | 
			
		||||
                {
 | 
			
		||||
                    throw new NotImplementedException();
 | 
			
		||||
                    return response.ToDefaultDictionary();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // TODO: findadd
 | 
			
		||||
 | 
			
		||||
            public class ListAll : IMpcCommand
 | 
			
		||||
            public class ListAll : IMpcCommand<string>
 | 
			
		||||
            {
 | 
			
		||||
                private readonly string _path;
 | 
			
		||||
 | 
			
		||||
@@ -60,9 +78,9 @@ namespace LibMpc
 | 
			
		||||
 | 
			
		||||
                public string Value => string.Join(" ", "listall", _path);
 | 
			
		||||
 | 
			
		||||
                public object ParseResponse(object response)
 | 
			
		||||
                public IDictionary<string, string> FormatResponse(IList<KeyValuePair<string, string>> response)
 | 
			
		||||
                {
 | 
			
		||||
                    throw new NotImplementedException();
 | 
			
		||||
                    return response.ToDefaultDictionary();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -74,13 +92,14 @@ namespace LibMpc
 | 
			
		||||
            // TODO: searchadd
 | 
			
		||||
            // TODO: searchaddpl
 | 
			
		||||
 | 
			
		||||
            public class Update : IMpcCommand
 | 
			
		||||
            public class Update : IMpcCommand<string>
 | 
			
		||||
            {
 | 
			
		||||
                // TODO: Extend command: < update [URI] >
 | 
			
		||||
                public string Value => "update";
 | 
			
		||||
 | 
			
		||||
                public object ParseResponse(object response)
 | 
			
		||||
                public IDictionary<string, string> FormatResponse(IList<KeyValuePair<string, string>> response)
 | 
			
		||||
                {
 | 
			
		||||
                    throw new NotImplementedException();
 | 
			
		||||
                    return response.ToDefaultDictionary();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
 
 | 
			
		||||
@@ -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 IDictionary<string, string> FormatResponse(IList<KeyValuePair<string, string>> response)
 | 
			
		||||
                {
 | 
			
		||||
                    throw new System.NotImplementedException();
 | 
			
		||||
                    return response.ToDefaultDictionary();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /// <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 IDictionary<string, string> FormatResponse(IList<KeyValuePair<string, string>> response)
 | 
			
		||||
                {
 | 
			
		||||
                    throw new System.NotImplementedException();
 | 
			
		||||
                    return response.ToDefaultDictionary();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -52,13 +54,32 @@
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// Shows information about all outputs.
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            public class Outputs : IMpcCommand
 | 
			
		||||
            public class Outputs : IMpcCommand<IList<IDictionary<string, string>>>
 | 
			
		||||
            {
 | 
			
		||||
                public string Value => "outputs";
 | 
			
		||||
                
 | 
			
		||||
                public object ParseResponse(object response)
 | 
			
		||||
                public IDictionary<string, IList<IDictionary<string, string>>> FormatResponse(IList<KeyValuePair<string, string>> response)
 | 
			
		||||
                {
 | 
			
		||||
                    throw new System.NotImplementedException();
 | 
			
		||||
                    var result = new Dictionary<string, IList<IDictionary<string, string>>>
 | 
			
		||||
                    {
 | 
			
		||||
                        { "outputs", new List<IDictionary<string, string>>() }
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                    for (var i = 0; i < response.Count; i += 3)
 | 
			
		||||
                    {
 | 
			
		||||
                        var outputId = response[i].Value;
 | 
			
		||||
                        var outputName = response[i + 1].Value;
 | 
			
		||||
                        var outputEnabled = response[i + 2].Value;
 | 
			
		||||
 | 
			
		||||
                        result["outputs"].Add(new Dictionary<string, string>
 | 
			
		||||
                        {
 | 
			
		||||
                            {"id", outputId},
 | 
			
		||||
                            {"name", outputName},
 | 
			
		||||
                            {"enabled", outputEnabled}
 | 
			
		||||
                        });
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return result;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,7 @@
 | 
			
		||||
namespace LibMpc
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
 | 
			
		||||
namespace LibMpc
 | 
			
		||||
{
 | 
			
		||||
    public partial class Commands
 | 
			
		||||
    {
 | 
			
		||||
@@ -11,13 +14,18 @@
 | 
			
		||||
            // TODO: commands
 | 
			
		||||
            // TODO: notcommands
 | 
			
		||||
 | 
			
		||||
            public class TagTypes : IMpcCommand
 | 
			
		||||
            public class TagTypes : IMpcCommand<IList<string>>
 | 
			
		||||
            {
 | 
			
		||||
                public string Value => "tagtypes";
 | 
			
		||||
 | 
			
		||||
                public object ParseResponse(object response)
 | 
			
		||||
                IDictionary<string, IList<string>> IMpcCommand<IList<string>>.FormatResponse(IList<KeyValuePair<string, string>> response)
 | 
			
		||||
                {
 | 
			
		||||
                    throw new System.NotImplementedException();
 | 
			
		||||
                    var result = new Dictionary<string, IList<string>>
 | 
			
		||||
                    {
 | 
			
		||||
                        { "tagtypes", response.Where(item => item.Key.Equals("tagtype")).Select(item => item.Value).ToList() }
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                    return result;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,20 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
 | 
			
		||||
namespace LibMpc
 | 
			
		||||
{
 | 
			
		||||
    public interface IMpcCommand
 | 
			
		||||
    public interface IMpcCommand<T>
 | 
			
		||||
    {
 | 
			
		||||
        string Value { get; }
 | 
			
		||||
 | 
			
		||||
        // TODO: Return IMpdResponse and create type-safe input.
 | 
			
		||||
        object ParseResponse(object response);
 | 
			
		||||
        IDictionary<string, T> FormatResponse(IList<KeyValuePair<string, string>> response);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    internal static class MpdCommandExtensions
 | 
			
		||||
    {
 | 
			
		||||
        public static IDictionary<string, string> ToDefaultDictionary(this IList<KeyValuePair<string, string>> items)
 | 
			
		||||
        {
 | 
			
		||||
            return items.ToDictionary(item => item.Key, item => item.Value);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								LibMpc/Constants.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								LibMpc/Constants.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace LibMpc
 | 
			
		||||
{
 | 
			
		||||
    public class Constants
 | 
			
		||||
    {
 | 
			
		||||
        public static readonly string Ok = "OK";
 | 
			
		||||
        public static readonly string Ack = "ACK";
 | 
			
		||||
 | 
			
		||||
        public static readonly string FirstLinePrefix = "OK MPD ";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										62
									
								
								LibMpc/Message/MpdMessage.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								LibMpc/Message/MpdMessage.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
 | 
			
		||||
namespace LibMpc
 | 
			
		||||
{
 | 
			
		||||
    public interface IMpdMessage<T>
 | 
			
		||||
    {
 | 
			
		||||
        IMpdRequest<T> Request { get; }
 | 
			
		||||
        IMpdResponse<T> Response { get; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class MpdMessage<T> : IMpdMessage<T>
 | 
			
		||||
    {
 | 
			
		||||
        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<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 IMpdRequest<T> Request { get; }
 | 
			
		||||
        public IMpdResponse<T> Response { get; }
 | 
			
		||||
 | 
			
		||||
        private IList<KeyValuePair<string, string>> GetValuesFromResponse()
 | 
			
		||||
        {
 | 
			
		||||
            var result = new List<KeyValuePair<string, 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))
 | 
			
		||||
                        {
 | 
			
		||||
                            result.Add(new KeyValuePair<string, string>(mpdKey, mpdValue));
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override string ToString()
 | 
			
		||||
        {
 | 
			
		||||
            return JsonConvert.SerializeObject(this, Formatting.Indented);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								LibMpc/Message/MpdRequest.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								LibMpc/Message/MpdRequest.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
namespace LibMpc
 | 
			
		||||
{
 | 
			
		||||
    public interface IMpdRequest<T>
 | 
			
		||||
    {
 | 
			
		||||
        IMpcCommand<T> Command { get; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class MpdRequest<T> : IMpdRequest<T>
 | 
			
		||||
    {
 | 
			
		||||
        public MpdRequest(IMpcCommand<T> command)
 | 
			
		||||
        {
 | 
			
		||||
            Command = command;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IMpcCommand<T> Command { get; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								LibMpc/Message/MpdResponse.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								LibMpc/Message/MpdResponse.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace LibMpc
 | 
			
		||||
{
 | 
			
		||||
    public interface IMpdResponse<T>
 | 
			
		||||
    {
 | 
			
		||||
        IMpdResponseState State { get; }
 | 
			
		||||
        IDictionary<string, T> Body { get; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class MpdResponse<T> : IMpdResponse<T>
 | 
			
		||||
    {
 | 
			
		||||
        public MpdResponse(string endLine, IDictionary<string, T> body, bool connected)
 | 
			
		||||
        {
 | 
			
		||||
            State = new MpdResponseState(endLine, connected);
 | 
			
		||||
            Body = body;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IMpdResponseState State { get; }
 | 
			
		||||
        public IDictionary<string, T> Body { get; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class CheckNotNullExtension
 | 
			
		||||
    {
 | 
			
		||||
        public static void CheckNotNull(this object toBeChecked)
 | 
			
		||||
        {
 | 
			
		||||
            if (toBeChecked == null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException(nameof(toBeChecked));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										66
									
								
								LibMpc/Message/MpdResponseState.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								LibMpc/Message/MpdResponseState.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
 | 
			
		||||
namespace LibMpc
 | 
			
		||||
{
 | 
			
		||||
    public interface IMpdResponseState
 | 
			
		||||
    {
 | 
			
		||||
        string Status { get; }
 | 
			
		||||
        string ErrorMessage { get; }
 | 
			
		||||
        string MpdError { get; }
 | 
			
		||||
        bool Error { get; }
 | 
			
		||||
        bool Connected { get; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class MpdResponseState : IMpdResponseState
 | 
			
		||||
    {
 | 
			
		||||
        private static readonly Regex ErrorPattern = new Regex("^ACK \\[(?<code>[0-9]*)@(?<nr>[0-9]*)] \\{(?<command>[a-z]*)} (?<message>.*)$");
 | 
			
		||||
 | 
			
		||||
        private readonly string _endLine;
 | 
			
		||||
 | 
			
		||||
        public MpdResponseState(string endLine, bool connected)
 | 
			
		||||
        {
 | 
			
		||||
            _endLine = endLine;
 | 
			
		||||
            Connected = connected;
 | 
			
		||||
 | 
			
		||||
            if (!string.IsNullOrEmpty(_endLine))
 | 
			
		||||
            {
 | 
			
		||||
                if (_endLine.Equals(Constants.Ok))
 | 
			
		||||
                {
 | 
			
		||||
                    Status = _endLine;
 | 
			
		||||
                    Error = false;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    ParseErrorResponse();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool Connected { get; } = false;
 | 
			
		||||
        public bool Error { get; } = true;
 | 
			
		||||
        public string Status { get; private set; } = "UNKNOWN";
 | 
			
		||||
        public string ErrorMessage { get; private set; } = string.Empty;
 | 
			
		||||
        public string MpdError { get; private set; } = string.Empty;
 | 
			
		||||
 | 
			
		||||
        private void ParseErrorResponse()
 | 
			
		||||
        {
 | 
			
		||||
            Status = "ERROR";
 | 
			
		||||
            MpdError = _endLine;
 | 
			
		||||
 | 
			
		||||
            var match = ErrorPattern.Match(_endLine);
 | 
			
		||||
 | 
			
		||||
            if (match.Groups.Count != 5)
 | 
			
		||||
            {
 | 
			
		||||
                ErrorMessage = "Unexpected response from server.";
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                var errorCode = match.Result("${code}");
 | 
			
		||||
                var commandListItem = match.Result("${nr}");
 | 
			
		||||
                var commandFailed = match.Result("${command}");
 | 
			
		||||
                var errorMessage = match.Result("${message}");
 | 
			
		||||
                ErrorMessage = $"ErrorCode: { errorCode }, CommandListItem: { commandListItem }, CommandFailed: { commandFailed }, ErrorMessage: { errorMessage }";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										267
									
								
								LibMpc/Mpc.cs
									
									
									
									
									
								
							
							
						
						
									
										267
									
								
								LibMpc/Mpc.cs
									
									
									
									
									
								
							@@ -52,148 +52,16 @@ namespace LibMpc
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // TODO: create response type
 | 
			
		||||
        public async Task<object> SendAsync(IMpcCommand command)
 | 
			
		||||
        public async Task<IMpdMessage<T>> 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.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The id of the output.</param>
 | 
			
		||||
        /// <returns>If the action was successful.</returns>
 | 
			
		||||
        public async Task<bool> DisableOutputAsync(int id)
 | 
			
		||||
        {
 | 
			
		||||
            var mpdResponse = await _connection.Exec("disableoutput", new string[] { id.ToString() });
 | 
			
		||||
            return !mpdResponse.IsError;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Enables an MPD output.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The id of the output.</param>
 | 
			
		||||
        /// <returns>If the action was successful.</returns>
 | 
			
		||||
        public async Task<bool> EnableOutputAsync(int id)
 | 
			
		||||
        {
 | 
			
		||||
            var mpdResponse = await _connection.Exec("enableoutput", new string[] { id.ToString() });
 | 
			
		||||
            return !mpdResponse.IsError;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Lists all outputs of the MPD.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>The list of all MPD outputs.</returns>
 | 
			
		||||
        public async Task<MpdOutput[]> OutputsAsync()
 | 
			
		||||
        {
 | 
			
		||||
            MpdResponse response = await _connection.Exec("outputs");
 | 
			
		||||
            if (response.Message.Count % 3 != 0)
 | 
			
		||||
                throw new InvalidMpdResponseException();
 | 
			
		||||
 | 
			
		||||
            MpdOutput[] ret = new MpdOutput[response.Message.Count / 3];
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < ret.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                int id;
 | 
			
		||||
                string name;
 | 
			
		||||
                int enabled;
 | 
			
		||||
 | 
			
		||||
                KeyValuePair<string, string> idLine = response[i * 3];
 | 
			
		||||
                if (idLine.Key == null)
 | 
			
		||||
                    throw new InvalidMpdResponseException("Invalid form of line " + (i * 3));
 | 
			
		||||
                if (!idLine.Key.Equals("outputid"))
 | 
			
		||||
                    throw new InvalidMpdResponseException("Key of line " + (i * 3) + " is not 'outputid'");
 | 
			
		||||
                if (!int.TryParse(idLine.Value, out id))
 | 
			
		||||
                    throw new InvalidMpdResponseException("Value of line " + (i * 3) + " is not a number");
 | 
			
		||||
 | 
			
		||||
                KeyValuePair<string, string> nameLine = response[i * 3 + 1];
 | 
			
		||||
                if (nameLine.Key == null)
 | 
			
		||||
                    throw new InvalidMpdResponseException("Invalid form of line " + (i * 3 + 1));
 | 
			
		||||
                if (!nameLine.Key.Equals("outputname"))
 | 
			
		||||
                    throw new InvalidMpdResponseException("Key of line " + (i * 3 + 1) + " is not 'outputname'");
 | 
			
		||||
                name = nameLine.Value;
 | 
			
		||||
 | 
			
		||||
                KeyValuePair<string, string> enabledLine = response[i * 3 + 2];
 | 
			
		||||
                if (enabledLine.Key == null)
 | 
			
		||||
                    throw new InvalidMpdResponseException("Invalid form of line " + (i * 3 + 2));
 | 
			
		||||
                if (!enabledLine.Key.Equals("outputenabled"))
 | 
			
		||||
                    throw new InvalidMpdResponseException("Key of line " + (i * 3 + 2) + " is not 'outputenabled'");
 | 
			
		||||
                if (!int.TryParse(enabledLine.Value, out enabled))
 | 
			
		||||
                    throw new InvalidMpdResponseException("Value of line " + (i * 3 + 2) + " is not a number");
 | 
			
		||||
 | 
			
		||||
                ret[i] = new MpdOutput(id, name, enabled > 0);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Returns the list of tag types the MPD supports.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>The list of tag types the MPD supports.</returns>
 | 
			
		||||
        public async Task<string[]> TagTypesAsync()
 | 
			
		||||
        {
 | 
			
		||||
            MpdResponse response = await _connection.Exec("tagtypes");
 | 
			
		||||
 | 
			
		||||
            string[] ret = new string[response.Message.Count];
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < ret.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                KeyValuePair<string, string> line = response[i];
 | 
			
		||||
                if (!line.Key.Equals("tagtype"))
 | 
			
		||||
                    throw new InvalidMpdResponseException("Key of line " + (i) + " is not 'tagtype'");
 | 
			
		||||
                ret[i] = line.Value;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Starts an update of the MPD database.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>An sequential number of the update process.</returns>
 | 
			
		||||
        public async Task<int> UpdateAsync()
 | 
			
		||||
        {
 | 
			
		||||
            MpdResponse response = await _connection.Exec("update");
 | 
			
		||||
 | 
			
		||||
            if (response.Message.Count != 1)
 | 
			
		||||
                throw new InvalidMpdResponseException("Respose message has more than one line.");
 | 
			
		||||
 | 
			
		||||
            int ret;
 | 
			
		||||
 | 
			
		||||
            KeyValuePair<string, string> line = response[0];
 | 
			
		||||
            if (!line.Key.Equals("updating_db"))
 | 
			
		||||
                throw new InvalidMpdResponseException("Key of line 0 is not 'updating_db'");
 | 
			
		||||
            if (!int.TryParse(line.Value, out ret))
 | 
			
		||||
                throw new InvalidMpdResponseException("Value of line 0 is not a number");
 | 
			
		||||
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
        #region Database Commands
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Returns all files in the database who's attribute matches the given token. Works like the Search command but is case sensitive.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="tag">Specifies the attribute to search for.</param>
 | 
			
		||||
        /// <param name="token">The value the files attribute must have to be included in the result.</param>
 | 
			
		||||
        /// <returns>All files in the database who's attribute matches the given token.</returns>
 | 
			
		||||
        public async Task<List<MpdFile>> FindAsync(ITag tag, string token)
 | 
			
		||||
        {
 | 
			
		||||
            if (token == null)
 | 
			
		||||
                throw new ArgumentNullException("token");
 | 
			
		||||
        
 | 
			
		||||
            MpdResponse response = await _connection.Exec("find", new string[] { tag.Value, token });
 | 
			
		||||
 | 
			
		||||
            if (response.IsError)
 | 
			
		||||
                throw new MpdResponseException(response.ErrorCode, response.ErrorMessage);
 | 
			
		||||
 | 
			
		||||
            return MpdFile.buildList(response);
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Returns all values found in files of the MPD for the given attribute.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -201,9 +69,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 +88,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 +105,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 +122,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 +146,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 +169,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 +189,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 +204,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 +226,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 +237,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 +250,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 +261,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 +275,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 +292,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 +304,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 +316,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 +327,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 +341,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 +354,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 +368,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 +382,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 +399,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 +446,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 +460,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 +470,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 +482,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 +494,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 +509,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 +526,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 +545,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 +559,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 +574,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 +590,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 +606,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 +624,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 +640,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 +650,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 +661,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 +671,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 +682,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 +692,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 +703,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 +713,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 +724,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 +735,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 +747,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 +759,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 +775,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 +785,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 +799,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 +807,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 +820,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 +837,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 +845,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 +853,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 +931,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 +1101,6 @@ namespace LibMpc
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
        */
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,9 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Collections.ObjectModel;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Net;
 | 
			
		||||
using System.Net.Sockets;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace LibMpc
 | 
			
		||||
@@ -17,12 +15,6 @@ namespace LibMpc
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class MpcConnection
 | 
			
		||||
    {
 | 
			
		||||
        private static readonly string FIRST_LINE_PREFIX = "OK MPD ";
 | 
			
		||||
 | 
			
		||||
        private static readonly string OK = "OK";
 | 
			
		||||
        private static readonly string ACK = "ACK";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private readonly IPEndPoint _server;
 | 
			
		||||
 | 
			
		||||
        private TcpClient _tcpClient;
 | 
			
		||||
@@ -61,12 +53,12 @@ namespace LibMpc
 | 
			
		||||
            _writer = new StreamWriter(_networkStream, Encoding.UTF8) { NewLine = "\n" };
 | 
			
		||||
 | 
			
		||||
            var firstLine = _reader.ReadLine();
 | 
			
		||||
            if (!firstLine.StartsWith(FIRST_LINE_PREFIX))
 | 
			
		||||
            if (!firstLine.StartsWith(Constants.FirstLinePrefix))
 | 
			
		||||
            {
 | 
			
		||||
                await DisconnectAsync();
 | 
			
		||||
                throw new InvalidDataException("Response of mpd does not start with \"" + FIRST_LINE_PREFIX + "\"." );
 | 
			
		||||
                throw new InvalidDataException("Response of mpd does not start with \"" + Constants.FirstLinePrefix + "\"." );
 | 
			
		||||
            }
 | 
			
		||||
            _version = firstLine.Substring(FIRST_LINE_PREFIX.Length);
 | 
			
		||||
            _version = firstLine.Substring(Constants.FirstLinePrefix.Length);
 | 
			
		||||
 | 
			
		||||
            await _writer.WriteLineAsync();
 | 
			
		||||
            _writer.Flush();
 | 
			
		||||
@@ -86,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()
 | 
			
		||||
@@ -176,41 +113,19 @@ 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>();
 | 
			
		||||
            var currentLine = _reader.ReadLine();
 | 
			
		||||
 | 
			
		||||
            // Read response untli reach end token (OK or ACK)
 | 
			
		||||
            while (!(currentLine.Equals(OK) || currentLine.StartsWith(ACK)))
 | 
			
		||||
            string responseLine;
 | 
			
		||||
            do
 | 
			
		||||
            {
 | 
			
		||||
                response.Add(currentLine);
 | 
			
		||||
                currentLine = await _reader.ReadLineAsync();
 | 
			
		||||
            }
 | 
			
		||||
                responseLine = await _reader.ReadLineAsync();
 | 
			
		||||
                response.Add(responseLine);
 | 
			
		||||
            } while (!(responseLine.Equals(Constants.Ok) || responseLine.StartsWith(Constants.Ack) || string.IsNullOrEmpty(responseLine)));
 | 
			
		||||
 | 
			
		||||
            if (currentLine.Equals(OK))
 | 
			
		||||
            {
 | 
			
		||||
                return new MpdResponse(new ReadOnlyCollection<string>(response));
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return AcknowledgeResponse.Parse(currentLine, response);
 | 
			
		||||
            }
 | 
			
		||||
            return response.ToArray();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ClearConnectionFields() 
 | 
			
		||||
@@ -222,24 +137,4 @@ namespace LibMpc
 | 
			
		||||
            _version = string.Empty;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class AcknowledgeResponse
 | 
			
		||||
    {
 | 
			
		||||
        private static readonly Regex AcknowledgePattern = new Regex("^ACK \\[(?<code>[0-9]*)@(?<nr>[0-9]*)] \\{(?<command>[a-z]*)} (?<message>.*)$");
 | 
			
		||||
 | 
			
		||||
        public static MpdResponse Parse(string acknowledgeResponse, IList<string> payload)
 | 
			
		||||
        {
 | 
			
		||||
            var match = AcknowledgePattern.Match(acknowledgeResponse);
 | 
			
		||||
 | 
			
		||||
            if (match.Groups.Count != 5)
 | 
			
		||||
                throw new InvalidDataException("Error response not as expected");
 | 
			
		||||
 | 
			
		||||
            return new MpdResponse(
 | 
			
		||||
                int.Parse(match.Result("${code}")),
 | 
			
		||||
                int.Parse(match.Result("${nr}")),
 | 
			
		||||
                match.Result("${command}"),
 | 
			
		||||
                match.Result("${message}"),
 | 
			
		||||
                new ReadOnlyCollection<string>(payload));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
        }
 | 
			
		||||
        */
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,308 +0,0 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Collections.ObjectModel;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
 | 
			
		||||
namespace LibMpc
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// The MpdResponse class parses the response to an MPD command in it's most
 | 
			
		||||
    /// basic structure.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class MpdResponse : IEnumerable<KeyValuePair<string, string>>
 | 
			
		||||
    {
 | 
			
		||||
        private const string OK = "OK";
 | 
			
		||||
        private const string ACK = "ACK";
 | 
			
		||||
 | 
			
		||||
        private static readonly Regex LINE_REGEX = new Regex("^(?<key>[A-Za-z]*):[ ]{0,1}(?<value>.*)$");
 | 
			
		||||
 | 
			
		||||
        private readonly bool isError;
 | 
			
		||||
        private readonly int errorCode;
 | 
			
		||||
        private readonly int commandListNum;
 | 
			
		||||
        private readonly string currentCommand;
 | 
			
		||||
        private readonly string errorMessage;
 | 
			
		||||
        private readonly ReadOnlyCollection<string> message;
 | 
			
		||||
 | 
			
		||||
        private Dictionary<string, string> dictionary = null;
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// If the response denotes an error in the last command.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool IsError { get { return this.isError; } }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The error code if an error occured.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public int ErrorCode { get { return this.errorCode; } }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// If an error occured the index of the invalid command in a command list.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public int CommandListNum { get { return this.commandListNum; } }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The command executed.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string CurrentCommand { get { return this.currentCommand; } }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The description of the error, if occured.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string ErrorMessage { get { return this.errorMessage; } }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The lines of the response message.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ReadOnlyCollection<string> Message { get { return this.message; } }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The value of an attribute in the MPD response.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="key">The name of the attribute.</param>
 | 
			
		||||
        /// <returns>The value of the attribute</returns>
 | 
			
		||||
        public string this[string key]
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                if (this.dictionary == null)
 | 
			
		||||
                {
 | 
			
		||||
                    this.dictionary = new Dictionary<string,string>();
 | 
			
		||||
 | 
			
		||||
                    foreach (string line in this.message)
 | 
			
		||||
                    {
 | 
			
		||||
                        Match match = LINE_REGEX.Match(line);
 | 
			
		||||
                        if (match.Success)
 | 
			
		||||
                            this.dictionary[match.Result("$key")] = match.Result("$value");
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return this.dictionary[key];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The number of lines in the response message.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public int Count { get { return this.message.Count; } }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// A line in the MPD response as KeyValuePair. If the message cannot be separated
 | 
			
		||||
        /// into key and value according to the MPD protocol spec, a KeyValuePair is returned
 | 
			
		||||
        /// with the key null and the value the whole text of the line.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="line">The index of the line.</param>
 | 
			
		||||
        /// <returns>The requested line as KeyValuePair.</returns>
 | 
			
		||||
        public KeyValuePair<string, string> this[int line]
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                Match match = LINE_REGEX.Match(this.message[line]);
 | 
			
		||||
                if (match.Success)
 | 
			
		||||
                    return new KeyValuePair<string, string>(match.Result("${key}"), match.Result("${value}"));
 | 
			
		||||
                else
 | 
			
		||||
                    return new KeyValuePair<string,string>(null, this.message[line]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Creates a new MpdResponse from a list of lines in case no error occured.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="message">The response to an MPD command.</param>
 | 
			
		||||
        public MpdResponse( ReadOnlyCollection<string> message )
 | 
			
		||||
        {
 | 
			
		||||
            if (message == null)
 | 
			
		||||
                throw new ArgumentNullException("message");
 | 
			
		||||
 | 
			
		||||
            this.isError = false;
 | 
			
		||||
            this.errorCode = -1;
 | 
			
		||||
            this.commandListNum = 0;
 | 
			
		||||
            this.currentCommand = null;
 | 
			
		||||
            this.errorMessage = null;
 | 
			
		||||
            this.message = message;
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Creates a new MpdResponse in case an error occured.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="errorCode">The code of the error.</param>
 | 
			
		||||
        /// <param name="commandListNum">The index of the command which raised the error.</param>
 | 
			
		||||
        /// <param name="currentCommand">The command that raised the error.</param>
 | 
			
		||||
        /// <param name="errorMessage">The message describing the error.</param>
 | 
			
		||||
        /// <param name="message">The text of the standard MPD response.</param>
 | 
			
		||||
        public MpdResponse( int errorCode, int commandListNum, string currentCommand, string errorMessage, ReadOnlyCollection<string> message)
 | 
			
		||||
        {
 | 
			
		||||
            if (currentCommand == null)
 | 
			
		||||
                throw new ArgumentNullException("currentCommand");
 | 
			
		||||
            if (errorMessage == null)
 | 
			
		||||
                throw new ArgumentNullException("errorMessage");
 | 
			
		||||
            if (message == null)
 | 
			
		||||
                throw new ArgumentNullException("message");
 | 
			
		||||
 | 
			
		||||
            this.isError = true;
 | 
			
		||||
            this.errorCode = errorCode;
 | 
			
		||||
            this.commandListNum = commandListNum;
 | 
			
		||||
            this.currentCommand = currentCommand;
 | 
			
		||||
            this.errorMessage = errorMessage;
 | 
			
		||||
            this.message = message;
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Returns the values in all lines with the given attribute.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="attribute">The attribute who's values are reguested.</param>
 | 
			
		||||
        /// <returns>The values in all lines with the given attribute.</returns>
 | 
			
		||||
        public List<string> getAttributeValueList(string attribute)
 | 
			
		||||
        {
 | 
			
		||||
            List<string> ret = new List<string>();
 | 
			
		||||
 | 
			
		||||
            foreach (string line in this.message)
 | 
			
		||||
            {
 | 
			
		||||
                Match match = LINE_REGEX.Match(line);
 | 
			
		||||
                if (match.Success)
 | 
			
		||||
                {
 | 
			
		||||
                    string key = match.Result("${key}");
 | 
			
		||||
                    if( ( key != null ) && key.Equals( attribute ) )
 | 
			
		||||
                    {
 | 
			
		||||
                        string value = match.Result("${value}");
 | 
			
		||||
                        if( value != null )
 | 
			
		||||
                            ret.Add( value );
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Returns only the value parts in all key/value pairs in the response.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>The list of values in all key/value pairs in the response.</returns>
 | 
			
		||||
        public List<string> getValueList()
 | 
			
		||||
        {
 | 
			
		||||
            List<string> ret = new List<string>();
 | 
			
		||||
 | 
			
		||||
            foreach (string line in this.message)
 | 
			
		||||
            {
 | 
			
		||||
                Match match = LINE_REGEX.Match(line);
 | 
			
		||||
                if (match.Success)
 | 
			
		||||
                {
 | 
			
		||||
                    string value = match.Result("${value}");
 | 
			
		||||
                    if (value != null)
 | 
			
		||||
                        ret.Add(value);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Builds the response text of the MPD server from the object.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>The response text of the MPD server from the object.</returns>
 | 
			
		||||
        public override string ToString()
 | 
			
		||||
        {
 | 
			
		||||
            StringBuilder builder = new StringBuilder();
 | 
			
		||||
            foreach (string line in this.message)
 | 
			
		||||
                builder.AppendLine(line);
 | 
			
		||||
 | 
			
		||||
            if (this.isError)
 | 
			
		||||
            {
 | 
			
		||||
                builder.Append(ACK);
 | 
			
		||||
                builder.Append(" [");
 | 
			
		||||
                builder.Append(this.errorMessage);
 | 
			
		||||
                builder.Append('@');
 | 
			
		||||
                builder.Append(this.commandListNum);
 | 
			
		||||
                builder.Append("] {");
 | 
			
		||||
                builder.Append(this.currentCommand);
 | 
			
		||||
                builder.Append("} ");
 | 
			
		||||
                builder.Append(this.errorMessage);
 | 
			
		||||
                //ACK [50@1] {play} song doesn't exist: "10240"
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
                builder.Append(OK);
 | 
			
		||||
 | 
			
		||||
            return builder.ToString();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region IEnumerable<KeyValuePair<string,string>> Members
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Returns an enumerator for all KeyValuePairs in the MPD response.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>An enumerator for all KeyValuePairs in the MPD response.</returns>
 | 
			
		||||
        IEnumerator<KeyValuePair<string, string>> IEnumerable<KeyValuePair<string, string>>.GetEnumerator()
 | 
			
		||||
        {
 | 
			
		||||
            return new MpdResponseEnumerator(this);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region IEnumerable Members
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Returns an enumerator for all KeyValuePairs in the MPD response.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>An enumerator for all KeyValuePairs in the MPD response.</returns>
 | 
			
		||||
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
 | 
			
		||||
        {
 | 
			
		||||
            return new MpdResponseEnumerator(this);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// A class for enumerating over the KeyValuePairs in the response.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class MpdResponseEnumerator :IEnumerator<KeyValuePair<string, string>>
 | 
			
		||||
    {
 | 
			
		||||
        private readonly MpdResponse response;
 | 
			
		||||
        private int position = -1;
 | 
			
		||||
        private KeyValuePair<string, string> current;
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Creates a new MpdResponseEnumerator.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="response">The response to enumerate over.</param>
 | 
			
		||||
        protected internal MpdResponseEnumerator(MpdResponse response)
 | 
			
		||||
        {
 | 
			
		||||
            this.response = response;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region IEnumerator<KeyValuePair<string,string>> Members
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Returns the current element of the enumerator.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        KeyValuePair<string, string> IEnumerator<KeyValuePair<string, string>>.Current
 | 
			
		||||
        {
 | 
			
		||||
            get { return this.current; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region IDisposable Members
 | 
			
		||||
 | 
			
		||||
        void IDisposable.Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            this.position = -1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region IEnumerator Members
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Returns the current element of the enumerator.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        object System.Collections.IEnumerator.Current
 | 
			
		||||
        {
 | 
			
		||||
            get { return this.current; }
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Moves the enumerator to the next KeyValuePair in the MPD response.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>If the enumerator has any values left.</returns>
 | 
			
		||||
        bool System.Collections.IEnumerator.MoveNext()
 | 
			
		||||
        {
 | 
			
		||||
            this.position++;
 | 
			
		||||
            if (this.position < this.response.Count)
 | 
			
		||||
            {
 | 
			
		||||
                this.current = this.response[this.position];
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
                return false;
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Sets the enumerator to it's initial state.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        void System.Collections.IEnumerator.Reset()
 | 
			
		||||
        {
 | 
			
		||||
            this.position = -1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,39 +0,0 @@
 | 
			
		||||
namespace LibMpc
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// https://www.musicpd.org/doc/protocol/tags.html
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class Tags
 | 
			
		||||
    {
 | 
			
		||||
        internal class Tag : ITag
 | 
			
		||||
        {
 | 
			
		||||
            internal Tag(string value)
 | 
			
		||||
            {
 | 
			
		||||
                Value = value;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            public string Value { get; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ITag Artist { get; } = new Tag("artist");
 | 
			
		||||
        public ITag ArtistSort { get; } = new Tag("artistsort");
 | 
			
		||||
        public ITag Album { get; } = new Tag("album");
 | 
			
		||||
        public ITag AlbumSort { get; } = new Tag("albumsort");
 | 
			
		||||
        public ITag AlbumArtist { get; } = new Tag("albumartist");
 | 
			
		||||
        public ITag AlbumArtistSort { get; } = new Tag("albumartistsort");
 | 
			
		||||
        public ITag Title { get; } = new Tag("title");
 | 
			
		||||
        public ITag Track { get; } = new Tag("track");
 | 
			
		||||
        public ITag Name { get; } = new Tag("name");
 | 
			
		||||
        public ITag Genre { get; } = new Tag("genre");
 | 
			
		||||
        public ITag Date { get; } = new Tag("date");
 | 
			
		||||
        public ITag Composer { get; } = new Tag("composer");
 | 
			
		||||
        public ITag Performer { get; } = new Tag("performer");
 | 
			
		||||
        public ITag Comment { get; } = new Tag("comment");
 | 
			
		||||
        public ITag Disc { get; } = new Tag("disc");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public interface ITag
 | 
			
		||||
    {
 | 
			
		||||
        string Value { get; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								LibMpc/Tags/FindTags.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								LibMpc/Tags/FindTags.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
namespace LibMpc
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// https://www.musicpd.org/doc/protocol/database.html : find {TYPE} {WHAT} [...] [window START:END]
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class FindTags
 | 
			
		||||
    {
 | 
			
		||||
        public static ITag Any { get; } = new Tag("any");
 | 
			
		||||
        public static ITag File { get; } = new Tag("file");
 | 
			
		||||
        public static ITag Base { get; } = new Tag("base");
 | 
			
		||||
        public static ITag ModifiedSince { get; } = new Tag("modified-since");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								LibMpc/Tags/MpdTags.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								LibMpc/Tags/MpdTags.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
namespace LibMpc
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// https://www.musicpd.org/doc/protocol/tags.html
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class MpdTags
 | 
			
		||||
    {
 | 
			
		||||
        public static ITag Artist { get; } = new Tag("artist");
 | 
			
		||||
        public static ITag ArtistSort { get; } = new Tag("artistsort");
 | 
			
		||||
        public static ITag Album { get; } = new Tag("album");
 | 
			
		||||
        public static ITag AlbumSort { get; } = new Tag("albumsort");
 | 
			
		||||
        public static ITag AlbumArtist { get; } = new Tag("albumartist");
 | 
			
		||||
        public static ITag AlbumArtistSort { get; } = new Tag("albumartistsort");
 | 
			
		||||
        public static ITag Title { get; } = new Tag("title");
 | 
			
		||||
        public static ITag Track { get; } = new Tag("track");
 | 
			
		||||
        public static ITag Name { get; } = new Tag("name");
 | 
			
		||||
        public static ITag Genre { get; } = new Tag("genre");
 | 
			
		||||
        public static ITag Date { get; } = new Tag("date");
 | 
			
		||||
        public static ITag Composer { get; } = new Tag("composer");
 | 
			
		||||
        public static ITag Performer { get; } = new Tag("performer");
 | 
			
		||||
        public static ITag Comment { get; } = new Tag("comment");
 | 
			
		||||
        public static ITag Disc { get; } = new Tag("disc");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								LibMpc/Tags/Tag.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								LibMpc/Tags/Tag.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
namespace LibMpc
 | 
			
		||||
{
 | 
			
		||||
    public interface ITag
 | 
			
		||||
    {
 | 
			
		||||
        string Value { get; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    internal class Tag : ITag
 | 
			
		||||
    {
 | 
			
		||||
        internal Tag(string value)
 | 
			
		||||
        {
 | 
			
		||||
            Value = value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string Value { get; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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": {
 | 
			
		||||
 
 | 
			
		||||
@@ -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,27 @@ 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;
 | 
			
		||||
 | 
			
		||||
                    case 313:
 | 
			
		||||
                        response = mpc.SendAsync(new Commands.Database.Update()).GetAwaiter().GetResult();
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                Console.WriteLine("Response: ");
 | 
			
		||||
@@ -55,7 +64,21 @@ namespace LibMpcApp
 | 
			
		||||
        {
 | 
			
		||||
            Console.WriteLine();
 | 
			
		||||
            Console.WriteLine("Commands: ");
 | 
			
		||||
            Console.WriteLine("1. tagtypes");
 | 
			
		||||
 | 
			
		||||
            Console.WriteLine();
 | 
			
		||||
            Console.WriteLine("11. disableoutput 0");
 | 
			
		||||
            Console.WriteLine("12. enableoutput 0");
 | 
			
		||||
            Console.WriteLine("13. outputs");
 | 
			
		||||
 | 
			
		||||
            Console.WriteLine();
 | 
			
		||||
            Console.WriteLine("Reflection");
 | 
			
		||||
            Console.WriteLine("24. tagtypes");
 | 
			
		||||
 | 
			
		||||
            Console.WriteLine();
 | 
			
		||||
            Console.WriteLine("Database");
 | 
			
		||||
            Console.WriteLine("313. update");
 | 
			
		||||
 | 
			
		||||
            Console.WriteLine();
 | 
			
		||||
            Console.WriteLine("99. Exit");
 | 
			
		||||
            Console.WriteLine();
 | 
			
		||||
            var result = Console.ReadLine();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user