Player and GUI mods for 2x 4x 6x and 8x fast for/backward
authorChris Tallon <chris@vomp.tv>
Sun, 24 Sep 2006 16:39:12 +0000 (16:39 +0000)
committerChris Tallon <chris@vomp.tv>
Sun, 24 Sep 2006 16:39:12 +0000 (16:39 +0000)
player.cc
player.h
vvideorec.cc
vvideorec.h

index adfc5b755ae1e4db027c8c4aca48cbe0e6c5b026..b8be8608ed2bde62b747accff1028766370ad3db 100644 (file)
--- a/player.cc
+++ b/player.cc
@@ -35,6 +35,7 @@ Player::Player(MessageQueue* messageQueue, bool tIsRecording, bool tIsRadio)
   lengthFrames = 0;
   currentFrameNumber = 0;
   state = S_STOP;
+  ifactor = 2;
 
   videoStartup = false;
   preBuffering = false;
@@ -170,7 +171,7 @@ void Player::stop()
   unLock();
 }
 
-void Player::togglePause()
+void Player::pause()
 {
   if (!initted) return;
   lock();
@@ -191,21 +192,51 @@ void Player::togglePause()
   unLock();
 }
 
-void Player::toggleFastForward()
+void Player::fastForward()
 {
   if (!initted) return;
   lock();
-  if (state == S_FFWD) switchState(S_PLAY);
-  else switchState(S_FFWD);
+
+  if (state == S_FFWD)
+  {
+    // change the rate
+    switch(ifactor)
+    {
+      case 2: ifactor = 4; break;
+      case 4: ifactor = 6; break;
+      case 6: ifactor = 8; break;
+      case 8: ifactor = 2; break;
+    }
+  }
+  else
+  {
+    ifactor = 2;
+    switchState(S_FFWD);
+  }
   unLock();
 }
 
-void Player::toggleFastBackward()
+void Player::fastBackward()
 {
   if (!initted) return;
   lock();
-  if (state == S_FBWD) switchState(S_PLAY);
-  else switchState(S_FBWD);
+
+  if (state == S_FBWD)
+  {
+    // change the rate
+    switch(ifactor)
+    {
+      case 2: ifactor = 4; break;
+      case 4: ifactor = 6; break;
+      case 6: ifactor = 8; break;
+      case 8: ifactor = 2; break;
+    }
+  }
+  else
+  {
+    ifactor = 2;
+    switchState(S_FBWD);
+  }
   unLock();
 }
 
@@ -963,54 +994,12 @@ void Player::threadFeedPlay()
   logger->log("Player", Log::DEBUG, "Message posted...");
 }
 
-/*
 void Player::threadFeedScan()
 {
-  ULONG direction = 0;
-  ULONG iframeNumber = 0;
-  ULONG iframeLength = 0;
-  ULLONG filePos;
-  UINT amountReceived;
-  UINT videoLength;
-
-  struct timeval displayDelayA;
-  struct timeval displayDelayB;
-  ULONG displayDelay;
-
-  ULONG iframesep;
-  ULONG sleeptime;
-
-  if (state == S_FFWD) direction = 1; // and 0 for backward
+  // This method is actually really simple - get frame from vdr,
+  // spit it at the video chip, wait for a time. Most of the code here
+  // is to get the wait right so that the scan occurs at the correct rate.
 
-  while(1)
-  {
-    gettimeofday(&displayDelayA, NULL);
-
-    if (!vdr->getNextIFrame(currentFrameNumber, direction, &filePos, &iframeNumber, &iframeLength)) break;
-    threadBuffer = vdr->getBlock(filePos, iframeLength, &amountReceived);
-    videoLength = demuxer->stripAudio(threadBuffer, amountReceived);
-    video->displayIFrame(threadBuffer, videoLength);
-    iframesep = abs(iframeNumber - currentFrameNumber);
-    currentFrameNumber = iframeNumber;
-    free(threadBuffer);
-    threadBuffer = NULL;
-    threadCheckExit();
-
-    // Calculate next jump delay
-    gettimeofday(&displayDelayB, NULL);
-    displayDelay = ((displayDelayB.tv_sec - displayDelayA.tv_sec) * 1000) + ((displayDelayB.tv_usec - displayDelayA.tv_usec) / 1000);
-    sleeptime = (1000 * iframesep) / (video->getFPS() * ifactor);
-    if (displayDelay > sleeptime) sleeptime = 0;
-    else sleeptime -= displayDelay;
-    logger->log("Player", Log::DEBUG, "iframesep %lu, fps %u, ifactor %u, displayDelay %lu, sleep %lu", iframesep, video->getFPS(), ifactor, displayDelay, sleeptime);
-    MILLISLEEP(sleeptime);
-  }
-  // scan has hit one end
-}
-*/
-
-void Player::threadFeedScan()
-{
   ULONG direction = 0;
   ULONG iframeNumber = 0;
   ULONG iframeLength = 0;
@@ -1074,6 +1063,7 @@ void Player::threadFeedScan()
 
     logger->log("Player", Log::DEBUG, "iframesep %lu, fps %u, ifactor %u, offset %lu, sleep %lu", iframesep, video->getFPS(), ifactor, offset, sleepTime);
     MILLISLEEP(sleepTime);
+    threadCheckExit();
   }
   // scan has hit one end
 }
index ab96c6ef9470e0cea9757af11fe428d973f5eb08..0920c589585450083ead1c01e03e91d2e3a4a12a 100644 (file)
--- a/player.h
+++ b/player.h
@@ -59,9 +59,9 @@ class Player : public Thread_TYPE, public Callback
 
     void play();
     void stop();
-    void togglePause();
-    void toggleFastForward();
-    void toggleFastBackward();
+    void pause();
+    void fastForward();
+    void fastBackward();
     void jumpToPercent(int percent);
     void skipForward(int seconds);
     void skipBackward(int seconds);
