/* * Copyright (C) 2005-2009 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC Remote; see the file license. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ package org.xbmc.jsonrpc.client; import org.codehaus.jackson.JsonNode; import org.xbmc.api.business.INotifiableManager; import org.xbmc.api.data.IControlClient; import org.xbmc.api.info.PlayStatus; import org.xbmc.api.object.Host; import org.xbmc.api.type.SeekType; import org.xbmc.jsonrpc.Connection; /** * The ControlClient class takes care of everything related to controlling * XBMC. These are essentially play controls, navigation controls other actions * the user may wants to execute. It equally reads the information instead of * setting it. * * @author Team XBMC */ public class ControlClient extends Client implements IControlClient { /** * Class constructor needs reference to HTTP client connection * @param connection */ public ControlClient(Connection connection) { super(connection); } /** * Updates host info on the connection. * @param host */ public void setHost(Host host) { mConnection.setHost(host); } /** * Adds a file or folder (<code>fileOrFolder</code> is either a file or a folder) to the current playlist. * @param manager Manager reference * @param fileOrFolder * @return true on success, false otherwise. */ public boolean addToPlaylist(INotifiableManager manager, String fileOrFolder, int playlistId) { String type = "file"; if(fileOrFolder.endsWith("/") || fileOrFolder.endsWith("\\")) type = "directory"; return mConnection.getString(manager, "Playlist.Add", obj().p("playlistid", playlistId).p("item", obj().p(type, fileOrFolder))).equals("OK"); } public boolean play(INotifiableManager manager, int playlistId){ return mConnection.getString(manager, "Player.Open", obj().p("item", obj().p("playlistid", playlistId))).equals("OK"); } /** * Starts playing the media file <code>filename</code> . * @param manager Manager reference * @param filename File to play * @return true on success, false otherwise. */ public boolean playFile(INotifiableManager manager, String filename, int playlistId) { return mConnection.getString(manager, "Player.Open", obj().p("item", obj().p("file", filename)).p("options", obj().p("resume", true))).equals("OK"); } /** * Starts playing/showing the next media/image in the current playlist or, * if currently showing a slideshow, the slideshow playlist. * @param manager Manager reference * @return true on success, false otherwise. */ public boolean playNext(INotifiableManager manager) { return mConnection.getString(manager, "Player.GoNext", obj().p("playlistid", getPlaylistId(manager))).equals("OK"); } /** * Starts playing/showing the previous media/image in the current playlist * or, if currently showing a slidshow, the slideshow playlist. * @param manager Manager reference * @return true on success, false otherwise. */ public boolean playPrevious(INotifiableManager manager) { return mConnection.getString(manager, "Player.GoPrevious", obj().p("playlistid", getPlaylistId(manager))).equals("OK"); } /** * Pauses the currently playing media. * @param manager Manager reference * @return true on success, false otherwise. */ public boolean pause(INotifiableManager manager) { mConnection.getInt(manager, "Player.PlayPause", obj().p("playerid", getActivePlayerId(manager)), "speed"); return true; } /** * Stops the currently playing media. * @param manager Manager reference * @return true on success, false otherwise. */ public boolean stop(INotifiableManager manager) { return mConnection.getString(manager, "Player.Stop", obj().p("playerid", getActivePlayerId(manager))).equals("OK"); } /** * Start playing the media file at the given URL * @param manager Manager reference * @param url An URL pointing to a supported media file * @return true on success, false otherwise. */ public boolean playUrl(INotifiableManager manager, String url) { return playFile(manager, url, 1); } /** * Show the picture file <code>filename</code> . * @param manager Manager reference * @param filename File to show * @return true on success, false otherwise. */ public boolean showPicture(INotifiableManager manager, String filename) { return playNext(manager); } /** * Send the string <code>text</code> via keys on the virtual keyboard. * @param manager Manager reference * @param text The text string to send. * @return true on success, false otherwise. */ public boolean sendText(INotifiableManager manager, String text) { boolean done = false; if(text.endsWith("\n")){ text = text.substring(0, text.length()-1); done = true; } return mConnection.getString(manager, "Input.SendText", obj().p("text", text).p("done", done)).equals("OK"); } /** * Sets the volume as a percentage of the maximum possible. * @param manager Manager reference * @param volume New volume (0-100) * @return true on success, false otherwise. */ public boolean setVolume(INotifiableManager manager, int volume) { return mConnection.getString(manager, "Application.SetVolume", obj().p("volume", volume)).equals("OK"); } /** * Seeks to a position. If type is * <ul> * <li><code>absolute</code> - Sets the playing position of the currently * playing media as a percentage of the media�s length.</li> * <li><code>relative</code> - Adds/Subtracts the current percentage on to * the current position in the song</li> * </ul> * * @param manager Manager reference * @param type Seek type, relative or absolute * @param progress Progress * @return true on success, false otherwise. */ public boolean seek(INotifiableManager manager, SeekType type, int progress) { if (type.compareTo(SeekType.absolute) == 0) return mConnection.getJson(manager, "Player.Seek", obj().p("playerid", getActivePlayerId(manager)).p("value", progress)).get("percentage")!=null; else return false;//mConnection.getBoolean(manager, "SeekPercentageRelative", String.valueOf(progress)); } /** * Toggles the sound on/off. * @param manager Manager reference * @return true on success, false otherwise. */ public boolean mute(INotifiableManager manager) { return mConnection.getString(manager, "Application.SetMute", obj().p("volume", 1)).equals("OK"); } /** * Retrieves the current playing position of the currently playing media as * a percentage of the media's length. * @param manager Manager reference * @return Percentage (0-100) */ public int getPercentage(INotifiableManager manager) { return mConnection.getInt(manager, "Player.GetProperties", obj().p("playerid", getActivePlayerId(manager)).p(PARAM_PROPERTIES, arr().add("percentage")), "percentage"); } /** * Retrieves the current volume setting as a percentage of the maximum * possible value. * @param manager Manager reference * @return Volume (0-100) */ public int getVolume(INotifiableManager manager) { return mConnection.getInt(manager, "Application.GetProperties", obj().p("playerid", getActivePlayerId(manager)).p(PARAM_PROPERTIES, arr().add("volume")), "volume"); } /** * Navigates... UP! * @param manager Manager reference * @return true on success, false otherwise. */ public boolean navUp(INotifiableManager manager) { return mConnection.getString(manager, "Input.Up", null).equals("OK"); } /** * Navigates... DOWN! * @param manager Manager reference * @return true on success, false otherwise. */ public boolean navDown(INotifiableManager manager) { return mConnection.getString(manager, "Input.Down", null).equals("OK"); } /** * Navigates... LEFT! * @param manager Manager reference * @return true on success, false otherwise. */ public boolean navLeft(INotifiableManager manager) { return mConnection.getString(manager, "Input.Left", null).equals("OK"); } /** * Navigates... RIGHT! * @param manager Manager reference * @return true on success, false otherwise. */ public boolean navRight(INotifiableManager manager) { return mConnection.getString(manager, "Input.Right", null).equals("OK"); } /** * Selects current item. * @param manager Manager reference * @return true on success, false otherwise. */ public boolean navSelect(INotifiableManager manager) { return mConnection.getString(manager, "Input.Select", null).equals("OK"); } /** * Takes either "video" or "music" as a parameter to begin updating the * corresponding database. * * TODO For "video" you can additionally specify a specific path to be scanned. * * @param manager Manager reference * @param mediaType Either <code>video</code> or <code>music</code>. * @return True on success, false otherwise. */ public boolean updateLibrary(INotifiableManager manager, String mediaType) { if(mediaType == "video") return mConnection.getString(manager, "VideoLibrary.Scan", null).equals("OK"); else if(mediaType == "music") return mConnection.getString(manager, "AudioLibrary.Scan", null).equals("OK"); else return false; } /** * Broadcast a message. Used to test broadcasting feature. * @param manager Manager reference * @param message * @return True on success, false otherwise. */ public boolean broadcast(INotifiableManager manager, String message) { //TODO return false;//mConnection.getBoolean(manager, "Broadcast", message); } /** * Returns the current broadcast port number, or 0 if deactivated. * @param manager Manager reference * @return Current broadcast port number. */ public int getBroadcast(INotifiableManager manager) { //TODO /*final String ret[] = mConnection.getString(manager, "GetBroadcast").split(";"); try { final int port = Integer.parseInt(ret[1]); return port > 1 && !ret[0].equals("0") ? port : 0; } catch (NumberFormatException e) { return 0; }*/ return 0; } /** * Sets the brodcast level and port. Level currently only takes three values: * <ul> * <li><code>0</code> - No broadcasts</li> * <li><code>1</code> - Media playback and startup & shutdown events * <li><code>2</code> - "OnAction" events (e.g. buttons) as well as level 1 events. * </ul> * * @param manager Manager reference * @param port Broadcast port * @param level Broadcast level * @return True on success, false otherwise. */ public boolean setBroadcast(INotifiableManager manager, int port, int level) { //TODO return false;//mConnection.getBoolean(manager, "SetBroadcast", level + ";" + port); } /** * Returns current play state * @param manager Manager reference * @return */ public int getPlayState(INotifiableManager manager) { return mConnection.getInt(manager, "Application.GetProperties", obj().p("playerid", getActivePlayerId(manager)).p(PARAM_PROPERTIES, arr().add("speed")), "speed"); } /** * Returns the current playlist identifier * @param manager Manager reference */ public int getPlaylistId(INotifiableManager manager) { return mConnection.getInt(manager, "Player.GetProperties", obj().p("playerid", getActivePlayerId(manager)).p(PARAM_PROPERTIES, arr().add("playlistid")), "playlistid"); } /** * Sets the current playlist identifier * @param manager Manager reference * @param id Playlist identifier * @return True on success, false otherwise. */ public boolean setPlaylistId(INotifiableManager manager, int id) { return mConnection.getString(manager, "Player.Open", obj().p("item", obj().p("playlistid", id))).equals("OK"); } /** * Sets the current playlist position * @param manager Manager reference0 * @param position New playlist position * @return True on success, false otherwise. */ public boolean setPlaylistPos(INotifiableManager manager, int playlistId, int position) { int playerid = getActivePlayerId(manager); int currentplaylistid = getPlaylistId(manager); if(playerid == -1 || currentplaylistid != playlistId) return mConnection.getString(manager, "Player.Open", obj().p("item", obj().p("playlistid", playlistId).p("position", position))).equals("OK"); else return mConnection.getString(manager, "Player.GoTo", obj().p("playerid", getActivePlayerId(manager)).p("position", position)).equals("OK"); } /** * Clears a playlist. * @param manager Manager reference * @param int Playlist to clear (0 = music, 1 = video) * @return True on success, false otherwise. */ public boolean clearPlaylist(INotifiableManager manager, int playlistId) { return mConnection.getString(manager, "Playlist.Clear", obj().p("playlistid", playlistId)).equals("OK"); } /** * Sets current playlist * @param manager Manager reference * @param playlistId Playlist ID ("0" = music, "1" = video) * @return True on success, false otherwise. */ public boolean setCurrentPlaylist(INotifiableManager manager, int playlistId) { return mConnection.getString(manager, "Player.Open", obj().p("item", obj().p("playlistid", playlistId))).equals("OK"); } /** * Sets the correct response format to default values * @param manager Manager reference * @return True on success, false otherwise. */ /** * Sets the gui setting of XBMC to value * @param manager * @param setting see {@link org.xbmc.api.info.GuiSettings} for the available settings * @param value the value to set * @return {@code true} if the value was set successfully */ public boolean setGuiSetting(INotifiableManager manager, final int setting, final String value) { return false;//mConnection.getBoolean(manager, "SetGUISetting", GuiSettings.getType(setting) + ";" + GuiSettings.getName(setting) + ";" + value); } /** * Returns state and type of the media currently playing. * @return */ public ICurrentlyPlaying getCurrentlyPlaying(INotifiableManager manager) { final IControlClient.ICurrentlyPlaying nothingPlaying = new IControlClient.ICurrentlyPlaying() { private static final long serialVersionUID = -1554068775915058884L; public boolean isPlaying() { return false; } public int getMediaType() { return 0; } public int getPlaylistPosition() { return -1; } public String getTitle() { return ""; } public int getTime() { return 0; } public int getPlayStatus() { return PlayStatus.STOPPED; } public float getPercentage() { return 0; } public String getFilename() { return ""; } public int getDuration() { return 0; } public String getArtist() { return ""; } public String getAlbum() { return ""; } public int getHeight() { return 0; } public int getWidth() { return 0; } }; final JsonNode active = mConnection.getJson(manager, "Player.GetActivePlayers", null); if(active.size() == 0) return nothingPlaying; int playerid = getActivePlayerId(manager); final JsonNode player_details = mConnection.getJson(manager, "Player.GetProperties", obj().p("playerid", playerid).p(PARAM_PROPERTIES, arr().add("percentage").add("position").add("speed").add("time").add("totaltime").add("type"))); if(player_details != null){ final JsonNode file_details = mConnection.getJson(manager, "Player.GetItem", obj().p("playerid", playerid).p(PARAM_PROPERTIES, arr().add("artist").add("album").add("duration").add("episode").add("genre").add("file").add("season").add("showtitle").add("tagline").add("title"))).get("item"); if(file_details.get("Filename") != null && file_details.get("Filename").getTextValue().contains("Nothing Playing")) { return nothingPlaying; } if(getString(file_details, "type").equals("episode")){ return TvShowClient.getCurrentlyPlaying(player_details, file_details); } else if(getString(player_details, "type").equals("video")){ return VideoClient.getCurrentlyPlaying(player_details, file_details); } if(getString(player_details, "type").equals("audio")){ return MusicClient.getCurrentlyPlaying(player_details, file_details); } else return nothingPlaying; } else return nothingPlaying; } public static int parseTime(JsonNode node) { int time=0; time += node.get("hours").getIntValue() * 3600; time += node.get("minutes").getIntValue() * 60; time += node.get("seconds").getIntValue(); return time; } }