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

src dir created

This commit is contained in:
glucaci 2017-04-12 11:21:29 +02:00
parent 21ceb47523
commit 4b1e3d7b70
61 changed files with 2869 additions and 2869 deletions

28
.gitignore vendored
View File

@ -2,21 +2,21 @@
# This .gitignore file was automatically created by Microsoft(R) Visual Studio. # This .gitignore file was automatically created by Microsoft(R) Visual Studio.
################################################################################ ################################################################################
/.vs /src/.vs
/LibMpc/bin /src/LibMpc/bin
/LibMpc/obj /src/LibMpc/obj
/LibMpc/LibMpc.xproj.user /src/LibMpc/LibMpc.xproj.user
/LibMpc/project.lock.json /src/LibMpc/project.lock.json
/LibMpcApp/bin /src/LibMpcApp/bin
/LibMpcApp/obj /src/LibMpcApp/obj
/LibMpcApp/LibMpcApp.xproj.user /src/LibMpcApp/LibMpcApp.xproj.user
/LibMpcApp/project.lock.json /src/LibMpcApp/project.lock.json
/LibMpcTest/bin /src/LibMpcTest/bin
/LibMpcTest/obj /src/LibMpcTest/obj
/LibMpcTest/LibMpcTest.xproj.user /src/LibMpcTest/LibMpcTest.xproj.user
/LibMpcTest/project.lock.json /src/LibMpcTest/project.lock.json
/LibMpc.sln.DotSettings.user /src/LibMpc.sln.DotSettings.user

View File

