Java tutorial
/** * Copyright Jana Klemp * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.klemp.middleware.controller; import java.beans.PropertyChangeSupport; import java.io.*; import java.io.IOException; import java.nio.CharBuffer; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.net.telnet.*; import org.apache.commons.net.telnet.TelnetClient; /** * This class is a copy from: * https://forum.videolan.org/viewtopic.php?f=14&t=85347 Exposes control of VLC * media player (videolan.org) from java. VLC must be set up to open a telnet * control on localhost:4444. * <p> * For VLC 1.1.5, use the following setup to expose the remote control (rc) * interrface for telnet control: * <p> * This setting is in VLC Tools/Preferences/Show settings (All)/Interface/Main * interfaces. Select the "Remote Control Interface" and replace "oldrc" with * "rc" in the text field. In VLC Tools/Preferences/Show settings * (All)/Interface/Main interfaces/RC/TCP command input, put the string * "localhost:4444" in the text field. * * @author Tobi */ public class VLCControl extends TelnetClient implements Runnable, TelnetNotificationHandler { /** VLC should be started with as "vlc --rc-host=localhost:4444" */ public static final int VLC_PORT = 4444; static final Logger log = Logger.getLogger("VLCControl"); private CharBuffer cbuf = CharBuffer.allocate(1024); private static VLCControl staticInstance = null; // used to communicate // among instances the // active client private PropertyChangeSupport support = new PropertyChangeSupport(this); // listeners // get // informed // by // output // from // VLC // strings public VLCControl() { } @Override public void disconnect() throws IOException { sendCommand("quit"); super.disconnect(); } public void connect() throws IOException { staticInstance = this; // used by reader to get input stream try { staticInstance.connect("localhost", VLC_PORT); Thread thread = new Thread(new VLCControl()); // starts the thread // to get the text // sent back from VLC thread.start(); staticInstance.registerNotifHandler(this); // notifications call // back to logger Runtime.getRuntime().addShutdownHook(new Thread() { // shutdown hook // here makes // sure to // disconnect // cleanly, as // long as we // are not // terminated @Override public void run() { try { if (isConnected()) { disconnect(); } } catch (IOException ex) { log.warning(ex.toString()); } } }); } catch (IOException e) { log.warning( "couldn't connect to VLC - you may need to start VLC with command line \"vlc --rc-host=localhost:4444\""); throw new IOException(e); } } /** * Sends a string command. Commands do not need to be terminated with a * newline. * <p> * * <pre> * +----[ Remote control commands ] * | add XYZ . . . . . . . . . . . . . . . . . . . . add XYZ to playlist * | enqueue XYZ . . . . . . . . . . . . . . . . . queue XYZ to playlist * | playlist . . . . . . . . . . . . . .show items currently in playlist * | search [string] . . search for items in playlist (or reset search) * | sort key . . . . . . . . . . . . . . . . . . . . . sort the playlist * | sd [sd] . . . . . . . . . . . . . show services discovery or toggle * | play . . . . . . . . . . . . . . . . . . . . . . . . . . play stream * | stop . . . . . . . . . . . . . . . . . . . . . . . . . . stop stream * | next . . . . . . . . . . . . . . . . . . . . . . next playlist item * | prev . . . . . . . . . . . . . . . . . . . . previous playlist item * | goto . . . . . . . . . . . . . . . . . . . . . . goto item at index * | repeat [on|off] . . . . . . . . . . . . . . toggle playlist repeat * | loop [on|off] . . . . . . . . . . . . . . . . toggle playlist loop * | random [on|off] . . . . . . . . . . . . . . toggle playlist random * | clear . . . . . . . . . . . . . . . . . . . . . .clear the playlist * | status . . . . . . . . . . . . . . . . . . . current playlist status * | title [X] . . . . . . . . . . . . . . set/get title in current item * | title_n . . . . . . . . . . . . . . . . next title in current item * | title_p . . . . . . . . . . . . . . previous title in current item * | chapter [X] . . . . . . . . . . . . set/get chapter in current item * | chapter_n . . . . . . . . . . . . . . next chapter in current item * | chapter_p . . . . . . . . . . . . previous chapter in current item * | * | seek X . . . . . . . . . . . seek in seconds, for instance `seek 12' * | pause . . . . . . . . . . . . . . . . . . . . . . . . toggle pause * | fastforward . . . . . . . . . . . . . . . . . . set to maximum rate * | rewind . . . . . . . . . . . . . . . . . . . . . set to minimum rate * | faster . . . . . . . . . . . . . . . . . . faster playing of stream * | slower . . . . . . . . . . . . . . . . . . slower playing of stream * | normal . . . . . . . . . . . . . . . . . . normal playing of stream * | rate [playback rate] . . . . . . . . . . set playback rate to value * | frame . . . . . . . . . . . . . . . . . . . . . play frame by frame * | fullscreen, f, F [on|off] . . . . . . . . . . . . toggle fullscreen * | info . . . . . . . . . . . . . .information about the current stream * | stats . . . . . . . . . . . . . . . . show statistical information * | get_time . . . . . . . . . .seconds elapsed since stream's beginning * | is_playing . . . . . . . . . . . . 1 if a stream plays, 0 otherwise * | get_title . . . . . . . . . . . . . the title of the current stream * | get_length . . . . . . . . . . . . the length of the current stream * | * | volume [X] . . . . . . . . . . . . . . . . . . set/get audio volume * | volup [X] . . . . . . . . . . . . . . . .raise audio volume X steps * | voldown [X] . . . . . . . . . . . . . . lower audio volume X steps * | adev [X] . . . . . . . . . . . . . . . . . . . .set/get audio device * | achan [X] . . . . . . . . . . . . . . . . . .set/get audio channels * | atrack [X] . . . . . . . . . . . . . . . . . . . set/get audio track * | vtrack [X] . . . . . . . . . . . . . . . . . . . set/get video track * | vratio [X] . . . . . . . . . . . . . . . .set/get video aspect ratio * | vcrop, crop [X] . . . . . . . . . . . . . . . . set/get video crop * | vzoom, zoom [X] . . . . . . . . . . . . . . . . set/get video zoom * | snapshot . . . . . . . . . . . . . . . . . . . . take video snapshot * | strack [X] . . . . . . . . . . . . . . . . . set/get subtitles track * | hotkey, key [hotkey name] . . . . . . . . . . simulate hotkey press * | menu [on|off|up|down|left|right|select] . . . . . . . . . .use menu * | * | set [var [value]] . . . . . . . . . . . . . . . . . set/get env var * | save_env . . . . . . . . . . . . save env vars (for future clients) * | alias [cmd] . . . . . . . . . . . . . . . . set/get command aliases * | description . . . . . . . . . . . . . . . . . .describe this module * | license . . . . . . . . . . . . . . . . print VLC's license message * | help, ? [pattern] . . . . . . . . . . . . . . . . . .a help message * | longhelp [pattern] . . . . . . . . . . . . . . a longer help message * | logout . . . . . . . . . . . . . . exit (if in a socket connection) * | quit . . . . . . . . quit VLC (or logout if in a socket connection) * | shutdown . . . . . . . . . . . . . . . . . . . . . . . .shutdown VLC * +----[ end of help ] * </pre> */ public String sendCommand(String s) throws IOException { if (!isConnected()) { connect(); } if (s == null) { return null; } if (!s.endsWith("\n")) { s = s + "\n"; } getOutputStream().write(s.getBytes()); getOutputStream().flush(); return s; } public static String PAUSE = "pause", PLAY = "play", STOP = "stop", NEXT = "next", PREV = "prev", VOLUP = "volup 1", VOLDOWN = "voldown 1"; public static final String CLIENT_MESSAGE = "ClientMessage"; /*** * Reader thread. Reads lines from the TelnetClient and echoes them on the * logger. PropertyChangeListeners are called with CLIENT_MESSAGE and String * sent from VLC. ***/ @Override public void run() { InputStream instr = staticInstance.getInputStream(); byte[] buff = new byte[1024]; int ret_read = 0; try { do { ret_read = instr.read(buff); if (ret_read > 0) { String s = new String(buff, 0, ret_read); log.info(s); staticInstance.getSupport().firePropertyChange(CLIENT_MESSAGE, null, s); // listener // on // static // instance // that // actually // is // connected // gets // the // message } } while (ret_read >= 0); } catch (Exception e) { log.log(Level.WARNING, "Reader ending - Exception while reading socket:{0}", e.getMessage()); } } /*** * Callback method called when TelnetClient receives an option negotiation * command. * <p> * * @param negotiation_code * - type of negotiation command received (RECEIVED_DO, * RECEIVED_DONT, RECEIVED_WILL, RECEIVED_WONT) * <p> * @param option_code * - code of the option negotiated * <p> ***/ @Override public void receivedNegotiation(int negotiation_code, int option_code) { String command = null; if (negotiation_code == TelnetNotificationHandler.RECEIVED_DO) { command = "DO"; } else if (negotiation_code == TelnetNotificationHandler.RECEIVED_DONT) { command = "DONT"; } else if (negotiation_code == TelnetNotificationHandler.RECEIVED_WILL) { command = "WILL"; } else if (negotiation_code == TelnetNotificationHandler.RECEIVED_WONT) { command = "WONT"; } log.log(Level.INFO, "Received {0} for option code {1}", new Object[] { command, option_code }); } /** * @return the support. Listeners can get the stuff sent back from VLC with * CLIENT_MESSAGE events. */ public PropertyChangeSupport getSupport() { return support; } }