| 1 | package tmcsim.cadsimulator.videocontrol; |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | import java.io.BufferedReader; |
|---|
| 5 | import java.io.IOException; |
|---|
| 6 | import java.io.InputStreamReader; |
|---|
| 7 | import java.io.OutputStream; |
|---|
| 8 | import java.net.InetSocketAddress; |
|---|
| 9 | import java.net.Socket; |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | /** |
|---|
| 13 | * DVDController extends from the Abstraact DVDController class to provide |
|---|
| 14 | * funtionality for controlling the Pioneer V5000 DVD Controller. |
|---|
| 15 | * |
|---|
| 16 | * @author Matthew Cechini (mcechini@calpoly.edu) |
|---|
| 17 | * @version $Date: 2006/06/15 19:08:15 $ $Revision: 1.5 $ |
|---|
| 18 | */ |
|---|
| 19 | public class PioneerV5000 extends DVDController { |
|---|
| 20 | |
|---|
| 21 | /** |
|---|
| 22 | * Enumeration of command strings used for DVD control. |
|---|
| 23 | * @author Matthew Cechini |
|---|
| 24 | */ |
|---|
| 25 | protected static enum COMMAND_CHARS { |
|---|
| 26 | OPEN ("OP"), |
|---|
| 27 | CLOSE ("CO"), |
|---|
| 28 | START ("SA"), |
|---|
| 29 | SEARCH ("SE"), |
|---|
| 30 | PLAY ("PL"), |
|---|
| 31 | SEARCH_PLAY ("SL"), |
|---|
| 32 | PAUSE ("PA"), |
|---|
| 33 | STILL ("ST"), |
|---|
| 34 | REJECT ("RJ"), |
|---|
| 35 | SCAN_FWD ("NF"), |
|---|
| 36 | SCAN_RVS ("NR"), |
|---|
| 37 | SCAN_STOP ("NS"), |
|---|
| 38 | TITLE ("TI"), |
|---|
| 39 | CHAPTER ("CH"), |
|---|
| 40 | GROUP ("GP"), |
|---|
| 41 | CMD_STACK_PL ("BS"), |
|---|
| 42 | UPLOAD_DATA ("BD"), //Data from computer to player. |
|---|
| 43 | DOWNLOAD_DATA ("BU"), //Data from player to computer. |
|---|
| 44 | SETUP ("MS"); |
|---|
| 45 | |
|---|
| 46 | public String cmd; |
|---|
| 47 | |
|---|
| 48 | private COMMAND_CHARS(String c) { |
|---|
| 49 | cmd = c; |
|---|
| 50 | } |
|---|
| 51 | } |
|---|
| 52 | |
|---|
| 53 | /** Maximum number of command retries =5. */ |
|---|
| 54 | protected final int MAX_RETRIES = 5; |
|---|
| 55 | |
|---|
| 56 | /** Maximum command length = 32. */ |
|---|
| 57 | protected final int MAX_COMMAND_LEN = 32; |
|---|
| 58 | |
|---|
| 59 | /** Maximum response length = 32. */ |
|---|
| 60 | protected final int MAX_RESPONSE_LEN = 32; |
|---|
| 61 | |
|---|
| 62 | /** Carriage return character. */ |
|---|
| 63 | protected final char CR = 0x0d; |
|---|
| 64 | |
|---|
| 65 | /** Buffer for creating command string. */ |
|---|
| 66 | protected StringBuffer commandString; |
|---|
| 67 | |
|---|
| 68 | /** Buffer to receive repsonse string. */ |
|---|
| 69 | protected StringBuffer responseString; |
|---|
| 70 | |
|---|
| 71 | /** DVD Player host. */ |
|---|
| 72 | protected String dvdHost = null; |
|---|
| 73 | |
|---|
| 74 | /** DVD Player port. */ |
|---|
| 75 | protected int dvdPort = 0; |
|---|
| 76 | |
|---|
| 77 | /** Socket used for communication with DVD player. */ |
|---|
| 78 | protected Socket serialInterfaceSocket = null; |
|---|
| 79 | |
|---|
| 80 | /** IOStream for writing out commands. */ |
|---|
| 81 | //protected ObjectOutputStream out = null; |
|---|
| 82 | protected OutputStream out = null; |
|---|
| 83 | |
|---|
| 84 | /** IOStream for reading dvd player responses. */ |
|---|
| 85 | protected BufferedReader in = null; |
|---|
| 86 | |
|---|
| 87 | |
|---|
| 88 | /** |
|---|
| 89 | * Constructor. |
|---|
| 90 | */ |
|---|
| 91 | public PioneerV5000() { |
|---|
| 92 | commandString = new StringBuffer(MAX_COMMAND_LEN); |
|---|
| 93 | responseString = new StringBuffer(MAX_RESPONSE_LEN); |
|---|
| 94 | } |
|---|
| 95 | |
|---|
| 96 | /** |
|---|
| 97 | * Sets the host and port connection information for this dvd player. |
|---|
| 98 | * |
|---|
| 99 | * @param host DVD player host string. |
|---|
| 100 | * @param port DVD player port value. |
|---|
| 101 | */ |
|---|
| 102 | public void setConnectionInfo(String host, int port) { |
|---|
| 103 | dvdHost = host; |
|---|
| 104 | dvdPort = port; |
|---|
| 105 | } |
|---|
| 106 | |
|---|
| 107 | /** |
|---|
| 108 | * Get the current connection information for this dvd player. The |
|---|
| 109 | * returned string is as follows: HOST:PORT |
|---|
| 110 | * |
|---|
| 111 | * @return DVD connection host:port |
|---|
| 112 | */ |
|---|
| 113 | public String getConnectionInfo() { |
|---|
| 114 | return dvdHost + ":" + dvdPort; |
|---|
| 115 | } |
|---|
| 116 | |
|---|
| 117 | public boolean isConnected() { |
|---|
| 118 | return isConnected; |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | /** |
|---|
| 122 | * Establish a connection with the dvd player through socket communication. |
|---|
| 123 | * If the port is successfully opened, input and ouput streams are opened |
|---|
| 124 | * on the socket. The isConnected boolean flag is set to true if this is |
|---|
| 125 | * successful. Observers are notified with a DVDStatusUpdate to show the |
|---|
| 126 | * new connection. |
|---|
| 127 | * |
|---|
| 128 | * @throws IOException if communication with the dvd player fails. |
|---|
| 129 | */ |
|---|
| 130 | public void connect() throws IOException { |
|---|
| 131 | |
|---|
| 132 | serialInterfaceSocket = new Socket(); |
|---|
| 133 | serialInterfaceSocket.connect(new InetSocketAddress(dvdHost, dvdPort), 5000); |
|---|
| 134 | serialInterfaceSocket.setSoTimeout(5000); |
|---|
| 135 | |
|---|
| 136 | //out = new ObjectOutputStream(serialInterfaceSocket.getOutputStream()); |
|---|
| 137 | out = serialInterfaceSocket.getOutputStream(); |
|---|
| 138 | in = new BufferedReader(new InputStreamReader(serialInterfaceSocket.getInputStream())); |
|---|
| 139 | |
|---|
| 140 | isConnected = true; |
|---|
| 141 | |
|---|
| 142 | setChanged(); |
|---|
| 143 | notifyObservers(new DVDStatusUpdate(getConnectionInfo(), |
|---|
| 144 | isConnected())); |
|---|
| 145 | } |
|---|
| 146 | |
|---|
| 147 | |
|---|
| 148 | /** |
|---|
| 149 | * Disconnect from the dvd player. Close all IOStreams and socket, then set |
|---|
| 150 | * the isConnected flag to false. Observers are notified with a |
|---|
| 151 | * DVDStatusUpdate to show the loss of the connection. |
|---|
| 152 | */ |
|---|
| 153 | public void disconnect() { |
|---|
| 154 | |
|---|
| 155 | try { |
|---|
| 156 | in.close(); |
|---|
| 157 | } |
|---|
| 158 | catch (Exception e) {} |
|---|
| 159 | |
|---|
| 160 | try { |
|---|
| 161 | out.close(); |
|---|
| 162 | } |
|---|
| 163 | catch (Exception e) {} |
|---|
| 164 | |
|---|
| 165 | try { |
|---|
| 166 | serialInterfaceSocket.close(); |
|---|
| 167 | } |
|---|
| 168 | catch (Exception e) {} |
|---|
| 169 | |
|---|
| 170 | |
|---|
| 171 | isConnected = false; |
|---|
| 172 | |
|---|
| 173 | setChanged(); |
|---|
| 174 | notifyObservers(new DVDStatusUpdate(getConnectionInfo(), |
|---|
| 175 | isConnected())); |
|---|
| 176 | |
|---|
| 177 | } |
|---|
| 178 | |
|---|
| 179 | /* |
|---|
| 180 | * If the command is sent while the player is in the Park mode, the dvd |
|---|
| 181 | * ejects and the player enters the Open mode. After the tray is ejected, |
|---|
| 182 | * player returns a completed status message. |
|---|
| 183 | * |
|---|
| 184 | * If the player is in any mode other than Open or Park, the disc stops, the |
|---|
| 185 | * player enters Open mode and the door opens. |
|---|
| 186 | * |
|---|
| 187 | * If the player is already in Open mode, an error message is returned. |
|---|
| 188 | */ |
|---|
| 189 | public void open() throws IOException { |
|---|
| 190 | commandString.append(COMMAND_CHARS.OPEN.cmd); |
|---|
| 191 | transmit(); |
|---|
| 192 | } |
|---|
| 193 | |
|---|
| 194 | |
|---|
| 195 | /* |
|---|
| 196 | * If the command is sent while the player door is open, the door |
|---|
| 197 | * closes then the player enters the Park mode. After the door closes, the |
|---|
| 198 | * player returns the completed status message. |
|---|
| 199 | * |
|---|
| 200 | * If the player is in any mode other than Open or if the player door is already |
|---|
| 201 | * closed, an error message is returned. |
|---|
| 202 | */ |
|---|
| 203 | public void close() throws IOException { |
|---|
| 204 | commandString.append(COMMAND_CHARS.CLOSE.cmd); |
|---|
| 205 | transmit(); |
|---|
| 206 | } |
|---|
| 207 | |
|---|
| 208 | /* |
|---|
| 209 | * If the command is sent while the player is in Open, Park or Reject |
|---|
| 210 | * mode, the player immediately enters Setup and the disc begins spinning up. |
|---|
| 211 | * The player is ready for playback when the device reaches the beginning of |
|---|
| 212 | * the program (DVD, CD or VCD disc pauses or stills at the first Track). The |
|---|
| 213 | * player returns the completed status when the disc pauses or stills. |
|---|
| 214 | * |
|---|
| 215 | * If the player receives the command while playing a menu, the player returns |
|---|
| 216 | * an error message. However, if the disc program does not allow new |
|---|
| 217 | * commands once playback begins, the player ignores the command. |
|---|
| 218 | */ |
|---|
| 219 | public void start() throws IOException { |
|---|
| 220 | commandString.append(COMMAND_CHARS.START.cmd); |
|---|
| 221 | transmit(); |
|---|
| 222 | } |
|---|
| 223 | |
|---|
| 224 | public void play() throws IOException { |
|---|
| 225 | commandString.append(COMMAND_CHARS.PLAY.cmd); |
|---|
| 226 | transmit(); |
|---|
| 227 | } |
|---|
| 228 | |
|---|
| 229 | public void playChapter(int chapter) throws IOException { |
|---|
| 230 | commandString.append(COMMAND_CHARS.CHAPTER.cmd + chapter); |
|---|
| 231 | commandString.append(COMMAND_CHARS.SEARCH_PLAY.cmd); |
|---|
| 232 | transmit(); |
|---|
| 233 | } |
|---|
| 234 | |
|---|
| 235 | public void playTitle(int title) throws IOException { |
|---|
| 236 | commandString.append(COMMAND_CHARS.TITLE.cmd + title); |
|---|
| 237 | commandString.append(COMMAND_CHARS.SEARCH_PLAY.cmd); |
|---|
| 238 | transmit(); |
|---|
| 239 | |
|---|
| 240 | } |
|---|
| 241 | |
|---|
| 242 | public void repeatTitle(int title) throws IOException { |
|---|
| 243 | commandString.append(title + COMMAND_CHARS.GROUP.cmd); |
|---|
| 244 | commandString.append("1" + COMMAND_CHARS.CMD_STACK_PL.cmd); |
|---|
| 245 | |
|---|
| 246 | transmit(); |
|---|
| 247 | } |
|---|
| 248 | |
|---|
| 249 | |
|---|
| 250 | /* |
|---|
| 251 | * If the command is sent while the player is in Random Access |
|---|
| 252 | * mode, the pause occurs at the current disc location. The player returns the |
|---|
| 253 | * completed status message immediately. |
|---|
| 254 | * |
|---|
| 255 | * In Pause mode, Still and Video Squelch are ACTIVE. However, if the disc |
|---|
| 256 | * program does not allow a pause, the player ignores the command and |
|---|
| 257 | * returns an error message (E04). |
|---|
| 258 | */ |
|---|
| 259 | public void pause() throws IOException { |
|---|
| 260 | commandString.append(COMMAND_CHARS.PAUSE.cmd); |
|---|
| 261 | transmit(); |
|---|
| 262 | } |
|---|
| 263 | |
|---|
| 264 | /* |
|---|
| 265 | * If the command is sent while the player is in Random Access |
|---|
| 266 | * mode, playback stops at the current disc position and the player enters Still |
|---|
| 267 | * mode. The player returns the completed status message immediately. |
|---|
| 268 | * |
|---|
| 269 | * However, if the disc program does not allow a pause, the player ignores the |
|---|
| 270 | * command and returns an error message (E04). |
|---|
| 271 | * |
|---|
| 272 | */ |
|---|
| 273 | public void still() throws IOException { |
|---|
| 274 | commandString.append(COMMAND_CHARS.STILL.cmd); |
|---|
| 275 | transmit(); |
|---|
| 276 | } |
|---|
| 277 | |
|---|
| 278 | public void stepForward() throws IOException {} |
|---|
| 279 | public void stepReverse() throws IOException {} |
|---|
| 280 | |
|---|
| 281 | /* |
|---|
| 282 | * If the command is sent while the player is in Random Access |
|---|
| 283 | * mode, the screen proceeds forward (NF) or in reverse (NR) quickly. When |
|---|
| 284 | * scanning is finished, the player resumes the Random Access mode and |
|---|
| 285 | * returns the completed status message. |
|---|
| 286 | * |
|---|
| 287 | * If the SCAN command is sent while the player is in Fast Forward or Reverse |
|---|
| 288 | * Playback, the player enters Scan mode. |
|---|
| 289 | * |
|---|
| 290 | * Once the NS command is sent, the player resets to the normal |
|---|
| 291 | *Playback mode and returns the completed status message. |
|---|
| 292 | */ |
|---|
| 293 | public void scanForward() throws IOException { |
|---|
| 294 | commandString.append(COMMAND_CHARS.SCAN_FWD.cmd); |
|---|
| 295 | transmit(); |
|---|
| 296 | } |
|---|
| 297 | |
|---|
| 298 | |
|---|
| 299 | public void scanReverse() throws IOException { |
|---|
| 300 | commandString.append(COMMAND_CHARS.SCAN_RVS.cmd); |
|---|
| 301 | transmit(); |
|---|
| 302 | } |
|---|
| 303 | |
|---|
| 304 | |
|---|
| 305 | public void scanStop() throws IOException { |
|---|
| 306 | commandString.append(COMMAND_CHARS.SCAN_STOP.cmd); |
|---|
| 307 | transmit(); |
|---|
| 308 | } |
|---|
| 309 | |
|---|
| 310 | public void upload(String cmdStack) throws IOException { |
|---|
| 311 | //park mode |
|---|
| 312 | //out.write((COMMAND_CHARS.REJECT.cmd + CR).toString().getBytes()); |
|---|
| 313 | |
|---|
| 314 | //try { Thread.sleep(500); } catch (Exception e) {} |
|---|
| 315 | |
|---|
| 316 | out.write((COMMAND_CHARS.UPLOAD_DATA.cmd + CR).toString().getBytes()); |
|---|
| 317 | out.flush(); |
|---|
| 318 | |
|---|
| 319 | try { Thread.sleep(500); } catch (Exception e) {} |
|---|
| 320 | |
|---|
| 321 | out.write((cmdStack + CR).toString().getBytes()); |
|---|
| 322 | out.flush(); |
|---|
| 323 | |
|---|
| 324 | |
|---|
| 325 | } |
|---|
| 326 | |
|---|
| 327 | public String download() throws Exception { |
|---|
| 328 | //park mode |
|---|
| 329 | commandString.append(COMMAND_CHARS.REJECT.cmd + CR); |
|---|
| 330 | transmit(); |
|---|
| 331 | |
|---|
| 332 | commandString.append(COMMAND_CHARS.DOWNLOAD_DATA.cmd + CR); |
|---|
| 333 | |
|---|
| 334 | //send carriage return to refresh the connection |
|---|
| 335 | //out.writeChar(CR); |
|---|
| 336 | out.write(CR); |
|---|
| 337 | out.flush(); |
|---|
| 338 | |
|---|
| 339 | //clear response buffer |
|---|
| 340 | while(in.ready()) |
|---|
| 341 | responseString.append(in.readLine()); |
|---|
| 342 | responseString.setLength(0); |
|---|
| 343 | |
|---|
| 344 | //send the command |
|---|
| 345 | //out.writeBytes(commandString.toString()); |
|---|
| 346 | out.write(commandString.toString().getBytes()); |
|---|
| 347 | out.flush(); |
|---|
| 348 | |
|---|
| 349 | //read in response |
|---|
| 350 | while(in.ready()) |
|---|
| 351 | responseString.append(in.readLine()); |
|---|
| 352 | |
|---|
| 353 | |
|---|
| 354 | if(responseString.indexOf("E") == 0) { |
|---|
| 355 | throw new Exception("Error in downloading from player."); |
|---|
| 356 | } |
|---|
| 357 | else { |
|---|
| 358 | return responseString.toString(); |
|---|
| 359 | } |
|---|
| 360 | |
|---|
| 361 | } |
|---|
| 362 | |
|---|
| 363 | /** |
|---|
| 364 | * This method spawns a thread to transmit the current command found in the |
|---|
| 365 | * commandString buffer to the DVD player. If the output stream is null, |
|---|
| 366 | * observers are notified with a DVDStatusUpdate containing the exception. |
|---|
| 367 | * The following steps are taken to transmit the command: <br> |
|---|
| 368 | * |
|---|
| 369 | * <nl> |
|---|
| 370 | * <li>A Carriage Return (CR) character is sent to refresh the connection.</li> |
|---|
| 371 | * <li>All response characters on the buffer are cleared.</li> |
|---|
| 372 | * <li>The command is transmitted with a CR to signify the end of the command.</li> |
|---|
| 373 | * <li>If the DVD response contains an 'E', then the command was not successful, |
|---|
| 374 | * repeat steps 1 - 3. Otherwise, the command was successful, the thread ends.</li> |
|---|
| 375 | * <li>If the retry command transmit fails, notify observers with a DVDStatusUpdate |
|---|
| 376 | * containing the exception.</li> |
|---|
| 377 | * <nl> |
|---|
| 378 | */ |
|---|
| 379 | protected synchronized void transmit() { |
|---|
| 380 | |
|---|
| 381 | Runnable transmitRun = new Runnable() { |
|---|
| 382 | public void run() { |
|---|
| 383 | |
|---|
| 384 | int retries = MAX_RETRIES; |
|---|
| 385 | |
|---|
| 386 | try { |
|---|
| 387 | if(out == null) { |
|---|
| 388 | throw new Exception("Cannot transmit to DVD " + |
|---|
| 389 | dvdHost + ":" + dvdPort + ". Reconnect to DVD."); |
|---|
| 390 | } |
|---|
| 391 | |
|---|
| 392 | while(retries > 0) { |
|---|
| 393 | System.out.println("sending [" + commandString.toString() + |
|---|
| 394 | "] to " + getConnectionInfo()); |
|---|
| 395 | |
|---|
| 396 | //send carriage return to refresh the connection |
|---|
| 397 | out.write(CR); |
|---|
| 398 | out.flush(); |
|---|
| 399 | |
|---|
| 400 | //Wait for DVD to respond |
|---|
| 401 | Thread.sleep(500); |
|---|
| 402 | |
|---|
| 403 | //clear response buffer |
|---|
| 404 | while(in.ready()) |
|---|
| 405 | responseString.append(in.readLine()); |
|---|
| 406 | responseString.setLength(0); |
|---|
| 407 | |
|---|
| 408 | //send the command |
|---|
| 409 | out.write(commandString.toString().getBytes()); |
|---|
| 410 | out.write(CR); |
|---|
| 411 | out.flush(); |
|---|
| 412 | |
|---|
| 413 | //Wait for DVD to respond |
|---|
| 414 | Thread.sleep(500); |
|---|
| 415 | |
|---|
| 416 | //read in response |
|---|
| 417 | while(in.ready()) |
|---|
| 418 | responseString.append(in.readLine()); |
|---|
| 419 | |
|---|
| 420 | //if an error occured, retry |
|---|
| 421 | if((responseString.indexOf("E") > -1)) { |
|---|
| 422 | System.out.println("response: " + responseString.toString()); |
|---|
| 423 | retries--; |
|---|
| 424 | } |
|---|
| 425 | else { |
|---|
| 426 | retries = 0; |
|---|
| 427 | System.out.println("response: " + responseString.toString()); |
|---|
| 428 | } |
|---|
| 429 | } |
|---|
| 430 | } |
|---|
| 431 | catch (Exception e) { |
|---|
| 432 | setChanged(); |
|---|
| 433 | notifyObservers(new DVDStatusUpdate(getConnectionInfo(), |
|---|
| 434 | isConnected(), e)); |
|---|
| 435 | } |
|---|
| 436 | finally { |
|---|
| 437 | commandString.setLength(0); |
|---|
| 438 | responseString.setLength(0); |
|---|
| 439 | } |
|---|
| 440 | } |
|---|
| 441 | }; |
|---|
| 442 | |
|---|
| 443 | Thread transmitThread = new Thread(transmitRun); |
|---|
| 444 | transmitThread.start(); |
|---|
| 445 | |
|---|
| 446 | } |
|---|
| 447 | |
|---|
| 448 | |
|---|
| 449 | |
|---|
| 450 | } |
|---|