@ -1,33 +1,33 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio 15
VisualStudioVersion = 15.0.26403.3 VisualStudioVersion = 15.0.26403.3
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Utilities", "Solution Utilities", "{83D06F7C-1336-4AC3-82BB-FDE7940D3C10}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Utilities", "Solution Utilities", "{83D06F7C-1336-4AC3-82BB-FDE7940D3C10}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
.travis.yml = .travis.yml .travis.yml = .travis.yml
EndProjectSection EndProjectSection
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibMpc", "LibMpc\LibMpc.csproj", "{8994C820-7BA9-4BB8-B9EA-C608B07C4A11}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibMpc", "LibMpc\LibMpc.csproj", "{8994C820-7BA9-4BB8-B9EA-C608B07C4A11}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibMpcTest", "LibMpcTest\LibMpcTest.csproj", "{69F1D68F-9CD5-4EA6-9B47-2A7A9BF8CED9}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibMpcTest", "LibMpcTest\LibMpcTest.csproj", "{69F1D68F-9CD5-4EA6-9B47-2A7A9BF8CED9}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8994C820-7BA9-4BB8-B9EA-C608B07C4A11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8994C820-7BA9-4BB8-B9EA-C608B07C4A11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8994C820-7BA9-4BB8-B9EA-C608B07C4A11}.Debug|Any CPU.Build.0 = Debug|Any CPU {8994C820-7BA9-4BB8-B9EA-C608B07C4A11}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8994C820-7BA9-4BB8-B9EA-C608B07C4A11}.Release|Any CPU.ActiveCfg = Release|Any CPU {8994C820-7BA9-4BB8-B9EA-C608B07C4A11}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8994C820-7BA9-4BB8-B9EA-C608B07C4A11}.Release|Any CPU.Build.0 = Release|Any CPU {8994C820-7BA9-4BB8-B9EA-C608B07C4A11}.Release|Any CPU.Build.0 = Release|Any CPU
{69F1D68F-9CD5-4EA6-9B47-2A7A9BF8CED9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {69F1D68F-9CD5-4EA6-9B47-2A7A9BF8CED9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{69F1D68F-9CD5-4EA6-9B47-2A7A9BF8CED9}.Debug|Any CPU.Build.0 = Debug|Any CPU {69F1D68F-9CD5-4EA6-9B47-2A7A9BF8CED9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{69F1D68F-9CD5-4EA6-9B47-2A7A9BF8CED9}.Release|Any CPU.ActiveCfg = Release|Any CPU {69F1D68F-9CD5-4EA6-9B47-2A7A9BF8CED9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{69F1D68F-9CD5-4EA6-9B47-2A7A9BF8CED9}.Release|Any CPU.Build.0 = Release|Any CPU {69F1D68F-9CD5-4EA6-9B47-2A7A9BF8CED9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@ -1,123 +1,123 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using LibMpc.Types; using LibMpc.Types;
namespace LibMpc namespace LibMpc
{ {
public partial class Commands public partial class Commands
{ {
/// <summary> /// <summary>
/// https://www.musicpd.org/doc/protocol/database.html /// https://www.musicpd.org/doc/protocol/database.html
/// </summary> /// </summary>
public class Database public class Database
{ {
// TODO: count // TODO: count
/// <summary> /// <summary>
/// Finds songs in the database that is exactly "searchText". /// Finds songs in the database that is exactly "searchText".
/// </summary> /// </summary>
public class Find : IMpcCommand<IEnumerable<IMpdFile>> public class Find : IMpcCommand<IEnumerable<IMpdFile>>
{ {
private readonly ITag _tag; private readonly ITag _tag;
private readonly string _searchText; private readonly string _searchText;
public Find(ITag tag, string searchText) public Find(ITag tag, string searchText)
{ {
_tag = tag; _tag = tag;
_searchText = searchText; _searchText = searchText;
} }
public string Value => string.Join(" ", "find", _tag.Value, _searchText); public string Value => string.Join(" ", "find", _tag.Value, _searchText);
public IEnumerable<IMpdFile> FormatResponse(IList<KeyValuePair<string, string>> response) public IEnumerable<IMpdFile> FormatResponse(IList<KeyValuePair<string, string>> response)
{ {
var results = new List<MpdFile>(); var results = new List<MpdFile>();
foreach (var line in response) foreach (var line in response)
{ {
if (line.Key.Equals("file")) if (line.Key.Equals("file"))
{ {
results.Add(new MpdFile(line.Value)); results.Add(new MpdFile(line.Value));
} }
else else
{ {
results.Last().AddTag(line.Key, line.Value); results.Last().AddTag(line.Key, line.Value);
} }
} }
return results; return results;
} }
} }
public class List : IMpcCommand<string> public class List : IMpcCommand<string>
{ {
private readonly ITag _tag; private readonly ITag _tag;
public List(ITag tag) public List(ITag tag)
{ {
_tag = tag; _tag = tag;
} }
public string Value => string.Join(" ", "list", _tag); public string Value => string.Join(" ", "list", _tag);
public string FormatResponse(IList<KeyValuePair<string, string>> response) public string FormatResponse(IList<KeyValuePair<string, string>> response)
{ {
// TODO: // TODO:
return response.ToString(); return response.ToString();
} }
} }
// TODO: findadd // TODO: findadd
public class ListAll : IMpcCommand<IEnumerable<MpdDirectory>> public class ListAll : IMpcCommand<IEnumerable<MpdDirectory>>
{ {
public string Value => "listall"; public string Value => "listall";
public IEnumerable<MpdDirectory> FormatResponse(IList<KeyValuePair<string, string>> response) public IEnumerable<MpdDirectory> FormatResponse(IList<KeyValuePair<string, string>> response)
{ {
var rootDirectory = new List<MpdDirectory> var rootDirectory = new List<MpdDirectory>
{ {
new MpdDirectory("/") // Add by default the root directory new MpdDirectory("/") // Add by default the root directory
}; };
foreach (var line in response) foreach (var line in response)
{ {
if (line.Key.Equals("file")) if (line.Key.Equals("file"))
{ {
rootDirectory.Last().AddFile(line.Value); rootDirectory.Last().AddFile(line.Value);
} }
if (line.Key.Equals("directory")) if (line.Key.Equals("directory"))
{ {
rootDirectory.Add(new MpdDirectory(line.Value)); rootDirectory.Add(new MpdDirectory(line.Value));
} }
} }
return rootDirectory; return rootDirectory;
} }
} }
// TODO: listallinfo // TODO: listallinfo
// TODO: listfiles // TODO: listfiles
// TODO: lsinfo // TODO: lsinfo
// TODO: readcomments // TODO: readcomments
// TODO: search // TODO: search
// TODO: searchadd // TODO: searchadd
// TODO: searchaddpl // TODO: searchaddpl
public class Update : IMpcCommand<string> public class Update : IMpcCommand<string>
{ {
// TODO: Extend command: < update [URI] > // TODO: Extend command: < update [URI] >
public string Value => "update"; public string Value => "update";
public string FormatResponse(IList<KeyValuePair<string, string>> response) public string FormatResponse(IList<KeyValuePair<string, string>> response)
{ {
// TODO: // TODO:
return response.ToString(); return response.ToString();
} }
} }
// TODO: rescan // TODO: rescan
} }
} }
} }

View File

@ -1,101 +1,101 @@
using System.Collections.Generic; using System.Collections.Generic;
using LibMpc.Types; using LibMpc.Types;
namespace LibMpc namespace LibMpc
{ {
public partial class Commands public partial class Commands
{ {
/// <summary> /// <summary>
/// https://www.musicpd.org/doc/protocol/output_commands.html /// https://www.musicpd.org/doc/protocol/output_commands.html
/// </summary> /// </summary>
public class Output public class Output
{ {
/// <summary> /// <summary>
/// Turns an output off. /// Turns an output off.
/// </summary> /// </summary>
public class DisableOutput : IMpcCommand<string> public class DisableOutput : IMpcCommand<string>
{ {
private readonly int _outputId; private readonly int _outputId;
public DisableOutput(int outputId) public DisableOutput(int outputId)
{ {
_outputId = outputId; _outputId = outputId;
} }
public string Value => string.Join(" ", "disableoutput", _outputId); public string Value => string.Join(" ", "disableoutput", _outputId);
public string FormatResponse(IList<KeyValuePair<string, string>> response) public string FormatResponse(IList<KeyValuePair<string, string>> response)
{ {
// Response should be empty. // Response should be empty.
return string.Join(", ", response); return string.Join(", ", response);
} }
} }
/// <summary> /// <summary>
/// Turns an output on. /// Turns an output on.
/// </summary> /// </summary>
public class EnableOutput : IMpcCommand<string> public class EnableOutput : IMpcCommand<string>
{ {
private readonly int _outputId; private readonly int _outputId;
public EnableOutput(int outputId) public EnableOutput(int outputId)
{ {
_outputId = outputId; _outputId = outputId;
} }
public string Value => string.Join(" ", "enableoutput", _outputId); public string Value => string.Join(" ", "enableoutput", _outputId);
public string FormatResponse(IList<KeyValuePair<string, string>> response) public string FormatResponse(IList<KeyValuePair<string, string>> response)
{ {
// Response should be empty. // Response should be empty.
return string.Join(", ", response); return string.Join(", ", response);
} }
} }
/// <summary> /// <summary>
/// Turns an output on or off, depending on the current state. /// Turns an output on or off, depending on the current state.
/// </summary> /// </summary>
public class ToggleOutput : IMpcCommand<string> public class ToggleOutput : IMpcCommand<string>
{ {
private readonly int _outputId; private readonly int _outputId;
public ToggleOutput(int outputId) public ToggleOutput(int outputId)
{ {
_outputId = outputId; _outputId = outputId;
} }
public string Value => string.Join(" ", "toggleoutput", _outputId); public string Value => string.Join(" ", "toggleoutput", _outputId);
public string FormatResponse(IList<KeyValuePair<string, string>> response) public string FormatResponse(IList<KeyValuePair<string, string>> response)
{ {
// Response should be empty. // Response should be empty.
return string.Join(", ", response); return string.Join(", ", response);
} }
} }
/// <summary> /// <summary>
/// Shows information about all outputs. /// Shows information about all outputs.
/// </summary> /// </summary>
public class Outputs : IMpcCommand<IEnumerable<MpdOutput>> public class Outputs : IMpcCommand<IEnumerable<MpdOutput>>
{ {
public string Value => "outputs"; public string Value => "outputs";
public IEnumerable<MpdOutput> FormatResponse(IList<KeyValuePair<string, string>> response) public IEnumerable<MpdOutput> FormatResponse(IList<KeyValuePair<string, string>> response)
{ {
var result = new List<MpdOutput>(); var result = new List<MpdOutput>();
for (var i = 0; i < response.Count; i += 3) for (var i = 0; i < response.Count; i += 3)
{ {
var outputId = int.Parse(response[i].Value); var outputId = int.Parse(response[i].Value);
var outputName = response[i + 1].Value; var outputName = response[i + 1].Value;
var outputEnabled = response[i + 2].Value == "1"; var outputEnabled = response[i + 2].Value == "1";
result.Add(new MpdOutput(outputId, outputName, outputEnabled)); result.Add(new MpdOutput(outputId, outputName, outputEnabled));
} }
return result; return result;
} }
} }
} }
} }
} }

View File

@ -1,103 +1,103 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using LibMpc.Types; using LibMpc.Types;
namespace LibMpc namespace LibMpc
{ {
public partial class Commands public partial class Commands
{ {
public static class Playlists public static class Playlists
{ {
/// <summary> /// <summary>
/// https://www.musicpd.org/doc/protocol/queue.html /// https://www.musicpd.org/doc/protocol/queue.html
/// </summary> /// </summary>
public static class Current public static class Current
{ {
} }
/// <summary> /// <summary>
/// https://www.musicpd.org/doc/protocol/playlist_files.html /// https://www.musicpd.org/doc/protocol/playlist_files.html
/// </summary> /// </summary>
public static class Stored public static class Stored
{ {
public class ListPlaylist : IMpcCommand<IEnumerable<IMpdFilePath>> public class ListPlaylist : IMpcCommand<IEnumerable<IMpdFilePath>>
{ {
private readonly string _playlistName; private readonly string _playlistName;
public ListPlaylist(string playlistName) public ListPlaylist(string playlistName)
{ {
_playlistName = playlistName; _playlistName = playlistName;
} }
public string Value => string.Join(" ", "listplaylist", $"\"{_playlistName}\""); public string Value => string.Join(" ", "listplaylist", $"\"{_playlistName}\"");
public IEnumerable<IMpdFilePath> FormatResponse(IList<KeyValuePair<string, string>> response) public IEnumerable<IMpdFilePath> FormatResponse(IList<KeyValuePair<string, string>> response)
{ {
var results = response.Where(line => line.Key.Equals("file")).Select(line => new MpdFile(line.Value)); var results = response.Where(line => line.Key.Equals("file")).Select(line => new MpdFile(line.Value));
return results; return results;
} }
} }
public class ListPlaylistInfo : IMpcCommand<IEnumerable<IMpdFile>> public class ListPlaylistInfo : IMpcCommand<IEnumerable<IMpdFile>>
{ {
private readonly string _playlistName; private readonly string _playlistName;
public ListPlaylistInfo(string playlistName) public ListPlaylistInfo(string playlistName)
{ {
_playlistName = playlistName; _playlistName = playlistName;
} }
public string Value => string.Join(" ", "listplaylistinfo", $"\"{_playlistName}\""); public string Value => string.Join(" ", "listplaylistinfo", $"\"{_playlistName}\"");
public IEnumerable<IMpdFile> FormatResponse(IList<KeyValuePair<string, string>> response) public IEnumerable<IMpdFile> FormatResponse(IList<KeyValuePair<string, string>> response)
{ {
var results = new List<MpdFile>(); var results = new List<MpdFile>();
foreach (var line in response) foreach (var line in response)
{ {
if (line.Key.Equals("file")) if (line.Key.Equals("file"))
{ {
results.Add(new MpdFile(line.Value)); results.Add(new MpdFile(line.Value));
} }
else else
{ {
results.Last().AddTag(line.Key, line.Value); results.Last().AddTag(line.Key, line.Value);
} }
} }
return results; return results;
} }
} }
/// <summary> /// <summary>
/// Prints a list of the playlist directory. /// Prints a list of the playlist directory.
/// </summary> /// </summary>
public class ListPlaylists : IMpcCommand<IEnumerable<MpdPlaylist>> public class ListPlaylists : IMpcCommand<IEnumerable<MpdPlaylist>>
{ {
public string Value => "listplaylists"; public string Value => "listplaylists";
public IEnumerable<MpdPlaylist> FormatResponse(IList<KeyValuePair<string, string>> response) public IEnumerable<MpdPlaylist> FormatResponse(IList<KeyValuePair<string, string>> response)
{ {
var result = new List<MpdPlaylist>(); var result = new List<MpdPlaylist>();
foreach (var line in response) foreach (var line in response)
{ {
if (line.Key.Equals("playlist")) if (line.Key.Equals("playlist"))
{ {
result.Add(new MpdPlaylist(line.Value)); result.Add(new MpdPlaylist(line.Value));
} }
else if (line.Key.Equals("Last-Modified")) else if (line.Key.Equals("Last-Modified"))
{ {
result.Last().AddLastModified(line.Value); result.Last().AddLastModified(line.Value);
} }
} }
return result; return result;
} }
} }
} }
} }
} }
} }

View File

@ -1,103 +1,103 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using LibMpc.Types; using LibMpc.Types;
namespace LibMpc namespace LibMpc
{ {
public partial class Commands public partial class Commands
{ {
/// <summary> /// <summary>
/// https://www.musicpd.org/doc/protocol/reflection_commands.html /// https://www.musicpd.org/doc/protocol/reflection_commands.html
/// </summary> /// </summary>
public static class Reflection public static class Reflection
{ {
// config : This command is only permitted to "local" clients (connected via UNIX domain socket). // config : This command is only permitted to "local" clients (connected via UNIX domain socket).
/// <summary> /// <summary>
/// Shows which commands the current user has access to. /// Shows which commands the current user has access to.
/// </summary> /// </summary>
public class Commands : IMpcCommand<IEnumerable<string>> public class Commands : IMpcCommand<IEnumerable<string>>
{ {
public string Value => "commands"; public string Value => "commands";
public IEnumerable<string> FormatResponse(IList<KeyValuePair<string, string>> response) public IEnumerable<string> FormatResponse(IList<KeyValuePair<string, string>> response)
{ {
var result = response.Where(item => item.Key.Equals("command")).Select(item => item.Value); var result = response.Where(item => item.Key.Equals("command")).Select(item => item.Value);
return result; return result;
} }
} }
// TODO: notcommands : Shows which commands the current user does not have access to. // TODO: notcommands : Shows which commands the current user does not have access to.
/// <summary> /// <summary>
/// Shows a list of available song metadata. /// Shows a list of available song metadata.
/// </summary> /// </summary>
public class TagTypes : IMpcCommand<IEnumerable<string>> public class TagTypes : IMpcCommand<IEnumerable<string>>
{ {
public string Value => "tagtypes"; public string Value => "tagtypes";
public IEnumerable<string> FormatResponse(IList<KeyValuePair<string, string>> response) public IEnumerable<string> FormatResponse(IList<KeyValuePair<string, string>> response)
{ {
var result = response.Where(item => item.Key.Equals("tagtype")).Select(item => item.Value); var result = response.Where(item => item.Key.Equals("tagtype")).Select(item => item.Value);
return result; return result;
} }
} }
/// <summary> /// <summary>
/// Gets a list of available URL handlers. /// Gets a list of available URL handlers.
/// </summary> /// </summary>
public class UrlHandlers : IMpcCommand<IEnumerable<string>> public class UrlHandlers : IMpcCommand<IEnumerable<string>>
{ {
public string Value => "urlhandlers"; public string Value => "urlhandlers";
public IEnumerable<string> FormatResponse(IList<KeyValuePair<string, string>> response) public IEnumerable<string> FormatResponse(IList<KeyValuePair<string, string>> response)
{ {
var result = response.Where(item => item.Key.Equals("handler")).Select(item => item.Value); var result = response.Where(item => item.Key.Equals("handler")).Select(item => item.Value);
return result; return result;
} }
} }
/// <summary> /// <summary>
/// Print a list of decoder plugins, followed by their supported suffixes and MIME types. /// Print a list of decoder plugins, followed by their supported suffixes and MIME types.
/// </summary> /// </summary>
public class Decoders : IMpcCommand<IEnumerable<MpdDecoderPlugin>> public class Decoders : IMpcCommand<IEnumerable<MpdDecoderPlugin>>
{ {
public string Value => "decoders"; public string Value => "decoders";
public IEnumerable<MpdDecoderPlugin> FormatResponse(IList<KeyValuePair<string, string>> response) public IEnumerable<MpdDecoderPlugin> FormatResponse(IList<KeyValuePair<string, string>> response)
{ {
var result = new List<MpdDecoderPlugin>(); var result = new List<MpdDecoderPlugin>();
var mpdDecoderPlugin = MpdDecoderPlugin.Empty; var mpdDecoderPlugin = MpdDecoderPlugin.Empty;
foreach (var line in response) foreach (var line in response)
{ {
if (line.Key.Equals("plugin")) if (line.Key.Equals("plugin"))
{ {
if (mpdDecoderPlugin.IsInitialized) if (mpdDecoderPlugin.IsInitialized)
{ {
result.Add(mpdDecoderPlugin); result.Add(mpdDecoderPlugin);
} }
mpdDecoderPlugin = new MpdDecoderPlugin(line.Value); mpdDecoderPlugin = new MpdDecoderPlugin(line.Value);
} }
if (line.Key.Equals("suffix") && mpdDecoderPlugin.IsInitialized) if (line.Key.Equals("suffix") && mpdDecoderPlugin.IsInitialized)
{ {
mpdDecoderPlugin.AddSuffix(line.Value); mpdDecoderPlugin.AddSuffix(line.Value);
} }
if (line.Key.Equals("mime_type") && mpdDecoderPlugin.IsInitialized) if (line.Key.Equals("mime_type") && mpdDecoderPlugin.IsInitialized)
{ {
mpdDecoderPlugin.AddMediaType(line.Value); mpdDecoderPlugin.AddMediaType(line.Value);
} }
} }
return result; return result;
} }
} }
} }
} }
} }

View File

@ -1,12 +1,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace LibMpc namespace LibMpc
{ {
public interface IMpcCommand<out T> public interface IMpcCommand<out T>
{ {
string Value { get; } string Value { get; }
T FormatResponse(IList<KeyValuePair<string, string>> response); T FormatResponse(IList<KeyValuePair<string, string>> response);
} }
} }

View File

@ -1,13 +1,13 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LibMpc namespace LibMpc
{ {
public class Constants public class Constants
{ {
public static readonly string Ok = "OK"; public static readonly string Ok = "OK";
public static readonly string Ack = "ACK"; public static readonly string Ack = "ACK";
public static readonly string FirstLinePrefix = "OK MPD "; public static readonly string FirstLinePrefix = "OK MPD ";
} }
} }

View File

@ -1,64 +1,64 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace LibMpc namespace LibMpc
{ {
public interface IMpdMessage<T> public interface IMpdMessage<T>
{ {
IMpdRequest<T> Request { get; } IMpdRequest<T> Request { get; }
IMpdResponse<T> Response { get; } IMpdResponse<T> Response { get; }
} }
[DebuggerDisplay("Request: {Request.Command.Value} | Response Status: {Response.State.Status}")] [DebuggerDisplay("Request: {Request.Command.Value} | Response Status: {Response.State.Status}")]
public class MpdMessage<T> : IMpdMessage<T> public class MpdMessage<T> : IMpdMessage<T>
{ {
private readonly Regex _linePattern = new Regex("^(?<key>[A-Za-z_-]*):[ ]{0,1}(?<value>.*)$"); private readonly Regex _linePattern = new Regex("^(?<key>[A-Za-z_-]*):[ ]{0,1}(?<value>.*)$");
private readonly IList<string> _rawResponse; private readonly IList<string> _rawResponse;
public MpdMessage(IMpcCommand<T> command, bool connected, IReadOnlyCollection<string> response) public MpdMessage(IMpcCommand<T> command, bool connected, IReadOnlyCollection<string> response)
{ {
Request = new MpdRequest<T>(command); Request = new MpdRequest<T>(command);
var endLine = response.Skip(response.Count - 1).Single(); var endLine = response.Skip(response.Count - 1).Single();
_rawResponse = response.Take(response.Count - 1).ToList(); _rawResponse = response.Take(response.Count - 1).ToList();
var values = Request.Command.FormatResponse(GetValuesFromResponse()); var values = Request.Command.FormatResponse(GetValuesFromResponse());
Response = new MpdResponse<T>(endLine, values, connected); Response = new MpdResponse<T>(endLine, values, connected);
} }
public IMpdRequest<T> Request { get; } public IMpdRequest<T> Request { get; }
public IMpdResponse<T> Response { get; } public IMpdResponse<T> Response { get; }
private IList<KeyValuePair<string, string>> GetValuesFromResponse() private IList<KeyValuePair<string, string>> GetValuesFromResponse()
{ {
var result = new List<KeyValuePair<string, string>>(); var result = new List<KeyValuePair<string, string>>();
foreach (var line in _rawResponse) foreach (var line in _rawResponse)
{ {
var match = _linePattern.Match(line); var match = _linePattern.Match(line);
if (match.Success) if (match.Success)
{ {
var mpdKey = match.Result("${key}"); var mpdKey = match.Result("${key}");
if (!string.IsNullOrEmpty(mpdKey)) if (!string.IsNullOrEmpty(mpdKey))
{ {
var mpdValue = match.Result("${value}"); var mpdValue = match.Result("${value}");
if (!string.IsNullOrEmpty(mpdValue)) if (!string.IsNullOrEmpty(mpdValue))
{ {
result.Add(new KeyValuePair<string, string>(mpdKey, mpdValue)); result.Add(new KeyValuePair<string, string>(mpdKey, mpdValue));
} }
} }
} }
} }
return result; return result;
} }
public override string ToString() public override string ToString()
{ {
return JsonConvert.SerializeObject(this, Formatting.Indented); return JsonConvert.SerializeObject(this, Formatting.Indented);
} }
} }
} }

View File

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

View File

@ -1,34 +1,34 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace LibMpc namespace LibMpc
{ {
public interface IMpdResponse<T> public interface IMpdResponse<T>
{ {
IMpdResponseState State { get; } IMpdResponseState State { get; }
T Body { get; } T Body { get; }
} }
public class MpdResponse<T> : IMpdResponse<T> public class MpdResponse<T> : IMpdResponse<T>
{ {
public MpdResponse(string endLine, T body, bool connected) public MpdResponse(string endLine, T body, bool connected)
{ {
State = new MpdResponseState(endLine, connected); State = new MpdResponseState(endLine, connected);
Body = body; Body = body;
} }
public IMpdResponseState State { get; } public IMpdResponseState State { get; }
public T Body { get; } public T Body { get; }
} }
public static class CheckNotNullExtension public static class CheckNotNullExtension
{ {
public static void CheckNotNull(this object toBeChecked) public static void CheckNotNull(this object toBeChecked)
{ {
if (toBeChecked == null) if (toBeChecked == null)
{ {
throw new ArgumentNullException(nameof(toBeChecked)); throw new ArgumentNullException(nameof(toBeChecked));
} }
} }
} }
} }

View File

@ -1,66 +1,66 @@
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace LibMpc namespace LibMpc
{ {
public interface IMpdResponseState public interface IMpdResponseState
{ {
string Status { get; } string Status { get; }
string ErrorMessage { get; } string ErrorMessage { get; }
string MpdError { get; } string MpdError { get; }
bool Error { get; } bool Error { get; }
bool Connected { get; } bool Connected { get; }
} }
public class MpdResponseState : IMpdResponseState public class MpdResponseState : IMpdResponseState
{ {
private static readonly Regex ErrorPattern = new Regex("^ACK \\[(?<code>[0-9]*)@(?<nr>[0-9]*)] \\{(?<command>[a-z]*)} (?<message>.*)$"); private static readonly Regex ErrorPattern = new Regex("^ACK \\[(?<code>[0-9]*)@(?<nr>[0-9]*)] \\{(?<command>[a-z]*)} (?<message>.*)$");
private readonly string _endLine; private readonly string _endLine;
public MpdResponseState(string endLine, bool connected) public MpdResponseState(string endLine, bool connected)
{ {
_endLine = endLine; _endLine = endLine;
Connected = connected; Connected = connected;
if (!string.IsNullOrEmpty(_endLine)) if (!string.IsNullOrEmpty(_endLine))
{ {
if (_endLine.Equals(Constants.Ok)) if (_endLine.Equals(Constants.Ok))
{ {
Status = _endLine; Status = _endLine;
Error = false; Error = false;
} }
else else
{ {
ParseErrorResponse(); ParseErrorResponse();
} }
} }
} }
public bool Connected { get; } = false; public bool Connected { get; } = false;
public bool Error { get; } = true; public bool Error { get; } = true;
public string Status { get; private set; } = "UNKNOWN"; public string Status { get; private set; } = "UNKNOWN";
public string ErrorMessage { get; private set; } = string.Empty; public string ErrorMessage { get; private set; } = string.Empty;
public string MpdError { get; private set; } = string.Empty; public string MpdError { get; private set; } = string.Empty;
private void ParseErrorResponse() private void ParseErrorResponse()
{ {
Status = "ERROR"; Status = "ERROR";
MpdError = _endLine; MpdError = _endLine;
var match = ErrorPattern.Match(_endLine); var match = ErrorPattern.Match(_endLine);
if (match.Groups.Count != 5) if (match.Groups.Count != 5)
{ {
ErrorMessage = "Unexpected response from server."; ErrorMessage = "Unexpected response from server.";
} }
else else
{ {
var errorCode = match.Result("${code}"); var errorCode = match.Result("${code}");
var commandListItem = match.Result("${nr}"); var commandListItem = match.Result("${nr}");
var commandFailed = match.Result("${command}"); var commandFailed = match.Result("${command}");
var errorMessage = match.Result("${message}"); var errorMessage = match.Result("${message}");
ErrorMessage = $"ErrorCode: { errorCode }, CommandListItem: { commandListItem }, CommandFailed: { commandFailed }, ErrorMessage: { errorMessage }"; ErrorMessage = $"ErrorCode: { errorCode }, CommandListItem: { commandListItem }, CommandFailed: { commandFailed }, ErrorMessage: { errorMessage }";
} }
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,137 +1,137 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LibMpc namespace LibMpc
{ {
/// <summary> /// <summary>
/// Keeps the connection to the MPD server and handels the most basic structure of the /// Keeps the connection to the MPD server and handels the most basic structure of the
/// MPD protocol. The high level commands are handeled in the <see cref="Mpc"/> /// MPD protocol. The high level commands are handeled in the <see cref="Mpc"/>
/// class. /// class.
/// </summary> /// </summary>
public class MpcConnection public class MpcConnection
{ {
private readonly IPEndPoint _server; private readonly IPEndPoint _server;
private TcpClient _tcpClient; private TcpClient _tcpClient;
private NetworkStream _networkStream; private NetworkStream _networkStream;
private StreamReader _reader; private StreamReader _reader;
private StreamWriter _writer; private StreamWriter _writer;
private string _version; private string _version;
public MpcConnection(IPEndPoint server) public MpcConnection(IPEndPoint server)
{ {
if (IsConnected) return; if (IsConnected) return;
ClearConnectionFields(); ClearConnectionFields();
_server = server; _server = server;
} }
public bool IsConnected => (_tcpClient != null) && _tcpClient.Connected; public bool IsConnected => (_tcpClient != null) && _tcpClient.Connected;
public string Version => _version; public string Version => _version;
public async Task ConnectAsync() public async Task ConnectAsync()
{ {
if (_server == null) if (_server == null)
throw new InvalidOperationException("Server IPEndPoint not set."); throw new InvalidOperationException("Server IPEndPoint not set.");
if (IsConnected) if (IsConnected)
throw new AlreadyConnectedException(); throw new AlreadyConnectedException();
_tcpClient = new TcpClient(); _tcpClient = new TcpClient();
await _tcpClient.ConnectAsync(_server.Address, _server.Port); await _tcpClient.ConnectAsync(_server.Address, _server.Port);
_networkStream = _tcpClient.GetStream(); _networkStream = _tcpClient.GetStream();
// Encoding UTF8 has some problems with TcpClient: https://bugs.musicpd.org/view.php?id=4501 // Encoding UTF8 has some problems with TcpClient: https://bugs.musicpd.org/view.php?id=4501
_reader = new StreamReader(_networkStream); _reader = new StreamReader(_networkStream);
_writer = new StreamWriter(_networkStream) { NewLine = "\n" }; _writer = new StreamWriter(_networkStream) { NewLine = "\n" };
var firstLine = _reader.ReadLine(); var firstLine = _reader.ReadLine();
if (!firstLine.StartsWith(Constants.FirstLinePrefix)) if (!firstLine.StartsWith(Constants.FirstLinePrefix))
{ {
await DisconnectAsync(); await DisconnectAsync();
throw new InvalidDataException("Response of mpd does not start with \"" + Constants.FirstLinePrefix + "\"." ); throw new InvalidDataException("Response of mpd does not start with \"" + Constants.FirstLinePrefix + "\"." );
} }
_version = firstLine.Substring(Constants.FirstLinePrefix.Length); _version = firstLine.Substring(Constants.FirstLinePrefix.Length);
} }
public Task DisconnectAsync() public Task DisconnectAsync()
{ {
if (_tcpClient == null) if (_tcpClient == null)
{ {
return Task.CompletedTask; return Task.CompletedTask;
} }
_networkStream.Dispose(); _networkStream.Dispose();
ClearConnectionFields(); ClearConnectionFields();
return Task.CompletedTask; return Task.CompletedTask;
} }
public async Task<IMpdMessage<T>> SendAsync<T>(IMpcCommand<T> command) public async Task<IMpdMessage<T>> SendAsync<T>(IMpcCommand<T> command)
{ {
command.CheckNotNull(); command.CheckNotNull();
var connected = await CheckConnectionAsync(); var connected = await CheckConnectionAsync();
string[] response; string[] response;
try try
{ {
_writer.WriteLine(command.Value); _writer.WriteLine(command.Value);
_writer.Flush(); _writer.Flush();
response = await ReadResponseAsync(); response = await ReadResponseAsync();
} }
catch (Exception) catch (Exception)
{ {
try { await DisconnectAsync(); } catch (Exception) { } try { await DisconnectAsync(); } catch (Exception) { }
return null; // TODO: Create Null Object for MpdResponse return null; // TODO: Create Null Object for MpdResponse
} }
return new MpdMessage<T>(command, connected, response); return new MpdMessage<T>(command, connected, response);
} }
private async Task<bool> CheckConnectionAsync() private async Task<bool> CheckConnectionAsync()
{ {
if (!IsConnected) if (!IsConnected)
{ {
await ConnectAsync(); await ConnectAsync();
} }
return IsConnected; return IsConnected;
} }
private async Task<string[]> ReadResponseAsync() private async Task<string[]> ReadResponseAsync()
{ {
var response = new List<string>(); var response = new List<string>();
// Read response untli reach end token (OK or ACK) // Read response untli reach end token (OK or ACK)
string responseLine; string responseLine;
do do
{ {
responseLine = await _reader.ReadLineAsync(); responseLine = await _reader.ReadLineAsync();
response.Add(responseLine); response.Add(responseLine);
} while (!(responseLine.Equals(Constants.Ok) || responseLine.StartsWith(Constants.Ack))); } while (!(responseLine.Equals(Constants.Ok) || responseLine.StartsWith(Constants.Ack)));
return response.Where(line => !string.IsNullOrEmpty(line)).ToArray(); return response.Where(line => !string.IsNullOrEmpty(line)).ToArray();
} }
private void ClearConnectionFields() private void ClearConnectionFields()
{ {
_writer?.Dispose(); _writer?.Dispose();
_reader?.Dispose(); _reader?.Dispose();
_networkStream?.Dispose(); _networkStream?.Dispose();
_tcpClient?.Dispose(); _tcpClient?.Dispose();
_version = string.Empty; _version = string.Empty;
} }
} }
} }

View File

@ -1,13 +1,13 @@
namespace LibMpc namespace LibMpc
{ {
/// <summary> /// <summary>
/// https://www.musicpd.org/doc/protocol/database.html : find {TYPE} {WHAT} [...] [window START:END] /// https://www.musicpd.org/doc/protocol/database.html : find {TYPE} {WHAT} [...] [window START:END]
/// </summary> /// </summary>
public class FindTags public class FindTags
{ {
public static ITag Any { get; } = new Tag("any"); public static ITag Any { get; } = new Tag("any");
public static ITag File { get; } = new Tag("file"); public static ITag File { get; } = new Tag("file");
public static ITag Base { get; } = new Tag("base"); public static ITag Base { get; } = new Tag("base");
public static ITag ModifiedSince { get; } = new Tag("modified-since"); public static ITag ModifiedSince { get; } = new Tag("modified-since");
} }
} }

View File

@ -1,24 +1,24 @@
namespace LibMpc namespace LibMpc
{ {
/// <summary> /// <summary>
/// https://www.musicpd.org/doc/protocol/tags.html /// https://www.musicpd.org/doc/protocol/tags.html
/// </summary> /// </summary>
public class MpdTags public class MpdTags
{ {
public static ITag Artist { get; } = new Tag("artist"); public static ITag Artist { get; } = new Tag("artist");
public static ITag ArtistSort { get; } = new Tag("artistsort"); public static ITag ArtistSort { get; } = new Tag("artistsort");
public static ITag Album { get; } = new Tag("album"); public static ITag Album { get; } = new Tag("album");
public static ITag AlbumSort { get; } = new Tag("albumsort"); public static ITag AlbumSort { get; } = new Tag("albumsort");
public static ITag AlbumArtist { get; } = new Tag("albumartist"); public static ITag AlbumArtist { get; } = new Tag("albumartist");
public static ITag AlbumArtistSort { get; } = new Tag("albumartistsort"); public static ITag AlbumArtistSort { get; } = new Tag("albumartistsort");
public static ITag Title { get; } = new Tag("title"); public static ITag Title { get; } = new Tag("title");
public static ITag Track { get; } = new Tag("track"); public static ITag Track { get; } = new Tag("track");
public static ITag Name { get; } = new Tag("name"); public static ITag Name { get; } = new Tag("name");
public static ITag Genre { get; } = new Tag("genre"); public static ITag Genre { get; } = new Tag("genre");
public static ITag Date { get; } = new Tag("date"); public static ITag Date { get; } = new Tag("date");
public static ITag Composer { get; } = new Tag("composer"); public static ITag Composer { get; } = new Tag("composer");
public static ITag Performer { get; } = new Tag("performer"); public static ITag Performer { get; } = new Tag("performer");
public static ITag Comment { get; } = new Tag("comment"); public static ITag Comment { get; } = new Tag("comment");
public static ITag Disc { get; } = new Tag("disc"); public static ITag Disc { get; } = new Tag("disc");
} }
} }

View File

@ -1,18 +1,18 @@
namespace LibMpc namespace LibMpc
{ {
public interface ITag public interface ITag
{ {
string Value { get; } string Value { get; }
} }
internal class Tag : ITag internal class Tag : ITag
{ {
internal Tag(string value) internal Tag(string value)
{ {
Value = value; Value = value;
} }
public string Value { get; } public string Value { get; }
} }
} }

View File

@ -1,28 +1,28 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace LibMpc.Types namespace LibMpc.Types
{ {
public interface IMpdFilePath public interface IMpdFilePath
{ {
string File { get; } string File { get; }
} }
public interface IMpdFile : IMpdFilePath public interface IMpdFile : IMpdFilePath
{ {
int Time { get; } int Time { get; }
string Album { get; } string Album { get; }
string Artist { get; } string Artist { get; }
string Title { get; } string Title { get; }
string Track { get; } string Track { get; }
string Name { get; } string Name { get; }
string Genre { get; } string Genre { get; }
string Date { get; } string Date { get; }
string Composer { get; } string Composer { get; }
string Performer { get; } string Performer { get; }
string Comment { get; } string Comment { get; }
int Disc { get; } int Disc { get; }
int Pos { get; } int Pos { get; }
int Id { get; } int Id { get; }
IDictionary<string, string> UnknownMetadata { get; } IDictionary<string, string> UnknownMetadata { get; }
} }
} }

View File

@ -1,36 +1,36 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace LibMpc.Types namespace LibMpc.Types
{ {
public class MpdDecoderPlugin public class MpdDecoderPlugin
{ {
public static readonly MpdDecoderPlugin Empty = new MpdDecoderPlugin(string.Empty); public static readonly MpdDecoderPlugin Empty = new MpdDecoderPlugin(string.Empty);
private readonly IList<string> _suffixes = new List<string>(); private readonly IList<string> _suffixes = new List<string>();
private readonly IList<string> _mediaTypes = new List<string>(); private readonly IList<string> _mediaTypes = new List<string>();
public MpdDecoderPlugin(string name) public MpdDecoderPlugin(string name)
{ {
name.CheckNotNull(); name.CheckNotNull();
Name = name; Name = name;
IsInitialized = !string.IsNullOrEmpty(name); IsInitialized = !string.IsNullOrEmpty(name);
} }
public string Name { get; } public string Name { get; }
public IEnumerable<string> Suffixes => _suffixes; public IEnumerable<string> Suffixes => _suffixes;
public IEnumerable<string> MediaTypes => _mediaTypes; public IEnumerable<string> MediaTypes => _mediaTypes;
internal bool IsInitialized { get; } internal bool IsInitialized { get; }
internal void AddSuffix(string suffix) internal void AddSuffix(string suffix)
{ {
_suffixes.Add(suffix); _suffixes.Add(suffix);
} }
internal void AddMediaType(string type) internal void AddMediaType(string type)
{ {
_mediaTypes.Add(type); _mediaTypes.Add(type);
} }
} }
} }

View File

@ -1,29 +1,29 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace LibMpc.Types namespace LibMpc.Types
{ {
public class MpdDirectory public class MpdDirectory
{ {
private readonly IList<IMpdFilePath> _files = new List<IMpdFilePath>(); private readonly IList<IMpdFilePath> _files = new List<IMpdFilePath>();
public MpdDirectory(string path) public MpdDirectory(string path)
{ {
path.CheckNotNull(); path.CheckNotNull();
Path = path; Path = path;
var name = path.Split('/').Last(); var name = path.Split('/').Last();
Name = string.IsNullOrEmpty(name) ? "root" : name; Name = string.IsNullOrEmpty(name) ? "root" : name;
} }
public string Path { get; } public string Path { get; }
public string Name { get; } public string Name { get; }
public IEnumerable<IMpdFilePath> Files => _files; public IEnumerable<IMpdFilePath> Files => _files;
internal void AddFile(string file) internal void AddFile(string file)
{ {
_files.Add(new MpdFile(file)); _files.Add(new MpdFile(file));
} }
} }
} }

View File

@ -1,103 +1,103 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace LibMpc.Types namespace LibMpc.Types
{ {
/// <summary> /// <summary>
/// The MpdFile class contains all meta data for a file of the MPD. /// The MpdFile class contains all meta data for a file of the MPD.
/// </summary> /// </summary>
internal class MpdFile : IMpdFile internal class MpdFile : IMpdFile
{ {
private const string TagTime = "Time"; private const string TagTime = "Time";
private const string TagArtist = "Artist"; private const string TagArtist = "Artist";
private const string TagAlbum = "Album"; private const string TagAlbum = "Album";
private const string TagTitle = "Title"; private const string TagTitle = "Title";
private const string TagTrack = "Track"; private const string TagTrack = "Track";
private const string TagName = "Name"; private const string TagName = "Name";
private const string TagGenre = "Genre"; private const string TagGenre = "Genre";
private const string TagDate = "Date"; private const string TagDate = "Date";
private const string TagComposer = "Composer"; private const string TagComposer = "Composer";
private const string TagPerformer = "Performer"; private const string TagPerformer = "Performer";
private const string TagComment = "Comment"; private const string TagComment = "Comment";
private const string TagDisc = "Disc"; private const string TagDisc = "Disc";
private const string TagPos = "Pos"; private const string TagPos = "Pos";
private const string TagId = "Id"; private const string TagId = "Id";
private readonly IDictionary<string, string> _unknownMetadata = new Dictionary<string, string>(); private readonly IDictionary<string, string> _unknownMetadata = new Dictionary<string, string>();
internal MpdFile(string file) internal MpdFile(string file)
{ {
file.CheckNotNull(); file.CheckNotNull();
File = file; File = file;
} }
public string File { get; } public string File { get; }
public int Time { get; private set; } = -1; public int Time { get; private set; } = -1;
public string Album { get; private set; } = string.Empty; public string Album { get; private set; } = string.Empty;
public string Artist { get; private set; } = string.Empty; public string Artist { get; private set; } = string.Empty;
public string Title { get; private set; } = string.Empty; public string Title { get; private set; } = string.Empty;
public string Track { get; private set; } = string.Empty; public string Track { get; private set; } = string.Empty;
public string Name { get; private set; } = string.Empty; public string Name { get; private set; } = string.Empty;
public string Genre { get; private set; } = string.Empty; public string Genre { get; private set; } = string.Empty;
public string Date { get; private set; } = string.Empty; public string Date { get; private set; } = string.Empty;
public string Composer { get; private set; } = string.Empty; public string Composer { get; private set; } = string.Empty;
public string Performer { get; private set; } = string.Empty; public string Performer { get; private set; } = string.Empty;
public string Comment { get; private set; } = string.Empty; public string Comment { get; private set; } = string.Empty;
public int Disc { get; private set; } = -1; public int Disc { get; private set; } = -1;
public int Pos { get; private set; } = -1; public int Pos { get; private set; } = -1;
public int Id { get; private set; } = -1; public int Id { get; private set; } = -1;
public IDictionary<string, string> UnknownMetadata => _unknownMetadata; public IDictionary<string, string> UnknownMetadata => _unknownMetadata;
internal void AddTag(string tag, string value) internal void AddTag(string tag, string value)
{ {
switch (tag) switch (tag)
{ {
case TagTime: case TagTime:
Time = int.Parse(value); Time = int.Parse(value);
break; break;
case TagArtist: case TagArtist:
Artist = value; Artist = value;
break; break;
case TagAlbum: case TagAlbum:
Album = value; Album = value;
break; break;
case TagTitle: case TagTitle:
Title = value; Title = value;
break; break;
case TagTrack: case TagTrack:
Track = value; Track = value;
break; break;
case TagName: case TagName:
Name = value; Name = value;
break; break;
case TagGenre: case TagGenre:
Genre = value; Genre = value;
break; break;
case TagDate: case TagDate:
Date = value; Date = value;
break; break;
case TagComposer: case TagComposer:
Composer = value; Composer = value;
break; break;
case TagPerformer: case TagPerformer:
Performer = value; Performer = value;
break; break;
case TagComment: case TagComment:
Comment = value; Comment = value;
break; break;
case TagDisc: case TagDisc:
Disc = int.Parse(value); Disc = int.Parse(value);
break; break;
case TagPos: case TagPos:
Pos = int.Parse(value); Pos = int.Parse(value);
break; break;
case TagId: case TagId:
Id = int.Parse(value); Id = int.Parse(value);
break; break;
default: default:
_unknownMetadata.Add(tag, value); _unknownMetadata.Add(tag, value);
break; break;
} }
} }
} }
} }

View File

@ -1,23 +1,23 @@
using System; using System;
using System.Globalization; using System.Globalization;
namespace LibMpc.Types namespace LibMpc.Types
{ {
public class MpdPlaylist public class MpdPlaylist
{ {
public MpdPlaylist(string name) public MpdPlaylist(string name)
{ {
name.CheckNotNull(); name.CheckNotNull();
Name = name; Name = name;
} }
public string Name { get; } public string Name { get; }
public DateTime LastModified { get; private set; } public DateTime LastModified { get; private set; }
internal void AddLastModified(string lastModified) internal void AddLastModified(string lastModified)
{ {
LastModified = DateTime.Parse(lastModified, CultureInfo.InvariantCulture); LastModified = DateTime.Parse(lastModified, CultureInfo.InvariantCulture);
} }
} }
} }

View File

@ -1,29 +1,29 @@
using LibMpc; using LibMpc;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using System; using System;
namespace LibMpcTest namespace LibMpcTest
{ {
[TestClass] [TestClass]
public partial class LibMpcTest public partial class LibMpcTest
{ {
private static MpdMock _mpdMock; private static MpdMock _mpdMock;
[ClassInitialize] [ClassInitialize]
public static void Init(TestContext context) public static void Init(TestContext context)
{ {
_mpdMock = new MpdMock(); _mpdMock = new MpdMock();
_mpdMock.Start(); _mpdMock.Start();
Mpc = new MpcMock().Client; Mpc = new MpcMock().Client;
} }
[ClassCleanup] [ClassCleanup]
public static void Cleanup() public static void Cleanup()
{ {
_mpdMock.Dispose(); _mpdMock.Dispose();
} }
internal static Mpc Mpc { get; private set; } internal static Mpc Mpc { get; private set; }
} }
} }

View File

@ -1,26 +1,26 @@
using LibMpc; using LibMpc;
using System; using System;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LibMpcTest namespace LibMpcTest
{ {
public class MpcMock : IDisposable public class MpcMock : IDisposable
{ {
public MpcMock() public MpcMock()
{ {
Client = new Mpc(new IPEndPoint(IPAddress.Loopback, 6600)); Client = new Mpc(new IPEndPoint(IPAddress.Loopback, 6600));
var connected = Task.Run(async () => await Client.ConnectAsync()).Result; var connected = Task.Run(async () => await Client.ConnectAsync()).Result;
TestOutput.WriteLine($"Connected to MPD : {connected}; Version: {Client.Version}"); TestOutput.WriteLine($"Connected to MPD : {connected}; Version: {Client.Version}");
} }
public Mpc Client { get; } public Mpc Client { get; }
public void Dispose() public void Dispose()
{ {
Client?.DisconnectAsync().GetAwaiter().GetResult(); Client?.DisconnectAsync().GetAwaiter().GetResult();
TestOutput.WriteLine($"Disconnected from MPD."); TestOutput.WriteLine($"Disconnected from MPD.");
} }
} }
} }

View File

@ -1,57 +1,57 @@
using System.IO; using System.IO;
using System.Text; using System.Text;
namespace LibMpcTest namespace LibMpcTest
{ {
public class MpdConf public class MpdConf
{ {
private const string MPD_CONF_FILE = "mpd.conf"; private const string MPD_CONF_FILE = "mpd.conf";
private const string MPD_LOG_FILE = "mpd_log.txt"; private const string MPD_LOG_FILE = "mpd_log.txt";
private const string MPD_DB_FILE = "mpd.db"; private const string MPD_DB_FILE = "mpd.db";
public static void Create(string rootDirectory) public static void Create(string rootDirectory)
{ {
File.Create(Path.Combine(rootDirectory, MPD_LOG_FILE)).Dispose(); File.Create(Path.Combine(rootDirectory, MPD_LOG_FILE)).Dispose();
CreateConfFile(rootDirectory); CreateConfFile(rootDirectory);
} }
private static void CreateConfFile(string rootDirectory) private static void CreateConfFile(string rootDirectory)
{ {
var builder = new StringBuilder(); var builder = new StringBuilder();
builder.AppendLine($"log_file \"{Path.Combine(rootDirectory, MPD_LOG_FILE).Replace("\\", "\\\\")}\""); builder.AppendLine($"log_file \"{Path.Combine(rootDirectory, MPD_LOG_FILE).Replace("\\", "\\\\")}\"");
builder.AppendLine($"db_file \"{Path.Combine(rootDirectory, MPD_DB_FILE).Replace("\\", "\\\\")}\""); builder.AppendLine($"db_file \"{Path.Combine(rootDirectory, MPD_DB_FILE).Replace("\\", "\\\\")}\"");
builder.AppendLine("bind_to_address \"any\""); builder.AppendLine("bind_to_address \"any\"");
builder.AppendLine($"music_directory \"{Path.Combine(rootDirectory, "Music").Replace("\\", "\\\\")}\""); builder.AppendLine($"music_directory \"{Path.Combine(rootDirectory, "Music").Replace("\\", "\\\\")}\"");
builder.AppendLine($"playlist_directory \"{Path.Combine(rootDirectory, "Playlists").Replace("\\", "\\\\")}\""); builder.AppendLine($"playlist_directory \"{Path.Combine(rootDirectory, "Playlists").Replace("\\", "\\\\")}\"");
builder.AppendLine("port \"6600\""); builder.AppendLine("port \"6600\"");
builder.AppendLine("audio_output {"); builder.AppendLine("audio_output {");
builder.AppendLine("type \"null\""); builder.AppendLine("type \"null\"");
builder.AppendLine("name \"Enabled output to be disabled\""); builder.AppendLine("name \"Enabled output to be disabled\"");
builder.AppendLine("enabled \"true\""); builder.AppendLine("enabled \"true\"");
builder.AppendLine("mixer_type \"none\""); builder.AppendLine("mixer_type \"none\"");
builder.AppendLine("}"); builder.AppendLine("}");
builder.AppendLine("audio_output {"); builder.AppendLine("audio_output {");
builder.AppendLine("type \"null\""); builder.AppendLine("type \"null\"");
builder.AppendLine("name \"Disabled output to be enabled\""); builder.AppendLine("name \"Disabled output to be enabled\"");
builder.AppendLine("enabled \"false\""); builder.AppendLine("enabled \"false\"");
builder.AppendLine("mixer_type \"none\""); builder.AppendLine("mixer_type \"none\"");
builder.AppendLine("}"); builder.AppendLine("}");
builder.AppendLine("audio_output {"); builder.AppendLine("audio_output {");
builder.AppendLine("type \"null\""); builder.AppendLine("type \"null\"");
builder.AppendLine("name \"Enabled output to be toggled\""); builder.AppendLine("name \"Enabled output to be toggled\"");
builder.AppendLine("enabled \"true\""); builder.AppendLine("enabled \"true\"");
builder.AppendLine("mixer_type \"none\""); builder.AppendLine("mixer_type \"none\"");
builder.AppendLine("}"); builder.AppendLine("}");
var mpdConfContent = builder.ToString(); var mpdConfContent = builder.ToString();
using (var file = File.CreateText(Path.Combine(rootDirectory, MPD_CONF_FILE))) using (var file = File.CreateText(Path.Combine(rootDirectory, MPD_CONF_FILE)))
{ {
file.Write(mpdConfContent); file.Write(mpdConfContent);
file.Flush(); file.Flush();
} }
} }
} }
} }

View File

@ -1,119 +1,119 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace LibMpcTest namespace LibMpcTest
{ {
public class MpdMock : IDisposable public class MpdMock : IDisposable
{ {
public void Start() public void Start()
{ {
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{ {
SendCommand("/usr/bin/pkill mpd"); SendCommand("/usr/bin/pkill mpd");
} }
MpdConf.Create(Path.Combine(AppContext.BaseDirectory, "Server")); MpdConf.Create(Path.Combine(AppContext.BaseDirectory, "Server"));
var server = GetServer(); var server = GetServer();
Process = new Process Process = new Process
{ {
StartInfo = new ProcessStartInfo StartInfo = new ProcessStartInfo
{ {
FileName = server.FileName, FileName = server.FileName,
WorkingDirectory = server.WorkingDirectory, WorkingDirectory = server.WorkingDirectory,
Arguments = server.Arguments, Arguments = server.Arguments,
UseShellExecute = false, UseShellExecute = false,
RedirectStandardOutput = true, RedirectStandardOutput = true,
RedirectStandardError = true, RedirectStandardError = true,
CreateNoWindow = true, CreateNoWindow = true,
} }
}; };
TestOutput.WriteLine($"Starting Server: {Process.StartInfo.FileName} {Process.StartInfo.Arguments}"); TestOutput.WriteLine($"Starting Server: {Process.StartInfo.FileName} {Process.StartInfo.Arguments}");
Process.Start(); Process.Start();
TestOutput.WriteLine($"Output: {Process.StandardOutput.ReadToEnd()}"); TestOutput.WriteLine($"Output: {Process.StandardOutput.ReadToEnd()}");
TestOutput.WriteLine($"Error: {Process.StandardError.ReadToEnd()}"); TestOutput.WriteLine($"Error: {Process.StandardError.ReadToEnd()}");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{ {
SendCommand("/bin/netstat -ntpl"); SendCommand("/bin/netstat -ntpl");
} }
} }
public Process Process { get; private set; } public Process Process { get; private set; }
private Server GetServer() private Server GetServer()
{ {
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{ {
return Server.Linux; return Server.Linux;
} }
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ {
return Server.Windows; return Server.Windows;
} }
throw new NotSupportedException("OS not supported"); throw new NotSupportedException("OS not supported");
} }
private void SendCommand(string command) private void SendCommand(string command)
{ {
var netcat = new Process var netcat = new Process
{ {
StartInfo = new ProcessStartInfo StartInfo = new ProcessStartInfo
{ {
FileName = "/bin/bash", FileName = "/bin/bash",
WorkingDirectory = "/bin/", WorkingDirectory = "/bin/",
Arguments = $"-c \"sudo {command}\"", Arguments = $"-c \"sudo {command}\"",
UseShellExecute = false, UseShellExecute = false,
RedirectStandardOutput = true, RedirectStandardOutput = true,
RedirectStandardError = true, RedirectStandardError = true,
CreateNoWindow = true, CreateNoWindow = true,
} }
}; };
netcat.Start(); netcat.Start();
netcat.WaitForExit(); netcat.WaitForExit();
TestOutput.WriteLine(command); TestOutput.WriteLine(command);
TestOutput.WriteLine($"Output: {netcat.StandardOutput.ReadToEnd()}"); TestOutput.WriteLine($"Output: {netcat.StandardOutput.ReadToEnd()}");
TestOutput.WriteLine($"Error: {netcat.StandardError.ReadToEnd()}"); TestOutput.WriteLine($"Error: {netcat.StandardError.ReadToEnd()}");
} }
public void Dispose() public void Dispose()
{ {
Process?.Kill(); Process?.Kill();
Process?.Dispose(); Process?.Dispose();
TestOutput.WriteLine("Server Stopped."); TestOutput.WriteLine("Server Stopped.");
} }
private class Server private class Server
{ {
public static Server Linux = new Server( public static Server Linux = new Server(
fileName: "/bin/bash", fileName: "/bin/bash",
workingDirectory: "/bin/", workingDirectory: "/bin/",
arguments: $"-c \"sudo /usr/bin/mpd {Path.Combine(AppContext.BaseDirectory, "Server", "mpd.conf")} -v\""); arguments: $"-c \"sudo /usr/bin/mpd {Path.Combine(AppContext.BaseDirectory, "Server", "mpd.conf")} -v\"");
public static Server Windows = new Server( public static Server Windows = new Server(
fileName: Path.Combine(AppContext.BaseDirectory, "Server", "mpd.exe"), fileName: Path.Combine(AppContext.BaseDirectory, "Server", "mpd.exe"),
workingDirectory: Path.Combine(AppContext.BaseDirectory, "Server"), workingDirectory: Path.Combine(AppContext.BaseDirectory, "Server"),
arguments: $"{Path.Combine(AppContext.BaseDirectory, "Server", "mpd.conf")} -v"); arguments: $"{Path.Combine(AppContext.BaseDirectory, "Server", "mpd.conf")} -v");
private Server(string fileName, string workingDirectory, string arguments) private Server(string fileName, string workingDirectory, string arguments)
{ {
FileName = fileName; FileName = fileName;
WorkingDirectory = workingDirectory; WorkingDirectory = workingDirectory;
Arguments = arguments; Arguments = arguments;
} }
public string FileName { get; } public string FileName { get; }
public string WorkingDirectory { get; } public string WorkingDirectory { get; }
public string Arguments { get; } public string Arguments { get; }
} }
} }
} }

View File

@ -1,19 +1,19 @@
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LibMpcTest")] [assembly: AssemblyProduct("LibMpcTest")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
// Setting ComVisible to false makes the types in this assembly not visible // Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from // to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type. // COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)] [assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM // The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("69f1d68f-9cd5-4ea6-9b47-2a7a9bf8ced9")] [assembly: Guid("69f1d68f-9cd5-4ea6-9b47-2a7a9bf8ced9")]

View File

@ -1,5 +1,5 @@
teaspoon-stirring-mug-of-coffee.mp3 teaspoon-stirring-mug-of-coffee.mp3
whistle-kettle-boiling.mp3 whistle-kettle-boiling.mp3
wine-glass-double-chink-clink-cheers.mp3 wine-glass-double-chink-clink-cheers.mp3
Directory With Spaces/coin-spin-light.mp3 Directory With Spaces/coin-spin-light.mp3
Directory With Spaces/finger-snap-click.mp3 Directory With Spaces/finger-snap-click.mp3

View File

@ -1,3 +1,3 @@
A long name directory with some spaces/pouring-water-into-mug-of-coffee.mp3 A long name directory with some spaces/pouring-water-into-mug-of-coffee.mp3
A long name directory with some spaces/Sub Directory Two/short-trouser-pants-zip-closing.mp3 A long name directory with some spaces/Sub Directory Two/short-trouser-pants-zip-closing.mp3
Directory/2-Kids-Laughing.mp3 Directory/2-Kids-Laughing.mp3

View File

@ -1,5 +1,5 @@
A long name directory with some spaces/Ghost-Sounds.mp3 A long name directory with some spaces/Ghost-Sounds.mp3
Directory/ambient-noise-server-room.mp3 Directory/ambient-noise-server-room.mp3
Directory With Spaces/SubDirectory One/central-locking-Ford-Mondeo-Mk-3.mp3 Directory With Spaces/SubDirectory One/central-locking-Ford-Mondeo-Mk-3.mp3
_My Directory/gas-fire-lighting.mp3 _My Directory/gas-fire-lighting.mp3
A long name directory with some spaces/Sub Directory Two/starting-engine-Ford-Mondeo-Mk-3-diesel.mp3 A long name directory with some spaces/Sub Directory Two/starting-engine-Ford-Mondeo-Mk-3-diesel.mp3

View File

@ -1,163 +1,163 @@
info_begin info_begin
format: 1 format: 1
mpd_version: 0.17.4 mpd_version: 0.17.4
fs_charset: cp1252 fs_charset: cp1252
tag: Artist tag: Artist
tag: ArtistSort tag: ArtistSort
tag: Album tag: Album
tag: AlbumArtist tag: AlbumArtist
tag: AlbumArtistSort tag: AlbumArtistSort
tag: Title tag: Title
tag: Track tag: Track
tag: Name tag: Name
tag: Genre tag: Genre
tag: Date tag: Date
tag: Composer tag: Composer
tag: Performer tag: Performer
tag: Disc tag: Disc
tag: MUSICBRAINZ_ARTISTID tag: MUSICBRAINZ_ARTISTID
tag: MUSICBRAINZ_ALBUMID tag: MUSICBRAINZ_ALBUMID
tag: MUSICBRAINZ_ALBUMARTISTID tag: MUSICBRAINZ_ALBUMARTISTID
tag: MUSICBRAINZ_TRACKID tag: MUSICBRAINZ_TRACKID
info_end info_end
directory: A long name directory with some spaces directory: A long name directory with some spaces
mtime: 1482142041 mtime: 1482142041
begin: A long name directory with some spaces begin: A long name directory with some spaces
directory: Sub Directory Two directory: Sub Directory Two
mtime: 1482142041 mtime: 1482142041
begin: A long name directory with some spaces/Sub Directory Two begin: A long name directory with some spaces/Sub Directory Two
song_begin: short-trouser-pants-zip-closing.mp3 song_begin: short-trouser-pants-zip-closing.mp3
Time: 1 Time: 1
Artist: Geek & Dummy Artist: Geek & Dummy
Title: Sound effect: short trouser pants zip closing Title: Sound effect: short trouser pants zip closing
Date: 2013 Date: 2013
Date: 2013 Date: 2013
mtime: 1481623577 mtime: 1481623577
song_end song_end
song_begin: starting-engine-Ford-Mondeo-Mk-3-diesel.mp3 song_begin: starting-engine-Ford-Mondeo-Mk-3-diesel.mp3
Time: 6 Time: 6
Artist: Geek & Dummy Artist: Geek & Dummy
Title: Sound effect: starting engine - Ford Mondeo Mk 3 diesel Title: Sound effect: starting engine - Ford Mondeo Mk 3 diesel
Album: Geek & Dummy Sound Library Album: Geek & Dummy Sound Library
Date: 2014 Date: 2014
Genre: soundfx Genre: soundfx
mtime: 1481623577 mtime: 1481623577
song_end song_end
end: A long name directory with some spaces/Sub Directory Two end: A long name directory with some spaces/Sub Directory Two
song_begin: pouring-water-into-mug-of-coffee.mp3 song_begin: pouring-water-into-mug-of-coffee.mp3
Time: 4 Time: 4
Artist: Geek & Dummy Artist: Geek & Dummy
Title: Sound effect: pouring water into mug of coffee Title: Sound effect: pouring water into mug of coffee
Date: 2013 Date: 2013
Date: 2013 Date: 2013
mtime: 1481623577 mtime: 1481623577
song_end song_end
song_begin: Ghost-Sounds.mp3 song_begin: Ghost-Sounds.mp3
Time: 95 Time: 95
Artist: Geek & Dummy Artist: Geek & Dummy
Title: Sound effect: ghostly haunted house (bells, ghostly laughs & knives sharpened) Title: Sound effect: ghostly haunted house (bells, ghostly laughs & knives sharpened)
Album: Geek & Dummy Sound Library Album: Geek & Dummy Sound Library
Date: 2014 Date: 2014
Date: 2014 Date: 2014
Genre: soundfx Genre: soundfx
mtime: 1481623577 mtime: 1481623577
song_end song_end
end: A long name directory with some spaces end: A long name directory with some spaces
directory: Directory directory: Directory
mtime: 1482142041 mtime: 1482142041
begin: Directory begin: Directory
song_begin: 2-Kids-Laughing.mp3 song_begin: 2-Kids-Laughing.mp3
Time: 30 Time: 30
Artist: Geek & Dummy Artist: Geek & Dummy
Title: Sound effect: two kids laughing Title: Sound effect: two kids laughing
Album: Geek & Dummy Sound Library Album: Geek & Dummy Sound Library
Date: 2014 Date: 2014
Date: 2014 Date: 2014
Genre: soundfx Genre: soundfx
mtime: 1481623577 mtime: 1481623577
song_end song_end
song_begin: ambient-noise-server-room.mp3 song_begin: ambient-noise-server-room.mp3
Time: 71 Time: 71
Artist: Geek & Dummy Artist: Geek & Dummy
Title: Sound effect: ambient noise - server room Title: Sound effect: ambient noise - server room
Album: Geek & Dummy Sound Library Album: Geek & Dummy Sound Library
Date: 2014 Date: 2014
Date: 2014 Date: 2014
Genre: soundfx Genre: soundfx
mtime: 1481623577 mtime: 1481623577
song_end song_end
end: Directory end: Directory
directory: Directory With Spaces directory: Directory With Spaces
mtime: 1482142041 mtime: 1482142041
begin: Directory With Spaces begin: Directory With Spaces
directory: SubDirectory One directory: SubDirectory One
mtime: 1482142041 mtime: 1482142041
begin: Directory With Spaces/SubDirectory One begin: Directory With Spaces/SubDirectory One
song_begin: central-locking-Ford-Mondeo-Mk-3.mp3 song_begin: central-locking-Ford-Mondeo-Mk-3.mp3
Time: 5 Time: 5
Artist: Geek & Dummy Artist: Geek & Dummy
Title: Sound effect: central locking - Ford Mondeo Mk 3 Title: Sound effect: central locking - Ford Mondeo Mk 3
Album: Geek & Dummy Sound Library Album: Geek & Dummy Sound Library
Date: 2014 Date: 2014
Date: 2014 Date: 2014
Genre: soundfx Genre: soundfx
mtime: 1481623577 mtime: 1481623577
song_end song_end
end: Directory With Spaces/SubDirectory One end: Directory With Spaces/SubDirectory One
song_begin: coin-spin-light.mp3 song_begin: coin-spin-light.mp3
Time: 5 Time: 5
Artist: Geek & Dummy Artist: Geek & Dummy
Title: Sound effect: coin spin (light coin) Title: Sound effect: coin spin (light coin)
Date: 2013 Date: 2013
Date: 2013 Date: 2013
mtime: 1481623577 mtime: 1481623577
song_end song_end
song_begin: finger-snap-click.mp3 song_begin: finger-snap-click.mp3
Time: 0 Time: 0
Artist: Geek & Dummy Artist: Geek & Dummy
Title: Sound effect: finger snap/click Title: Sound effect: finger snap/click
Album: Geek & Dummy Sound Library Album: Geek & Dummy Sound Library
Date: 2014 Date: 2014
Date: 2014 Date: 2014
Genre: soundfx Genre: soundfx
mtime: 1481623577 mtime: 1481623577
song_end song_end
end: Directory With Spaces end: Directory With Spaces
directory: _My Directory directory: _My Directory
mtime: 1482142041 mtime: 1482142041
begin: _My Directory begin: _My Directory
song_begin: gas-fire-lighting.mp3 song_begin: gas-fire-lighting.mp3
Time: 58 Time: 58
Artist: Geek & Dummy Artist: Geek & Dummy
Title: Sound effect: gas fire lighting and warming up Title: Sound effect: gas fire lighting and warming up
Album: Geek & Dummy Sound Library Album: Geek & Dummy Sound Library
Date: 2014 Date: 2014
Date: 2014 Date: 2014
Genre: soundfx Genre: soundfx
mtime: 1481623577 mtime: 1481623577
song_end song_end
end: _My Directory end: _My Directory
song_begin: teaspoon-stirring-mug-of-coffee.mp3 song_begin: teaspoon-stirring-mug-of-coffee.mp3
Time: 4 Time: 4
Artist: Geek & Dummy Artist: Geek & Dummy
Title: Sound effect: teaspoon stirring mug of coffee Title: Sound effect: teaspoon stirring mug of coffee
Date: 2013 Date: 2013
Date: 2013 Date: 2013
mtime: 1481623577 mtime: 1481623577
song_end song_end
song_begin: whistle-kettle-boiling.mp3 song_begin: whistle-kettle-boiling.mp3
Time: 36 Time: 36
Artist: Geek & Dummy Artist: Geek & Dummy
Title: Sound effect: whistle kettle boiling Title: Sound effect: whistle kettle boiling
Date: 2013 Date: 2013
Date: 2013 Date: 2013
mtime: 1481623577 mtime: 1481623577
song_end song_end
song_begin: wine-glass-double-chink-clink-cheers.mp3 song_begin: wine-glass-double-chink-clink-cheers.mp3
Time: 1 Time: 1
Artist: Geek & Dummy Artist: Geek & Dummy
Title: Sound effect: wine glass double chink/clink/cheers Title: Sound effect: wine glass double chink/clink/cheers
Date: 2013 Date: 2013
Date: 2013 Date: 2013
mtime: 1481623577 mtime: 1481623577
song_end song_end

View File

@ -1,12 +1,12 @@
using System; using System;
namespace LibMpcTest namespace LibMpcTest
{ {
internal class TestOutput internal class TestOutput
{ {
internal static void WriteLine(string value) internal static void WriteLine(string value)
{ {
Console.Out.WriteLine(value); Console.Out.WriteLine(value);
} }
} }
} }

View File

@ -1,33 +1,33 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Linq; using System.Linq;
using LibMpc; using LibMpc;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace LibMpcTest namespace LibMpcTest
{ {
public partial class LibMpcTest public partial class LibMpcTest
{ {
[TestMethod] [TestMethod]
public async Task ListAllTest() public async Task ListAllTest()
{ {
var response = await Mpc.SendAsync(new Commands.Database.ListAll()); var response = await Mpc.SendAsync(new Commands.Database.ListAll());
TestOutput.WriteLine("ListAllTest Result:"); TestOutput.WriteLine("ListAllTest Result:");
TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented)); TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));
Assert.IsTrue(response.Response.Body.Count().Equals(7)); Assert.IsTrue(response.Response.Body.Count().Equals(7));
} }
[TestMethod] [TestMethod]
public async Task FindGenreTest() public async Task FindGenreTest()
{ {
var response = await Mpc.SendAsync(new Commands.Database.Find(MpdTags.Genre, "soundfx")); var response = await Mpc.SendAsync(new Commands.Database.Find(MpdTags.Genre, "soundfx"));
TestOutput.WriteLine("FindGenreTest Result:"); TestOutput.WriteLine("FindGenreTest Result:");
TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented)); TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));
Assert.IsTrue(response.Response.Body.Count().Equals(7)); Assert.IsTrue(response.Response.Body.Count().Equals(7));
} }
} }
} }

View File

@ -1,77 +1,77 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using LibMpc; using LibMpc;
using System.Linq; using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace LibMpcTest namespace LibMpcTest
{ {
public partial class LibMpcTest public partial class LibMpcTest
{ {
[TestMethod] [TestMethod]
public async Task DisableOutputTest() public async Task DisableOutputTest()
{ {
var responseOutputs = await Mpc.SendAsync(new Commands.Output.Outputs()); var responseOutputs = await Mpc.SendAsync(new Commands.Output.Outputs());
Assert.IsTrue(responseOutputs.Response.Body.Single(output => output.Id.Equals(0)).IsEnabled); Assert.IsTrue(responseOutputs.Response.Body.Single(output => output.Id.Equals(0)).IsEnabled);
var response = await Mpc.SendAsync(new Commands.Output.DisableOutput(0)); var response = await Mpc.SendAsync(new Commands.Output.DisableOutput(0));
TestOutput.WriteLine("DisableOutputTest Result:"); TestOutput.WriteLine("DisableOutputTest Result:");
TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented)); TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));
Assert.IsTrue(response.Response.Body.Equals(string.Empty)); Assert.IsTrue(response.Response.Body.Equals(string.Empty));
Assert.IsTrue(response.Response.State.Status.Equals("OK")); Assert.IsTrue(response.Response.State.Status.Equals("OK"));
responseOutputs = await Mpc.SendAsync(new Commands.Output.Outputs()); responseOutputs = await Mpc.SendAsync(new Commands.Output.Outputs());
Assert.IsFalse(responseOutputs.Response.Body.Single(output => output.Id.Equals(0)).IsEnabled); Assert.IsFalse(responseOutputs.Response.Body.Single(output => output.Id.Equals(0)).IsEnabled);
} }
[TestMethod] [TestMethod]
public async Task EnableOutputTest() public async Task EnableOutputTest()
{ {
var responseOutputs = await Mpc.SendAsync(new Commands.Output.Outputs()); var responseOutputs = await Mpc.SendAsync(new Commands.Output.Outputs());
// By default should be disable from mpd.config // By default should be disable from mpd.config
Assert.IsFalse(responseOutputs.Response.Body.Single(output => output.Id.Equals(1)).IsEnabled); Assert.IsFalse(responseOutputs.Response.Body.Single(output => output.Id.Equals(1)).IsEnabled);
var response = await Mpc.SendAsync(new Commands.Output.EnableOutput(1)); var response = await Mpc.SendAsync(new Commands.Output.EnableOutput(1));
TestOutput.WriteLine("EnableOutputTest Result:"); TestOutput.WriteLine("EnableOutputTest Result:");
TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented)); TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));
Assert.IsTrue(response.Response.Body.Equals(string.Empty)); Assert.IsTrue(response.Response.Body.Equals(string.Empty));
Assert.IsTrue(response.Response.State.Status.Equals("OK")); Assert.IsTrue(response.Response.State.Status.Equals("OK"));
responseOutputs = await Mpc.SendAsync(new Commands.Output.Outputs()); responseOutputs = await Mpc.SendAsync(new Commands.Output.Outputs());
Assert.IsTrue(responseOutputs.Response.Body.Single(output => output.Id.Equals(1)).IsEnabled); Assert.IsTrue(responseOutputs.Response.Body.Single(output => output.Id.Equals(1)).IsEnabled);
} }
[TestMethod] [TestMethod]
public async Task ToggleOutputTest() public async Task ToggleOutputTest()
{ {
var responseOutputs = await Mpc.SendAsync(new Commands.Output.Outputs()); var responseOutputs = await Mpc.SendAsync(new Commands.Output.Outputs());
Assert.IsTrue(responseOutputs.Response.Body.Single(output => output.Id.Equals(2)).IsEnabled); Assert.IsTrue(responseOutputs.Response.Body.Single(output => output.Id.Equals(2)).IsEnabled);
var response = await Mpc.SendAsync(new Commands.Output.ToggleOutput(2)); var response = await Mpc.SendAsync(new Commands.Output.ToggleOutput(2));
TestOutput.WriteLine("ToggleOutputTest Result:"); TestOutput.WriteLine("ToggleOutputTest Result:");
TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented)); TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));
Assert.IsTrue(response.Response.Body.Equals(string.Empty)); Assert.IsTrue(response.Response.Body.Equals(string.Empty));
Assert.IsTrue(response.Response.State.Status.Equals("OK")); Assert.IsTrue(response.Response.State.Status.Equals("OK"));
responseOutputs = await Mpc.SendAsync(new Commands.Output.Outputs()); responseOutputs = await Mpc.SendAsync(new Commands.Output.Outputs());
Assert.IsFalse(responseOutputs.Response.Body.Single(output => output.Id.Equals(2)).IsEnabled); Assert.IsFalse(responseOutputs.Response.Body.Single(output => output.Id.Equals(2)).IsEnabled);
} }
[TestMethod] [TestMethod]
public async Task LisOutputsTest() public async Task LisOutputsTest()
{ {
var response = await Mpc.SendAsync(new Commands.Output.Outputs()); var response = await Mpc.SendAsync(new Commands.Output.Outputs());
TestOutput.WriteLine("LisOutputsTest Result:"); TestOutput.WriteLine("LisOutputsTest Result:");
TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented)); TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));
Assert.IsTrue(response.Response.Body.Count().Equals(3)); Assert.IsTrue(response.Response.Body.Count().Equals(3));
} }
} }
} }

