package tmcsim.cadsimulator.videocontrol; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.Socket; /** * DVDController extends from the Abstraact DVDController class to provide * funtionality for controlling the Pioneer V5000 DVD Controller. * * @author Matthew Cechini (mcechini@calpoly.edu) * @version $Date: 2006/06/15 19:08:15 $ $Revision: 1.5 $ */ public class PioneerV5000 extends DVDController { /** * Enumeration of command strings used for DVD control. * @author Matthew Cechini */ protected static enum COMMAND_CHARS { OPEN ("OP"), CLOSE ("CO"), START ("SA"), SEARCH ("SE"), PLAY ("PL"), SEARCH_PLAY ("SL"), PAUSE ("PA"), STILL ("ST"), REJECT ("RJ"), SCAN_FWD ("NF"), SCAN_RVS ("NR"), SCAN_STOP ("NS"), TITLE ("TI"), CHAPTER ("CH"), GROUP ("GP"), CMD_STACK_PL ("BS"), UPLOAD_DATA ("BD"), //Data from computer to player. DOWNLOAD_DATA ("BU"), //Data from player to computer. SETUP ("MS"); public String cmd; private COMMAND_CHARS(String c) { cmd = c; } } /** Maximum number of command retries =5. */ protected final int MAX_RETRIES = 5; /** Maximum command length = 32. */ protected final int MAX_COMMAND_LEN = 32; /** Maximum response length = 32. */ protected final int MAX_RESPONSE_LEN = 32; /** Carriage return character. */ protected final char CR = 0x0d; /** Buffer for creating command string. */ protected StringBuffer commandString; /** Buffer to receive repsonse string. */ protected StringBuffer responseString; /** DVD Player host. */ protected String dvdHost = null; /** DVD Player port. */ protected int dvdPort = 0; /** Socket used for communication with DVD player. */ protected Socket serialInterfaceSocket = null; /** IOStream for writing out commands. */ //protected ObjectOutputStream out = null; protected OutputStream out = null; /** IOStream for reading dvd player responses. */ protected BufferedReader in = null; /** * Constructor. */ public PioneerV5000() { commandString = new StringBuffer(MAX_COMMAND_LEN); responseString = new StringBuffer(MAX_RESPONSE_LEN); } /** * Sets the host and port connection information for this dvd player. * * @param host DVD player host string. * @param port DVD player port value. */ public void setConnectionInfo(String host, int port) { dvdHost = host; dvdPort = port; } /** * Get the current connection information for this dvd player. The * returned string is as follows: HOST:PORT * * @return DVD connection host:port */ public String getConnectionInfo() { return dvdHost + ":" + dvdPort; } public boolean isConnected() { return isConnected; } /** * Establish a connection with the dvd player through socket communication. * If the port is successfully opened, input and ouput streams are opened * on the socket. The isConnected boolean flag is set to true if this is * successful. Observers are notified with a DVDStatusUpdate to show the * new connection. * * @throws IOException if communication with the dvd player fails. */ public void connect() throws IOException { serialInterfaceSocket = new Socket(); serialInterfaceSocket.connect(new InetSocketAddress(dvdHost, dvdPort), 5000); serialInterfaceSocket.setSoTimeout(5000); //out = new ObjectOutputStream(serialInterfaceSocket.getOutputStream()); out = serialInterfaceSocket.getOutputStream(); in = new BufferedReader(new InputStreamReader(serialInterfaceSocket.getInputStream())); isConnected = true; setChanged(); notifyObservers(new DVDStatusUpdate(getConnectionInfo(), isConnected())); } /** * Disconnect from the dvd player. Close all IOStreams and socket, then set * the isConnected flag to false. Observers are notified with a * DVDStatusUpdate to show the loss of the connection. */ public void disconnect() { try { in.close(); } catch (Exception e) {} try { out.close(); } catch (Exception e) {} try { serialInterfaceSocket.close(); } catch (Exception e) {} isConnected = false; setChanged(); notifyObservers(new DVDStatusUpdate(getConnectionInfo(), isConnected())); } /* * If the command is sent while the player is in the Park mode, the dvd * ejects and the player enters the Open mode. After the tray is ejected, * player returns a completed status message. * * If the player is in any mode other than Open or Park, the disc stops, the * player enters Open mode and the door opens. * * If the player is already in Open mode, an error message is returned. */ public void open() throws IOException { commandString.append(COMMAND_CHARS.OPEN.cmd); transmit(); } /* * If the command is sent while the player door is open, the door * closes then the player enters the Park mode. After the door closes, the * player returns the completed status message. * * If the player is in any mode other than Open or if the player door is already * closed, an error message is returned. */ public void close() throws IOException { commandString.append(COMMAND_CHARS.CLOSE.cmd); transmit(); } /* * If the command is sent while the player is in Open, Park or Reject * mode, the player immediately enters Setup and the disc begins spinning up. * The player is ready for playback when the device reaches the beginning of * the program (DVD, CD or VCD disc pauses or stills at the first Track). The * player returns the completed status when the disc pauses or stills. * * If the player receives the command while playing a menu, the player returns * an error message. However, if the disc program does not allow new * commands once playback begins, the player ignores the command. */ public void start() throws IOException { commandString.append(COMMAND_CHARS.START.cmd); transmit(); } public void play() throws IOException { commandString.append(COMMAND_CHARS.PLAY.cmd); transmit(); } public void playChapter(int chapter) throws IOException { commandString.append(COMMAND_CHARS.CHAPTER.cmd + chapter); commandString.append(COMMAND_CHARS.SEARCH_PLAY.cmd); transmit(); } public void playTitle(int title) throws IOException { commandString.append(COMMAND_CHARS.TITLE.cmd + title); commandString.append(COMMAND_CHARS.SEARCH_PLAY.cmd); transmit(); } public void repeatTitle(int title) throws IOException { commandString.append(title + COMMAND_CHARS.GROUP.cmd); commandString.append("1" + COMMAND_CHARS.CMD_STACK_PL.cmd); transmit(); } /* * If the command is sent while the player is in Random Access * mode, the pause occurs at the current disc location. The player returns the * completed status message immediately. * * In Pause mode, Still and Video Squelch are ACTIVE. However, if the disc * program does not allow a pause, the player ignores the command and * returns an error message (E04). */ public void pause() throws IOException { commandString.append(COMMAND_CHARS.PAUSE.cmd); transmit(); } /* * If the command is sent while the player is in Random Access * mode, playback stops at the current disc position and the player enters Still * mode. The player returns the completed status message immediately. * * However, if the disc program does not allow a pause, the player ignores the * command and returns an error message (E04). * */ public void still() throws IOException { commandString.append(COMMAND_CHARS.STILL.cmd); transmit(); } public void stepForward() throws IOException {} public void stepReverse() throws IOException {} /* * If the command is sent while the player is in Random Access * mode, the screen proceeds forward (NF) or in reverse (NR) quickly. When * scanning is finished, the player resumes the Random Access mode and * returns the completed status message. * * If the SCAN command is sent while the player is in Fast Forward or Reverse * Playback, the player enters Scan mode. * * Once the NS command is sent, the player resets to the normal *Playback mode and returns the completed status message. */ public void scanForward() throws IOException { commandString.append(COMMAND_CHARS.SCAN_FWD.cmd); transmit(); } public void scanReverse() throws IOException { commandString.append(COMMAND_CHARS.SCAN_RVS.cmd); transmit(); } public void scanStop() throws IOException { commandString.append(COMMAND_CHARS.SCAN_STOP.cmd); transmit(); } public void upload(String cmdStack) throws IOException { //park mode //out.write((COMMAND_CHARS.REJECT.cmd + CR).toString().getBytes()); //try { Thread.sleep(500); } catch (Exception e) {} out.write((COMMAND_CHARS.UPLOAD_DATA.cmd + CR).toString().getBytes()); out.flush(); try { Thread.sleep(500); } catch (Exception e) {} out.write((cmdStack + CR).toString().getBytes()); out.flush(); } public String download() throws Exception { //park mode commandString.append(COMMAND_CHARS.REJECT.cmd + CR); transmit(); commandString.append(COMMAND_CHARS.DOWNLOAD_DATA.cmd + CR); //send carriage return to refresh the connection //out.writeChar(CR); out.write(CR); out.flush(); //clear response buffer while(in.ready()) responseString.append(in.readLine()); responseString.setLength(0); //send the command //out.writeBytes(commandString.toString()); out.write(commandString.toString().getBytes()); out.flush(); //read in response while(in.ready()) responseString.append(in.readLine()); if(responseString.indexOf("E") == 0) { throw new Exception("Error in downloading from player."); } else { return responseString.toString(); } } /** * This method spawns a thread to transmit the current command found in the * commandString buffer to the DVD player. If the output stream is null, * observers are notified with a DVDStatusUpdate containing the exception. * The following steps are taken to transmit the command:
* * *
  • A Carriage Return (CR) character is sent to refresh the connection.
  • *
  • All response characters on the buffer are cleared.
  • *
  • The command is transmitted with a CR to signify the end of the command.
  • *
  • If the DVD response contains an 'E', then the command was not successful, * repeat steps 1 - 3. Otherwise, the command was successful, the thread ends.
  • *
  • If the retry command transmit fails, notify observers with a DVDStatusUpdate * containing the exception.
  • * */ protected synchronized void transmit() { Runnable transmitRun = new Runnable() { public void run() { int retries = MAX_RETRIES; try { if(out == null) { throw new Exception("Cannot transmit to DVD " + dvdHost + ":" + dvdPort + ". Reconnect to DVD."); } while(retries > 0) { System.out.println("sending [" + commandString.toString() + "] to " + getConnectionInfo()); //send carriage return to refresh the connection out.write(CR); out.flush(); //Wait for DVD to respond Thread.sleep(500); //clear response buffer while(in.ready()) responseString.append(in.readLine()); responseString.setLength(0); //send the command out.write(commandString.toString().getBytes()); out.write(CR); out.flush(); //Wait for DVD to respond Thread.sleep(500); //read in response while(in.ready()) responseString.append(in.readLine()); //if an error occured, retry if((responseString.indexOf("E") > -1)) { System.out.println("response: " + responseString.toString()); retries--; } else { retries = 0; System.out.println("response: " + responseString.toString()); } } } catch (Exception e) { setChanged(); notifyObservers(new DVDStatusUpdate(getConnectionInfo(), isConnected(), e)); } finally { commandString.setLength(0); responseString.setLength(0); } } }; Thread transmitThread = new Thread(transmitRun); transmitThread.start(); } }