Changes in architecture to support pausing in the FbsInputStream
instead of using VncCanvas for that. RfbPlayer does not need to
remember current state any more. Play/Stop button removed. Added a
field to set playback speed, non-working yet.


git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@2509 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/java/src/com/tightvnc/rfbplayer/ButtonPanel.java b/java/src/com/tightvnc/rfbplayer/ButtonPanel.java
index 1a9db17..cbfffc9 100644
--- a/java/src/com/tightvnc/rfbplayer/ButtonPanel.java
+++ b/java/src/com/tightvnc/rfbplayer/ButtonPanel.java
@@ -25,8 +25,8 @@
 
   protected RfbPlayer player;
   protected Button playButton;
-  protected Button pauseButton;
   protected TextField posText;
+  protected TextField timeScaleText;
 
   protected int lastPos = -1;
 
@@ -40,42 +40,31 @@
     add(playButton);
     playButton.addActionListener(this);
 
-    pauseButton = new Button("Pause");
-    pauseButton.setEnabled(false);
-    add(pauseButton);
-    pauseButton.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("1.0");
+    timeScaleText.setEnabled(false);
+    timeScaleText.setEditable(false);
+    add(timeScaleText);
+    timeScaleText.addActionListener(this);
   }
 
-  public void setMode(int mode) {
-    switch(mode) {
-    case RfbPlayer.MODE_PLAYBACK:
-      playButton.setLabel("Stop");
-      playButton.setEnabled(true);
-      pauseButton.setLabel("Pause");
-      pauseButton.setEnabled(true);
-      posText.setEditable(false);
-      break;
-    case RfbPlayer.MODE_PAUSED:
-      playButton.setLabel("Stop");
-      playButton.setEnabled(true);
-      pauseButton.setLabel("Resume");
-      pauseButton.setEnabled(true);
-      posText.setEditable(true);
-      break;
-    default:
-      // case RfbPlayer.MODE_STOPPED:
+  public void setPaused(boolean paused)
+  {
+    if (paused) {
       playButton.setLabel("Play");
-      playButton.setEnabled(true);
-      pauseButton.setLabel("Pause");
-      pauseButton.setEnabled(false);
       posText.setEditable(true);
-      break;
+    } else {
+      playButton.setLabel("Pause");
+      posText.setEditable(false);
     }
-    player.setMode(mode);
+    playButton.setEnabled(true);
+    player.setPaused(paused);
   }
 
   public void setPos(int pos) {
@@ -97,11 +86,7 @@
 
   public void actionPerformed(ActionEvent evt) {
     if (evt.getSource() == playButton) {
-      setMode((player.getMode() == RfbPlayer.MODE_STOPPED) ?
-              RfbPlayer.MODE_PLAYBACK : RfbPlayer.MODE_STOPPED);
-    } else if (evt.getSource() == pauseButton) {
-      setMode((player.getMode() == RfbPlayer.MODE_PAUSED) ?
-              RfbPlayer.MODE_PLAYBACK : RfbPlayer.MODE_PAUSED);
+      setPaused(playButton.getLabel().equals("Pause"));
     } else if (evt.getSource() == posText) {
       player.setPos(Integer.parseInt(posText.getText()));
     }
diff --git a/java/src/com/tightvnc/rfbplayer/FbsInputStream.java b/java/src/com/tightvnc/rfbplayer/FbsInputStream.java
index 30ee42b..48c5b41 100644
--- a/java/src/com/tightvnc/rfbplayer/FbsInputStream.java
+++ b/java/src/com/tightvnc/rfbplayer/FbsInputStream.java
@@ -27,6 +27,7 @@
 
   protected InputStream in;
   protected long startTime;
+  protected long pausedTime;
   protected long timeOffset;
 
   protected byte[] buffer;
@@ -41,10 +42,15 @@
     throw new IOException("FbsInputStream: no such constructor");
   }
 
+  //
+  // Construct FbsInputStream object, begin playback.
+  //
+
   FbsInputStream(InputStream in) throws IOException
   {
     this.in = in;
     startTime = System.currentTimeMillis();
+    pausedTime = -1;
     timeOffset = 0;
 
     byte[] b = new byte[12];
@@ -85,11 +91,12 @@
     return bufferSize;
   }
 
-  public void close() throws IOException
+  public synchronized void close() throws IOException
   {
     in.close();
     in = null;
-    startTime = 0;
+    startTime = -1;
+    pausedTime = -1;
     timeOffset = 0;
 
     buffer = null;
@@ -101,12 +108,12 @@
   // Methods providing additional functionality.
   //
 
-  public int getPos()
+  public long getTimeOffset()
   {
-    return (int)(timeOffset / 1000);
+    return timeOffset;
   }
 
-  public void setPos(int pos)
+  public void setTimeOffset(int pos)
   {
   }
 
@@ -115,13 +122,18 @@
     return false;
   }
 
-  public void pausePlayback()
+  public synchronized void pausePlayback()
   {
+    // FIXME: There is no need to remember the time?
+    pausedTime = System.currentTimeMillis();
+    notify();
   }
 
-  public void resumePlayback()
+  public synchronized void resumePlayback()
   {
     startTime = System.currentTimeMillis() - timeOffset;
+    pausedTime = -1;
+    notify();
   }
 
   //
@@ -130,6 +142,8 @@
 
   private boolean fillBuffer() throws IOException
   {
+    waitWhilePaused();
+
     bufferSize = (int)readUnsigned32();
     if (bufferSize >= 0) {
       int realSize = (bufferSize + 3) & 0xFFFFFFFC;
@@ -152,15 +166,34 @@
       if (timeDiff <= 0) {
 	break;
       }
-      try {
-	Thread.currentThread().sleep(timeDiff);
-      } catch (InterruptedException e) {
+      synchronized(this) {
+	try {
+	  wait(timeDiff);
+	} catch (InterruptedException e) {
+	}
       }
+      waitWhilePaused();
     }
 
     return true;
   }
 
+  //
+  // In paused mode, wait for external notification on this object.
+  //
+
+  private void waitWhilePaused()
+  {
+    while (pausedTime >= 0) {
+      synchronized(this) {
+	try {
+	  wait();
+	} catch (InterruptedException e) {
+	}
+      }
+    }
+  }
+
   private long readUnsigned32() throws IOException
   {
     byte[] buf = new byte[4];
diff --git a/java/src/com/tightvnc/rfbplayer/RfbPlayer.java b/java/src/com/tightvnc/rfbplayer/RfbPlayer.java
index 16b3889..099148b 100644
--- a/java/src/com/tightvnc/rfbplayer/RfbPlayer.java
+++ b/java/src/com/tightvnc/rfbplayer/RfbPlayer.java
@@ -49,11 +49,6 @@
   RfbProto rfb;
   Thread rfbThread;
 
-  public static final int MODE_STOPPED  = 0;
-  public static final int MODE_PLAYBACK = 1;
-  public static final int MODE_PAUSED   = 2;
-  protected int mode;
-
   FbsInputStream fbsStream;
 
   Frame vncFrame;
@@ -163,7 +158,7 @@
 
       while (true) {
 	try {
-	  buttonPanel.setMode(MODE_STOPPED);
+	  buttonPanel.setPaused(true);
 	  vc.processNormalProtocol();
 	} catch (EOFException e) {
 	  fbsStream.close();
@@ -181,25 +176,22 @@
     
   }
 
-  public int getMode() {
-    return mode;
-  }
-
-  public void setMode(int mode) {
-    this.mode = mode;
-    if (vc != null) {
-      synchronized(vc) {
-	vc.notify();
+  public void setPaused(boolean paused) {
+    if (fbsStream != null) {
+      if (paused) {
+	fbsStream.pausePlayback();
+      } else {
+	fbsStream.resumePlayback();
       }
     }
   }
 
   public void setPos(int pos) {
-    fbsStream.setPos(pos);
+    fbsStream.setTimeOffset(pos * 1000);
   }
 
   public void updatePos() {
-    buttonPanel.setPos(fbsStream.getPos());
+    buttonPanel.setPos((int)(fbsStream.getTimeOffset() / 1000));
   }
 
   //
diff --git a/java/src/com/tightvnc/rfbplayer/VncCanvas.java b/java/src/com/tightvnc/rfbplayer/VncCanvas.java
index e0d9994..fa4bde7 100644
--- a/java/src/com/tightvnc/rfbplayer/VncCanvas.java
+++ b/java/src/com/tightvnc/rfbplayer/VncCanvas.java
@@ -214,21 +214,6 @@
 
     while (true) {
 
-      while (player.getMode() != player.MODE_PLAYBACK) {
-	synchronized(this) {
-	  try {
-	    wait();
-	  } catch (InterruptedException e) {
-	  }
-	}
-	if (player.getMode() == player.MODE_STOPPED) {
-	  throw new EOFException("Playback stopped");
-	}
-	if (player.getMode() == player.MODE_PLAYBACK) {
-	  player.fbsStream.resumePlayback();
-	}
-      }
-
       int msgType = rfb.readServerMessageType();
 
       switch (msgType) {
@@ -485,10 +470,6 @@
       }
 
       player.updatePos();
-
-      if (player.getMode() == player.MODE_STOPPED) {
-	throw new EOFException("Playback stopped");
-      }
     }
   }