@@ -69,6 +69,7 @@ class Player : public Thread_TYPE, public Callback
     UCHAR getState() { return state; }
     ULONG getCurrentFrameNum();
     ULONG getLengthFrames();
+    UCHAR getIScanRate() { return ifactor; }
 
     void call(void*); // for callback interface
 
@@ -131,8 +132,7 @@ class Player : public Thread_TYPE, public Callback
     UINT startupBlockSize;
     UCHAR* threadBuffer;
     UCHAR state;
-
-    const static UINT ifactor = 5;
+    UCHAR ifactor;
 };
 
 #endif
index 873e9b7a72fe30ea4aaa0ba26981b60d66094dfc..8e6c5b751f0f96efe9703ec6e938dc74469b9be2 100644 (file)
@@ -65,7 +65,7 @@ VVideoRec::VVideoRec(Recording* rec)
   setBackgroundColour(transparent);
 
   barRegion.x = 0;
-  barRegion.y = video->getScreenHeight() - 66;   // FIXME, need to be - 1? and below?
+  barRegion.y = video->getScreenHeight() - 58;   // FIXME, need to be - 1? and below?
   barRegion.w = video->getScreenWidth();
   barRegion.h = 66;
 
@@ -77,6 +77,7 @@ VVideoRec::VVideoRec(Recording* rec)
   barBlue.set(0, 0, 150, 150);
 
   barShowing = false;
+  stickyBar = false;
 }
 
 VVideoRec::~VVideoRec()
@@ -165,7 +166,7 @@ int VVideoRec::handleCommand(int command)
     }
     case Remote::PAUSE:
     {
-      player->togglePause();
+      player->pause();
       doBar(0);
       return 2;
     }
@@ -183,13 +184,13 @@ int VVideoRec::handleCommand(int command)
     }
     case Remote::FORWARD:
     {
-      player->toggleFastForward();
+      player->fastForward();
       doBar(0);
       return 2;
     }
     case Remote::REVERSE:
     {
-      player->toggleFastBackward();
+      player->fastBackward();
       doBar(0);
       return 2;
     }
@@ -330,7 +331,9 @@ void VVideoRec::doBar(int action)
   WSymbol w;
   w.setSurface(surface);
   w.nextSymbol = 0;
-  w.setSurfaceOffset(76, barRegion.y + 16);
+  w.setSurfaceOffset(barRegion.x + 66, barRegion.y + 16);
+
+  UCHAR playerState = 0;
 
   if (action)
   {
@@ -341,7 +344,7 @@ void VVideoRec::doBar(int action)
   }
   else
   {
-    UCHAR playerState = player->getState();
+    playerState = player->getState();
     if (playerState == Player::S_PAUSE_P)      w.nextSymbol = WSymbol::PAUSE;
     else if (playerState == Player::S_PAUSE_I) w.nextSymbol = WSymbol::PAUSE;
     else if (playerState == Player::S_FFWD)    w.nextSymbol = WSymbol::FFWD;
@@ -351,10 +354,32 @@ void VVideoRec::doBar(int action)
 
   w.draw();
 
+  if ((playerState == Player::S_FFWD) || (playerState == Player::S_FBWD))
+  {
+    // draw blips to show how fast the scan is
+    UCHAR scanrate = player->getIScanRate();
+    if (scanrate >= 2)
+    {
+      char* text = new char[5];
+      SNPRINTF(text, 5, "%ux", scanrate);
+      drawText(text, barRegion.x + 102, barRegion.y + 12, Colour::LIGHTTEXT);
+    }
+  }
+
   drawBarClocks();
 
   ViewMan::getInstance()->updateView(this, &barRegion);
-  timers->setTimerD(this, 1, 4);
+
+  if ((playerState == Player::S_FFWD) || (playerState == Player::S_FBWD))
+  {
+    timers->cancelTimer(this, 1);
+    stickyBar = true;
+  }
+  else
+  {
+    timers->setTimerD(this, 1, 4); // only set the getridofbar timer if not ffwd/fbwd
+    stickyBar = false;
+  }
   timers->setTimerD(this, 2, 0, 200000000);
 }
 
@@ -382,6 +407,22 @@ void VVideoRec::timercall(int clientReference)
 
 void VVideoRec::drawBarClocks()
 {
+  if (stickyBar)
+  {
+    UCHAR playerState = player->getState();
+    // sticky bar is set if we are in ffwd/fbwd mode
+    // if player has gone to S_PLAY then kill stickyBar, and run doBar(0) which
+    // will repaint all the bar (it will call this function again, but
+    // this section won't run because stickyBar will then == false)
+
+    if ((playerState != Player::S_FFWD) && (playerState != Player::S_FBWD))
+    {
+      stickyBar = false;
+      doBar(0);
+      return; // doBar will call this function and do the rest
+    }
+  }
+
   Log* logger = Log::getInstance();
   logger->log("VVideoRec", Log::DEBUG, "Draw bar clocks");
 
@@ -457,6 +498,7 @@ void VVideoRec::removeBar()
   if (!barShowing) return;
   timers->cancelTimer(this, 2);
   barShowing = false;
+  stickyBar = false;
   rectangle(barRegion, transparent);
   ViewMan::getInstance()->updateView(this, &barRegion);
 }
index 6916e0c6b315acec14d234b7c2436a9bd2f0e162..dfd013ce2de0af9307a50761fa3b6bfebff0461d 100644 (file)
@@ -63,6 +63,7 @@ class VVideoRec : public View, public TimerReceiver
 
     bool playing;
     bool barShowing;
+    bool stickyBar;
     void doBar(int action);
     void drawBarClocks();
     void stopPlay();