View File

@ -1,53 +1,53 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using LibMpc; using LibMpc;
using System.Linq; using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace LibMpcTest namespace LibMpcTest
{ {
public partial class LibMpcTest public partial class LibMpcTest
{ {
[DataTestMethod] [DataTestMethod]
[DataRow("Playlist One", 5)] [DataRow("Playlist One", 5)]
[DataRow("Playlist Two", 3)] [DataRow("Playlist Two", 3)]
[DataRow("_My Playlist", 5)] [DataRow("_My Playlist", 5)]
public async Task ListPlaylistTest(string playlistName, int numberOfFiles) public async Task ListPlaylistTest(string playlistName, int numberOfFiles)
{ {
var response = await Mpc.SendAsync(new Commands.Playlists.Stored.ListPlaylist(playlistName)); var response = await Mpc.SendAsync(new Commands.Playlists.Stored.ListPlaylist(playlistName));
TestOutput.WriteLine($"ListPlaylistTest (playlistName: {playlistName}) Result:"); TestOutput.WriteLine($"ListPlaylistTest (playlistName: {playlistName}) Result:");
TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented)); TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));
Assert.IsTrue(response.Response.Body.Count().Equals(numberOfFiles)); Assert.IsTrue(response.Response.Body.Count().Equals(numberOfFiles));
} }
[DataTestMethod] [DataTestMethod]
[DataRow("Playlist One", 5)] [DataRow("Playlist One", 5)]
[DataRow("Playlist Two", 3)] [DataRow("Playlist Two", 3)]
[DataRow("_My Playlist", 5)] [DataRow("_My Playlist", 5)]
public async Task ListPlaylistInfoTest(string playlistName, int numberOfFiles) public async Task ListPlaylistInfoTest(string playlistName, int numberOfFiles)
{ {
var response = await Mpc.SendAsync(new Commands.Playlists.Stored.ListPlaylistInfo(playlistName)); var response = await Mpc.SendAsync(new Commands.Playlists.Stored.ListPlaylistInfo(playlistName));
TestOutput.WriteLine($"ListPlaylistTest (playlistName: {playlistName}) Result:"); TestOutput.WriteLine($"ListPlaylistTest (playlistName: {playlistName}) Result:");
TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented)); TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));
Assert.IsTrue(response.Response.Body.Count().Equals(numberOfFiles)); Assert.IsTrue(response.Response.Body.Count().Equals(numberOfFiles));
Assert.IsTrue(response.Response.Body.All(item => !string.IsNullOrEmpty(item.Artist))); Assert.IsTrue(response.Response.Body.All(item => !string.IsNullOrEmpty(item.Artist)));
Assert.IsTrue(response.Response.Body.All(item => !string.IsNullOrEmpty(item.Title))); Assert.IsTrue(response.Response.Body.All(item => !string.IsNullOrEmpty(item.Title)));
Assert.IsTrue(response.Response.Body.All(item => !string.IsNullOrEmpty(item.Date))); Assert.IsTrue(response.Response.Body.All(item => !string.IsNullOrEmpty(item.Date)));
} }
[TestMethod] [TestMethod]
public async Task ListPlaylistsTest() public async Task ListPlaylistsTest()
{ {
var response = await Mpc.SendAsync(new Commands.Playlists.Stored.ListPlaylists()); var response = await Mpc.SendAsync(new Commands.Playlists.Stored.ListPlaylists());
TestOutput.WriteLine($"ListPlaylistsTest Result:"); TestOutput.WriteLine($"ListPlaylistsTest Result:");
TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented)); TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));
Assert.IsTrue(response.Response.Body.Count().Equals(3)); Assert.IsTrue(response.Response.Body.Count().Equals(3));
} }
} }
} }

