mirror of
https://github.com/ZetaKebab/MpcNET.git
synced 2025-01-14 22:18:43 +00:00
Original code base
This commit is contained in:
parent
d95448d4a4
commit
dd938883e5
80
LibMpc/Enum.cs
Normal file
80
LibMpc/Enum.cs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Matthias Sessler
|
||||||
|
*
|
||||||
|
* This file is part of LibMpc.net.
|
||||||
|
*
|
||||||
|
* LibMpc.net is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* LibMpc.net is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with LibMpc.net. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
namespace Libmpc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The scope specifier for search commands.
|
||||||
|
/// </summary>
|
||||||
|
public enum ScopeSpecifier
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Any attribute of a file.
|
||||||
|
/// </summary>
|
||||||
|
Any,
|
||||||
|
/// <summary>
|
||||||
|
/// The path and name of the file.
|
||||||
|
/// </summary>
|
||||||
|
Filename,
|
||||||
|
/// <summary>
|
||||||
|
/// The artist of the track.
|
||||||
|
/// </summary>
|
||||||
|
Artist,
|
||||||
|
/// <summary>
|
||||||
|
/// The album the track appears on.
|
||||||
|
/// </summary>
|
||||||
|
Album,
|
||||||
|
/// <summary>
|
||||||
|
/// The title of the track.
|
||||||
|
/// </summary>
|
||||||
|
Title,
|
||||||
|
/// <summary>
|
||||||
|
/// The index of the track on its album.
|
||||||
|
/// </summary>
|
||||||
|
Track,
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the track.
|
||||||
|
/// </summary>
|
||||||
|
Name,
|
||||||
|
/// <summary>
|
||||||
|
/// The genre of the song.
|
||||||
|
/// </summary>
|
||||||
|
Genre,
|
||||||
|
/// <summary>
|
||||||
|
/// The date the track was released.
|
||||||
|
/// </summary>
|
||||||
|
Date,
|
||||||
|
/// <summary>
|
||||||
|
/// The composer of the song.
|
||||||
|
/// </summary>
|
||||||
|
Composer,
|
||||||
|
/// <summary>
|
||||||
|
/// The performer of the song.
|
||||||
|
/// </summary>
|
||||||
|
Performer,
|
||||||
|
/// <summary>
|
||||||
|
/// A comment for the track.
|
||||||
|
/// </summary>
|
||||||
|
Comment,
|
||||||
|
/// <summary>
|
||||||
|
/// The disc of a multidisc album the track is on.
|
||||||
|
/// </summary>
|
||||||
|
Disc
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
90
LibMpc/Exception.cs
Normal file
90
LibMpc/Exception.cs
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Matthias Sessler
|
||||||
|
*
|
||||||
|
* This file is part of LibMpc.net.
|
||||||
|
*
|
||||||
|
* LibMpc.net is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* LibMpc.net is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with LibMpc.net. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Libmpc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Is thrown when a command is to be executed on a disconnected <see cref="MpcConnection"/>
|
||||||
|
/// where the <see cref="MpcConnection.AutoConnect"/> property is set to false.
|
||||||
|
/// </summary>
|
||||||
|
public class NotConnectedException : InvalidOperationException
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new NotConnectedException.
|
||||||
|
/// </summary>
|
||||||
|
public NotConnectedException() : base("Not connected.") {}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Is thrown when the connect method is invoked on an already connected <see cref="MpcConnection"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class AlreadyConnectedException : InvalidOperationException
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new AlreadyConnectedException.
|
||||||
|
/// </summary>
|
||||||
|
public AlreadyConnectedException() : base("Connected already established.") { }
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Is thrown if the response from a MPD server is not as expected. This should never happen when
|
||||||
|
/// working with a tested version of the MPD server.
|
||||||
|
/// </summary>
|
||||||
|
public class InvalidMpdResponseException : Exception
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new InvalidMpdResponseException.
|
||||||
|
/// </summary>
|
||||||
|
public InvalidMpdResponseException() : base( "Invalid Mpd Response." ) {}
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new InvalidMpdResponseException.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">A message describing the error.</param>
|
||||||
|
public InvalidMpdResponseException(string message) : base("Invalid Mpd Response: " + message) { }
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Is thrown when the MPD server returns an error to a command.
|
||||||
|
/// </summary>
|
||||||
|
public class MpdResponseException : Exception
|
||||||
|
{
|
||||||
|
private int errorCode;
|
||||||
|
private string errorMessage;
|
||||||
|
/// <summary>
|
||||||
|
/// The error code of the mpd server.
|
||||||
|
/// </summary>
|
||||||
|
public int ErrorCode { get { return this.errorCode; } }
|
||||||
|
/// <summary>
|
||||||
|
/// A message describing what went wrong.
|
||||||
|
/// </summary>
|
||||||
|
public string ErrorMessage { get { return this.errorMessage; } }
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new MpdResponseException.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="errorCode">The error code of the mpd server.</param>
|
||||||
|
/// <param name="errorMessage">A message describing what went wrong.</param>
|
||||||
|
public MpdResponseException(int errorCode, string errorMessage)
|
||||||
|
: base("MPD" + errorCode + " " + errorMessage)
|
||||||
|
{
|
||||||
|
this.errorCode = errorCode;
|
||||||
|
this.errorMessage = errorMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1337
LibMpc/Mpc.cs
Normal file
1337
LibMpc/Mpc.cs
Normal file
File diff suppressed because it is too large
Load Diff
316
LibMpc/MpcConnection.cs
Normal file
316
LibMpc/MpcConnection.cs
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Matthias Sessler
|
||||||
|
*
|
||||||
|
* This file is part of LibMpc.net.
|
||||||
|
*
|
||||||
|
* LibMpc.net is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* LibMpc.net is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with LibMpc.net. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
|
||||||
|
namespace Libmpc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The delegate for the <see cref="MpcConnection.OnConnected"/> and <see cref="MpcConnection.OnDisconnected"/> events.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connection">The connection firing the event.</param>
|
||||||
|
public delegate void MpcConnectionEventDelegate( MpcConnection connection );
|
||||||
|
/// <summary>
|
||||||
|
/// 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="Libmpc.Mpc"/>
|
||||||
|
/// class.
|
||||||
|
/// </summary>
|
||||||
|
public class MpcConnection
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Is fired when a connection to a MPD server is established.
|
||||||
|
/// </summary>
|
||||||
|
public event MpcConnectionEventDelegate OnConnected;
|
||||||
|
/// <summary>
|
||||||
|
/// Is fired when the connection to the MPD server is closed.
|
||||||
|
/// </summary>
|
||||||
|
public event MpcConnectionEventDelegate OnDisconnected;
|
||||||
|
|
||||||
|
private static readonly string FIRST_LINE_PREFIX = "OK MPD ";
|
||||||
|
|
||||||
|
private static readonly string OK = "OK";
|
||||||
|
private static readonly string ACK = "ACK";
|
||||||
|
|
||||||
|
private static readonly Regex ACK_REGEX = new Regex("^ACK \\[(?<code>[0-9]*)@(?<nr>[0-9]*)] \\{(?<command>[a-z]*)} (?<message>.*)$");
|
||||||
|
|
||||||
|
private IPEndPoint ipEndPoint = null;
|
||||||
|
|
||||||
|
private TcpClient tcpClient = null;
|
||||||
|
private NetworkStream networkStream = null;
|
||||||
|
|
||||||
|
private StreamReader reader;
|
||||||
|
private StreamWriter writer;
|
||||||
|
|
||||||
|
private string version;
|
||||||
|
/// <summary>
|
||||||
|
/// If the connection to the MPD is connected.
|
||||||
|
/// </summary>
|
||||||
|
public bool Connected { get { return (this.tcpClient != null) && this.tcpClient.Connected; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The version of the MPD.
|
||||||
|
/// </summary>
|
||||||
|
public string Version { get { return this.version; } }
|
||||||
|
|
||||||
|
private bool autoConnect = false;
|
||||||
|
/// <summary>
|
||||||
|
/// If a connection should be established when a command is to be
|
||||||
|
/// executed in disconnected state.
|
||||||
|
/// </summary>
|
||||||
|
public bool AutoConnect
|
||||||
|
{
|
||||||
|
get{ return this.autoConnect; }
|
||||||
|
set { this.autoConnect = value; }
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new MpdConnection.
|
||||||
|
/// </summary>
|
||||||
|
public MpcConnection() {}
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new MpdConnection.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="server">The IPEndPoint of the MPD server.</param>
|
||||||
|
public MpcConnection(IPEndPoint server) { this.Connect(server); }
|
||||||
|
/// <summary>
|
||||||
|
/// The IPEndPoint of the MPD server.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="AlreadyConnectedException">When a conenction to a MPD server is already established.</exception>
|
||||||
|
public IPEndPoint Server
|
||||||
|
{
|
||||||
|
get { return this.ipEndPoint; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (this.Connected)
|
||||||
|
throw new AlreadyConnectedException();
|
||||||
|
|
||||||
|
this.ipEndPoint = value;
|
||||||
|
|
||||||
|
this.ClearConnectionFields();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Connects to a MPD server.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="server">The IPEndPoint of the server.</param>
|
||||||
|
public void Connect(IPEndPoint server)
|
||||||
|
{
|
||||||
|
this.Server = server;
|
||||||
|
this.Connect();
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Connects to the MPD server who's IPEndPoint was set in the Server property.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="InvalidOperationException">If no IPEndPoint was set to the Server property.</exception>
|
||||||
|
public void Connect()
|
||||||
|
{
|
||||||
|
if (this.ipEndPoint == null)
|
||||||
|
throw new InvalidOperationException("Server IPEndPoint not set.");
|
||||||
|
|
||||||
|
if (this.Connected)
|
||||||
|
throw new AlreadyConnectedException();
|
||||||
|
|
||||||
|
this.tcpClient = new TcpClient(
|
||||||
|
this.ipEndPoint.Address.ToString(),
|
||||||
|
this.ipEndPoint.Port);
|
||||||
|
this.networkStream = this.tcpClient.GetStream();
|
||||||
|
|
||||||
|
this.reader = new StreamReader(this.networkStream, Encoding.UTF8);
|
||||||
|
this.writer = new StreamWriter(this.networkStream, Encoding.UTF8);
|
||||||
|
this.writer.NewLine = "\n";
|
||||||
|
|
||||||
|
string firstLine = this.reader.ReadLine();
|
||||||
|
if( !firstLine.StartsWith( FIRST_LINE_PREFIX ) )
|
||||||
|
{
|
||||||
|
this.Disconnect();
|
||||||
|
throw new InvalidDataException("Response of mpd does not start with \"" + FIRST_LINE_PREFIX + "\"." );
|
||||||
|
}
|
||||||
|
this.version = firstLine.Substring(FIRST_LINE_PREFIX.Length);
|
||||||
|
|
||||||
|
this.writer.WriteLine();
|
||||||
|
this.writer.Flush();
|
||||||
|
|
||||||
|
this.readResponse();
|
||||||
|
|
||||||
|
if( this.OnConnected != null )
|
||||||
|
this.OnConnected.Invoke( this );
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Disconnects from the current MPD server.
|
||||||
|
/// </summary>
|
||||||
|
public void Disconnect()
|
||||||
|
{
|
||||||
|
if (this.tcpClient == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.networkStream.Close();
|
||||||
|
|
||||||
|
this.ClearConnectionFields();
|
||||||
|
|
||||||
|
if( this.OnDisconnected != null )
|
||||||
|
this.OnDisconnected.Invoke( this );
|
||||||
|
}
|
||||||
|
/// <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 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");
|
||||||
|
|
||||||
|
this.CheckConnected();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.writer.WriteLine(command);
|
||||||
|
this.writer.Flush();
|
||||||
|
|
||||||
|
return this.readResponse();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
try { this.Disconnect(); }
|
||||||
|
catch (Exception) { }
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <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 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");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.CheckConnected();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.writer.Write(command);
|
||||||
|
foreach (string arg in argument)
|
||||||
|
{
|
||||||
|
this.writer.Write(' ');
|
||||||
|
this.WriteToken(arg);
|
||||||
|
}
|
||||||
|
this.writer.WriteLine();
|
||||||
|
this.writer.Flush();
|
||||||
|
|
||||||
|
return this.readResponse();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
try { this.Disconnect(); } catch (Exception) { }
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckConnected()
|
||||||
|
{
|
||||||
|
if (!this.Connected)
|
||||||
|
{
|
||||||
|
if (this.autoConnect)
|
||||||
|
this.Connect();
|
||||||
|
else
|
||||||
|
throw new NotConnectedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteToken(string token)
|
||||||
|
{
|
||||||
|
if (token.Contains(" "))
|
||||||
|
{
|
||||||
|
this.writer.Write("\"");
|
||||||
|
foreach (char chr in token)
|
||||||
|
if (chr == '"')
|
||||||
|
this.writer.Write("\\\"");
|
||||||
|
else
|
||||||
|
this.writer.Write(chr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
this.writer.Write(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MpdResponse readResponse()
|
||||||
|
{
|
||||||
|
List<string> ret = new List<string>();
|
||||||
|
string line = this.reader.ReadLine();
|
||||||
|
while (!(line.Equals(OK) || line.StartsWith(ACK)))
|
||||||
|
{
|
||||||
|
ret.Add(line);
|
||||||
|
line = this.reader.ReadLine();
|
||||||
|
}
|
||||||
|
if (line.Equals(OK))
|
||||||
|
return new MpdResponse(new ReadOnlyCollection<string>(ret));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Match match = ACK_REGEX.Match(line);
|
||||||
|
|
||||||
|
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>(ret)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearConnectionFields()
|
||||||
|
{
|
||||||
|
this.tcpClient = null;
|
||||||
|
this.networkStream = null;
|
||||||
|
this.reader = null;
|
||||||
|
this.writer = null;
|
||||||
|
this.version = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
84
LibMpc/MpdDirectoryListing.cs
Normal file
84
LibMpc/MpdDirectoryListing.cs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Matthias Sessler
|
||||||
|
*
|
||||||
|
* This file is part of LibMpc.net.
|
||||||
|
*
|
||||||
|
* LibMpc.net is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* LibMpc.net is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with LibMpc.net. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Libmpc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The MpdDirectoryListing class contains the response of a MPD server to a list command.
|
||||||
|
/// </summary>
|
||||||
|
public class MpdDirectoryListing
|
||||||
|
{
|
||||||
|
private readonly ReadOnlyCollection<MpdFile> file;
|
||||||
|
private readonly ReadOnlyCollection<string> directory;
|
||||||
|
private readonly ReadOnlyCollection<string> playlist;
|
||||||
|
/// <summary>
|
||||||
|
/// The list of files in the directory.
|
||||||
|
/// </summary>
|
||||||
|
public ReadOnlyCollection<MpdFile> FileList { get { return this.file; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The list of subdirectories in the directory.
|
||||||
|
/// </summary>
|
||||||
|
public ReadOnlyCollection<string> DirectoryList { get { return this.directory; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The list of playlists in the directory.
|
||||||
|
/// </summary>
|
||||||
|
public ReadOnlyCollection<string> PlaylistList { get { return this.playlist; } }
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new MpdDirectoryListing.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="file">The list of files in the directory.</param>
|
||||||
|
/// <param name="directory">The list of subdirectories in the directory.</param>
|
||||||
|
/// <param name="playlist">The list of playlists in the directory.</param>
|
||||||
|
public MpdDirectoryListing(List<MpdFile> file, List<string> directory, List<string> playlist)
|
||||||
|
{
|
||||||
|
if (file == null)
|
||||||
|
throw new ArgumentNullException("file");
|
||||||
|
if (directory == null)
|
||||||
|
throw new ArgumentNullException("directory");
|
||||||
|
if (playlist == null)
|
||||||
|
throw new ArgumentNullException("playlist");
|
||||||
|
|
||||||
|
this.file = new ReadOnlyCollection<MpdFile>(file);
|
||||||
|
this.directory = new ReadOnlyCollection<string>(directory);
|
||||||
|
this.playlist = new ReadOnlyCollection<string>(playlist);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new MpdDirectoryListing.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="file">The list of files in the directory.</param>
|
||||||
|
/// <param name="directory">The list of subdirectories in the directory.</param>
|
||||||
|
/// <param name="playlist">The list of playlists in the directory.</param>
|
||||||
|
public MpdDirectoryListing(ReadOnlyCollection<MpdFile> file, ReadOnlyCollection<string> directory, ReadOnlyCollection<string> playlist)
|
||||||
|
{
|
||||||
|
if (file == null)
|
||||||
|
throw new ArgumentNullException("file");
|
||||||
|
if (directory == null)
|
||||||
|
throw new ArgumentNullException("directory");
|
||||||
|
if (playlist == null)
|
||||||
|
throw new ArgumentNullException("playlist");
|
||||||
|
|
||||||
|
this.file = file;
|
||||||
|
this.directory = directory;
|
||||||
|
this.playlist = playlist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
559
LibMpc/MpdFile.cs
Normal file
559
LibMpc/MpdFile.cs
Normal file
@ -0,0 +1,559 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Matthias Sessler
|
||||||
|
*
|
||||||
|
* This file is part of LibMpc.net.
|
||||||
|
*
|
||||||
|
* LibMpc.net is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* LibMpc.net is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with LibMpc.net. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Libmpc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The MpdFile class contains all meta data for a file of the MPD.
|
||||||
|
/// </summary>
|
||||||
|
public class MpdFile
|
||||||
|
{
|
||||||
|
private const string TAG_FILE = "file";
|
||||||
|
private const string TAG_TIME = "Time";
|
||||||
|
private const string TAG_ARTIST = "Artist";
|
||||||
|
private const string TAG_ALBUM = "Album";
|
||||||
|
private const string TAG_TITLE = "Title";
|
||||||
|
private const string TAG_TRACK = "Track";
|
||||||
|
private const string TAG_NAME = "Name";
|
||||||
|
private const string TAG_GENRE = "Genre";
|
||||||
|
private const string TAG_DATE = "Date";
|
||||||
|
private const string TAG_COMPOSER = "Composer";
|
||||||
|
private const string TAG_PERFORMER = "Performer";
|
||||||
|
private const string TAG_COMMENT = "Comment";
|
||||||
|
private const string TAG_DISC = "Disc";
|
||||||
|
private const string TAG_POS = "Pos";
|
||||||
|
private const string TAG_ID = "Id";
|
||||||
|
|
||||||
|
private const int NO_TIME = -1;
|
||||||
|
private const string NO_ALBUM = null;
|
||||||
|
private const string NO_ARTIST = null;
|
||||||
|
private const string NO_TITLE = null;
|
||||||
|
private const string NO_TRACK = null;
|
||||||
|
private const string NO_NAME = null;
|
||||||
|
private const string NO_GENRE = null;
|
||||||
|
private const string NO_DATE = null;
|
||||||
|
private const string NO_COMPOSER = null;
|
||||||
|
private const string NO_PERFORMER = null;
|
||||||
|
private const string NO_COMMENT = null;
|
||||||
|
private const int NO_DISC = -1;
|
||||||
|
private const int NO_POS = -1;
|
||||||
|
private const int NO_ID = -1;
|
||||||
|
|
||||||
|
private readonly string file;
|
||||||
|
private readonly int time;
|
||||||
|
private readonly string album;
|
||||||
|
private readonly string artist;
|
||||||
|
private readonly string title;
|
||||||
|
private readonly string track;
|
||||||
|
private readonly string name;
|
||||||
|
private readonly string genre;
|
||||||
|
private readonly string date;
|
||||||
|
private readonly string composer;
|
||||||
|
private readonly string performer;
|
||||||
|
private readonly string comment;
|
||||||
|
private readonly int disc;
|
||||||
|
private readonly int pos;
|
||||||
|
private readonly int id;
|
||||||
|
/// <summary>
|
||||||
|
/// The name and path of the file.
|
||||||
|
/// </summary>
|
||||||
|
public string File { get { return this.file; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The length of the file in seconds.
|
||||||
|
/// </summary>
|
||||||
|
public int Time { get { return this.time; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The album of the file.
|
||||||
|
/// </summary>
|
||||||
|
public string Album { get { return this.album; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The artist of the file.
|
||||||
|
/// </summary>
|
||||||
|
public string Artist { get { return this.artist; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The title of the file.
|
||||||
|
/// </summary>
|
||||||
|
public string Title { get { return this.title; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The value of the track property of the file.
|
||||||
|
/// </summary>
|
||||||
|
public string Track { get { return this.track; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the song.
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get { return this.name; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The genre of the song.
|
||||||
|
/// </summary>
|
||||||
|
public string Genre { get { return this.genre; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The date the song was released.
|
||||||
|
/// </summary>
|
||||||
|
public string Date { get { return this.date; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The composer of the song.
|
||||||
|
/// </summary>
|
||||||
|
public string Composer { get { return this.composer; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The performer of the song.
|
||||||
|
/// </summary>
|
||||||
|
public string Performer { get { return this.performer; } }
|
||||||
|
/// <summary>
|
||||||
|
/// A comment to the file.
|
||||||
|
/// </summary>
|
||||||
|
public string Comment { get { return this.comment; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The number of the disc on a multidisc album.
|
||||||
|
/// </summary>
|
||||||
|
public int Disc { get { return this.disc; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The index of the file in a playlist.
|
||||||
|
/// </summary>
|
||||||
|
public int Pos { get { return this.pos; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The id of the file in a playlist.
|
||||||
|
/// </summary>
|
||||||
|
public int Id { get { return this.id; } }
|
||||||
|
/// <summary>
|
||||||
|
/// If the MpdFile has the <see cref="Time"/> property set.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasTime { get { return this.time != NO_TIME; } }
|
||||||
|
/// <summary>
|
||||||
|
/// If the MpdFile has the <see cref="Album"/> property set.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasAlbum { get { return this.album != NO_ALBUM; } }
|
||||||
|
/// <summary>
|
||||||
|
/// If the MpdFile has the <see cref="Artist"/> property set.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasArtist { get { return this.artist != NO_ARTIST; } }
|
||||||
|
/// <summary>
|
||||||
|
/// If the MpdFile has the <see cref="Title"/> property set.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasTitle { get { return this.title != NO_TITLE; } }
|
||||||
|
/// <summary>
|
||||||
|
/// If the MpdFile has the <see cref="Track"/> property set.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasTrack { get { return this.track != NO_TRACK; } }
|
||||||
|
/// <summary>
|
||||||
|
/// If the MpdFile has the <see cref="Name"/> property set.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasName { get { return this.name != NO_NAME; } }
|
||||||
|
/// <summary>
|
||||||
|
/// If the MpdFile has the <see cref="Genre"/> property set.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasGenre { get { return this.genre != NO_GENRE; } }
|
||||||
|
/// <summary>
|
||||||
|
/// If the MpdFile has the <see cref="Date"/> property set.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasDate { get { return this.date != NO_DATE; } }
|
||||||
|
/// <summary>
|
||||||
|
/// If the MpdFile has the <see cref="Composer"/> property set.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasComposer { get { return this.composer != NO_COMPOSER; } }
|
||||||
|
/// <summary>
|
||||||
|
/// If the MpdFile has the <see cref="Performer"/> property set.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasPerformer { get { return this.performer != NO_PERFORMER; } }
|
||||||
|
/// <summary>
|
||||||
|
/// If the MpdFile has the <see cref="Comment"/> property set.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasComment { get { return this.comment != NO_COMMENT; } }
|
||||||
|
/// <summary>
|
||||||
|
/// If the MpdFile has the <see cref="Disc"/> property set.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasDisc { get { return this.disc != NO_DISC; } }
|
||||||
|
/// <summary>
|
||||||
|
/// If the MpdFile has the <see cref="Pos"/> property set.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasPos { get { return this.pos != NO_POS; } }
|
||||||
|
/// <summary>
|
||||||
|
/// If the MpdFile has the <see cref="Id"/> property set.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasId { get { return this.id != NO_ID; } }
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new MpdFile.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="file">The name and path of the file.</param>
|
||||||
|
/// <param name="time">The length of the file in seconds.</param>
|
||||||
|
/// <param name="album">The album of the file.</param>
|
||||||
|
/// <param name="artist">The artist of the file.</param>
|
||||||
|
/// <param name="title">The title of the file.</param>
|
||||||
|
/// <param name="track">The value of the track property of the file.</param>
|
||||||
|
/// <param name="name">The name of the song.</param>
|
||||||
|
/// <param name="genre">The genre of the song.</param>
|
||||||
|
/// <param name="date">The date the song was released.</param>
|
||||||
|
/// <param name="composer">The composer of the song.</param>
|
||||||
|
/// <param name="performer">The performer of the song.</param>
|
||||||
|
/// <param name="comment">A comment to the file.</param>
|
||||||
|
/// <param name="disc">The number of the disc on a multidisc album.</param>
|
||||||
|
/// <param name="pos">The index of the file in a playlist.</param>
|
||||||
|
/// <param name="id">The id of the file in a playlist.</param>
|
||||||
|
public MpdFile(string file,
|
||||||
|
int time,
|
||||||
|
string album,
|
||||||
|
string artist,
|
||||||
|
string title,
|
||||||
|
string track,
|
||||||
|
string name,
|
||||||
|
string genre,
|
||||||
|
string date,
|
||||||
|
string composer,
|
||||||
|
string performer,
|
||||||
|
string comment,
|
||||||
|
int disc,
|
||||||
|
int pos,
|
||||||
|
int id)
|
||||||
|
{
|
||||||
|
if (file == null)
|
||||||
|
throw new ArgumentNullException("file");
|
||||||
|
|
||||||
|
this.file = file;
|
||||||
|
this.time = time;
|
||||||
|
this.album = album;
|
||||||
|
this.artist = artist;
|
||||||
|
this.title = title;
|
||||||
|
this.track = track;
|
||||||
|
this.name = name;
|
||||||
|
this.genre = genre;
|
||||||
|
this.date = date;
|
||||||
|
this.composer = composer;
|
||||||
|
this.performer = performer;
|
||||||
|
this.comment = comment;
|
||||||
|
this.disc = disc;
|
||||||
|
this.pos = pos;
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// A string containing all the properties of the file.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
appendString(builder, TAG_FILE, this.file);
|
||||||
|
if (this.HasTime)
|
||||||
|
appendInt(builder, TAG_TIME, this.time);
|
||||||
|
if (this.HasAlbum)
|
||||||
|
appendString(builder, TAG_ALBUM, this.album);
|
||||||
|
if (this.HasArtist)
|
||||||
|
appendString(builder, TAG_ARTIST, this.artist);
|
||||||
|
if (this.HasTitle)
|
||||||
|
appendString(builder, TAG_TITLE, this.title);
|
||||||
|
if (this.HasTrack)
|
||||||
|
appendString(builder, TAG_TRACK, this.track);
|
||||||
|
if (this.HasName)
|
||||||
|
appendString(builder, TAG_NAME, this.name);
|
||||||
|
if (this.HasGenre)
|
||||||
|
appendString(builder, TAG_GENRE, this.genre);
|
||||||
|
if (this.HasDate)
|
||||||
|
appendString(builder, TAG_DATE, this.date);
|
||||||
|
if (this.HasComposer)
|
||||||
|
appendString(builder, TAG_COMPOSER, this.composer);
|
||||||
|
if (this.HasPerformer)
|
||||||
|
appendString(builder, TAG_PERFORMER, this.performer);
|
||||||
|
if (this.HasComment)
|
||||||
|
appendString(builder, TAG_COMMENT, this.comment);
|
||||||
|
if (this.HasDisc)
|
||||||
|
appendInt(builder, TAG_DISC, this.disc);
|
||||||
|
if (this.HasPos)
|
||||||
|
appendInt(builder, TAG_POS, this.pos);
|
||||||
|
if (this.HasId)
|
||||||
|
appendInt(builder, TAG_ID, this.id);
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void appendString(StringBuilder builder, string name, string value)
|
||||||
|
{
|
||||||
|
builder.Append(name);
|
||||||
|
builder.Append(": ");
|
||||||
|
builder.Append(value);
|
||||||
|
builder.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void appendInt(StringBuilder builder, string name, int value)
|
||||||
|
{
|
||||||
|
builder.Append(name);
|
||||||
|
builder.Append(": ");
|
||||||
|
builder.Append(value);
|
||||||
|
builder.AppendLine();
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a MpdFile object from a MpdResponse object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="response">The response of the MPD server.</param>
|
||||||
|
/// <returns>A new MpdFile object build from the MpdResponse object.</returns>
|
||||||
|
public static MpdFile build(MpdResponse response)
|
||||||
|
{
|
||||||
|
if (response == null)
|
||||||
|
throw new ArgumentNullException("response");
|
||||||
|
|
||||||
|
string file = null;
|
||||||
|
int time = NO_TIME;
|
||||||
|
string album = NO_ALBUM;
|
||||||
|
string artist = NO_ARTIST;
|
||||||
|
string title = NO_TITLE;
|
||||||
|
string track = NO_TRACK;
|
||||||
|
string name = NO_NAME;
|
||||||
|
string genre = NO_GENRE;
|
||||||
|
string date = NO_DATE;
|
||||||
|
string composer = NO_COMPOSER;
|
||||||
|
string performer = NO_PERFORMER;
|
||||||
|
string comment = NO_COMMENT;
|
||||||
|
int disc = NO_DISC;
|
||||||
|
int pos = NO_POS;
|
||||||
|
int id = NO_ID;
|
||||||
|
|
||||||
|
|
||||||
|
foreach (KeyValuePair<string, string> line in response)
|
||||||
|
{
|
||||||
|
if( line.Key != null )
|
||||||
|
switch (line.Key)
|
||||||
|
{
|
||||||
|
case TAG_FILE:
|
||||||
|
file = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_TIME:
|
||||||
|
int tryTime;
|
||||||
|
if( int.TryParse( line.Value, out tryTime ) )
|
||||||
|
time = tryTime;
|
||||||
|
break;
|
||||||
|
case TAG_ALBUM:
|
||||||
|
album = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_ARTIST:
|
||||||
|
artist = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_TITLE:
|
||||||
|
title = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_TRACK:
|
||||||
|
track = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_NAME:
|
||||||
|
name = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_GENRE:
|
||||||
|
genre = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_DATE:
|
||||||
|
date = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_COMPOSER:
|
||||||
|
composer = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_PERFORMER:
|
||||||
|
performer = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_COMMENT:
|
||||||
|
comment = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_DISC:
|
||||||
|
int tryDisc;
|
||||||
|
if (int.TryParse(line.Value, out tryDisc))
|
||||||
|
disc = tryDisc;
|
||||||
|
break;
|
||||||
|
case TAG_POS:
|
||||||
|
int tryPos;
|
||||||
|
if (int.TryParse(line.Value, out tryPos))
|
||||||
|
pos = tryPos;
|
||||||
|
break;
|
||||||
|
case TAG_ID:
|
||||||
|
int tryId;
|
||||||
|
if (int.TryParse(line.Value, out tryId))
|
||||||
|
id = tryId;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file == null)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return new MpdFile(
|
||||||
|
file,
|
||||||
|
time,
|
||||||
|
album,
|
||||||
|
artist,
|
||||||
|
title,
|
||||||
|
track,
|
||||||
|
name,
|
||||||
|
genre,
|
||||||
|
date,
|
||||||
|
composer,
|
||||||
|
performer,
|
||||||
|
comment,
|
||||||
|
disc,
|
||||||
|
pos,
|
||||||
|
id);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Builds a list of MpdFile objects from a MpdResponse object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="response">The MpdResponse object to build the list of MpdFiles from.</param>
|
||||||
|
/// <returns>A list ob MpdFiles built from the MpdResponse object.</returns>
|
||||||
|
public static List<MpdFile> buildList(MpdResponse response)
|
||||||
|
{
|
||||||
|
if (response == null)
|
||||||
|
throw new ArgumentNullException("response");
|
||||||
|
|
||||||
|
List<MpdFile> ret = new List<MpdFile>();
|
||||||
|
|
||||||
|
string file = null;
|
||||||
|
int time = NO_TIME;
|
||||||
|
string album = NO_ALBUM;
|
||||||
|
string artist = NO_ARTIST;
|
||||||
|
string title = NO_TITLE;
|
||||||
|
string track = NO_TRACK;
|
||||||
|
string name = NO_NAME;
|
||||||
|
string genre = NO_GENRE;
|
||||||
|
string date = NO_DATE;
|
||||||
|
string composer = NO_COMPOSER;
|
||||||
|
string performer = NO_PERFORMER;
|
||||||
|
string comment = NO_COMMENT;
|
||||||
|
int disc = NO_DISC;
|
||||||
|
int pos = NO_POS;
|
||||||
|
int id = NO_ID;
|
||||||
|
|
||||||
|
|
||||||
|
foreach (KeyValuePair<string, string> line in response)
|
||||||
|
{
|
||||||
|
if( line.Key != null )
|
||||||
|
switch (line.Key)
|
||||||
|
{
|
||||||
|
case TAG_FILE:
|
||||||
|
if( file != null )
|
||||||
|
ret.Add( new MpdFile(
|
||||||
|
file,
|
||||||
|
time,
|
||||||
|
album,
|
||||||
|
artist,
|
||||||
|
title,
|
||||||
|
track,
|
||||||
|
name,
|
||||||
|
genre,
|
||||||
|
date,
|
||||||
|
composer,
|
||||||
|
performer,
|
||||||
|
comment,
|
||||||
|
disc,
|
||||||
|
pos,
|
||||||
|
id ) );
|
||||||
|
|
||||||
|
file = line.Value;
|
||||||
|
|
||||||
|
time = NO_TIME;
|
||||||
|
album = NO_ALBUM;
|
||||||
|
artist = NO_ARTIST;
|
||||||
|
title = NO_TITLE;
|
||||||
|
track = NO_TRACK;
|
||||||
|
name = NO_NAME;
|
||||||
|
genre = NO_GENRE;
|
||||||
|
date = NO_DATE;
|
||||||
|
composer = NO_COMPOSER;
|
||||||
|
performer = NO_PERFORMER;
|
||||||
|
comment = NO_COMMENT;
|
||||||
|
disc = NO_DISC;
|
||||||
|
pos = NO_POS;
|
||||||
|
id = NO_ID;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case TAG_TIME:
|
||||||
|
int tryTime;
|
||||||
|
if( int.TryParse( line.Value, out tryTime ) )
|
||||||
|
time = tryTime;
|
||||||
|
break;
|
||||||
|
case TAG_ALBUM:
|
||||||
|
album = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_ARTIST:
|
||||||
|
artist = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_TITLE:
|
||||||
|
title = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_TRACK:
|
||||||
|
track = line.Value;
|
||||||
|
/*
|
||||||
|
int tryTrack;
|
||||||
|
if (int.TryParse(line.Value, out tryTrack))
|
||||||
|
track = tryTrack;
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
case TAG_NAME:
|
||||||
|
name = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_GENRE:
|
||||||
|
genre = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_DATE:
|
||||||
|
date = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_COMPOSER:
|
||||||
|
composer = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_PERFORMER:
|
||||||
|
performer = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_COMMENT:
|
||||||
|
comment = line.Value;
|
||||||
|
break;
|
||||||
|
case TAG_DISC:
|
||||||
|
int tryDisc;
|
||||||
|
if (int.TryParse(line.Value, out tryDisc))
|
||||||
|
disc = tryDisc;
|
||||||
|
break;
|
||||||
|
case TAG_POS:
|
||||||
|
int tryPos;
|
||||||
|
if (int.TryParse(line.Value, out tryPos))
|
||||||
|
pos = tryPos;
|
||||||
|
break;
|
||||||
|
case TAG_ID:
|
||||||
|
int tryId;
|
||||||
|
if (int.TryParse(line.Value, out tryId))
|
||||||
|
id = tryId;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file != null)
|
||||||
|
ret.Add(new MpdFile(
|
||||||
|
file,
|
||||||
|
time,
|
||||||
|
album,
|
||||||
|
artist,
|
||||||
|
title,
|
||||||
|
track,
|
||||||
|
name,
|
||||||
|
genre,
|
||||||
|
date,
|
||||||
|
composer,
|
||||||
|
performer,
|
||||||
|
comment,
|
||||||
|
disc,
|
||||||
|
pos,
|
||||||
|
id ));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
69
LibMpc/MpdOutput.cs
Normal file
69
LibMpc/MpdOutput.cs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Matthias Sessler
|
||||||
|
*
|
||||||
|
* This file is part of LibMpc.net.
|
||||||
|
*
|
||||||
|
* LibMpc.net is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* LibMpc.net is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with LibMpc.net. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Libmpc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The MpdOutput class contains all attributes of an output device of the MPD.
|
||||||
|
/// </summary>
|
||||||
|
public class MpdOutput
|
||||||
|
{
|
||||||
|
private readonly int id;
|
||||||
|
private readonly string name;
|
||||||
|
private readonly bool enabled;
|
||||||
|
/// <summary>
|
||||||
|
/// The id of the output.
|
||||||
|
/// </summary>
|
||||||
|
public int Id { get { return this.id; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the output.
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get { return this.name; } }
|
||||||
|
/// <summary>
|
||||||
|
/// If the output is enabled.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsEnabled { get { return this.enabled; } }
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new MpdOutput object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The id of the output.</param>
|
||||||
|
/// <param name="name">The name of the output.</param>
|
||||||
|
/// <param name="enabled">If the output is enabled.</param>
|
||||||
|
public MpdOutput(int id, string name, bool enabled)
|
||||||
|
{
|
||||||
|
if (name == null)
|
||||||
|
throw new ArgumentNullException("name");
|
||||||
|
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a string representation of the object mainly for debuging purpose.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string representation of the object.</returns>
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return this.id + "::" + this.name + "::" + this.enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
326
LibMpc/MpdResponse.cs
Normal file
326
LibMpc/MpdResponse.cs
Normal file
@ -0,0 +1,326 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Matthias Sessler
|
||||||
|
*
|
||||||
|
* This file is part of LibMpc.net.
|
||||||
|
*
|
||||||
|
* LibMpc.net is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* LibMpc.net is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with LibMpc.net. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
134
LibMpc/MpdStatistics.cs
Normal file
134
LibMpc/MpdStatistics.cs
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Matthias Sessler
|
||||||
|
*
|
||||||
|
* This file is part of LibMpc.net.
|
||||||
|
*
|
||||||
|
* LibMpc.net is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* LibMpc.net is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with LibMpc.net. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Libmpc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The MpdStatistics class contains statistics of the MPD file database.
|
||||||
|
/// </summary>
|
||||||
|
public class MpdStatistics
|
||||||
|
{
|
||||||
|
private readonly int artists;
|
||||||
|
private readonly int albums;
|
||||||
|
private readonly int songs;
|
||||||
|
private readonly int uptime;
|
||||||
|
private readonly int playtime;
|
||||||
|
private readonly int db_playtime;
|
||||||
|
private readonly long db_update;
|
||||||
|
/// <summary>
|
||||||
|
/// The number of artists in the MPD database.
|
||||||
|
/// </summary>
|
||||||
|
public int Artists { get { return this.artists; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The number of albums in the MPD database.
|
||||||
|
/// </summary>
|
||||||
|
public int Albums { get { return this.albums; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The number of songs in the MPD database.
|
||||||
|
/// </summary>
|
||||||
|
public int Songs { get { return this.songs; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The time the MPD server is running in seconds.
|
||||||
|
/// </summary>
|
||||||
|
public int Uptime { get { return this.uptime; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The number of seconds the MPD played so far.
|
||||||
|
/// </summary>
|
||||||
|
public int Playtime { get { return this.playtime; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The total playtime of all songs in the MPD database.
|
||||||
|
/// </summary>
|
||||||
|
public int DbPlaytime { get { return this.db_playtime; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The timestamp of the last MPD database update.
|
||||||
|
/// </summary>
|
||||||
|
public long DbUpdate { get { return this.db_update; } }
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new MpdStatistics object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="artists">The number of artists in the MPD database.</param>
|
||||||
|
/// <param name="albums">The number of albums in the MPD database.</param>
|
||||||
|
/// <param name="songs">The number of songs in the MPD database.</param>
|
||||||
|
/// <param name="uptime">The time the MPD server is running in seconds.</param>
|
||||||
|
/// <param name="playtime">The number of seconds the MPD played so far.</param>
|
||||||
|
/// <param name="db_playtime">The total playtime of all songs in the MPD database.</param>
|
||||||
|
/// <param name="db_update">The timestamp of the last MPD database update.</param>
|
||||||
|
public MpdStatistics(
|
||||||
|
int artists,
|
||||||
|
int albums,
|
||||||
|
int songs,
|
||||||
|
int uptime,
|
||||||
|
int playtime,
|
||||||
|
int db_playtime,
|
||||||
|
long db_update
|
||||||
|
)
|
||||||
|
{
|
||||||
|
this.artists = artists;
|
||||||
|
this.albums = albums;
|
||||||
|
this.songs = songs;
|
||||||
|
this.uptime = uptime;
|
||||||
|
this.playtime = playtime;
|
||||||
|
this.db_playtime = db_playtime;
|
||||||
|
this.db_update = db_update;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a string representation of the object mainly for debugging purpuse.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string representation of the object.</returns>
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
appendInt(builder, "artists", this.artists);
|
||||||
|
appendInt(builder, "songs", this.songs);
|
||||||
|
appendInt(builder, "uptime", this.uptime);
|
||||||
|
appendInt(builder, "playtime", this.playtime);
|
||||||
|
appendInt(builder, "db_playtime", this.db_playtime);
|
||||||
|
appendLong(builder, "db_update", this.db_update);
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void appendInt(StringBuilder builder, string name, int value)
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
builder.Append(name);
|
||||||
|
builder.Append(": ");
|
||||||
|
builder.Append(value);
|
||||||
|
builder.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void appendLong(StringBuilder builder, string name, long value)
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
builder.Append(name);
|
||||||
|
builder.Append(": ");
|
||||||
|
builder.Append(value);
|
||||||
|
builder.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
271
LibMpc/MpdStatus.cs
Normal file
271
LibMpc/MpdStatus.cs
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008 Matthias Sessler
|
||||||
|
*
|
||||||
|
* This file is part of LibMpc.net.
|
||||||
|
*
|
||||||
|
* LibMpc.net is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* LibMpc.net is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with LibMpc.net. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Libmpc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The possible states of the MPD.
|
||||||
|
/// </summary>
|
||||||
|
public enum MpdState
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The state of the MPD could not be translated into this enumeration.
|
||||||
|
/// </summary>
|
||||||
|
Unknown,
|
||||||
|
/// <summary>
|
||||||
|
/// The MPD is playing a track.
|
||||||
|
/// </summary>
|
||||||
|
Play,
|
||||||
|
/// <summary>
|
||||||
|
/// The MPD is not playing a track.
|
||||||
|
/// </summary>
|
||||||
|
Stop,
|
||||||
|
/// <summary>
|
||||||
|
/// The playback of the MPD is currently paused.
|
||||||
|
/// </summary>
|
||||||
|
Pause
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// The MpdStatus class contains all values describing the current status of the MPD.
|
||||||
|
/// </summary>
|
||||||
|
public class MpdStatus
|
||||||
|
{
|
||||||
|
private int volume;
|
||||||
|
private bool repeat;
|
||||||
|
private bool random;
|
||||||
|
private int playlist;
|
||||||
|
private int playlistLength;
|
||||||
|
private int xFade;
|
||||||
|
private MpdState state;
|
||||||
|
private int song;
|
||||||
|
private int songId;
|
||||||
|
private int timeElapsed;
|
||||||
|
private int timeTotal;
|
||||||
|
private int bitrate;
|
||||||
|
private int audioSampleRate;
|
||||||
|
private int audioBits;
|
||||||
|
private int audioChannels;
|
||||||
|
private int updatingDb;
|
||||||
|
private string error;
|
||||||
|
/// <summary>
|
||||||
|
/// The current volume of the output.
|
||||||
|
/// </summary>
|
||||||
|
public int Volume { get { return this.volume; } }
|
||||||
|
/// <summary>
|
||||||
|
/// If the playlist is repeated after finish.
|
||||||
|
/// </summary>
|
||||||
|
public bool Repeat { get { return this.repeat; } }
|
||||||
|
/// <summary>
|
||||||
|
/// If the playlist is played in random order.
|
||||||
|
/// </summary>
|
||||||
|
public bool Random { get { return this.random; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The version number of the playlist.
|
||||||
|
/// </summary>
|
||||||
|
public int Playlist { get { return this.playlist; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The length of the playlist.
|
||||||
|
/// </summary>
|
||||||
|
public int PlaylistLength { get { return this.playlistLength; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The number of seconds crossfaded between song changes.
|
||||||
|
/// </summary>
|
||||||
|
public int XFade { get { return this.xFade; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The state of the MPD.
|
||||||
|
/// </summary>
|
||||||
|
public MpdState State { get { return this.state; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The index of the currently played song in the playlist.
|
||||||
|
/// </summary>
|
||||||
|
public int Song { get { return this.song; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The id of the song currently played.
|
||||||
|
/// </summary>
|
||||||
|
public int SongId { get { return this.songId; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The number of seconds already played of the current song.
|
||||||
|
/// </summary>
|
||||||
|
public int TimeElapsed { get { return this.timeElapsed; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The length of the current song in seconds.
|
||||||
|
/// </summary>
|
||||||
|
public int TimeTotal { get { return this.timeTotal; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The bitrate of the current song.
|
||||||
|
/// </summary>
|
||||||
|
public int Bitrate { get { return this.bitrate; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The audio sample rate of the current song.
|
||||||
|
/// </summary>
|
||||||
|
public int AudioSampleRate { get { return this.audioSampleRate; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The audio bits of the current song.
|
||||||
|
/// </summary>
|
||||||
|
public int AudioBits { get { return this.audioBits; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The number of audio channels of the current song.
|
||||||
|
/// </summary>
|
||||||
|
public int AudioChannels { get { return this.audioChannels; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The number of the update on the MPD database currently running.
|
||||||
|
/// </summary>
|
||||||
|
public int UpdatingDb { get { return this.updatingDb; } }
|
||||||
|
/// <summary>
|
||||||
|
/// An error message, if there is an error.
|
||||||
|
/// </summary>
|
||||||
|
public string Error { get { return this.error; } }
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new MpdStatus object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="volume">The current volume of the output.</param>
|
||||||
|
/// <param name="repeat">If the playlist is repeated after finish.</param>
|
||||||
|
/// <param name="random">If the playlist is played in random order.</param>
|
||||||
|
/// <param name="playlist">The version number of the playlist.</param>
|
||||||
|
/// <param name="playlistLength">The length of the playlist.</param>
|
||||||
|
/// <param name="xFade">The number of seconds crossfaded between song changes.</param>
|
||||||
|
/// <param name="state">The state of the MPD.</param>
|
||||||
|
/// <param name="song">The index of the currently played song in the playlist.</param>
|
||||||
|
/// <param name="songId">The id of the song currently played.</param>
|
||||||
|
/// <param name="timeElapsed">The number of seconds already played of the current song.</param>
|
||||||
|
/// <param name="timeTotal">The length of the current song in seconds.</param>
|
||||||
|
/// <param name="bitrate">The bitrate of the current song.</param>
|
||||||
|
/// <param name="audioSampleRate">The audio sample rate of the current song.</param>
|
||||||
|
/// <param name="audioBits">The audio bits of the current song.</param>
|
||||||
|
/// <param name="audioChannels">The number of audio channels of the current song.</param>
|
||||||
|
/// <param name="updatingDb">The number of the update on the MPD database currently running.</param>
|
||||||
|
/// <param name="error">An error message, if there is an error.</param>
|
||||||
|
public MpdStatus(
|
||||||
|
int volume,
|
||||||
|
bool repeat,
|
||||||
|
bool random,
|
||||||
|
int playlist,
|
||||||
|
int playlistLength,
|
||||||
|
int xFade,
|
||||||
|
MpdState state,
|
||||||
|
int song,
|
||||||
|
int songId,
|
||||||
|
int timeElapsed,
|
||||||
|
int timeTotal,
|
||||||
|
int bitrate,
|
||||||
|
int audioSampleRate,
|
||||||
|
int audioBits,
|
||||||
|
int audioChannels,
|
||||||
|
int updatingDb,
|
||||||
|
string error
|
||||||
|
)
|
||||||
|
{
|
||||||
|
this.volume = volume;
|
||||||
|
this.repeat = repeat;
|
||||||
|
this.random = random;
|
||||||
|
this.playlist = playlist;
|
||||||
|
this.playlistLength = playlistLength;
|
||||||
|
this.xFade = xFade;
|
||||||
|
this.state = state;
|
||||||
|
this.song = song;
|
||||||
|
this.songId = songId;
|
||||||
|
this.timeElapsed = timeElapsed;
|
||||||
|
this.timeTotal = timeTotal;
|
||||||
|
this.bitrate = bitrate;
|
||||||
|
this.audioSampleRate = audioSampleRate;
|
||||||
|
this.audioBits = audioBits;
|
||||||
|
this.audioChannels = audioChannels;
|
||||||
|
this.updatingDb = updatingDb;
|
||||||
|
this.error = error;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a string representation of the object maily for debugging purpuses.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string representation of the object.</returns>
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
appendInt(builder, "volume", this.volume);
|
||||||
|
appendBool(builder, "repeat", this.repeat);
|
||||||
|
appendBool(builder, "random", this.random);
|
||||||
|
appendInt(builder, "playlist", this.playlist);
|
||||||
|
appendInt(builder, "playlistlength", this.playlistLength);
|
||||||
|
appendInt(builder, "xfade", this.xFade);
|
||||||
|
switch (this.state)
|
||||||
|
{
|
||||||
|
case MpdState.Play:
|
||||||
|
builder.AppendLine("state: play");
|
||||||
|
break;
|
||||||
|
case MpdState.Pause:
|
||||||
|
builder.AppendLine("state: pause");
|
||||||
|
break;
|
||||||
|
case MpdState.Stop:
|
||||||
|
builder.AppendLine("state: stop");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
appendInt(builder, "song", this.song);
|
||||||
|
appendInt(builder, "songid", this.songId);
|
||||||
|
if ((this.timeElapsed >= 0) || (this.timeTotal >= 0))
|
||||||
|
{
|
||||||
|
builder.Append("time: ");
|
||||||
|
builder.Append(this.timeElapsed);
|
||||||
|
builder.Append(":");
|
||||||
|
builder.Append(this.timeTotal);
|
||||||
|
builder.AppendLine();
|
||||||
|
}
|
||||||
|
appendInt(builder, "bitrate", this.bitrate);
|
||||||
|
if ((this.audioSampleRate >= 0) || (this.audioBits >= 0) || (this.audioChannels >= 0))
|
||||||
|
{
|
||||||
|
builder.Append("audio: ");
|
||||||
|
builder.Append(this.audioSampleRate);
|
||||||
|
builder.Append(":");
|
||||||
|
builder.Append(this.audioBits);
|
||||||
|
builder.Append(":");
|
||||||
|
builder.Append(this.audioChannels);
|
||||||
|
builder.AppendLine();
|
||||||
|
}
|
||||||
|
appendInt(builder, "updating_db", this.updatingDb);
|
||||||
|
if (this.error != null)
|
||||||
|
{
|
||||||
|
builder.Append("error: ");
|
||||||
|
builder.AppendLine(this.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void appendInt(StringBuilder builder, string name, int value)
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
builder.Append(name);
|
||||||
|
builder.Append(": ");
|
||||||
|
builder.Append(value);
|
||||||
|
builder.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void appendBool(StringBuilder builder, string name, bool value)
|
||||||
|
{
|
||||||
|
builder.Append(name);
|
||||||
|
builder.Append(": ");
|
||||||
|
builder.Append(value ? '1' : '0');
|
||||||
|
builder.AppendLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user