diff --git a/JMPDComm/src/main/java/org/a0z/mpd/MPDCommand.java b/JMPDComm/src/main/java/org/a0z/mpd/MPDCommand.java index 195507c915..784001e8c5 100644 --- a/JMPDComm/src/main/java/org/a0z/mpd/MPDCommand.java +++ b/JMPDComm/src/main/java/org/a0z/mpd/MPDCommand.java @@ -46,8 +46,6 @@ public class MPDCommand { public static final String MPD_CMD_CLOSE = "close"; - public static final String MPD_CMD_COMMANDS = "commands"; - public static final String MPD_CMD_CONSUME = "consume"; public static final String MPD_CMD_COUNT = "count"; @@ -89,8 +87,6 @@ public class MPDCommand { public static final String MPD_CMD_PAUSE = "pause"; - public static final String MPD_CMD_PERMISSION = "permission"; - public static final String MPD_CMD_PING = "ping"; public static final String MPD_CMD_PLAY = "play"; diff --git a/JMPDComm/src/main/java/org/a0z/mpd/connection/MPDConnection.java b/JMPDComm/src/main/java/org/a0z/mpd/connection/MPDConnection.java index a3b27b2fcf..5aef1336fa 100644 --- a/JMPDComm/src/main/java/org/a0z/mpd/connection/MPDConnection.java +++ b/JMPDComm/src/main/java/org/a0z/mpd/connection/MPDConnection.java @@ -32,6 +32,7 @@ import org.a0z.mpd.MPDStatusMonitor; import org.a0z.mpd.Tools; import org.a0z.mpd.exception.MPDException; +import org.a0z.mpd.subsystem.Reflection; import java.io.BufferedReader; import java.io.EOFException; @@ -52,8 +53,6 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import static org.a0z.mpd.Tools.VALUE; - /** * Class representing a connection to MPD Server. */ @@ -127,23 +126,6 @@ public abstract class MPDConnection { } } - /** - * Puts all available commands into a set backed collection. - * - * @param response The media server response to the {@link MPDCommand#MPD_CMD_COMMANDS} - * command. - * @return A collection of available commands from the response. - */ - private static Collection getCommands(final Collection response) { - final Collection commands = new HashSet<>(response.size()); - - for (final String[] pair : Tools.splitResponse(response)) { - commands.add(pair[VALUE]); - } - - return commands; - } - /** * Sets up connection to host/port pair with MPD password. * @@ -162,12 +144,14 @@ public final void connect(final InetAddress host, final int port, final String p mPassword = password; mSocketAddress = new InetSocketAddress(host, port); - final MPDCommand mpdCommand = new MPDCommand(MPDCommand.MPD_CMD_COMMANDS); + final MPDCommand mpdCommand = new MPDCommand(Reflection.CMD_ACTION_COMMANDS); final CommandResult commandResult = processCommand(mpdCommand); synchronized (mAvailableCommands) { + final Collection response = Tools. + parseResponse(commandResult.getResult(), Reflection.CMD_RESPONSE_COMMANDS); mAvailableCommands.clear(); - mAvailableCommands.addAll(getCommands(commandResult.getResult())); + mAvailableCommands.addAll(response); } if (!commandResult.isHeaderValid()) { diff --git a/JMPDComm/src/main/java/org/a0z/mpd/subsystem/Reflection.java b/JMPDComm/src/main/java/org/a0z/mpd/subsystem/Reflection.java new file mode 100644 index 0000000000..7501e86999 --- /dev/null +++ b/JMPDComm/src/main/java/org/a0z/mpd/subsystem/Reflection.java @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2004 Felipe Gustavo de Almeida + * Copyright (C) 2010-2014 The MPDroid Project + * + * All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice,this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.a0z.mpd.subsystem; + +import org.a0z.mpd.connection.MPDConnection; +import org.a0z.mpd.exception.MPDException; + +import java.io.IOException; +import java.util.Collection; +import java.util.List; + +import static org.a0z.mpd.Tools.parseResponse; + +/** + * A class to manage the + * reflection subsystem + * of the MPD protocol. This will query various + * capabilities and configuration for the currently connected media server. + */ +public class Reflection { + + /** + * Command text required to generate a command to retrieve a list of permitted commands. + *

+ * Protocol command syntax:
{@code commands} + *

+ *
Sample protocol output:
+ * {@code commands}
+ * {@code command: add}
+ * ... (removed for clarity)
+ * {@code OK}
+ */ + public static final String CMD_ACTION_COMMANDS = "commands"; + + /** + * Command text required to generate a command to retrieve server configuration options. + *

+ * This is currently not functional for this library due to lack of socket connection + * functionality. + */ + public static final String CMD_ACTION_CONFIG = "config"; + + /** + * Command text required to generate a command to receive a list of supported decoders. + *

+ * Protocol command syntax: {@code decoders} + *

+ *
Sample protocol output:
+ * {@code decoders}
+ * {@code plugin: mad}
+ * {@code suffix: mp3}
+ * {@code suffix: mp2}
+ * {@code mime_type: audio/mpeg}
+ * {@code OK} + */ + public static final String CMD_ACTION_DECODERS = "decoders"; + + /** + * Command text required to generate a command to receive a list of non-permitted commands. + *

+ * Protocol command syntax:
{@code notcommands} + *

+ *
Sample protocol output:
+ * {@code notcommands}
+ * {@code command: config}
+ * {@code command: kill}
+ * {@code OK}
+ */ + public static final String CMD_ACTION_NOT_COMMANDS = "notcommands"; + + /** + * Command text required to generate a command to receive a list of available metadata for + * {@code Music} objects. + *

+ * Protocol command syntax: {@code tagtypes} + * {@code tagtypes}
+ * {@code tagtype: Artist}
+ * {@code tagtype: ArtistSort}
+ * ... (removed for clarity)
+ * {@code OK}
+ */ + public static final String CMD_ACTION_TAG_TYPES = "tagtypes"; + + /** + * Command text required to generate a command to receive a list of URL handlers. + *

+ * Protocol command syntax:
{@code urlhandlers} + *

+ *
Sample protocol output:
+ * {@code urlhandlers}
+ * {@code handler: file}
+ * {@code handler: http}
+ * {@code handler: https}
+ * {@code handler: local}
+ * {@code OK}
+ */ + public static final String CMD_ACTION_URL_HANDLERS = "urlhandlers"; + + /** + * A response returned from the {@link #CMD_ACTION_COMMANDS} command. + */ + public static final String CMD_RESPONSE_COMMANDS = "command"; + + /** + * A response returned from the {@link #CMD_ACTION_DECODERS} command. + */ + public static final String CMD_RESPONSE_DECODER_MIME_TYPE = "mimetype"; + + /** + * A response returned from the {@link #CMD_ACTION_DECODERS} command. + */ + public static final String CMD_RESPONSE_DECODER_PLUGIN = "plugin"; + + /** + * A response returned from the {@link #CMD_ACTION_DECODERS} command. + */ + public static final String CMD_RESPONSE_DECODER_SUFFIX = "suffix"; + + /** + * A response key returned from the {@link #CMD_ACTION_TAG_TYPES} command. + */ + public static final String CMD_RESPONSE_TAG_TYPES = "tagtype"; + + /** + * A response key returned from the {@link #CMD_ACTION_URL_HANDLERS} command. + */ + public static final String CMD_RESPONSE_URL_HANDLERS = "handler"; + + /** + * The current connection to the media server used to + * query the media server for reflection handling. + */ + private final MPDConnection mConnection; + + /** + * Constructor for the MPD protocol {@code Reflection} subsystem. + * + * @param connection The connection to use to query the media server for reflection handling. + */ + public Reflection(final MPDConnection connection) { + super(); + + mConnection = connection; + } + + /** + * Retrieves and returns a collection of available commands on + * the current media server with the current permissions. + * + * @return A collection of available commands with the + * current permissions on the connected media server. + * @throws IOException Thrown upon a communication error with the server. + * @throws MPDException Thrown if an error occurs as a result of command execution. + * @see org.a0z.mpd.MPDCommand#MPD_CMD_PASSWORD For modifying available commands. + */ + public Collection getCommands() throws IOException, MPDException { + return getList(CMD_ACTION_COMMANDS, CMD_RESPONSE_COMMANDS); + } + + /** + * Retrieves and returns a list of all available file type + * suffixes supported by the connected media server. + * + * @return A collection of supported file type suffixes. + * @throws IOException Thrown upon a communication error with the server. + * @throws MPDException Thrown if an error occurs as a result of command execution. + */ + public Collection getFileSuffixes() throws IOException, MPDException { + return getList(CMD_ACTION_DECODERS, CMD_RESPONSE_DECODER_SUFFIX); + } + + /** + * A generic method to send a {@code command} and retrieve only {@code element} responses. + * + * @param command The command text to send. + * @param element The command response to add to the collection. + * @return A collection of responses matching {@code element} as a key value. + * @throws IOException Thrown upon a communication error with the server. + * @throws MPDException Thrown if an error occurs as a result of command execution. + */ + private Collection getList(final String command, final String element) + throws IOException, MPDException { + final List response = mConnection.sendCommand(command); + + return parseResponse(response, element); + } + + /** + * Retrieves and returns a collection of all available + * mime types supported by the connected media server. + * + * @return A list of all available mime types for the connected media server. + * @throws IOException Thrown upon a communication error with the server. + * @throws MPDException Thrown if an error occurs as a result of command execution. + */ + public Collection getMIMETypes() throws IOException, MPDException { + return getList(CMD_ACTION_DECODERS, CMD_RESPONSE_DECODER_MIME_TYPE); + } + + /** + * Returns a collection of commands explicitly not permitted for use. + * + * Retrieves and returns a collection of commands explicitly not permitted + * to use on the current media server with the current permissions. + * + * @return A collection of commands explicitly not permitted for use on the currently connected + * se + * @throws IOException Thrown upon a communication error with the server. + * @throws MPDException Thrown if an error occurs as a result of command execution. + * @see org.a0z.mpd.MPDCommand#MPD_CMD_PASSWORD For modifying available commands. + */ + public Collection getNotCommands() throws IOException, MPDException { + return getList(CMD_ACTION_NOT_COMMANDS, CMD_RESPONSE_COMMANDS); + } + + /** + * Returns a list of available {@code Music} metadata tag types which are available from the + * currently connected media server. + * + * @return A collection of metadata tag types from the current server. + * @throws IOException Thrown upon a communication error with the server. + * @throws MPDException Thrown if an error occurs as a result of command execution. + */ + public Collection getTagTypes() throws IOException, MPDException { + return getList(CMD_ACTION_TAG_TYPES, CMD_RESPONSE_TAG_TYPES); + } + + /** + * Retrieves and returns a list of URL handlers. + * + * @return A collection of available URL handlers for the connected media server. + * @throws IOException Thrown upon a communication error with the server. + * @throws MPDException Thrown if an error occurs as a result of command execution. + */ + public Collection getURLHandlers() throws IOException, MPDException { + return getList(CMD_ACTION_URL_HANDLERS, CMD_RESPONSE_URL_HANDLERS); + } +}