View File

@ -1,80 +1,80 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using LibMpc; using LibMpc;
using System.Linq; using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace LibMpcTest namespace LibMpcTest
{ {
public partial class LibMpcTest public partial class LibMpcTest
{ {
[TestMethod] [TestMethod]
public async Task CommandsTest() public async Task CommandsTest()
{ {
var response = await Mpc.SendAsync(new Commands.Reflection.Commands()); var response = await Mpc.SendAsync(new Commands.Reflection.Commands());
TestOutput.WriteLine($"CommandsTest (commands: {response.Response.Body.Count()}) Result:"); TestOutput.WriteLine($"CommandsTest (commands: {response.Response.Body.Count()}) Result:");
TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented)); TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));
// Different answer from MPD on Windows and on Linux, beacuse of Version. // Different answer from MPD on Windows and on Linux, beacuse of Version.
// Check some of the commands. // Check some of the commands.
Assert.IsTrue(response.Response.Body.Any(command => command.Equals("listall"))); Assert.IsTrue(response.Response.Body.Any(command => command.Equals("listall")));
Assert.IsTrue(response.Response.Body.Any(command => command.Equals("outputs"))); Assert.IsTrue(response.Response.Body.Any(command => command.Equals("outputs")));
Assert.IsTrue(response.Response.Body.Any(command => command.Equals("pause"))); Assert.IsTrue(response.Response.Body.Any(command => command.Equals("pause")));
Assert.IsTrue(response.Response.Body.Any(command => command.Equals("play"))); Assert.IsTrue(response.Response.Body.Any(command => command.Equals("play")));
Assert.IsTrue(response.Response.Body.Any(command => command.Equals("setvol"))); Assert.IsTrue(response.Response.Body.Any(command => command.Equals("setvol")));
Assert.IsTrue(response.Response.Body.Any(command => command.Equals("stop"))); Assert.IsTrue(response.Response.Body.Any(command => command.Equals("stop")));
} }
[TestMethod] [TestMethod]
public async Task TagTypesTest() public async Task TagTypesTest()
{ {
var response = await Mpc.SendAsync(new Commands.Reflection.TagTypes()); var response = await Mpc.SendAsync(new Commands.Reflection.TagTypes());
TestOutput.WriteLine("TagTypesTest Result:"); TestOutput.WriteLine("TagTypesTest Result:");
TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented)); TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));
Assert.IsTrue(response.Response.Body.Count().Equals(17)); Assert.IsTrue(response.Response.Body.Count().Equals(17));
} }
[TestMethod] [TestMethod]
public async Task UrlHandlersTest() public async Task UrlHandlersTest()
{ {
var response = await Mpc.SendAsync(new Commands.Reflection.UrlHandlers()); var response = await Mpc.SendAsync(new Commands.Reflection.UrlHandlers());
TestOutput.WriteLine($"UrlHandlersTest (handlers: {response.Response.Body.Count()}) Result:"); TestOutput.WriteLine($"UrlHandlersTest (handlers: {response.Response.Body.Count()}) Result:");
TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented)); TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));
// Different answer from MPD on Windows and on Linux. // Different answer from MPD on Windows and on Linux.
// Check some of the handlers. // Check some of the handlers.
Assert.IsTrue(response.Response.Body.Any(handler => handler.Equals("http://"))); Assert.IsTrue(response.Response.Body.Any(handler => handler.Equals("http://")));
Assert.IsTrue(response.Response.Body.Any(handler => handler.Equals("mms://"))); Assert.IsTrue(response.Response.Body.Any(handler => handler.Equals("mms://")));
Assert.IsTrue(response.Response.Body.Any(handler => handler.Equals("gopher://"))); Assert.IsTrue(response.Response.Body.Any(handler => handler.Equals("gopher://")));
Assert.IsTrue(response.Response.Body.Any(handler => handler.Equals("rtp://"))); Assert.IsTrue(response.Response.Body.Any(handler => handler.Equals("rtp://")));
} }
[TestMethod] [TestMethod]
public async Task DecodersTest() public async Task DecodersTest()
{ {
var response = await Mpc.SendAsync(new Commands.Reflection.Decoders()); var response = await Mpc.SendAsync(new Commands.Reflection.Decoders());
TestOutput.WriteLine($"DecodersTest (decoders: {response.Response.Body.Count()}) Result:"); TestOutput.WriteLine($"DecodersTest (decoders: {response.Response.Body.Count()}) Result:");
TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented)); TestOutput.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));
// Different answer from MPD on Windows and on Linux. // Different answer from MPD on Windows and on Linux.
// Check some of the decoders. // Check some of the decoders.
Assert.IsTrue(response.Response.Body.Any(decoder => decoder.Name.Equals("mad"))); Assert.IsTrue(response.Response.Body.Any(decoder => decoder.Name.Equals("mad")));
Assert.IsTrue(response.Response.Body.Any(decoder => decoder.Suffixes.Any(suffix => suffix.Equals("mp3")))); Assert.IsTrue(response.Response.Body.Any(decoder => decoder.Suffixes.Any(suffix => suffix.Equals("mp3"))));
Assert.IsTrue(response.Response.Body.Any(decoder => decoder.MediaTypes.Any(mediaType => mediaType.Equals("audio/mpeg")))); Assert.IsTrue(response.Response.Body.Any(decoder => decoder.MediaTypes.Any(mediaType => mediaType.Equals("audio/mpeg"))));
Assert.IsTrue(response.Response.Body.Any(decoder => decoder.Name.Equals("flac"))); Assert.IsTrue(response.Response.Body.Any(decoder => decoder.Name.Equals("flac")));
Assert.IsTrue(response.Response.Body.Any(decoder => decoder.Suffixes.Any(suffix => suffix.Equals("flac")))); Assert.IsTrue(response.Response.Body.Any(decoder => decoder.Suffixes.Any(suffix => suffix.Equals("flac"))));
Assert.IsTrue(response.Response.Body.Any(decoder => decoder.MediaTypes.Any(mediaType => mediaType.Equals("audio/flac")))); Assert.IsTrue(response.Response.Body.Any(decoder => decoder.MediaTypes.Any(mediaType => mediaType.Equals("audio/flac"))));
Assert.IsTrue(response.Response.Body.Any(decoder => decoder.MediaTypes.Any(mediaType => mediaType.Equals("audio/x-flac")))); Assert.IsTrue(response.Response.Body.Any(decoder => decoder.MediaTypes.Any(mediaType => mediaType.Equals("audio/x-flac"))));
Assert.IsTrue(response.Response.Body.Any(decoder => decoder.Name.Equals("ffmpeg"))); Assert.IsTrue(response.Response.Body.Any(decoder => decoder.Name.Equals("ffmpeg")));
Assert.IsTrue(response.Response.Body.Any(decoder => decoder.Suffixes.Any(suffix => suffix.Equals("aac")))); Assert.IsTrue(response.Response.Body.Any(decoder => decoder.Suffixes.Any(suffix => suffix.Equals("aac"))));
Assert.IsTrue(response.Response.Body.Any(decoder => decoder.Suffixes.Any(suffix => suffix.Equals("mpeg")))); Assert.IsTrue(response.Response.Body.Any(decoder => decoder.Suffixes.Any(suffix => suffix.Equals("mpeg"))));
Assert.IsTrue(response.Response.Body.Any(decoder => decoder.MediaTypes.Any(mediaType => mediaType.Equals("audio/aac")))); Assert.IsTrue(response.Response.Body.Any(decoder => decoder.MediaTypes.Any(mediaType => mediaType.Equals("audio/aac"))));
Assert.IsTrue(response.Response.Body.Any(decoder => decoder.MediaTypes.Any(mediaType => mediaType.Equals("audio/mpeg")))); Assert.IsTrue(response.Response.Body.Any(decoder => decoder.MediaTypes.Any(mediaType => mediaType.Equals("audio/mpeg"))));
} }
} }
} }