From 6f752eb54475bc3d5138304ac74bd2031d62b3ca Mon Sep 17 00:00:00 2001 From: =?utf8?q?Peter=20=C3=85strand?= Date: Wed, 25 Feb 2009 09:58:28 +0000 Subject: [PATCH] Removed Java-based rfbplayer, not a part of the TigerVNC project. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@3614 3789f03b-4d11-0410-bbf8-ca57d06f2519 --- .../com/tightvnc/rfbplayer/ButtonPanel.java | 97 -- .../com/tightvnc/rfbplayer/FbsConnection.java | 274 ---- .../com/tightvnc/rfbplayer/FbsEntryPoint.java | 83 - .../tightvnc/rfbplayer/FbsInputStream.java | 344 ----- java/src/com/tightvnc/rfbplayer/LICENCE.TXT | 340 ----- .../com/tightvnc/rfbplayer/LWScrollPane.java | 260 ---- java/src/com/tightvnc/rfbplayer/Makefile | 31 - .../com/tightvnc/rfbplayer/PARfbSender.java | 28 - java/src/com/tightvnc/rfbplayer/README | 99 -- .../src/com/tightvnc/rfbplayer/RfbPlayer.java | 472 ------ .../rfbplayer/RfbPlayerSetDisplaySize.java | 20 - java/src/com/tightvnc/rfbplayer/RfbProto.java | 292 ---- .../tightvnc/rfbplayer/RfbSharedStatic.java | 9 - .../src/com/tightvnc/rfbplayer/VncCanvas.java | 1336 ----------------- java/src/com/tightvnc/rfbplayer/index.html | 9 - 15 files changed, 3694 deletions(-) delete mode 100644 java/src/com/tightvnc/rfbplayer/ButtonPanel.java delete mode 100644 java/src/com/tightvnc/rfbplayer/FbsConnection.java delete mode 100644 java/src/com/tightvnc/rfbplayer/FbsEntryPoint.java delete mode 100644 java/src/com/tightvnc/rfbplayer/FbsInputStream.java delete mode 100644 java/src/com/tightvnc/rfbplayer/LICENCE.TXT delete mode 100644 java/src/com/tightvnc/rfbplayer/LWScrollPane.java delete mode 100644 java/src/com/tightvnc/rfbplayer/Makefile delete mode 100644 java/src/com/tightvnc/rfbplayer/PARfbSender.java delete mode 100644 java/src/com/tightvnc/rfbplayer/README delete mode 100644 java/src/com/tightvnc/rfbplayer/RfbPlayer.java delete mode 100644 java/src/com/tightvnc/rfbplayer/RfbPlayerSetDisplaySize.java delete mode 100644 java/src/com/tightvnc/rfbplayer/RfbProto.java delete mode 100644 java/src/com/tightvnc/rfbplayer/RfbSharedStatic.java delete mode 100644 java/src/com/tightvnc/rfbplayer/VncCanvas.java delete mode 100644 java/src/com/tightvnc/rfbplayer/index.html diff --git a/java/src/com/tightvnc/rfbplayer/ButtonPanel.java b/java/src/com/tightvnc/rfbplayer/ButtonPanel.java deleted file mode 100644 index 56d8ad35..00000000 --- a/java/src/com/tightvnc/rfbplayer/ButtonPanel.java +++ /dev/null @@ -1,97 +0,0 @@ -// -// Copyright (C) 2002 HorizonLive.com, Inc. All Rights Reserved. -// -// This 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 of the License, or -// (at your option) any later version. -// -// This software 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 this software; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -// USA. -// - -package com.tightvnc.rfbplayer; - -import java.awt.*; -import java.awt.event.*; - -class ButtonPanel extends Panel implements ActionListener { - - protected RfbPlayer player; - protected Button playButton; - protected TextField posText; - protected TextField timeScaleText; - - protected int lastPosSeconds = -1; - - ButtonPanel(RfbPlayer player) { - this.player = player; - - setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); - - playButton = new Button("Play"); - playButton.setEnabled(false); - add(playButton); - playButton.addActionListener(this); - - add(new Label(" Position:")); - posText = new TextField(5); - add(posText); - posText.addActionListener(this); - - add(new Label(" Speed:")); - timeScaleText = new TextField(5); - timeScaleText.setText(String.valueOf(player.getSpeed())); - add(timeScaleText); - timeScaleText.addActionListener(this); - } - - public void setPaused(boolean paused) { - if (paused) { - playButton.setLabel("Play"); - } else { - playButton.setLabel("Pause"); - } - playButton.setEnabled(true); - } - - public void setPos(long pos) { - int seconds = (int)(pos / 1000); - if (seconds != lastPosSeconds) { - lastPosSeconds = seconds; - char[] zeroes = {'0', '0', '0', '0'}; - String text = String.valueOf(seconds); - if (text.length() < 4) { - text = new String(zeroes, 0, 4 - text.length()) + text; - } - posText.setText(text); - posText.setCaretPosition(text.length()); - } - } - - // - // Event processing. - // - public void actionPerformed(ActionEvent evt) { - if (evt.getSource() == playButton) { - player.setPaused(playButton.getLabel().equals("Pause")); - } else if (evt.getSource() == posText) { - player.setPos(Long.parseLong(posText.getText()) * 1000); - } else if (evt.getSource() == timeScaleText) { - double speed = Double.valueOf(timeScaleText.getText()).doubleValue(); - if (speed <= 0.0) - speed = 1.0; - timeScaleText.setText(String.valueOf(speed)); - player.setSpeed(speed); - } - } - -} - diff --git a/java/src/com/tightvnc/rfbplayer/FbsConnection.java b/java/src/com/tightvnc/rfbplayer/FbsConnection.java deleted file mode 100644 index 5bbf4e0c..00000000 --- a/java/src/com/tightvnc/rfbplayer/FbsConnection.java +++ /dev/null @@ -1,274 +0,0 @@ -// -// Copyright (C) 2008 Wimba, Inc. All Rights Reserved. -// -// This 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 of the License, or -// (at your option) any later version. -// -// This software 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 this software; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -// USA. -// - -// -// FbsConnection.java -// - -package com.tightvnc.rfbplayer; - -import java.io.*; -import java.net.*; -import java.applet.Applet; - -public class FbsConnection { - - URL fbsURL; - URL fbiURL; - URL fbkURL; - - /** Index data loaded from the .fbi file. */ - FbsEntryPoint[] indexData; - int numIndexRecords; - - /** RFB initialization data loaded from the .fbi file. */ - byte[] rfbInitData; - - FbsConnection(String fbsLocation, String indexLocationPrefix, Applet applet) - throws MalformedURLException { - - // Construct URLs from strings. - URL base = null; - if (applet != null) { - base = applet.getCodeBase(); - } - fbsURL = new URL(base, fbsLocation); - fbiURL = fbkURL = null; - if (indexLocationPrefix != null) { - try { - fbiURL = new URL(base, indexLocationPrefix + ".fbi"); - fbkURL = new URL(base, indexLocationPrefix + ".fbk"); - } catch (MalformedURLException e) { - fbiURL = fbkURL = null; - } - } - - // Try to load the .fbi index file. - indexData = null; - numIndexRecords = 0; - rfbInitData = null; - loadIndex(); - } - - FbsInputStream connect(long timeOffset) throws IOException { - FbsInputStream fbs = null; - - // Try efficient seeking first. - int i = indexForTimeOffset(timeOffset); - if (i >= 0) { - FbsEntryPoint entryPoint = indexData[i]; - if (entryPoint.key_size < entryPoint.fbs_fpos) { - try { - fbs = openFbsFile(entryPoint); - } catch (IOException e) { - System.err.println(e); - } - if (fbs == null) { - System.err.println("Could not open FBS file at entry point " + - entryPoint.timestamp + " ms"); - } - } - } - - // Fallback to the dumb version of openFbsFile(). - if (fbs == null) { - fbs = openFbsFile(); - } - - // Seek to the specified position. - fbs.setTimeOffset(timeOffset, false); - return fbs; - } - - /** - * Load index data from .fbi file to {@link #indexData}. - */ - private void loadIndex() { - // Loading .fbi makes sense only if both .fbi and .fbk files are available. - if (fbiURL != null && fbkURL != null) { - FbsEntryPoint[] newIndex; - int numRecordsRead = 0; - byte[] newInitData; - try { - // Connect. - URLConnection connection = fbiURL.openConnection(); - connection.connect(); - DataInputStream is = new DataInputStream(connection.getInputStream()); - - // Check file signature. - byte[] b = new byte[12]; - is.readFully(b); - if (b[0] != 'F' || b[1] != 'B' || b[2] != 'I' || b[3] != ' ' || - b[4] != '0' || b[5] != '0' || b[6] != '1' || b[7] != '.' || - b[8] < '0' || b[8] > '9' || b[9] < '0' || b[9] > '9' || - b[10] < '0' || b[10] > '9' || b[11] != '\n') { - System.err.println("Could not load index: bad .fbi file signature"); - return; - } - - // Read the record counter and allocate index array. - int numRecords = is.readInt(); - if (numRecords <= 0) { - System.err.println("Could not load index: bad .fbi record counter"); - return; - } - newIndex = new FbsEntryPoint[numRecords]; - - // Read byte counter and allocate byte array for RFB initialization. - int initSize = is.readInt(); - if (initSize <= 0) { - System.err.println("Could not load index: bad RFB init data size"); - return; - } - newInitData = new byte[initSize]; - - // Load index from the .fbi file. - try { - for (int i = 0; i < numRecords; i++) { - FbsEntryPoint record = new FbsEntryPoint(); - record.timestamp = (long)is.readInt() & 0xFFFFFFFFL; - record.key_fpos = (long)is.readInt() & 0xFFFFFFFFL; - record.key_size = (long)is.readInt() & 0xFFFFFFFFL; - record.fbs_fpos = (long)is.readInt() & 0xFFFFFFFFL; - record.fbs_skip = (long)is.readInt() & 0xFFFFFFFFL; - newIndex[i] = record; - numRecordsRead++; - } - } catch (EOFException e) { - System.err.println("Preliminary end of .fbi file"); - } catch (IOException e) { - System.err.println("Ignored exception: " + e); - } - if (numRecordsRead == 0) { - System.err.println("Could not load index: failed to read .fbi data"); - return; - } else if (numRecordsRead != numRecords) { - System.err.println("Warning: read not as much .fbi data as expected"); - } - is.readFully(newInitData); - } catch (FileNotFoundException e) { - System.err.println("Could not load index: .fbi file not found: " + - e.getMessage()); - return; - } catch (IOException e) { - System.err.println(e); - System.err.println("Could not load index: failed to load .fbi file"); - return; - } - // Check correctness of the data read. - for (int i = 1; i < numRecordsRead; i++) { - if (newIndex[i].timestamp <= newIndex[i - 1].timestamp) { - System.err.println("Could not load index: wrong .fbi file contents"); - return; - } - } - // Loaded successfully. - indexData = newIndex; - numIndexRecords = numRecordsRead; - rfbInitData = newInitData; - System.err.println("Loaded index data, " + numRecordsRead + " records"); - } - } - - private int indexForTimeOffset(long timeOffset) { - if (timeOffset > 0 && indexData != null && numIndexRecords > 0) { - int i = 0; - while (i < numIndexRecords && indexData[i].timestamp <= timeOffset) { - i++; - } - return i - 1; - } else { - return -1; - } - } - - /** - * Open FBS file identified by {@link #fbsURL}. The file is open at its very - * beginning, no seek is performed. - * - * @return a newly created FBS input stream. - * @throws java.io.IOException if an I/O exception occurs. - */ - private FbsInputStream openFbsFile() throws IOException { - return new FbsInputStream(fbsURL.openStream()); - } - - /** - * Open FBS file identified by {@link #fbsURL}. The stream is - * positioned at the entry point described by entryPoint. - * - * @param entryPoint entry point information. - * - * @return a newly created FBS input stream on success, null if - * any error occured and the FBS stream is not opened. - * @throws java.io.IOException if an I/O exception occurs. - */ - private FbsInputStream openFbsFile(FbsEntryPoint entry) - throws IOException { - - System.err.println("Entering FBS at " + entry.timestamp + " ms"); - - // Make sure the protocol is HTTP. - if (!fbkURL.getProtocol().equalsIgnoreCase("http") || - !fbsURL.getProtocol().equalsIgnoreCase("http")) { - System.err.println("Indexed access requires HTTP protocol in URLs"); - return null; - } - - // Seek to the keyframe. - InputStream is = openHttpByteRange(fbkURL, entry.key_fpos, entry.key_size); - if (is == null) { - return null; - } - - // Load keyframe data from the .fbk file, prepend RFB initialization data. - DataInputStream data = new DataInputStream(is); - byte[] keyData = new byte[rfbInitData.length + (int)entry.key_size]; - System.arraycopy(rfbInitData, 0, keyData, 0, rfbInitData.length); - data.readFully(keyData, rfbInitData.length, (int)entry.key_size); - data.close(); - - // Open the FBS stream. - is = openHttpByteRange(fbsURL, entry.fbs_fpos, -1); - if (is == null) { - return null; - } - return new FbsInputStream(is, entry.timestamp, keyData, entry.fbs_skip); - } - - private static InputStream openHttpByteRange(URL url, long offset, long len) - throws IOException { - HttpURLConnection conn = (HttpURLConnection)url.openConnection(); - String rangeSpec = "bytes=" + offset + "-"; - if (len != -1) { - long lastByteOffset = offset + len - 1; - rangeSpec += lastByteOffset; - } - conn.setRequestProperty("Range", rangeSpec); - conn.connect(); - InputStream is = conn.getInputStream(); - if (conn.getResponseCode() != HttpURLConnection.HTTP_PARTIAL) { - System.err.println("HTTP server does not support Range request headers"); - is.close(); - return null; - } - return is; - } - -} diff --git a/java/src/com/tightvnc/rfbplayer/FbsEntryPoint.java b/java/src/com/tightvnc/rfbplayer/FbsEntryPoint.java deleted file mode 100644 index 100933f5..00000000 --- a/java/src/com/tightvnc/rfbplayer/FbsEntryPoint.java +++ /dev/null @@ -1,83 +0,0 @@ -// -// Copyright (C) 2008 Wimba, Inc. All Rights Reserved. -// -// This 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 of the License, or -// (at your option) any later version. -// -// This software 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 this software; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -// USA. -// - -// -// FbsEntryPoint.java -// - -package com.tightvnc.rfbplayer; - -/** - * Representation of an individual record of the .fbi (FrameBuffer Index) file. - * It includes data that constitutes an entry point to indexed framebuffer - * stream at a particular time offset. - * - * @author Constantin Kaplinsky - */ -public class FbsEntryPoint { - - /** - * Timestamp in milliseconds corresponding to the keyframe data. - * 32-bit unsigned integer. - */ - public long timestamp; - - /** - * Keyframe position in the respective .fbk file, offset in bytes from the - * very beginning of the file. It should point to the byte counter of an FBS - * data block. 32-bit unsigned integer. - */ - public long key_fpos; - - /** - * Keyframe data size in the respective .fbk file, in bytes. 32-bit unsigned - * integer. - */ - public long key_size; - - /** - * Position of the next update in the .fbs file, offset in bytes from the - * very beginning of the file. It should point to the byte counter of an FBS - * data block. 32-bit unsigned integer. - */ - public long fbs_fpos; - - /** - * Offset in the FBS data block referenced by fbs_fpos. It allows addressing - * those updates that begin not on the data block boundary. 32-bit unsigned - * integer. - */ - public long fbs_skip; - - /** - * A replacement for {@link Object#toString()}. - * - * @return a string representation of the object. - */ - public String toString() { - String s = "[ timestamp:" + timestamp; - s += " key_fpos:" + key_fpos; - s += " key_size:" + key_size; - s += " fbs_fpos:" + fbs_fpos; - s += " fbs_skip:" + fbs_skip + " ]"; - - return s; - } - -} diff --git a/java/src/com/tightvnc/rfbplayer/FbsInputStream.java b/java/src/com/tightvnc/rfbplayer/FbsInputStream.java deleted file mode 100644 index f5f4b391..00000000 --- a/java/src/com/tightvnc/rfbplayer/FbsInputStream.java +++ /dev/null @@ -1,344 +0,0 @@ -// -// Copyright (C) 2002 HorizonLive.com, Inc. All Rights Reserved. -// Copyright (C) 2008 Wimba, Inc. All Rights Reserved. -// -// This 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 of the License, or -// (at your option) any later version. -// -// This software 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 this software; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -// USA. -// - -// -// FbsInputStream.java -// - -package com.tightvnc.rfbplayer; - -import java.io.*; -import java.util.*; - -class FbsInputStream extends InputStream { - - protected InputStream in; - protected long startTime; - protected long timeOffset; - protected long seekOffset; - protected boolean farSeeking; - protected boolean paused; - protected boolean isQuitting = false; - protected double playbackSpeed; - - protected byte[] buffer; - protected int bufferSize; - protected int bufferPos; - - /** The number of bytes to skip in the beginning of the next data block. */ - protected long nextBlockOffset; - - protected Observer obs; - - /** - * Construct FbsInputStream object based on the given InputStream, positioned - * at the very beginning of the corresponding FBS file. This constructor - * reads and checks FBS file signature which would look like "FBS 001.000\n", - * but any decimal number is allowed after the dot. - * - * @param in the InputStream object that will be used as a base for this new - * FbsInputStream instance. It should be positioned at the very beginning of - * the corresponding FBS file, so that first 12 bytes read from the stream - * should form FBS file signature. - * @throws java.io.IOException thrown on read error or on incorrect FBS file - * signature. - */ - FbsInputStream(InputStream in) throws IOException { - this(in, 0, null, 0); - - byte[] b = new byte[12]; - readFully(b); - - if (b[0] != 'F' || b[1] != 'B' || b[2] != 'S' || b[3] != ' ' || - b[4] != '0' || b[5] != '0' || b[6] != '1' || b[7] != '.' || - b[8] < '0' || b[8] > '9' || b[9] < '0' || b[9] > '9' || - b[10] < '0' || b[10] > '9' || b[11] != '\n') { - throw new IOException("Incorrect FBS file signature"); - } - } - - /** - * Construct FbsInputStream object based on the given byte array and - * continued in the specified InputStream. Arbitrary position in the FBS file - * is allowed. - * - * @param in - * the input stream for reading future data, after buffer - * will be exhausted. The stream should be positioned at any data block - * boundary (byte counter should follow in next four bytes). - * @param timeOffset - * time position corresponding the the data block provided in - * buffer. - * @param buffer - * the data block that will be treated as the beginning of this FBS data - * stream. This byte array is not copied into the new object so it should - * not be altered by the caller afterwards. - * @param nextBlockOffset - * the number of bytes that should be skipped in first data block read - * from in. - */ - FbsInputStream(InputStream in, long timeOffset, byte[] buffer, - long nextBlockOffset) { - - this.in = in; - startTime = System.currentTimeMillis() - timeOffset; - this.timeOffset = timeOffset; - seekOffset = -1; - farSeeking = false; - paused = false; - playbackSpeed = 1.0; - - this.buffer = buffer; - bufferSize = (buffer != null) ? buffer.length : 0; - bufferPos = 0; - - this.nextBlockOffset = nextBlockOffset; - } - - // Force stream to finish any wait. - public void quit() { - isQuitting = true; - synchronized(this) { - notify(); - } - } - - // - // Basic methods overriding InputStream's methods. - // - public int read() throws IOException { - while (bufferSize == 0) { - if (!fillBuffer()) - return -1; - } - bufferSize--; - return buffer[bufferPos++] & 0xFF; - } - - public int available() throws IOException { - // FIXME: This will work incorrectly if our caller will wait until - // some amount of data is available when the buffer contains less - // data than then that. Current implementation never reads more - // data until the buffer is fully exhausted. - return bufferSize; - } - - public synchronized void close() throws IOException { - if (in != null) - in.close(); - in = null; - startTime = -1; - timeOffset = 0; - seekOffset = -1; - farSeeking = false; - paused = false; - playbackSpeed = 1.0; - - buffer = null; - bufferSize = 0; - bufferPos = 0; - - nextBlockOffset = 0; - obs = null; - } - - // - // Methods providing additional functionality. - // - public synchronized long getTimeOffset() { - long off = Math.max(seekOffset, timeOffset); - return (long)(off * playbackSpeed); - } - - public synchronized void setTimeOffset(long pos, boolean allowJump) { - seekOffset = (long)(pos / playbackSpeed); - if (allowJump) { - long minJumpForwardOffset = timeOffset + (long)(10000 / playbackSpeed); - if (seekOffset < timeOffset || seekOffset > minJumpForwardOffset) { - farSeeking = true; - } - } - notify(); - } - - public synchronized void setSpeed(double newSpeed) { - long newOffset = (long)(timeOffset * playbackSpeed / newSpeed); - startTime += timeOffset - newOffset; - timeOffset = newOffset; - if (isSeeking()) { - seekOffset = (long)(seekOffset * playbackSpeed / newSpeed); - } - playbackSpeed = newSpeed; - } - - public boolean isSeeking() { - return (seekOffset >= 0); - } - - public long getSeekOffset() { - return (long)(seekOffset * playbackSpeed); - } - - public boolean isPaused() { - return paused; - } - - public synchronized void pausePlayback() { - paused = true; - notify(); - } - - public synchronized void resumePlayback() { - paused = false; - startTime = System.currentTimeMillis() - timeOffset; - notify(); - } - - public void addObserver(Observer target) { - obs = target; - } - - // - // Methods for internal use. - // - private synchronized boolean fillBuffer() throws IOException { - // The reading thread should be interrupted on far seeking. - if (farSeeking) - throw new EOFException("[JUMP]"); - - // Just wait unless we are performing playback OR seeking. - waitWhilePaused(); - - if (!readDataBlock()) { - return false; - } - - if (seekOffset >= 0) { - if (timeOffset >= seekOffset) { - startTime = System.currentTimeMillis() - seekOffset; - seekOffset = -1; - } else { - return true; - } - } - - while (!isQuitting) { - long timeDiff = startTime + timeOffset - System.currentTimeMillis(); - if (timeDiff <= 0) { - break; - } - try { - wait(timeDiff); - } catch (InterruptedException e) { - } - waitWhilePaused(); - } - - return true; - } - - /** - * Read FBS data block into the buffer. - * If {@link #nextBlockOffset} is not zero, that number of bytes will be - * skipped in the beginning of the data block. - * - * @return true on success, false if end of file was reached. - * @throws java.io.IOException can be thrown while reading from the - * underlying input stream, or as a result of bad FBS file data. - */ - private boolean readDataBlock() throws IOException { - // Read byte counter, check for EOF condition. - long readResult = readUnsigned32(); - if (readResult < 0) { - return false; - } - - bufferSize = (int)readResult; - int alignedSize = (bufferSize + 3) & 0xFFFFFFFC; - - if (nextBlockOffset > 0) { - in.skip(nextBlockOffset); - bufferSize -= nextBlockOffset; - alignedSize -= nextBlockOffset; - nextBlockOffset = 0; - } - - if (bufferSize >= 0) { - buffer = new byte[alignedSize]; - readFully(buffer); - bufferPos = 0; - timeOffset = (long)(readUnsigned32() / playbackSpeed); - } - - if (bufferSize < 0 || timeOffset < 0 || bufferPos >= bufferSize) { - buffer = null; - bufferSize = 0; - bufferPos = 0; - throw new IOException("Invalid FBS file data"); - } - - return true; - } - - // - // In paused mode, wait for external notification on this object. - // - private void waitWhilePaused() { - while (paused && !isSeeking() && !isQuitting) { - synchronized(this) { - try { - // Note: we call Observer.update(Observable,Object) method - // directly instead of maintaining an Observable object. - obs.update(null, null); - wait(); - } catch (InterruptedException e) { - } - } - } - } - - private long readUnsigned32() throws IOException { - byte[] buf = new byte[4]; - if (!readFully(buf)) - return -1; - - return ((long)(buf[0] & 0xFF) << 24 | - (buf[1] & 0xFF) << 16 | - (buf[2] & 0xFF) << 8 | - (buf[3] & 0xFF)); - } - - private boolean readFully(byte[] b) throws IOException { - int off = 0; - int len = b.length; - - while (off != len) { - int count = in.read(b, off, len - off); - if (count < 0) { - return false; - } - off += count; - } - - return true; - } - -} - diff --git a/java/src/com/tightvnc/rfbplayer/LICENCE.TXT b/java/src/com/tightvnc/rfbplayer/LICENCE.TXT deleted file mode 100644 index ae3b5319..00000000 --- a/java/src/com/tightvnc/rfbplayer/LICENCE.TXT +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - Appendix: How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - 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 of the License, 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 this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/java/src/com/tightvnc/rfbplayer/LWScrollPane.java b/java/src/com/tightvnc/rfbplayer/LWScrollPane.java deleted file mode 100644 index 7325c8c9..00000000 --- a/java/src/com/tightvnc/rfbplayer/LWScrollPane.java +++ /dev/null @@ -1,260 +0,0 @@ - -package com.tightvnc.rfbplayer; - -import java.awt.*; -import java.awt.event.*; - -class LWScrollPane extends Container implements AdjustmentListener { - - /** position info */ - private Point scrollPosition = new Point(0, 0); - - /** panel to hold component to scroll */ - private Panel innerPanel = new Panel() { - - public void update(Graphics g) { - if (needClear) { - super.update(g); - needClear = false; - } else - this.paint(g); - } - - }; - - /** component to display */ - private Component containedComp; - - /** layout info */ - private GridBagLayout gb; - private GridBagConstraints gbc; - - /** scroll bars */ - private Scrollbar xScroller; - private Scrollbar yScroller; - - /** flags indicating which scollbars are visible */ - private boolean showingXScroll = false; - private boolean showingYScroll = false; - - /** flag indicating when innerpanel needs to repaint background */ - private boolean needClear = false; - - /** dimensions for our preferred size */ - private int width = 0; - private int height = 0; - - /** c'tor for a new scroll pane */ - public LWScrollPane() { - // create scroll bars - xScroller = new Scrollbar(Scrollbar.HORIZONTAL) { - - public boolean isFocusable() { - return false; - } - - }; - yScroller = new Scrollbar(Scrollbar.VERTICAL) { - - public boolean isFocusable() { - return false; - } - - }; - xScroller.addAdjustmentListener(this); - yScroller.addAdjustmentListener(this); - - // layout info - gb = new GridBagLayout(); - gbc = new GridBagConstraints(); - setLayout(gb); - setBackground(Color.white); - - // added inner panel - //innerPanel.setBackground(Color.blue); - gbc.fill = GridBagConstraints.BOTH; - gbc.gridx = 0; - gbc.gridy = 0; - gbc.weightx = 100; - gbc.weighty = 100; - gb.setConstraints(innerPanel, gbc); - add(innerPanel); - innerPanel.setLayout(null); - } - /* - public void update(Graphics g) { - paint(g); - } - */ - /* - public void paint(Graphics g) { - super.paint(g); - } - */ - - /** - * Provided to allow the containing frame to resize. - * OS X JVM 1.3 would not allow a frame to be made - * smaller without overriding getMinimumSize. - */ - public Dimension getMinimumSize() { - return new Dimension(0, 0); - } - - public Dimension getPreferredSize() { - return new Dimension(width, height); - } - - public void setSize(int width, int height) { - this.width = width; - this.height = height; - super.setSize(width, height); - } - - public void setSize(Dimension d) { - setSize(d.width, d.height); - } - - /** - * Force component to clear itself before repainting. - * Primarily useful if the contained component shrinks - * without the scroll pane reducing in size. - */ - public void clearAndRepaint() { - needClear = true; - innerPanel.repaint(); - } - - /** Add the component to be scrolled by scroll pane */ - void addComp(Component comp) { - containedComp = comp; - innerPanel.add(containedComp); - } - - /** - * Set the point of the component to display in the - * upper left corner of the viewport. - */ - void setScrollPosition(int x, int y) { - Dimension vps = getViewportSize(); - Dimension ccs = containedComp.getPreferredSize(); - - // skip entirely if component smaller than viewer - if (ccs.width <= vps.width && ccs.height <= vps.height) - return; - - // don't scroll too far left or up - if (x < 0) - x = 0; - if (y < 0) - y = 0; - - // don't scroll too far right or down - if (ccs.width <= vps.width) - x = 0; - else if (x > (ccs.width - vps.width)) - x = ccs.width - vps.width; - if (ccs.height <= vps.height) - y = 0; - else if (y > (ccs.height - vps.height)) - y = ccs.height - vps.height; - - scrollPosition = new Point(x, y); - containedComp.setLocation(-scrollPosition.x, -scrollPosition.y); - xScroller.setValue(scrollPosition.x); - yScroller.setValue(scrollPosition.y); - } - - /** Returns the point at the upper left corner of viewport */ - Point getScrollPosition() { - return new Point(scrollPosition); - } - - /** Return the dimensions of the viewport */ - public Dimension getViewportSize() { - int vpW, vpH; - Dimension size = getSize(); - vpW = size.width; - vpH = size.height; - if (showingYScroll) - vpW -= yScroller.getSize().width; - if (showingXScroll) - vpH -= xScroller.getSize().height; - - return new Dimension(vpW, vpH); - } - - /** - * Ensure that the scroll pane is properly arranged after - * a component is added, the pane is resized, etc. - */ - public void doLayout() { - /** Add scroll bars as necessary */ - boolean needX = false, needY = false; - Dimension innerSize = containedComp.getPreferredSize(); - Dimension scrollDimension = getSize(); - - if (innerSize.width > scrollDimension.width) - needX = true; - if (innerSize.height > scrollDimension.height) - needY = true; - - showingXScroll = false; - showingYScroll = false; - remove(yScroller); - remove(xScroller); - - if (needY) { - gbc.gridy = 0; - gbc.gridx = 1; - gbc.weightx = 0; - gb.setConstraints(yScroller, gbc); - add(yScroller); - showingYScroll = true; - } - - if (needX) { - gbc.gridy = 1; - gbc.gridx = 0; - gbc.weightx = 100; - gbc.weighty = 0; - gb.setConstraints(xScroller, gbc); - add(xScroller); - showingXScroll = true; - } - - /* set scroll bar values */ - int vpW, vpH; - vpW = scrollDimension.width; - vpH = scrollDimension.height; - if (showingYScroll) - vpW -= yScroller.getSize().width; - if (showingXScroll) - vpH -= xScroller.getSize().height; - yScroller.setValues(0, vpH, 0, innerSize.height); - xScroller.setValues(0, vpW, 0, innerSize.width); - - containedComp.setLocation(0, 0); - super.doLayout(); - } - - /** - * Adjustment listener method for receiving callbacks - * from scroll actions. - * - * @param e the AdjustmentEvent - * @return void - */ - public void adjustmentValueChanged(AdjustmentEvent e) { - Point p = containedComp.getLocation(); - if (e.getAdjustable() == xScroller) { - p.x = -e.getValue(); - scrollPosition.x = e.getValue(); - } else { - p.y = -e.getValue(); - scrollPosition.y = e.getValue(); - } - containedComp.setLocation(p); - } - -} diff --git a/java/src/com/tightvnc/rfbplayer/Makefile b/java/src/com/tightvnc/rfbplayer/Makefile deleted file mode 100644 index 42d10474..00000000 --- a/java/src/com/tightvnc/rfbplayer/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -# -# Making the VNC applet. -# - -CP = cp -RM = rm -JC = javac -JAR = jar -ARCHIVE = RfbPlayer.jar -PAGES = index.html -INSTALL_DIR = ./classes - -CLASSES = RfbPlayer.class RfbProto.class ButtonPanel.class VncCanvas.class \ - FbsInputStream.class - -SOURCES = RfbPlayer.java RfbProto.java ButtonPanel.java VncCanvas.java \ - FbsInputStream.java - -all: $(CLASSES) $(ARCHIVE) - -$(CLASSES): $(SOURCES) - $(JC) -g $(SOURCES) - -$(ARCHIVE): $(CLASSES) - $(JAR) cf $(ARCHIVE) $(CLASSES) - -install: $(CLASSES) $(ARCHIVE) - $(CP) $(CLASSES) $(ARCHIVE) $(PAGES) $(INSTALL_DIR) - -clean:: - $(RM) *.class *.jar diff --git a/java/src/com/tightvnc/rfbplayer/PARfbSender.java b/java/src/com/tightvnc/rfbplayer/PARfbSender.java deleted file mode 100644 index 73d09fb3..00000000 --- a/java/src/com/tightvnc/rfbplayer/PARfbSender.java +++ /dev/null @@ -1,28 +0,0 @@ - -package com.tightvnc.rfbplayer; - -import java.applet.*; - -public class PARfbSender extends Applet { - - public void init() { - Applet receiver = null; - receiver = RfbSharedStatic.refApplet; - long time = Long.valueOf(getParameter("time")).longValue(); - boolean pause = (Integer.parseInt(getParameter("pause")) != 0); - boolean unpause = (Integer.parseInt(getParameter("unpause")) != 0); - - if (receiver != null) { - - if (pause) { - ((RfbPlayer)receiver).setPaused(true); - } else if (unpause) { - ((RfbPlayer)receiver).setPaused(false); - } else { - ((RfbPlayer)receiver).jumpTo(time); - } - } else - System.err.println("Couldn't jump to time: " + time + " in RfbPlayer."); - } - -} diff --git a/java/src/com/tightvnc/rfbplayer/README b/java/src/com/tightvnc/rfbplayer/README deleted file mode 100644 index b9bb52b5..00000000 --- a/java/src/com/tightvnc/rfbplayer/README +++ /dev/null @@ -1,99 +0,0 @@ - -RFB Session Player 1.0.1 -======================== - -RFB Session Player is a Java application/applet for playing back RFB session -files in FBS format saved by such programs as VNC Reflector or rfbproxy. - -Usage: java RfbPlayer URL file:test.fbs position 5000 - java RfbPlayer URL http://remote.host/sessions/test.fbs - - -Applet Parameters -================= - ---> "URL" - - Value: URL of the session file to play. - Default: none (required parameter). - - This parameter tells the player which session file to play. The URL can - be either a complete one (e.g. "file:/your/path/session.fbs") or relative - (e.g. "session.fbs"). Please note that if the player operates as an - unsigned applet, it is able to play only files from the host where the - applet was loaded from. It's a usual JVM security limitation. - ---> "Position" - - Value: time in milliseconds. - Default: 0. - - Set initial time position in the session file, in milliseconds. - ---> "Autoplay" - - Values: "Yes", "No". - Default: "No". - - If set to "Yes", then start in the playback mode. By default, the - player starts in the paused state. - ---> "Open new window" (applicable only in the applet mode) - - Values: "Yes", "No". - Default: "No". - - Operate in a separate window. This makes possible resizing the desktop, - and adds scroll bars when necessary. If the server supports variable - desktop size, the window will resize automatically when remote desktop - size changes. - ---> "Show controls" - - Values: "Yes", "No". - Default: "Yes". - - Set to "No" if you want to get rid of the control panel at the top. - Please note that hiding the panel in current version makes playback - impossible. :-) - ---> "Defer screen updates" - - Value: time in milliseconds. - Default: "20". - - When updating the desktop contents after reading each update, schedule - repaint within the specified number of milliseconds. Small delay helps to - coalesce several small updates into one drawing operation, improving CPU - usage. Set this parameter to 0 to disable deferred updates. - ---> "Speed" - - Value: positive fixed-point or floating-point number. - Default: "1.0". - - Sets playback speed where 1 is normal speed, 2 is double speed, - and 0.5 is half speed etc. Both number formats like 0.2 and 2e-1 - are acceptable. - - -Licensing Terms -=============== - -RFB Session Player is - - Copyright (C) 2002 HorizonLive.com, Inc. All Rights Reserved. - -This software is based on the TightVNC Java viewer which is - - Copyright (C) 2001,2002 HorizonLive.com, Inc. All Rights Reserved. - Copyright (C) 2001 Constantin Kaplinsky. All Rights Reserved. - Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. - -This software is distributed under the GNU General Public Licence as -published by the Free Software Foundation. See the file LICENCE.TXT -for the conditions under which this software is made available. VNC -also contains code from other sources. See the Acknowledgements -section below, and the individual files for details of the conditions -under which they are made available. - diff --git a/java/src/com/tightvnc/rfbplayer/RfbPlayer.java b/java/src/com/tightvnc/rfbplayer/RfbPlayer.java deleted file mode 100644 index e696d95f..00000000 --- a/java/src/com/tightvnc/rfbplayer/RfbPlayer.java +++ /dev/null @@ -1,472 +0,0 @@ -// -// Copyright (C) 2001,2002 HorizonLive.com, Inc. All Rights Reserved. -// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -// -// This 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 of the License, or -// (at your option) any later version. -// -// This software 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 this software; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -// USA. -// - -package com.tightvnc.rfbplayer; - -import java.awt.*; -import java.awt.event.*; -import java.io.*; - -public class RfbPlayer extends java.applet.Applet - implements java.lang.Runnable, WindowListener { - - boolean inAnApplet = true; - boolean inSeparateFrame = false; - - /** current applet width */ - int dispW = 300; - /** current applet height */ - int dispH = 200; - - // - // main() is called when run as a java program from the command line. - // It simply runs the applet inside a newly-created frame. - // - public static void main(String[] argv) { - RfbPlayer p = new RfbPlayer(); - p.mainArgs = argv; - p.inAnApplet = false; - p.inSeparateFrame = true; - - p.init(); - p.start(); - } - - String[] mainArgs; - - FbsInputStream fbs; - RfbProto rfb; - Thread rfbThread; - - Frame vncFrame; - Container vncContainer; - //ScrollPane desktopScrollPane; - LWScrollPane desktopScrollPane; - GridBagLayout gridbag; - ButtonPanel buttonPanel; - VncCanvas vc; - - String sessionURL; - String idxPrefix; - long initialTimeOffset; - double playbackSpeed; - boolean autoPlay; - boolean showControls; - boolean isQuitting = false; - int deferScreenUpdates; - - // - // init() - // - public void init() { - - // LiveConnect work-a-round - RfbSharedStatic.refApplet = this; - - readParameters(); - - if (inSeparateFrame) { - vncFrame = new Frame("RFB Session Player"); - if (!inAnApplet) { - vncFrame.add("Center", this); - } - vncContainer = vncFrame; - } else { - vncContainer = this; - } - - if (inSeparateFrame) - vncFrame.addWindowListener(this); - - rfbThread = new Thread(this, "RfbThread"); - rfbThread.start(); - } - - public void update(Graphics g) { - } - - // - // run() - executed by the rfbThread to read RFB data. - // - public void run() { - - gridbag = new GridBagLayout(); - vncContainer.setLayout(gridbag); - - GridBagConstraints gbc = new GridBagConstraints(); - gbc.gridwidth = GridBagConstraints.REMAINDER; - gbc.anchor = GridBagConstraints.NORTHWEST; - - if (showControls) { - buttonPanel = new ButtonPanel(this); - buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); - gridbag.setConstraints(buttonPanel, gbc); - vncContainer.add(buttonPanel); - } - - if (inSeparateFrame) { - vncFrame.pack(); - vncFrame.setVisible(true); - } else { - validate(); - } - - try { - java.applet.Applet applet = (inAnApplet) ? this : null; - FbsConnection conn = new FbsConnection(sessionURL, idxPrefix, applet); - fbs = conn.connect(initialTimeOffset); - rfb = new RfbProto(fbs); - - vc = new VncCanvas(this); - gbc.weightx = 1.0; - gbc.weighty = 1.0; - - // Create a panel which itself is resizeable and can hold - // non-resizeable VncCanvas component at the top left corner. - //Panel canvasPanel = new Panel(); - //canvasPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); - //canvasPanel.add(vc); - - // Create a ScrollPane which will hold a panel with VncCanvas - // inside. - //desktopScrollPane = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED); - desktopScrollPane = new LWScrollPane(); - gbc.fill = GridBagConstraints.BOTH; - gridbag.setConstraints(vc, gbc); - //gridbag.setConstraints(canvasPanel, gbc); - desktopScrollPane.addComp(vc); - desktopScrollPane.setSize(dispW, dispH); - //desktopScrollPane.add(canvasPanel); - - // Now add the scroll bar to the container. - if (inSeparateFrame) { - gridbag.setConstraints(desktopScrollPane, gbc); - vncFrame.add(desktopScrollPane); - vncFrame.setTitle(rfb.desktopName); - vc.resizeDesktopFrame(); - } else { - // Size the scroll pane to display size. - desktopScrollPane.setSize(dispW, dispH); - - // Just add the VncCanvas component to the Applet. - gbc.fill = GridBagConstraints.NONE; - gridbag.setConstraints(desktopScrollPane, gbc); - add(desktopScrollPane); - validate(); - vc.resizeEmbeddedApplet(); - } - - while (!isQuitting) { - try { - setPaused(!autoPlay); - fbs.setSpeed(playbackSpeed); - vc.processNormalProtocol(); - } catch (EOFException e) { - long newTimeOffset; - if (e.getMessage() != null && e.getMessage().equals("[JUMP]")) { - // A special type of EOFException allowing us to close FBS stream - // and then re-open it for jumping to a different time offset. - newTimeOffset = fbs.getSeekOffset(); - autoPlay = !fbs.isPaused(); - } else { - // Return to the beginning after the playback is finished. - newTimeOffset = 0; - autoPlay = false; - } - fbs.close(); - fbs = conn.connect(newTimeOffset); - rfb.newSession(fbs); - vc.updateFramebufferSize(); - } catch (NullPointerException e) { - // catching this causes a hang with 1.4.1 JVM's under Win32 IE - throw e; - } - } - - } catch (FileNotFoundException e) { - fatalError(e.toString()); - } catch (Exception e) { - e.printStackTrace(); - fatalError(e.toString()); - } - - } - - public void setPausedInt(String paused) { - // default to true (pause) - int pause = 1; - - try { - pause = Integer.parseInt(paused); - } catch (NumberFormatException e) { - } - - if (pause == 0) { - setPaused(false); - } else { - setPaused(true); - } - } - - public void setPaused(boolean paused) { - if (showControls) - buttonPanel.setPaused(paused); - if (paused) { - fbs.pausePlayback(); - } else { - fbs.resumePlayback(); - } - } - - public double getSpeed() { - return playbackSpeed; - } - - public void setSpeed(double speed) { - playbackSpeed = speed; - fbs.setSpeed(speed); - } - - public void jumpTo(long pos) { - long diff = Math.abs(pos - fbs.getTimeOffset()); - - // Current threshold is 5 seconds - if (diff > 5000) { - fbs.pausePlayback(); - setPos(pos); - fbs.resumePlayback(); - } - } - - public void setPos(long pos) { - fbs.setTimeOffset(pos, true); - } - - public void updatePos() { - if (showControls && buttonPanel != null) - buttonPanel.setPos(fbs.getTimeOffset()); - } - - // - // readParameters() - read parameters from the html source or from the - // command line. On the command line, the arguments are just a sequence of - // param_name/param_value pairs where the names and values correspond to - // those expected in the html applet tag source. - // - public void readParameters() { - - sessionURL = readParameter("URL", true); - idxPrefix = readParameter("Index", false); - - initialTimeOffset = readLongParameter("Position", 0); - if (initialTimeOffset < 0) - initialTimeOffset = 0; - - playbackSpeed = readDoubleParameter("Speed", 1.0); - if (playbackSpeed <= 0.0) - playbackSpeed = 1.0; - - autoPlay = false; - String str = readParameter("Autoplay", false); - if (str != null && str.equalsIgnoreCase("Yes")) - autoPlay = true; - - showControls = true; - str = readParameter("Show_Controls", false); - if (str != null && str.equalsIgnoreCase("No")) - showControls = false; - - if (inAnApplet) { - str = readParameter("Open_New_Window", false); - if (str != null && str.equalsIgnoreCase("Yes")) - inSeparateFrame = true; - } - - // Fine tuning options. - deferScreenUpdates = (int)readLongParameter("Defer_screen_updates", 20); - if (deferScreenUpdates < 0) - deferScreenUpdates = 0; // Just in case. - - // Display width and height. - dispW = readIntParameter("DISPLAY_WIDTH", dispW); - dispH = readIntParameter("DISPLAY_HEIGHT", dispH); - } - - public String readParameter(String name, boolean required) { - if (inAnApplet) { - String s = getParameter(name); - if ((s == null) && required) { - fatalError(name + " parameter not specified"); - } - return s; - } - - for (int i = 0; i < mainArgs.length; i += 2) { - if (mainArgs[i].equalsIgnoreCase(name)) { - try { - return mainArgs[i + 1]; - } catch (Exception e) { - if (required) { - fatalError(name + " parameter not specified"); - } - return null; - } - } - } - if (required) { - fatalError(name + " parameter not specified"); - } - return null; - } - - long readLongParameter(String name, long defaultValue) { - String str = readParameter(name, false); - long result = defaultValue; - if (str != null) { - try { - result = Long.parseLong(str); - } catch (NumberFormatException e) { - } - } - return result; - } - - double readDoubleParameter(String name, double defaultValue) { - String str = readParameter(name, false); - double result = defaultValue; - if (str != null) { - try { - result = Double.valueOf(str).doubleValue(); - } catch (NumberFormatException e) { - } - } - return result; - } - - int readIntParameter(String name, int defaultValue) { - String str = readParameter(name, false); - int result = defaultValue; - if (str != null) { - try { - result = Integer.parseInt(str); - } catch (NumberFormatException e) { - } - } - return result; - } - - // - // fatalError() - print out a fatal error message. - // - public void fatalError(String str) { - System.err.println(str); - - if (inAnApplet) { - vncContainer.removeAll(); - if (rfb != null) { - rfb = null; - } - Label errLabel = new Label(str); - errLabel.setFont(new Font("Helvetica", Font.PLAIN, 12)); - vncContainer.setLayout(new FlowLayout(FlowLayout.LEFT, 30, 30)); - vncContainer.add(errLabel); - if (inSeparateFrame) { - vncFrame.pack(); - } else { - validate(); - } - Thread.currentThread().stop(); - } else { - System.exit(1); - } - } - - - // - // This method is called before the applet is destroyed. - // - public void destroy() { - isQuitting = true; - vncContainer.removeAll(); - if (fbs != null) { - fbs.quit(); - try { - fbs.close(); - } catch (IOException e) { - } - } - try { - rfbThread.join(); - } catch (InterruptedException e) { - } - if (inSeparateFrame) { - vncFrame.removeWindowListener(this); - vncFrame.dispose(); - } - } - - // - // Set the new width and height of the applet. Call when browser is resized to - // resize the viewer. - // - public void displaySize(int width, int height) { - dispW = width; - dispH = height; - if (!inSeparateFrame) { - vc.resizeEmbeddedApplet(); - } - } - - // - // Close application properly on window close event. - // - public void windowClosing(WindowEvent evt) { - vncContainer.removeAll(); - if (rfb != null) - rfb = null; - - vncFrame.dispose(); - if (!inAnApplet) { - System.exit(0); - } - } - - // - // Ignore window events we're not interested in. - // - public void windowActivated(WindowEvent evt) { - } - - public void windowDeactivated(WindowEvent evt) { - } - - public void windowOpened(WindowEvent evt) { - } - - public void windowClosed(WindowEvent evt) { - } - - public void windowIconified(WindowEvent evt) { - } - - public void windowDeiconified(WindowEvent evt) { - } - -} diff --git a/java/src/com/tightvnc/rfbplayer/RfbPlayerSetDisplaySize.java b/java/src/com/tightvnc/rfbplayer/RfbPlayerSetDisplaySize.java deleted file mode 100644 index f78770fb..00000000 --- a/java/src/com/tightvnc/rfbplayer/RfbPlayerSetDisplaySize.java +++ /dev/null @@ -1,20 +0,0 @@ - -package com.tightvnc.rfbplayer; - -import java.applet.*; - -public class RfbPlayerSetDisplaySize extends Applet { - - public void init() { - Applet receiver = null; - receiver = RfbSharedStatic.refApplet; - int width = Integer.valueOf(getParameter("DISPLAY_WIDTH")).intValue(); - int height = Integer.valueOf(getParameter("DISPLAY_HEIGHT")).intValue(); - - if (receiver != null) { - ((RfbPlayer)receiver).displaySize(width, height); - } else - System.err.println("Couldn't resize RfbPlayer."); - } - -} diff --git a/java/src/com/tightvnc/rfbplayer/RfbProto.java b/java/src/com/tightvnc/rfbplayer/RfbProto.java deleted file mode 100644 index 191173ef..00000000 --- a/java/src/com/tightvnc/rfbplayer/RfbProto.java +++ /dev/null @@ -1,292 +0,0 @@ -// -// Copyright (C) 2008 Wimba, Inc. All Rights Reserved. -// Copyright (C) 2001,2002 HorizonLive.com, Inc. All Rights Reserved. -// Copyright (C) 2001 Constantin Kaplinsky. All Rights Reserved. -// Copyright (C) 2000 Tridia Corporation. All Rights Reserved. -// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -// -// This 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 of the License, or -// (at your option) any later version. -// -// This software 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 this software; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -// USA. -// - -// -// RfbProto.java -// - -package com.tightvnc.rfbplayer; - -import java.io.*; - -class RfbProto { - - final static String versionMsg = "RFB 003.003\n"; - - final static int ConnFailed = 0; - final static int NoAuth = 1; - final static int VncAuth = 2; - - final static int VncAuthOK = 0; - final static int VncAuthFailed = 1; - final static int VncAuthTooMany = 2; - - final static int FramebufferUpdate = 0; - final static int SetColourMapEntries = 1; - final static int Bell = 2; - final static int ServerCutText = 3; - - final static int SetPixelFormat = 0; - final static int FixColourMapEntries = 1; - final static int SetEncodings = 2; - final static int FramebufferUpdateRequest = 3; - final static int KeyboardEvent = 4; - final static int PointerEvent = 5; - final static int ClientCutText = 6; - - final static int EncodingRaw = 0; - final static int EncodingCopyRect = 1; - final static int EncodingRRE = 2; - final static int EncodingCoRRE = 4; - final static int EncodingHextile = 5; - final static int EncodingZlib = 6; - final static int EncodingTight = 7; - final static int EncodingCompressLevel0 = 0xFFFFFF00; - final static int EncodingQualityLevel0 = 0xFFFFFFE0; - final static int EncodingXCursor = 0xFFFFFF10; - final static int EncodingRichCursor = 0xFFFFFF11; - final static int EncodingPointerPos = 0xFFFFFF18; - final static int EncodingLastRect = 0xFFFFFF20; - final static int EncodingNewFBSize = 0xFFFFFF21; - - final static int MaxNormalEncoding = 7; - - final static int HextileRaw = (1 << 0); - final static int HextileBackgroundSpecified = (1 << 1); - final static int HextileForegroundSpecified = (1 << 2); - final static int HextileAnySubrects = (1 << 3); - final static int HextileSubrectsColoured = (1 << 4); - - final static int TightExplicitFilter = 0x04; - final static int TightFill = 0x08; - final static int TightJpeg = 0x09; - final static int TightMaxSubencoding = 0x09; - final static int TightFilterCopy = 0x00; - final static int TightFilterPalette = 0x01; - final static int TightFilterGradient = 0x02; - - final static int TightMinToCompress = 12; - - DataInputStream is; - - /** - * Constructor. It calls {@link #newSession(InputStream)} to open - * new session. - * - * @param is the input stream from which RFB data will be read. - * @throws java.lang.Exception - * @throws java.io.IOException - */ - RfbProto(InputStream is) throws Exception { - newSession(is); - } - - /** - * Open new session that can be read from the specified InputStream. - * - * @param is the input stream. - * @throws java.lang.Exception - * @throws java.io.IOException - */ - public void newSession(InputStream is) throws Exception { - - this.is = new DataInputStream(is); - - readVersionMsg(); - if (readAuthScheme() != NoAuth) { - throw new Exception("Wrong authentication type in the session file"); - } - readServerInit(); - } - - // - // Read server's protocol version message. - // - int serverMajor, serverMinor; - - void readVersionMsg() throws IOException { - - byte[] b = new byte[12]; - - for (int i = 0; i < b.length; i++) - b[i] = (byte)'0'; - - is.readFully(b); - - if ((b[0] != 'R') || (b[1] != 'F') || (b[2] != 'B') || (b[3] != ' ') || - (b[4] < '0') || (b[4] > '9') || (b[5] < '0') || (b[5] > '9') || (b[6] < - '0') || (b[6] > '9') || (b[7] != '.') || (b[8] < '0') || (b[8] > '9') || - (b[9] < '0') || (b[9] > '9') || (b[10] < '0') || (b[10] > '9') || - (b[11] != '\n')) { - throw new IOException("Incorrect protocol version"); - } - - serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0'); - serverMinor = (b[8] - '0') * 100 + (b[9] - '0') * 10 + (b[10] - '0'); - } - - - // - // Find out the authentication scheme. - // - int readAuthScheme() throws IOException { - int authScheme = is.readInt(); - - switch (authScheme) { - - case ConnFailed: - int reasonLen = is.readInt(); - byte[] reason = new byte[reasonLen]; - is.readFully(reason); - throw new IOException(new String(reason)); - - case NoAuth: - case VncAuth: - return authScheme; - - default: - throw new IOException("Unknown authentication scheme " + authScheme); - - } - } - - - // - // Read the server initialisation message - // - String desktopName; - int framebufferWidth, framebufferHeight; - int bitsPerPixel, depth; - boolean bigEndian, trueColour; - int redMax, greenMax, blueMax, redShift, greenShift, blueShift; - - void readServerInit() throws Exception { - framebufferWidth = is.readUnsignedShort(); - framebufferHeight = is.readUnsignedShort(); - bitsPerPixel = is.readUnsignedByte(); - depth = is.readUnsignedByte(); - bigEndian = (is.readUnsignedByte() != 0); - trueColour = (is.readUnsignedByte() != 0); - redMax = is.readUnsignedShort(); - greenMax = is.readUnsignedShort(); - blueMax = is.readUnsignedShort(); - redShift = is.readUnsignedByte(); - greenShift = is.readUnsignedByte(); - blueShift = is.readUnsignedByte(); - byte[] pad = new byte[3]; - is.readFully(pad); - int nameLength = is.readInt(); - byte[] name = new byte[nameLength]; - is.readFully(name); - desktopName = new String(name); - } - - - // - // Set new framebuffer size - // - void setFramebufferSize(int width, int height) { - framebufferWidth = width; - framebufferHeight = height; - } - - - // - // Read the server message type - // - int readServerMessageType() throws IOException { - return is.readUnsignedByte(); - } - - - // - // Read a FramebufferUpdate message - // - int updateNRects; - - void readFramebufferUpdate() throws IOException { - is.readByte(); - updateNRects = is.readUnsignedShort(); - } - - // Read a FramebufferUpdate rectangle header - int updateRectX, updateRectY, updateRectW, updateRectH, updateRectEncoding; - - void readFramebufferUpdateRectHdr() throws IOException { - updateRectX = is.readUnsignedShort(); - updateRectY = is.readUnsignedShort(); - updateRectW = is.readUnsignedShort(); - updateRectH = is.readUnsignedShort(); - updateRectEncoding = is.readInt(); - - if (updateRectEncoding < 0 || updateRectEncoding > MaxNormalEncoding) - return; - - if ((updateRectX + updateRectW > framebufferWidth) || - (updateRectY + updateRectH > framebufferHeight)) { - throw new IOException("Framebuffer update rectangle too large: " + - updateRectW + "x" + updateRectH + " at (" + - updateRectX + "," + updateRectY + ")"); - } - } - - // Read CopyRect source X and Y. - int copyRectSrcX, copyRectSrcY; - - void readCopyRect() throws IOException { - copyRectSrcX = is.readUnsignedShort(); - copyRectSrcY = is.readUnsignedShort(); - } - - - // - // Read a ServerCutText message - // - String readServerCutText() throws IOException { - byte[] pad = new byte[3]; - is.readFully(pad); - int len = is.readInt(); - byte[] text = new byte[len]; - is.readFully(text); - return new String(text); - } - - - // - // Read integer in compact representation - // - int readCompactLen() throws IOException { - int portion = is.readUnsignedByte(); - int len = portion & 0x7F; - if ((portion & 0x80) != 0) { - portion = is.readUnsignedByte(); - len |= (portion & 0x7F) << 7; - if ((portion & 0x80) != 0) { - portion = is.readUnsignedByte(); - len |= (portion & 0xFF) << 14; - } - } - return len; - } - -} diff --git a/java/src/com/tightvnc/rfbplayer/RfbSharedStatic.java b/java/src/com/tightvnc/rfbplayer/RfbSharedStatic.java deleted file mode 100644 index 7cf9cf1d..00000000 --- a/java/src/com/tightvnc/rfbplayer/RfbSharedStatic.java +++ /dev/null @@ -1,9 +0,0 @@ - -package com.tightvnc.rfbplayer; - -import java.applet.*; - -public class RfbSharedStatic { - - public static Applet refApplet; -} diff --git a/java/src/com/tightvnc/rfbplayer/VncCanvas.java b/java/src/com/tightvnc/rfbplayer/VncCanvas.java deleted file mode 100644 index 7bb8d296..00000000 --- a/java/src/com/tightvnc/rfbplayer/VncCanvas.java +++ /dev/null @@ -1,1336 +0,0 @@ -// -// Copyright (C) 2004 Horizon Wimba. All Rights Reserved. -// Copyright (C) 2001-2003 HorizonLive.com, Inc. All Rights Reserved. -// Copyright (C) 2001 Constantin Kaplinsky. All Rights Reserved. -// Copyright (C) 2000 Tridia Corporation. All Rights Reserved. -// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. -// -// This 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 of the License, or -// (at your option) any later version. -// -// This software 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 this software; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -// USA. -// - -package com.tightvnc.rfbplayer; - -import java.awt.*; -import java.awt.image.*; -import java.io.*; -import java.util.*; -import java.util.zip.*; - - -// -// VncCanvas is a subclass of Canvas which draws a VNC desktop on it. -// -class VncCanvas extends Component - implements Observer { - - RfbPlayer appClass; - RfbProto rfb; - ColorModel cm8, cm24; - int bytesPixel; - - Image memImage; - Graphics memGraphics; - - Image offImage; - Graphics offGraphics; - - Image rawPixelsImage; - MemoryImageSource pixelsSource; - byte[] pixels8; - int[] pixels24; - - // Zlib encoder's data. - byte[] zlibBuf; - int zlibBufLen = 0; - Inflater zlibInflater; - - // Tight encoder's data. - final static int tightZlibBufferSize = 512; - Inflater[] tightInflaters; - - // Since JPEG images are loaded asynchronously, we have to remember - // their position in the framebuffer. Also, this jpegRect object is - // used for synchronization between the rfbThread and a JVM's thread - // which decodes and loads JPEG images. - Rectangle jpegRect; - - // When we're in the seeking mode, we should not update the desktop. - // This variable helps us to remember that repainting the desktop at - // once is necessary when the seek operation is finished. - boolean seekMode; - - // Distance of mouse from viewer border to trigger automatic scrolling - final static int SCROLL_MARGIN = 50; - - // Color for border around small shared area - static final Color DARK_GRAY = new Color(132, 138, 156); - - // - // The constructor. - // - VncCanvas(RfbPlayer player) throws IOException { - this.appClass = player; - rfb = appClass.rfb; - seekMode = false; - - cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF); - - setPixelFormat(); - - // Style canvas. - setBackground(Color.white); - - } - - // - // Override the 1.4 focus traversal keys accesor to allow - // our keyListener to receive tab presses. - // - public boolean getFocusTraversalKeysEnabled() { - return false; - } - - // - // Callback methods to determine geometry of our Component. - // - public Dimension getPreferredSize() { - Dimension d = appClass.desktopScrollPane.getViewportSize(); - Dimension sz = new Dimension(rfb.framebufferWidth, rfb.framebufferHeight); - if (d.width > sz.width) - sz.width = d.width; - if (d.height > sz.height) - sz.height = d.height; - return sz; - } - - public Dimension getMinimumSize() { - return getPreferredSize(); - } - - public Dimension getMaximumSize() { - return getPreferredSize(); - } - - Point getImageOrigin() { - int x = 0, y = 0; - Dimension d = appClass.desktopScrollPane.getViewportSize(); - if (rfb.framebufferWidth < d.width) - x = d.width / 2 - rfb.framebufferWidth / 2; - if (rfb.framebufferHeight < d.height) - y = d.height / 2 - rfb.framebufferHeight / 2; - return new Point(x, y); - } - - // - // All painting is performed here. - // - public void update(Graphics g) { - paint(g); - } - - public void paint(Graphics g) { - Point o = getImageOrigin(); - Dimension d = getPreferredSize(); - - // create new offscreen - if (offImage == null) { - offImage = createImage(d.width, d.height); - offGraphics = offImage.getGraphics(); - } else if (offImage.getWidth(null) != d.width || - offImage.getHeight(null) != d.height) { - offGraphics.dispose(); - offGraphics = null; - offImage.flush(); - offImage = null; - offImage = createImage(d.width, d.height); - offGraphics = offImage.getGraphics(); - } - - synchronized(memImage) { - offGraphics.drawImage(memImage, o.x, o.y, null); - } - - // fill in background - if (o.x > 0 || o.y > 0) { - // left, right, top, bottom - Color c = g.getColor(); - offGraphics.setColor(Color.white); - offGraphics.fillRect(0, 0, o.x, d.height); - offGraphics.fillRect(o.x + rfb.framebufferWidth, 0, d.width - (o.x + - rfb.framebufferWidth), d.height); - offGraphics.fillRect(o.x, 0, rfb.framebufferWidth, o.y); - offGraphics.fillRect(o.x, o.y + rfb.framebufferHeight, - rfb.framebufferWidth, d.height - (o.y + - rfb.framebufferHeight)); - offGraphics.setColor(c); - } - - // draw border - Color oc = g.getColor(); - offGraphics.setColor(DARK_GRAY); - offGraphics.drawRect(o.x - 1, o.y - 1, rfb.framebufferWidth + 1, - rfb.framebufferHeight + 1); - offGraphics.setColor(oc); - - // draw cursor - if (showSoftCursor) { - int x0 = cursorX - hotX, y0 = cursorY - hotY; - x0 += o.x; - y0 += o.y; - Rectangle r = new Rectangle(x0, y0, cursorWidth, cursorHeight); - if (r.intersects(g.getClipBounds())) { - offGraphics.setClip(o.x, o.y, rfb.framebufferWidth, - rfb.framebufferHeight); - offGraphics.drawImage(softCursor, x0, y0, null); - offGraphics.setClip(null); - } - } - - // draw offscreen - g.drawImage(offImage, 0, 0, null); - } - - // - // Override the ImageObserver interface method to handle drawing of - // JPEG-encoded data. - // - public boolean imageUpdate(Image img, int infoflags, - int x, int y, int width, int height) { - if ((infoflags & (ALLBITS | ABORT)) == 0) { - return true; // We need more image data. - } else { - // If the whole image is available, draw it now. - if ((infoflags & ALLBITS) != 0) { - if (jpegRect != null) { - synchronized(jpegRect) { - memGraphics.drawImage(img, jpegRect.x, jpegRect.y, null); - scheduleRepaint(jpegRect.x, jpegRect.y, - jpegRect.width, jpegRect.height); - jpegRect.notify(); - } - } - } - return false; // All image data was processed. - } - } - - private void setPixelFormat() throws IOException { - bytesPixel = 4; - updateFramebufferSize(); - } - - void updateFramebufferSize() { - - // Useful shortcuts. - int fbWidth = rfb.framebufferWidth; - int fbHeight = rfb.framebufferHeight; - - // Create new off-screen image either if it does not exist, or if - // its geometry should be changed. It's not necessary to replace - // existing image if only pixel format should be changed. - if (memImage == null) { - memImage = appClass.createImage(fbWidth, fbHeight); - memGraphics = memImage.getGraphics(); - } else if (memImage.getWidth(null) != fbWidth || - memImage.getHeight(null) != fbHeight) { - synchronized(memImage) { - memImage = appClass.createImage(fbWidth, fbHeight); - memGraphics = memImage.getGraphics(); - } - } - - // Images with raw pixels should be re-allocated on every change - // of geometry or pixel format. - if (bytesPixel == 1) { - pixels24 = null; - pixels8 = new byte[fbWidth * fbHeight]; - - pixelsSource = - new MemoryImageSource(fbWidth, fbHeight, cm8, pixels8, 0, fbWidth); - } else { - pixels8 = null; - pixels24 = new int[fbWidth * fbHeight]; - - pixelsSource = - new MemoryImageSource(fbWidth, fbHeight, cm24, pixels24, 0, fbWidth); - } - pixelsSource.setAnimated(true); - rawPixelsImage = createImage(pixelsSource); - - // Update the size of desktop containers unless seeking - if (!seekMode && appClass.desktopScrollPane != null) { - if (appClass.inSeparateFrame) { - resizeDesktopFrame(); - } else { - resizeEmbeddedApplet(); - // if the framebuffer shrunk, need to clear and repaint - appClass.desktopScrollPane.clearAndRepaint(); - } - } - } - - void resizeDesktopFrame() { - // determine screen size - Dimension screenSize = appClass.vncFrame.getToolkit().getScreenSize(); - Dimension scrollSize = appClass.desktopScrollPane.getSize(); - - // Reduce Screen Size by 30 pixels in each direction; - // This is a (poor) attempt to account for - // 1) Menu bar on Macintosh (should really also account for - // Dock on OSX). Usually 22px on top of screen. - // 2) Taxkbar on Windows (usually about 28 px on bottom) - // 3) Other obstructions. - screenSize.height -= 30; - screenSize.width -= 30; - - // Further reduce the screen size to account for the - // scroll pane's insets. - Insets insets = appClass.desktopScrollPane.getInsets(); - screenSize.height -= insets.top + insets.bottom; - screenSize.width -= insets.left + insets.right; - - // Limit pane size to fit on screen. - boolean needResize = false; - if (scrollSize.width != rfb.framebufferWidth || - scrollSize.height != rfb.framebufferHeight) - needResize = true; - int w = rfb.framebufferWidth, h = rfb.framebufferHeight; - if (w > screenSize.width) { - w = screenSize.width; - needResize = true; - } - if (h > screenSize.height) { - h = screenSize.height; - needResize = true; - } - if (needResize) { - appClass.desktopScrollPane.setSize(w, h); - appClass.desktopScrollPane.validate(); - } - - // size the canvas - setSize(getPreferredSize()); - - appClass.vncFrame.pack(); - } - - void resizeEmbeddedApplet() { - // resize scroll pane if necessary - Dimension scrollSize = appClass.desktopScrollPane.getSize(); - if (scrollSize.width != appClass.dispW || - scrollSize.height != appClass.dispH) { - appClass.desktopScrollPane.setSize(appClass.dispW, appClass.dispH); - } - appClass.desktopScrollPane.validate(); - // size the canvas - setSize(getPreferredSize()); - } - - // - // processNormalProtocol() - executed by the rfbThread to deal with - // the RFB data. - // - public void processNormalProtocol() throws Exception { - - zlibInflater = new Inflater(); - tightInflaters = new Inflater[4]; - - // Show current time position in the control panel. - appClass.updatePos(); - - // Tell our FbsInputStream object to notify us when it goes to the - // `paused' mode. - appClass.fbs.addObserver(this); - - // - // main dispatch loop - // - - while (true) { - - int msgType = rfb.readServerMessageType(); - - // Process the message depending on its type. - switch (msgType) { - case RfbProto.FramebufferUpdate: - rfb.readFramebufferUpdate(); - - for (int i = 0; i < rfb.updateNRects; i++) { - rfb.readFramebufferUpdateRectHdr(); - int rx = rfb.updateRectX, ry = rfb.updateRectY; - int rw = rfb.updateRectW, rh = rfb.updateRectH; - - if (rfb.updateRectEncoding == rfb.EncodingLastRect) - break; - - if (rfb.updateRectEncoding == rfb.EncodingNewFBSize) { - if (rw != 0 && rh != 0) { - rfb.setFramebufferSize(rw, rh); - updateFramebufferSize(); - } - break; - } - - if (rfb.updateRectEncoding == rfb.EncodingXCursor || - rfb.updateRectEncoding == rfb.EncodingRichCursor) { - handleCursorShapeUpdate(rfb.updateRectEncoding, rx, ry, rw, rh); - continue; - } - - if (rfb.updateRectEncoding == rfb.EncodingPointerPos) { - softCursorMove(rx, ry); - continue; - } - - switch (rfb.updateRectEncoding) { - case RfbProto.EncodingRaw: - handleRawRect(rx, ry, rw, rh); - break; - case RfbProto.EncodingCopyRect: - handleCopyRect(rx, ry, rw, rh); - break; - case RfbProto.EncodingRRE: - handleRRERect(rx, ry, rw, rh); - break; - case RfbProto.EncodingCoRRE: - handleCoRRERect(rx, ry, rw, rh); - break; - case RfbProto.EncodingHextile: - handleHextileRect(rx, ry, rw, rh); - break; - case RfbProto.EncodingZlib: - handleZlibRect(rx, ry, rw, rh); - break; - case RfbProto.EncodingTight: - handleTightRect(rx, ry, rw, rh); - break; - default: - throw new Exception("Unknown RFB rectangle encoding " + - Integer.toString(rfb.updateRectEncoding, 16)); - } - } - break; - - case RfbProto.SetColourMapEntries: - throw new Exception("Can't handle SetColourMapEntries message"); - - case RfbProto.Bell: - Toolkit.getDefaultToolkit().beep(); - break; - - case RfbProto.ServerCutText: - rfb.readServerCutText(); - break; - - default: - throw new Exception("Unknown RFB message type " + msgType); - } - - appClass.updatePos(); - } - } - - - // - // Handle a raw rectangle. The second form with paint==false is used - // by the Hextile decoder for raw-encoded tiles. - // - void handleRawRect(int x, int y, int w, int h) throws IOException { - handleRawRect(x, y, w, h, true); - } - - void handleRawRect(int x, int y, int w, int h, boolean paint) - throws IOException { - - if (bytesPixel == 1) { - for (int dy = y; dy < y + h; dy++) { - rfb.is.readFully(pixels8, dy * rfb.framebufferWidth + x, w); - //if (rfb.rec != null) { - // rfb.rec.write(pixels8, dy * rfb.framebufferWidth + x, w); - //} - } - } else { - byte[] buf = new byte[w * 4]; - int i, offset; - for (int dy = y; dy < y + h; dy++) { - rfb.is.readFully(buf); - //if (rfb.rec != null) { - // rfb.rec.write(buf); - //} - offset = dy * rfb.framebufferWidth + x; - for (i = 0; i < w; i++) { - pixels24[offset + i] = - (buf[i * 4 + 2] & 0xFF) << 16 | - (buf[i * 4 + 1] & 0xFF) << 8 | - (buf[i * 4] & 0xFF); - } - } - } - - handleUpdatedPixels(x, y, w, h); - if (paint) - scheduleRepaint(x, y, w, h); - } - - // - // Handle a CopyRect rectangle. - // - void handleCopyRect(int x, int y, int w, int h) throws IOException { - - rfb.readCopyRect(); - memGraphics.copyArea(rfb.copyRectSrcX, rfb.copyRectSrcY, w, h, - x - rfb.copyRectSrcX, y - rfb.copyRectSrcY); - - scheduleRepaint(x, y, w, h); - } - - // - // Handle an RRE-encoded rectangle. - // - void handleRRERect(int x, int y, int w, int h) throws IOException { - - int nSubrects = rfb.is.readInt(); - int sx, sy, sw, sh; - - byte[] buf = new byte[4]; - rfb.is.readFully(buf); - Color pixel = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF); - memGraphics.setColor(pixel); - memGraphics.fillRect(x, y, w, h); - - for (int j = 0; j < nSubrects; j++) { - rfb.is.readFully(buf); - pixel = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF); - sx = x + rfb.is.readUnsignedShort(); - sy = y + rfb.is.readUnsignedShort(); - sw = rfb.is.readUnsignedShort(); - sh = rfb.is.readUnsignedShort(); - - memGraphics.setColor(pixel); - memGraphics.fillRect(sx, sy, sw, sh); - } - - scheduleRepaint(x, y, w, h); - } - - // - // Handle a CoRRE-encoded rectangle. - // - void handleCoRRERect(int x, int y, int w, int h) throws IOException { - int nSubrects = rfb.is.readInt(); - int sx, sy, sw, sh; - - byte[] buf = new byte[4]; - rfb.is.readFully(buf); - Color pixel = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF); - memGraphics.setColor(pixel); - memGraphics.fillRect(x, y, w, h); - - for (int j = 0; j < nSubrects; j++) { - rfb.is.readFully(buf); - pixel = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF); - sx = x + rfb.is.readUnsignedByte(); - sy = y + rfb.is.readUnsignedByte(); - sw = rfb.is.readUnsignedByte(); - sh = rfb.is.readUnsignedByte(); - - memGraphics.setColor(pixel); - memGraphics.fillRect(sx, sy, sw, sh); - } - - scheduleRepaint(x, y, w, h); - } - - // - // Handle a Hextile-encoded rectangle. - // - - // These colors should be kept between handleHextileSubrect() calls. - private Color hextile_bg, hextile_fg; - - void handleHextileRect(int x, int y, int w, int h) throws IOException { - - hextile_bg = new Color(0); - hextile_fg = new Color(0); - - for (int ty = y; ty < y + h; ty += 16) { - int th = 16; - if (y + h - ty < 16) - th = y + h - ty; - - for (int tx = x; tx < x + w; tx += 16) { - int tw = 16; - if (x + w - tx < 16) - tw = x + w - tx; - - handleHextileSubrect(tx, ty, tw, th); - } - - // Finished with a row of tiles, now let's show it. - scheduleRepaint(x, y, w, h); - } - } - - // - // Handle one tile in the Hextile-encoded data. - // - void handleHextileSubrect(int tx, int ty, int tw, int th) - throws IOException { - - byte[] buf = new byte[256 * 4]; - - int subencoding = rfb.is.readUnsignedByte(); - - // Is it a raw-encoded sub-rectangle? - if ((subencoding & rfb.HextileRaw) != 0) { - int count, offset; - for (int j = ty; j < ty + th; j++) { - rfb.is.readFully(buf, 0, tw * 4); - offset = j * rfb.framebufferWidth + tx; - for (count = 0; count < tw; count++) { - pixels24[offset + count] = - (buf[count * 4 + 2] & 0xFF) << 16 | - (buf[count * 4 + 1] & 0xFF) << 8 | - (buf[count * 4] & 0xFF); - } - } - handleUpdatedPixels(tx, ty, tw, th); - return; - } - - // Read and draw the background if specified. - if ((subencoding & rfb.HextileBackgroundSpecified) != 0) { - rfb.is.readFully(buf, 0, 4); - hextile_bg = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF); - } - memGraphics.setColor(hextile_bg); - memGraphics.fillRect(tx, ty, tw, th); - - // Read the foreground color if specified. - if ((subencoding & rfb.HextileForegroundSpecified) != 0) { - rfb.is.readFully(buf, 0, 4); - hextile_fg = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF); - } - - // Done with this tile if there is no sub-rectangles. - if ((subencoding & rfb.HextileAnySubrects) == 0) - return; - - int nSubrects = rfb.is.readUnsignedByte(); - - int b1, b2, sx, sy, sw, sh; - if ((subencoding & rfb.HextileSubrectsColoured) != 0) { - for (int j = 0; j < nSubrects; j++) { - rfb.is.readFully(buf, 0, 4); - hextile_fg = new Color(buf[2] & 0xFF, buf[1] & 0xFF, buf[0] & 0xFF); - b1 = rfb.is.readUnsignedByte(); - b2 = rfb.is.readUnsignedByte(); - sx = tx + (b1 >> 4); - sy = ty + (b1 & 0xf); - sw = (b2 >> 4) + 1; - sh = (b2 & 0xf) + 1; - memGraphics.setColor(hextile_fg); - memGraphics.fillRect(sx, sy, sw, sh); - } - - } else { - memGraphics.setColor(hextile_fg); - for (int j = 0; j < nSubrects; j++) { - b1 = rfb.is.readUnsignedByte(); - b2 = rfb.is.readUnsignedByte(); - sx = tx + (b1 >> 4); - sy = ty + (b1 & 0xf); - sw = (b2 >> 4) + 1; - sh = (b2 & 0xf) + 1; - memGraphics.fillRect(sx, sy, sw, sh); - } - - } - } - - // - // Handle a Zlib-encoded rectangle. - // - void handleZlibRect(int x, int y, int w, int h) throws Exception { - - int nBytes = rfb.is.readInt(); - - if (zlibBuf == null || zlibBufLen < nBytes) { - zlibBufLen = nBytes * 2; - zlibBuf = new byte[zlibBufLen]; - } - - rfb.is.readFully(zlibBuf, 0, nBytes); - zlibInflater.setInput(zlibBuf, 0, nBytes); - - try { - byte[] buf = new byte[w * 4]; - int i, offset; - for (int dy = y; dy < y + h; dy++) { - zlibInflater.inflate(buf); - offset = dy * rfb.framebufferWidth + x; - for (i = 0; i < w; i++) { - pixels24[offset + i] = - (buf[i * 4 + 2] & 0xFF) << 16 | - (buf[i * 4 + 1] & 0xFF) << 8 | - (buf[i * 4] & 0xFF); - } - } - } catch (DataFormatException dfe) { - throw new Exception(dfe.toString()); - } - - handleUpdatedPixels(x, y, w, h); - scheduleRepaint(x, y, w, h); - } - - // - // Handle a Tight-encoded rectangle. - // - void handleTightRect(int x, int y, int w, int h) throws Exception { - - int comp_ctl = rfb.is.readUnsignedByte(); - - // Flush zlib streams if we are told by the server to do so. - for (int stream_id = 0; stream_id < 4; stream_id++) { - if ((comp_ctl & 1) != 0 && tightInflaters[stream_id] != null) { - tightInflaters[stream_id] = null; - } - comp_ctl >>= 1; - } - - // Check correctness of subencoding value. - if (comp_ctl > rfb.TightMaxSubencoding) { - throw new Exception("Incorrect tight subencoding: " + comp_ctl); - } - - // Handle solid-color rectangles. - if (comp_ctl == rfb.TightFill) { - byte[] buf = new byte[3]; - rfb.is.readFully(buf); - Color bg = new Color(buf[0] & 0xFF, buf[1] & 0xFF, buf[2] & 0xFF); - memGraphics.setColor(bg); - memGraphics.fillRect(x, y, w, h); - scheduleRepaint(x, y, w, h); - return; - - } - - if (comp_ctl == rfb.TightJpeg) { - - // Read JPEG data. - byte[] jpegData = new byte[rfb.readCompactLen()]; - rfb.is.readFully(jpegData); - - // Create an Image object from the JPEG data. - Image jpegImage = Toolkit.getDefaultToolkit().createImage(jpegData); - - // Remember the rectangle where the image should be drawn. - jpegRect = new Rectangle(x, y, w, h); - - // Let the imageUpdate() method do the actual drawing, here just - // wait until the image is fully loaded and drawn. - synchronized(jpegRect) { - Toolkit.getDefaultToolkit().prepareImage(jpegImage, -1, -1, this); - try { - // Wait no longer than three seconds. - jpegRect.wait(3000); - } catch (InterruptedException e) { - throw new Exception("Interrupted while decoding JPEG image"); - } - } - - // Done, jpegRect is not needed any more. - jpegRect = null; - return; - - } - - // Read filter id and parameters. - int numColors = 0, rowSize = w; - int[] palette24 = new int[256]; - boolean useGradient = false; - if ((comp_ctl & rfb.TightExplicitFilter) != 0) { - int filter_id = rfb.is.readUnsignedByte(); - if (filter_id == rfb.TightFilterPalette) { - numColors = rfb.is.readUnsignedByte() + 1; - byte[] buf = new byte[numColors * 3]; - rfb.is.readFully(buf); - for (int i = 0; i < numColors; i++) { - palette24[i] = ((buf[i * 3] & 0xFF) << 16 | - (buf[i * 3 + 1] & 0xFF) << 8 | - (buf[i * 3 + 2] & 0xFF)); - } - if (numColors == 2) - rowSize = (w + 7) / 8; - } else if (filter_id == rfb.TightFilterGradient) { - useGradient = true; - } else if (filter_id != rfb.TightFilterCopy) { - throw new Exception("Incorrect tight filter id: " + filter_id); - } - } - if (numColors == 0 && bytesPixel == 4) - rowSize *= 3; - - // Read, optionally uncompress and decode data. - int dataSize = h * rowSize; - if (dataSize < rfb.TightMinToCompress) { - // Data size is small - not compressed with zlib. - if (numColors != 0) { - // Indexed colors. - byte[] indexedData = new byte[dataSize]; - rfb.is.readFully(indexedData); - if (numColors == 2) { - // Two colors. - //if (bytesPixel == 1) { - // decodeMonoData(x, y, w, h, indexedData, palette8); - //} else { - decodeMonoData(x, y, w, h, indexedData, palette24); - //} - } else { - // 3..255 colors (assuming bytesPixel == 4). - int i = 0; - for (int dy = y; dy < y + h; dy++) { - for (int dx = x; dx < x + w; dx++) { - pixels24[dy * rfb.framebufferWidth + dx] = - palette24[indexedData[i++] & 0xFF]; - } - } - } - } else if (useGradient) { - // "Gradient"-processed data - byte[] buf = new byte[w * h * 3]; - rfb.is.readFully(buf); - decodeGradientData(x, y, w, h, buf); - } else { - // Raw truecolor data. - if (bytesPixel == 1) { - for (int dy = y; dy < y + h; dy++) { - rfb.is.readFully(pixels8, dy * rfb.framebufferWidth + x, w); - //if (rfb.rec != null) { - // rfb.rec.write(pixels8, dy * rfb.framebufferWidth + x, w); - //} - } - } else { - byte[] buf = new byte[w * 3]; - int i, offset; - for (int dy = y; dy < y + h; dy++) { - rfb.is.readFully(buf); - //if (rfb.rec != null) { - // rfb.rec.write(buf); - //} - offset = dy * rfb.framebufferWidth + x; - for (i = 0; i < w; i++) { - pixels24[offset + i] = - (buf[i * 3] & 0xFF) << 16 | - (buf[i * 3 + 1] & 0xFF) << 8 | - (buf[i * 3 + 2] & 0xFF); - } - } - } - } - } else { - // Data was compressed with zlib. - int zlibDataLen = rfb.readCompactLen(); - byte[] zlibData = new byte[zlibDataLen]; - rfb.is.readFully(zlibData); - int stream_id = comp_ctl & 0x03; - if (tightInflaters[stream_id] == null) { - tightInflaters[stream_id] = new Inflater(); - } - Inflater myInflater = tightInflaters[stream_id]; - myInflater.setInput(zlibData); - try { - if (numColors != 0) { - // Indexed colors. - byte[] indexedData = new byte[dataSize]; - myInflater.inflate(indexedData); - if (numColors == 2) { - // Two colors. - decodeMonoData(x, y, w, h, indexedData, palette24); - } else { - // More than two colors. - int i = 0; - for (int dy = y; dy < y + h; dy++) { - for (int dx = x; dx < x + w; dx++) { - pixels24[dy * rfb.framebufferWidth + dx] = - palette24[indexedData[i++] & 0xFF]; - } - } - } - } else if (useGradient) { - // Compressed "Gradient"-filtered data. - byte[] buf = new byte[w * h * 3]; - myInflater.inflate(buf); - decodeGradientData(x, y, w, h, buf); - } else { - // Compressed truecolor data. - byte[] buf = new byte[w * 3]; - int i, offset; - for (int dy = y; dy < y + h; dy++) { - myInflater.inflate(buf); - offset = dy * rfb.framebufferWidth + x; - for (i = 0; i < w; i++) { - pixels24[offset + i] = - (buf[i * 3] & 0xFF) << 16 | - (buf[i * 3 + 1] & 0xFF) << 8 | - (buf[i * 3 + 2] & 0xFF); - } - } - } - } catch (DataFormatException dfe) { - throw new Exception(dfe.toString()); - } - } - - handleUpdatedPixels(x, y, w, h); - scheduleRepaint(x, y, w, h); - } - - // - // Decode 1bpp-encoded bi-color rectangle (8-bit and 24-bit versions). - // - void decodeMonoData(int x, int y, int w, int h, byte[] src, byte[] palette) { - - int dx, dy, n; - int i = y * rfb.framebufferWidth + x; - int rowBytes = (w + 7) / 8; - byte b; - - for (dy = 0; dy < h; dy++) { - for (dx = 0; dx < w / 8; dx++) { - b = src[dy * rowBytes + dx]; - for (n = 7; n >= 0; n--) - pixels8[i++] = palette[b >> n & 1]; - } - for (n = 7; n >= 8 - w % 8; n--) { - pixels8[i++] = palette[src[dy * rowBytes + dx] >> n & 1]; - } - i += (rfb.framebufferWidth - w); - } - } - - void decodeMonoData(int x, int y, int w, int h, byte[] src, int[] palette) { - - int dx, dy, n; - int i = y * rfb.framebufferWidth + x; - int rowBytes = (w + 7) / 8; - byte b; - - for (dy = 0; dy < h; dy++) { - for (dx = 0; dx < w / 8; dx++) { - b = src[dy * rowBytes + dx]; - for (n = 7; n >= 0; n--) - pixels24[i++] = palette[b >> n & 1]; - } - for (n = 7; n >= 8 - w % 8; n--) { - pixels24[i++] = palette[src[dy * rowBytes + dx] >> n & 1]; - } - i += (rfb.framebufferWidth - w); - } - } - - // - // Decode data processed with the "Gradient" filter. - // - void decodeGradientData(int x, int y, int w, int h, byte[] buf) { - - int dx, dy, c; - byte[] prevRow = new byte[w * 3]; - byte[] thisRow = new byte[w * 3]; - byte[] pix = new byte[3]; - int[] est = new int[3]; - - int offset = y * rfb.framebufferWidth + x; - - for (dy = 0; dy < h; dy++) { - - /* First pixel in a row */ - for (c = 0; c < 3; c++) { - pix[c] = (byte)(prevRow[c] + buf[dy * w * 3 + c]); - thisRow[c] = pix[c]; - } - pixels24[offset++] = - (pix[0] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[2] & 0xFF); - - /* Remaining pixels of a row */ - for (dx = 1; dx < w; dx++) { - for (c = 0; c < 3; c++) { - est[c] = ((prevRow[dx * 3 + c] & 0xFF) + (pix[c] & 0xFF) - - (prevRow[(dx - 1) * 3 + c] & 0xFF)); - if (est[c] > 0xFF) { - est[c] = 0xFF; - } else if (est[c] < 0x00) { - est[c] = 0x00; - } - pix[c] = (byte)(est[c] + buf[(dy * w + dx) * 3 + c]); - thisRow[dx * 3 + c] = pix[c]; - } - pixels24[offset++] = - (pix[0] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[2] & 0xFF); - } - - System.arraycopy(thisRow, 0, prevRow, 0, w * 3); - offset += (rfb.framebufferWidth - w); - } - } - - // - // Display newly updated area of pixels. - // - void handleUpdatedPixels(int x, int y, int w, int h) { - - // Draw updated pixels of the off-screen image. - pixelsSource.newPixels(x, y, w, h); - memGraphics.setClip(x, y, w, h); - memGraphics.drawImage(rawPixelsImage, 0, 0, null); - memGraphics.setClip(0, 0, rfb.framebufferWidth, rfb.framebufferHeight); - } - - // - // Tell JVM to repaint specified desktop area. - // - void scheduleRepaint(int x, int y, int w, int h) { - if (appClass.fbs.isSeeking()) { - // Do nothing, and remember we are seeking. - seekMode = true; - } else { - if (seekMode) { - // Immediate repaint of the whole desktop after seeking. - seekMode = false; - if (showSoftCursor) - scrollToPoint(cursorX, cursorY); - updateFramebufferSize(); - repaint(); - } else { - // Usual incremental repaint. - Point o = getImageOrigin(); - repaint(appClass.deferScreenUpdates, o.x + x, o.y + y, w, h); - } - } - } - - - ////////////////////////////////////////////////////////////////// - // - // Handle cursor shape updates (XCursor and RichCursor encodings). - // - boolean showSoftCursor = false; - - MemoryImageSource softCursorSource; - Image softCursor; - - int cursorX = 0, cursorY = 0; - int cursorWidth, cursorHeight; - int origCursorWidth, origCursorHeight; - int hotX, hotY; - int origHotX, origHotY; - - // - // Handle cursor shape update (XCursor and RichCursor encodings). - // - synchronized void handleCursorShapeUpdate(int encodingType, - int xhot, int yhot, int width, - int height) - throws IOException { - - softCursorFree(); - - if (width * height == 0) - return; - - // Ignore cursor shape data if requested by user. - //if (appClass.options.ignoreCursorUpdates) { - if (false) { - int bytesPerRow = (width + 7) / 8; - int bytesMaskData = bytesPerRow * height; - - if (encodingType == rfb.EncodingXCursor) { - rfb.is.skipBytes(6 + bytesMaskData * 2); - } else { - // rfb.EncodingRichCursor - rfb.is.skipBytes(width * height + bytesMaskData); - } - return; - } - - // Decode cursor pixel data. - softCursorSource = decodeCursorShape(encodingType, width, height); - - // Set original (non-scaled) cursor dimensions. - origCursorWidth = width; - origCursorHeight = height; - origHotX = xhot; - origHotY = yhot; - - // Create off-screen cursor image. - createSoftCursor(); - - // Show the cursor. - showSoftCursor = true; - Point p = getImageOrigin(); - scheduleCursorRepaint(cursorX - hotX + p.x, cursorY - hotY + p.y, - cursorWidth, cursorHeight, 5); - } - - // - // decodeCursorShape(). Decode cursor pixel data and return - // corresponding MemoryImageSource instance. - // - synchronized MemoryImageSource decodeCursorShape(int encodingType, int width, - int height) - throws IOException { - - int bytesPerRow = (width + 7) / 8; - int bytesMaskData = bytesPerRow * height; - - int[] softCursorPixels = new int[width * height]; - - if (encodingType == rfb.EncodingXCursor) { - - // Read foreground and background colors of the cursor. - byte[] rgb = new byte[6]; - rfb.is.readFully(rgb); - int[] colors = {(0xFF000000 | (rgb[3] & 0xFF) << 16 | - (rgb[4] & 0xFF) << 8 | (rgb[5] & 0xFF)), - (0xFF000000 | (rgb[0] & 0xFF) << 16 | - (rgb[1] & 0xFF) << 8 | (rgb[2] & 0xFF)) - }; - - // Read pixel and mask data. - byte[] pixBuf = new byte[bytesMaskData]; - rfb.is.readFully(pixBuf); - byte[] maskBuf = new byte[bytesMaskData]; - rfb.is.readFully(maskBuf); - - // Decode pixel data into softCursorPixels[]. - byte pixByte, maskByte; - int x, y, n, result; - int i = 0; - for (y = 0; y < height; y++) { - for (x = 0; x < width / 8; x++) { - pixByte = pixBuf[y * bytesPerRow + x]; - maskByte = maskBuf[y * bytesPerRow + x]; - for (n = 7; n >= 0; n--) { - if ((maskByte >> n & 1) != 0) { - result = colors[pixByte >> n & 1]; - } else { - result = 0; // Transparent pixel - } - softCursorPixels[i++] = result; - } - } - for (n = 7; n >= 8 - width % 8; n--) { - if ((maskBuf[y * bytesPerRow + x] >> n & 1) != 0) { - result = colors[pixBuf[y * bytesPerRow + x] >> n & 1]; - } else { - result = 0; // Transparent pixel - } - softCursorPixels[i++] = result; - } - } - - } else { - // encodingType == rfb.EncodingRichCursor - - // Read pixel and mask data. - byte[] pixBuf = new byte[width * height * bytesPixel]; - rfb.is.readFully(pixBuf); - byte[] maskBuf = new byte[bytesMaskData]; - rfb.is.readFully(maskBuf); - - // Decode pixel data into softCursorPixels[]. - byte maskByte; - int x, y, n, result; - int i = 0; - for (y = 0; y < height; y++) { - for (x = 0; x < width / 8; x++) { - maskByte = maskBuf[y * bytesPerRow + x]; - for (n = 7; n >= 0; n--) { - if ((maskByte >> n & 1) != 0) { - if (bytesPixel == 1) { - result = cm8.getRGB(pixBuf[i]); - } else { - result = (pixBuf[i * 4] & 0xFF) << 24 | - (pixBuf[i * 4 + 1] & 0xFF) << 16 | - (pixBuf[i * 4 + 2] & 0xFF) << 8 | - (pixBuf[i * 4 + 3] & 0xFF); - } - } else { - result = 0; // Transparent pixel - } - softCursorPixels[i++] = result; - } - } - for (n = 7; n >= 8 - width % 8; n--) { - if ((maskBuf[y * bytesPerRow + x] >> n & 1) != 0) { - if (bytesPixel == 1) { - result = cm8.getRGB(pixBuf[i]); - } else { - result = 0xFF000000 | - (pixBuf[i * 4 + 1] & 0xFF) << 16 | - (pixBuf[i * 4 + 2] & 0xFF) << 8 | - (pixBuf[i * 4 + 3] & 0xFF); - } - } else { - result = 0; // Transparent pixel - } - softCursorPixels[i++] = result; - } - } - - } - - return new MemoryImageSource(width, height, softCursorPixels, 0, width); - } - - // - // createSoftCursor(). Assign softCursor new Image (scaled if necessary). - // Uses softCursorSource as a source for new cursor image. - // - synchronized void createSoftCursor() { - - if (softCursorSource == null) - return; - - int scaleCursor = 100; - //int scaleCursor = appClass.options.scaleCursor; - //if (scaleCursor == 0 || !inputEnabled) - //scaleCursor = 100; - - cursorWidth = (origCursorWidth * scaleCursor + 50) / 100; - cursorHeight = (origCursorHeight * scaleCursor + 50) / 100; - hotX = (origHotX * scaleCursor + 50) / 100; - hotY = (origHotY * scaleCursor + 50) / 100; - softCursor = Toolkit.getDefaultToolkit().createImage(softCursorSource); - - if (scaleCursor != 100) { - softCursor = softCursor.getScaledInstance(cursorWidth, cursorHeight, - Image.SCALE_SMOOTH); - } - } - - private void scrollToPoint(int x, int y) { - // Automatic viewport scrolling - if (appClass.desktopScrollPane != null) { - boolean needScroll = false; - Dimension d = appClass.desktopScrollPane.getViewportSize(); - Point topLeft = appClass.desktopScrollPane.getScrollPosition(); - Point botRight = new Point(topLeft.x + d.width, topLeft.y + d.height); - - if (x < topLeft.x + SCROLL_MARGIN) { - // shift left - topLeft.x = x - SCROLL_MARGIN; - needScroll = true; - } else if (x > botRight.x - SCROLL_MARGIN) { - // shift right - topLeft.x = x - d.width + SCROLL_MARGIN; - needScroll = true; - } - if (y < topLeft.y + SCROLL_MARGIN) { - // shift up - topLeft.y = y - SCROLL_MARGIN; - needScroll = true; - } else if (y > botRight.y - SCROLL_MARGIN) { - // shift down - topLeft.y = y - d.height + SCROLL_MARGIN; - needScroll = true; - } - if (needScroll) - appClass.desktopScrollPane.setScrollPosition(topLeft.x, topLeft.y); - } - } - - // - // softCursorMove(). Moves soft cursor into a particular location. - // - synchronized void softCursorMove(int x, int y) { - Point o = getImageOrigin(); - int oldX = cursorX + o.x; - int oldY = cursorY + o.y; - cursorX = x; - cursorY = y; - if (showSoftCursor) { - scheduleCursorRepaint(oldX - hotX, oldY - hotY, cursorWidth, cursorHeight, - 0); - scheduleCursorRepaint(cursorX - hotX + o.x, cursorY - hotY + o.y, - cursorWidth, cursorHeight, 1); - if (!seekMode) - scrollToPoint(x, y); - } - } - - // - // softCursorFree(). Remove soft cursor, dispose resources. - // - synchronized void softCursorFree() { - if (showSoftCursor) { - showSoftCursor = false; - softCursor = null; - softCursorSource = null; - - Point p = getImageOrigin(); - scheduleCursorRepaint(cursorX - hotX + p.x, cursorY - hotY + p.y, - cursorWidth, cursorHeight, 3); - } - } - - Point getFrameCenter() { - Dimension d = appClass.desktopScrollPane.getViewportSize(); - Point p = appClass.desktopScrollPane.getScrollPosition(); - if (d.width > rfb.framebufferWidth) - p.x = d.width / 2; - else - p.x += d.width / 2; - if (d.height > rfb.framebufferHeight) - p.y = d.height / 2; - else - p.y += d.height / 2; - return p; - } - - // - // We are observing our FbsInputStream object to get notified on - // switching to the `paused' mode. In such cases we want to repaint - // our desktop if we were seeking. - // - public void update(Observable o, Object arg) { - // Immediate repaint of the whole desktop after seeking. - repaint(); - // Let next scheduleRepaint() call invoke incremental drawing. - seekMode = false; - } - - void scheduleCursorRepaint(int x, int y, int w, int h, int n) { - if (appClass.fbs.isSeeking()) { - // Do nothing, and remember we are seeking. - seekMode = true; - } else { - if (seekMode) { - // Immediate repaint of the whole desktop after seeking. - seekMode = false; - if (showSoftCursor) - scrollToPoint(cursorX, cursorY); - updateFramebufferSize(); - repaint(); - } else { - // Usual incremental repaint. - repaint(appClass.deferScreenUpdates, x, y, w, h); - } - } - } - -} diff --git a/java/src/com/tightvnc/rfbplayer/index.html b/java/src/com/tightvnc/rfbplayer/index.html deleted file mode 100644 index 303bc5d2..00000000 --- a/java/src/com/tightvnc/rfbplayer/index.html +++ /dev/null @@ -1,9 +0,0 @@ - -RFB Session Playback - - - - - - -- 2.39.5