OBJECTS = main.o command.o log.o remote.o led.o mtd.o video.o audio.o tcp.o directory.o thread.o event.o \
player.o demuxer.o stream.o vfeed.o afeed.o afeedr.o osd.o surface.o viewman.o vdr.o dsock.o box.o \
- recording.o channel.o message.o playervideo.o messagequeue.o rectimer.o vtimeredit.o voptionsmenu.o \
+ recording.o channel.o message.o messagequeue.o rectimer.o vtimeredit.o voptionsmenu.o \
view.o vinfo.o vwallpaper.o vvolume.o vrecordinglist.o vlivebanner.o vmute.o vtimerlist.o \
vrecordingmenu.o vquestion.o vchannellist.o vwelcome.o vvideolive.o vvideorec.o vepgsettimer.o \
vchannelselect.o vserverselect.o colour.o vconnect.o voptions.o vepg.o region.o \
widget.o wselectlist.o wjpeg.o wsymbol.o wbutton.o woptionbox.o wtextbox.o i18n.o timers.o \
fonts/helvB24.o fonts/helvB18.o
-# playerradio.o vradiolive.o
.PHONY: clean fresh all install strip
if (alen)
{
- // Log::getInstance()->log("AFeed", Log::DEBUG, "Written %i", alen);
+// Log::getInstance()->log("AFeed", Log::DEBUG, "Written %i", alen);
cb.call(this);
}
else
{
+// Log::getInstance()->log("AFeed", Log::DEBUG, "No data delay");
nanosleep(&delayTime, NULL);
}
}
viewman->updateView(vw);
// Enter pre-keys here
- handleCommand(Remote::THREE);
- handleCommand(Remote::DOWN);
- handleCommand(Remote::OK);
- handleCommand(Remote::PLAY);
+// handleCommand(Remote::THREE);
+// handleCommand(Remote::DOWN);
+// handleCommand(Remote::OK);
+// handleCommand(Remote::PLAY);
}
void MessageQueue::postMessage(Message* m)
{
messages.push(m);
- Log::getInstance()->log("MessageQueue", Log::DEBUG, "have stored message in queue");
+ Log::getInstance()->log("MessageQueue", Log::DEBUG, "have stored message %lu in queue", m->message);
}
void MessageQueue::processMessageQueue()
#include "player.h"
-Player::Player()
+Player::Player(MessageQueue* messageQueue, UCHAR tIsRecording, UCHAR isRadio)
+: vfeed(this), afeed(this)
{
+ commandMessageQueue = messageQueue;
+ audio = Audio::getInstance();
+ video = Video::getInstance();
+ logger = Log::getInstance();
initted = 0;
-
+ paused = false;
+ playing = false;
+ ffwd = false;
+ fbwd = false;
streamLength = 0;
- // FIXME - this might need settings back to zero for new live play depending on what is done with it
+ feedPosition = 0;
+ feedMode = MODE_NORMAL;
+ isRecording = tIsRecording;
+ lastRescan = 0;
+ startTS = 0;
+ endTS = 0;
+ startup = 1;
+ threadBuffer = NULL;
- audio = Audio::getInstance();
+ if (isRadio)
+ {
+ blockSize = 20000;
+ startupBlockSize = 60000;
+ }
+ else
+ {
+ blockSize = 100000;
+ startupBlockSize = 250000;
+ }
+}
+
+Player::~Player()
+{
+ if (initted) shutdown();
+}
+
+int Player::init()
+{
+ if (initted) return 0;
+
+ if (!demuxer.init(this))
+ {
+ logger->log("Player", Log::ERR, "Demuxer failed to init");
+ shutdown();
+ return 0;
+ }
+
+ vfeed.init(video->getFD());
+ afeed.init(audio->getFD());
+
+ video->stop();
+ video->blank();
+ audio->stop();
+
+ initted = 1;
+ return 1;
+}
+
+int Player::shutdown()
+{
+ if (!initted) return 0;
+ initted = 0;
+
+ logger->log("Player", Log::DEBUG, "Player shutdown...");
+
+ // copy of stop
+ if (playing)
+ {
+ playing = false;
+ threadStop();
+ video->stop();
+ video->blank();
+ audio->stop();
+ vfeed.stop();
+ afeed.stop();
+ video->reset();
+ demuxer.reset();
+ feedPosition = 0;
+ }
+ logger->log("Player", Log::DEBUG, "Player shutdown done");
+
+ return 1;
+}
+
+void Player::resyncAudio()
+{
+ // Temp hopefully
+ if (!initted) return;
+ audio->pause();
+ usleep(500000);
+ audio->unPause();
+}
+
+void Player::resyncVideo()
+{
+ // Temp hopefully
+ if (!initted) return;
+ video->pause();
+ usleep(500000);
+ video->unPause();
+}
+
+int Player::play()
+{
+ if (!initted) return 0;
+
+ // If we are just paused, unpause!
+ if (paused)
+ {
+ togglePause();
+ return 1;
+ }
+
+ // If we are fast forwarding, set to normal
+ if (ffwd)
+ {
+ toggleFastForward();
+ return 1;
+ }
+
+ // If we are fast backwarding, set to normal
+ if (fbwd)
+ {
+ toggleFastBackward();
+ return 1;
+ }
+
+ // If we are already playing, bail // FIXME - resync?
+ if (playing)
+ {
+ logger->log("Player", Log::DEBUG, "DOING RESYNC");
+ resyncVideo();
+ return 1;
+ }
+
+ // Standard play start
+ logger->log("Player", Log::DEBUG, "Standard play start");
+
+ audio->reset();
+ video->reset();
+ demuxer.reset();
+
+// ------------------------ This one works, but doesn't allow any pre-buffering.
+ threadStart();
+ vfeed.start();
+ afeed.start();
+ audio->play();
+ video->play();
+ video->sync();
+ audio->sync();
+
+ resyncVideo();
+// ------------------------ This one doesn't work, but it should, and would allow for prebuffering.
+
+/*
+ threadStart();
+// sleep(1);
+
+// struct timespec delay;
+// delay.tv_sec = 1;
+// delay.tv_nsec = 500000000;
+// nanosleep(&delay, NULL);
+
+ vfeed.start();
+ afeed.start();
+ video->play();
+ audio->play();
+ video->sync();
+ audio->sync();
+
+ video->pause();
+ usleep(500000); // SYNC
+ video->sync();
+ video->unPause();
+ video->sync();
+*/
+
+// ------------------------------------------------------------------------------------------------
+
+ playing = true;
+ return 1;
+}
+
+void Player::stop()
+{
+ if (!initted) return;
+ if (!playing) return;
+
+ if (ffwd || fbwd)
+ {
+ ffwd = false;
+ fbwd = false;
+ afeed.enable();
+ video->unFastForward();
+ audio->systemMuteOff();
+ feedMode = MODE_NORMAL;
+ }
+
+ playing = false;
+ paused = false;
+
+ vfeed.stop();
+ afeed.stop();
+ threadStop();
+ video->stop();
+ video->blank();
+ audio->stop();
+ audio->unPause();
+ video->reset();
+ demuxer.reset();
+
+ feedPosition = 0;
+}
+
+void Player::togglePause()
+{
+ if (!initted) return;
+ if (!playing) return;
+
+ if (ffwd) toggleFastForward();
+ if (fbwd) toggleFastBackward();
+
+ if (paused)
+ {
+ video->unPause();
+ audio->unPause();
+ paused = false;
+ }
+ else
+ {
+ video->pause();
+ audio->pause();
+ paused = true;
+ }
}
-Player::~Player() {}
+void Player::setPosition(ULLONG position)
+{
+ feedPosition = position;
+}
+
+void Player::setLength(ULLONG length)
+{
+ lastRescan = time(NULL);
+ streamLength = length;
+ logger->log("Player", Log::DEBUG, "Player has received length of %llu", streamLength);
+}
+
+void Player::skipForward(int seconds)
+{
+ // skip forward 1 minute
+ logger->log("Player", Log::DEBUG, "SKIP FORWARD %i SECONDS", seconds);
+
+ if (paused) togglePause();
+
+ ULLONG moveBy = seconds * 500000;
+
+ vfeed.stop();
+ afeed.stop();
+ threadStop();
+ video->stop();
+ video->reset();
+ audio->reset();
+ audio->doMuting(); // ???
+ demuxer.flush();
+ feedPosition += moveBy;
+ vfeed.start();
+ afeed.start();
+ threadStart();
+ audio->play();
+ video->play();
+ video->sync();
+ audio->sync();
+
+ resyncVideo();
+}
+
+void Player::skipBackward(int seconds)
+{
+ // skip forward 1 minute
+ logger->log("Player", Log::DEBUG, "SKIP BACKWARD %i SECONDS", seconds);
+
+ if (paused) togglePause();
+
+ ULLONG moveBy = seconds * 500000;
+
+ vfeed.stop();
+ afeed.stop();
+ threadStop();
+ video->stop();
+ audio->stop();
+ video->reset();
+ audio->reset();
+ audio->doMuting(); // ???
+ demuxer.flush();
+ if (feedPosition > moveBy) feedPosition -= moveBy;
+ vfeed.start();
+ afeed.start();
+ threadStart();
+ audio->play();
+ video->play();
+ video->sync();
+ audio->sync();
+
+ resyncVideo();
+}
+
+void Player::toggleFastForward()
+{
+ if (!initted) return;
+ if (!playing) return;
+
+ if (paused) togglePause();
+ if (fbwd) toggleFastBackward();
+
+ if (ffwd)
+ {
+ ffwd = false;
+// video->unFastForward();
+
+
+ vfeed.stop();
+ afeed.stop();
+ threadStop();
+ video->stop();
+ audio->stop();
+ video->reset();
+ audio->reset();
+ demuxer.flush();
+// demuxer.seek();
+ vfeed.start();
+ afeed.enable();
+ afeed.start();
+ threadStart();
+ video->play();
+ audio->play();
+ video->sync();
+ audio->sync();
+
+ audio->systemMuteOff();
+
+ resyncVideo();
+/*
+ demuxer.flushAudio();
+ audio->reset();
+ afeed.enable();
+ //video->reset();
+ audio->play();
+ video->play();
+ video->sync();
+ audio->sync();
+ audio->systemMuteOff();
+*/
+ }
+ else
+ {
+ ffwd = true;
+ afeed.disable();
+ audio->systemMuteOn();
+ video->fastForward();
+ }
+}
+
+void Player::toggleFastBackward()
+{
+ if (!initted) return;
+ if (!playing) return;
+
+ if (paused) togglePause();
+ if (ffwd) toggleFastForward();
+
+ if (fbwd)
+ {
+ fbwd = false;
+ afeed.enable();
+ audio->systemMuteOff();
+
+// threadStop();
+ feedMode = MODE_NORMAL;
+// threadStart();
+ }
+ else
+ {
+ fbwd = false;
+ afeed.disable();
+ audio->systemMuteOn();
+
+ threadStop();
+ feedMode = MODE_BACKWARDS;
+ video->reset();
+ video->play();
+ demuxer.flush();
+ threadStart();
+ }
+}
+
+void Player::jumpToPercent(int percent)
+{
+ if (paused) togglePause();
+ if (ffwd) toggleFastForward();
+
+ vfeed.stop();
+ afeed.stop();
+ threadStop();
+ video->stop();
+ audio->stop();
+ video->reset();
+ audio->reset();
+ demuxer.flush();
+ demuxer.seek();
+ feedPosition = streamLength * percent / 100;
+ vfeed.start();
+ afeed.start();
+ threadStart();
+ audio->play();
+ video->play();
+ video->sync();
+ audio->sync();
+
+ resyncVideo();
+}
+
+ULLONG Player::getPositionTS()
+{
+ if (startup) return 0ULL;
+ long long currentTS = video->getCurrentTimestamp() - startTS;
+ if (currentTS < 0) currentTS += 8589934592ULL;
+ return (ULLONG)currentTS;
+}
+
+ULLONG Player::getEndTS()
+{
+ long long rendTS = endTS - startTS;
+ if (rendTS < 0) rendTS += 8589934592ULL;
+ return (ULLONG)rendTS;
+}
+
+void Player::call(void* caller)
+{
+ if (caller == &demuxer)
+ {
+ logger->log("Player", Log::DEBUG, "Callback from demuxer");
+
+ if (video->getTVsize() == Video::ASPECT4X3)
+ {
+ logger->log("Player", Log::DEBUG, "TV is 4:3, ignoring aspect switching");
+ return;
+ }
+
+ int dxCurrentAspect = demuxer.getAspectRatio();
+ if (dxCurrentAspect == Demuxer::ASPECT_4_3)
+ {
+ logger->log("Player", Log::DEBUG, "Demuxer said video is 4:3 aspect, switching TV");
+ video->setAspectRatio(Video::ASPECT4X3);
+ }
+ else if (dxCurrentAspect == Demuxer::ASPECT_16_9)
+ {
+ logger->log("Player", Log::DEBUG, "Demuxer said video is 16:9 aspect, switching TV");
+ video->setAspectRatio(Video::ASPECT16X9);
+ }
+ else
+ {
+ logger->log("Player", Log::DEBUG, "Demuxer said video is something else... ignoring");
+ }
+
+ }
+ else
+ {
+ threadSignalNoLock();
+ }
+}
+
+// Feed thread
+
+void Player::threadMethod()
+{
+ UINT thisRead;
+ UINT writeLength;
+ UINT thisWrite;
+
+ VDR* vdr = VDR::getInstance();
+
+ UINT askFor;
+ while(1)
+ {
+ thisRead = 0;
+ writeLength = 0;
+ thisWrite = 0;
+
+ threadCheckExit();
+
+ // If we havn't rescanned for a while..
+ if (isRecording && ((lastRescan + 60) < time(NULL)))
+ {
+ streamLength = vdr->rescanRecording();
+ Log::getInstance()->log("Player", Log::DEBUG, "Rescanned and reset length: %llu", streamLength);
+ lastRescan = time(NULL);
+ setEndTS();
+ }
+
+ if (streamLength) // is playing a recording
+ {
+ if (feedPosition >= streamLength) break; // finished playback
+
+ if (startup)
+ {
+ if (startupBlockSize > streamLength)
+ askFor = streamLength; // is a very small recording!
+ else
+ askFor = startupBlockSize; // normal, but a startup sized block to detect all the audio streams
+ }
+ else
+ {
+ if ((feedPosition + blockSize) > streamLength) // last block of recording
+ askFor = streamLength - feedPosition;
+ else // normal
+ askFor = blockSize;
+ }
+ }
+ else // is playing live
+ {
+ if (startup)
+ askFor = startupBlockSize; // find audio streams sized block
+ else
+ askFor = blockSize; // normal
+ }
+
+ threadBuffer = vdr->getBlock(feedPosition, askFor, &thisRead);
+ if (!threadBuffer) break;
+
+ if (startup)
+ {
+ int a_stream = demuxer.scan(threadBuffer, thisRead);
+ demuxer.setAudioStream(a_stream);
+ Log::getInstance()->log("Player", Log::DEBUG, "Startup Audio stream chosen %x", a_stream);
+
+ setStartTS(thisRead);
+
+ if (isRecording) setEndTS();
+
+ startup = 0;
+ }
+
+ if (feedMode == MODE_NORMAL)
+ {
+ feedPosition += thisRead;
+ }
+ else if (feedMode == MODE_BACKWARDS)
+ {
+ if (feedPosition >= blockSize)
+ {
+ feedPosition -= blockSize;
+ demuxer.seek();
+ }
+ else
+ {
+ // got to the start of the recording.. revert to play mode? how?
+ feedPosition += thisRead;
+ }
+ }
+
+ threadCheckExit();
+
+ while(writeLength < thisRead)
+ {
+ thisWrite = demuxer.put(threadBuffer + writeLength, thisRead - writeLength);
+ writeLength += thisWrite;
+
+ if (!thisWrite)
+ {
+// Log::getInstance()->log("Player", Log::DEBUG, "DEMUXER FULL!!!");
+ // demuxer is full and cant take anymore
+ threadLock();
+ threadWaitForSignal();
+ threadUnlock();
+// Log::getInstance()->log("Player", Log::DEBUG, "BACK FROM WAIT");
+ }
+
+ threadCheckExit();
+ }
+
+ free(threadBuffer);
+ threadBuffer = NULL;
+
+ }
+
+ // end of recording
+ Log::getInstance()->log("Player", Log::DEBUG, "Recording playback ends");
+ Message* m = new Message(); // Must be done after this thread finishes, and must break into master mutex
+ if (streamLength) m->message = Message::STOP_PLAYBACK; // recording
+ else m->message = Message::STREAM_END; // live
+ Log::getInstance()->log("Player", Log::DEBUG, "Posting message to %p...", commandMessageQueue);
+ commandMessageQueue->postMessage(m);
+ Log::getInstance()->log("Player", Log::DEBUG, "Message posted...");
+}
+
+void Player::threadPostStopCleanup()
+{
+ Log::getInstance()->log("Player", Log::DEBUG, "Post stop cleanup 1");
+ if (threadBuffer)
+ {
+ Log::getInstance()->log("Player", Log::DEBUG, "Post stop cleanup 2");
+ free(threadBuffer);
+ threadBuffer = NULL;
+ }
+ Log::getInstance()->log("Player", Log::DEBUG, "Post stop cleanup 3");
+}
+
+void Player::setStartTS(UINT dataInBuffer)
+{
+ if (isRecording && feedPosition) // (feedPosition != 0)
+ {
+ // FIXME find out how much data need to get to find a TS
+ // Need to get the actual start of the recording
+
+ UINT thisRead;
+ UCHAR* tempBuffer = VDR::getInstance()->getBlock(0, 100000, &thisRead);
+ if (!tempBuffer) return;
+ if (thisRead) demuxer.findVideoPTS(tempBuffer, thisRead, &startTS);
+ free(tempBuffer);
+ }
+ else
+ {
+ demuxer.findVideoPTS(threadBuffer, dataInBuffer, &startTS);
+ }
+}
+
+void Player::setEndTS()
+{
+ Log::getInstance()->log("Player", Log::DEBUG, "Setting end TS");
+
+ UINT thisRead;
+ UCHAR* tempBuffer = VDR::getInstance()->getBlock((streamLength - 100000), 100000, &thisRead);
+ if (!tempBuffer) return;
+ if (thisRead) demuxer.findVideoPTS(tempBuffer, thisRead, &endTS);
+ free(tempBuffer);
+ Log::getInstance()->log("Player", Log::DEBUG, "Set end TS");
+}
+
+#ifdef DEV
+void Player::test1()
+{
+ Log::getInstance()->log("Player", Log::DEBUG, "PLAYER TEST 1");
+}
+
+void Player::test2()
+{
+ Log::getInstance()->log("Player", Log::DEBUG, "PLAYER TEST 2");
+}
+#endif
#ifndef PLAYER_H
#define PLAYER_H
+#include <stdio.h>
+
+#include "audio.h"
+#include "video.h"
+#include "demuxer.h"
+#include "vfeed.h"
+#include "afeed.h"
+#include "remote.h"
#include "thread.h"
+#include "vdr.h"
#include "callback.h"
-#include "defines.h"
-#include "log.h"
-#include "audio.h"
+#include "message.h"
+#include "messagequeue.h"
class Player : public Thread, public Callback
{
public:
- Player();
+ Player(MessageQueue* messageQueue, UCHAR isRecording, UCHAR isRadio);
virtual ~Player();
- virtual int init()=0;
- virtual int shutdown()=0;
- virtual int play()=0;
- virtual void stop()=0;
- virtual void togglePause()=0;
- virtual void toggleFastForward()=0;
- virtual void toggleFastBackward()=0;
- virtual void jumpToPercent(int percent)=0;
- virtual void skipForward(int seconds)=0;
- virtual void skipBackward(int seconds)=0;
- virtual void setPosition(ULLONG position)=0;
- virtual void setLength(ULLONG length)=0;
- virtual void resyncAudio()=0;
- virtual bool isPaused()=0;
- virtual bool isFfwd()=0;
- virtual bool isFbwd()=0;
- virtual ULLONG getPositionTS()=0;
- virtual ULLONG getEndTS()=0;
+
+ int init();
+ int shutdown();
+
+ int play();
+ void stop();
+ void togglePause();
+ void toggleFastForward();
+ void toggleFastBackward();
+ void jumpToPercent(int percent);
+ void skipForward(int seconds);
+ void skipBackward(int seconds);
+ void call(void*); // for callback interface
+ void setPosition(ULLONG position);
+ void setLength(ULLONG length);
+ void resyncAudio();
+ ULLONG getPositionTS();
+ ULLONG getEndTS();
+
+ bool isPaused() { return paused; }
+ bool isFfwd() { return ffwd; }
+ bool isFbwd() { return fbwd; }
#ifdef DEV
- virtual void test1()=0;
- virtual void test2()=0;
+ void test1();
+ void test2();
#endif
- virtual void call(void*)=0; // for callback interface
- virtual void threadMethod()=0; // for thread interface
- virtual void threadPostStopCleanup()=0;
+ void threadMethod();
+ void threadPostStopCleanup();
- protected:
- int initted;
- ULLONG streamLength;
+ private:
+ void resyncVideo();
+ void setStartTS(UINT dataInBuffer);
+ void setEndTS();
+
+ int initted;
+ MessageQueue* commandMessageQueue;
+ Log* logger;
Audio* audio;
+ Video* video;
+ Demuxer demuxer;
+ int startup;
+ VFeed vfeed;
+ AFeed afeed;
+
+ ULLONG startTS;
+ ULLONG endTS;
+ ULLONG streamLength;
+ ULLONG feedPosition;
+ UCHAR feedMode;
+ UCHAR isRecording;
+ time_t lastRescan;
+ UINT blockSize;
+ UINT startupBlockSize;
+ const static UCHAR MODE_NORMAL = 1;
+ const static UCHAR MODE_BACKWARDS = 2;
+ UCHAR* threadBuffer;
+ bool playing; // As in not stopped, (playing && paused) can == TRUE
+ bool paused; // Must be in playing state as well
+ bool ffwd; // Must be in playing state as well
+ bool fbwd; // Must be in playing state as well
};
#endif
+++ /dev/null
-/*
- Copyright 2004-2005 Chris Tallon
-
- This file is part of VOMP.
-
- VOMP 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.
-
- VOMP 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 VOMP; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-// this is a total copy from player but with video stuff taken out
-// most of this isn't used because it's designed for recording playback
-
-
-#include "playerradio.h"
-
-PlayerRadio::PlayerRadio()
-: afeedr(this, &stream)
-{
- paused = 0;
- playing = 0;
- ffwd = 0;
- fbwd = 0;
- feedPosition = 0;
- feedMode = MODE_NORMAL;
-}
-
-PlayerRadio::~PlayerRadio()
-{
- if (initted) shutdown();
-}
-
-int PlayerRadio::init()
-{
- if (initted) return 0;
-
- stream.init(120000);
- afeedr.init(audio->getFD());
-
- audio->stop();
-
-
- initted = 1;
- return 1;
-}
-
-int PlayerRadio::shutdown()
-{
- if (!initted) return 0;
- initted = 0;
-
- Log::getInstance()->log("PlayerRadio", Log::DEBUG, "PlayerRadio shutdown...");
-
- // copy of stop
- if (playing)
- {
- playing = 0;
- threadStop();
- audio->stop();
- afeedr.stop();
- feedPosition = 0;
- }
-
- return 1;
-}
-
-int PlayerRadio::play()
-{
- if (!initted) return 0;
-
- // If we are just paused, unpause!
- if (paused)
- {
- togglePause();
- return 1;
- }
-
- // If we are fast forwarding, set to normal
- if (ffwd)
- {
- toggleFastForward();
- return 1;
- }
-
- // If we are fast backwarding, set to normal
- if (fbwd)
- {
- toggleFastBackward();
- return 1;
- }
-
- // If we are already playing, bail // FIXME - resync?
- if (playing)
- {
- Log::getInstance()->log("PlayerRadio", Log::DEBUG, "DOING RESYNC");
-
- afeedr.stop();
- audio->reset();
- afeedr.start();
-
-
- audio->play();
- call(this);
-
- return 1;
- }
-
- // Standard play start
-
- audio->reset();
- audio->stop();
-
-/*
-// ------------------------ This one works, but doesn't allow any pre-buffering.
- threadStart();
- afeedr.start();
- audio->play();
- audio->sync();
-
-// ------------------------ This one doesn't work, but it should, and would allow for prebuffering.
-*/
-
-// audio->test();
- threadStart();
- sleep(6);
-
-// struct timespec delay;
-// delay.tv_sec = 1;
-// delay.tv_nsec = 500000000;
-// nanosleep(&delay, NULL);
-
-
- afeedr.start();
- audio->play();
-// audio->sync();
-// ------------------------------------------------------------------------------------------------
-
- playing = 1;
- return 1;
-}
-
-void PlayerRadio::stop()
-{
- if (!initted) return;
- if (!playing) return;
- playing = 0;
-
- threadCancel();
- audio->stop();
- afeedr.stop();
-
- feedPosition = 0;
-}
-
-void PlayerRadio::togglePause()
-{
- if (!initted) return;
- if (!playing) return;
-
- if (ffwd) toggleFastForward();
- if (fbwd) toggleFastBackward();
-
- if (paused)
- {
- audio->unPause();
- paused = 0;
- }
- else
- {
- audio->pause();
- paused = 1;
- }
-}
-
-void PlayerRadio::setPosition(ULLONG position)
-{
- feedPosition = position;
-}
-
-void PlayerRadio::setLength(ULLONG length)
-{
- streamLength = length;
- Log::getInstance()->log("PlayerRadio", Log::DEBUG, "Player has received length of %llu", streamLength);
-}
-
-void PlayerRadio::skipForward()
-{
- // skip forward 1 minute
- Log::getInstance()->log("PlayerRadio", Log::DEBUG, "SKIP FORWARD 1 MINUTE");
-
- if (paused) togglePause();
-
- threadStop();
- afeedr.stop();
- audio->stop();
- audio->reset();
- audio->doMuting(); // ???
- feedPosition += 30000000;
- afeedr.start();
- threadStart();
- audio->play();
-}
-
-void PlayerRadio::skipBackward()
-{
- // skip forward 1 minute
- Log::getInstance()->log("PlayerRadio", Log::DEBUG, "SKIP BACKWARD 1 MINUTE");
-
- if (paused) togglePause();
-
- threadStop();
- afeedr.stop();
- audio->stop();
- audio->reset();
- audio->doMuting(); // ???
- if (feedPosition > 30000000) feedPosition -= 30000000;
- afeedr.start();
- threadStart();
- audio->play();
-}
-
-void PlayerRadio::toggleFastForward()
-{
- if (!initted) return;
- if (!playing) return;
-
- if (paused) togglePause();
- if (fbwd) toggleFastBackward();
-
- if (ffwd)
- {
- ffwd = 0;
-// afeedr.enable();
- audio->reset();
- audio->systemMuteOff();
- }
- else
- {
- ffwd = 1;
-// afeedr.disable();
- audio->systemMuteOn();
- }
-}
-
-void PlayerRadio::toggleFastBackward()
-{
- if (!initted) return;
- if (!playing) return;
-
- if (paused) togglePause();
- if (ffwd) toggleFastForward();
-
- if (fbwd)
- {
- fbwd = 0;
-// afeedr.enable();
- audio->systemMuteOff();
-
-// threadStop();
- feedMode = MODE_NORMAL;
-// threadStart();
- }
- else
- {
- fbwd = 1;
-// afeedr.disable();
- audio->systemMuteOn();
-
- threadStop();
- feedMode = MODE_BACKWARDS;
- threadStart();
- }
-}
-
-void PlayerRadio::jumpToPercent(int percent)
-{
- threadStop();
- afeedr.stop();
- audio->stop();
- audio->reset();
- feedPosition = streamLength * percent / 100;
- afeedr.start();
- threadStart();
- audio->play();
- audio->sync();
-}
-
-
-void PlayerRadio::call(void* caller)
-{
- Log::getInstance()->log("PlayerRadio", Log::DEBUG, "playerradio called\n");
-// threadSignalNoLock();
-}
-
-// Feed thread
-
-void PlayerRadio::threadMethod()
-{
- UCHAR* buf;
- UINT thisRead;
- UINT writeLength;
- UINT thisWrite;
-
- VDR* vdr = VDR::getInstance();
-
- UINT askFor;
- while(1)
- {
- thisRead = 0;
- writeLength = 0;
- thisWrite = 0;
-
- threadCheckExit();
-
- // a bit hackey. this needs to be split to live and rec players
- if (streamLength && (feedPosition >= streamLength)) break;
- askFor = blockSize;
- if (streamLength && ((feedPosition + blockSize) > streamLength))
- {
- askFor = streamLength - feedPosition;
- }
- buf = vdr->getBlock(feedPosition, askFor, &thisRead);
- if (!buf) break;
-
- printf("Written direct: %i\n", write(audio->getFD(), buf, thisRead)); // temp
-
-
-
- if (feedMode == MODE_NORMAL)
- {
- feedPosition += thisRead;
- }
- else if (feedMode == MODE_BACKWARDS)
- {
- if (feedPosition >= blockSize)
- {
- feedPosition -= blockSize;
- }
- else
- {
- // got to the start of the recording.. revert to play mode? how?
- feedPosition += thisRead;
- }
- }
-
- threadCheckExit();
-
- free(buf);
-
-/* while(writeLength < thisRead)
- {
- thisWrite = stream.put(buf + writeLength, thisRead - writeLength);
- Log::getInstance()->log("PlayerRadio", Log::DEBUG, "Just put %i to stream", thisWrite);
-
- writeLength += thisWrite;
-
- if (!thisWrite)
- {
- Log::getInstance()->log("PlayerRadio", Log::DEBUG, "RADIO OUTPUT STREAM FULL!!!");
- // stream is full and cant take anymore
- threadLock();
- threadWaitForSignal();
- threadUnlock();
- Log::getInstance()->log("PlayerRadio", Log::DEBUG, "BACK FROM WAIT");
- }
-
- threadCheckExit();
- }
-
- Log::getInstance()->log("PlayerRadio", Log::DEBUG, "Written audio");
-*/
- }
-}
+++ /dev/null
-/*
- Copyright 2004-2005 Chris Tallon
-
- This file is part of VOMP.
-
- VOMP 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.
-
- VOMP 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 VOMP; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef PLAYERRADIO_H
-#define PLAYERRADIO_H
-
-#include <stdio.h>
-
-#include "player.h"
-#include "audio.h"
-#include "afeedr.h"
-#include "remote.h"
-#include "thread.h"
-#include "vdr.h"
-#include "callback.h"
-#include "stream.h"
-
-class PlayerRadio : public Player
-{
- public:
- PlayerRadio();
- virtual ~PlayerRadio();
-
- int init();
- int shutdown();
-
- int play();
- void stop();
- void togglePause();
- void toggleFastForward();
- void toggleFastBackward();
- void jumpToPercent(int percent);
- void skipForward();
- void skipBackward();
- void call(void*); // for callback interface
- void setPosition(ULLONG position);
- void setLength(ULLONG length);
-
- void threadMethod();
- void threadPostStopCleanup() {};
-
- void skipForward(int) {};
- void skipBackward(int) {};
- void test1() {};
- void test2() {};
-
- private:
- Stream stream;
- AFeedR afeedr;
- ULLONG feedPosition;
- UCHAR feedMode;
- const static UCHAR MODE_NORMAL = 1;
- const static UCHAR MODE_BACKWARDS = 2;
- const static UINT blockSize = 2000;
-
- UCHAR playing; // As in not stopped, (playing && paused) can == TRUE
- UCHAR paused; // Must be in playing state as well
- UCHAR ffwd; // Must be in playing state as well
- UCHAR fbwd; // Must be in playing state as well
-};
-
-#endif
+++ /dev/null
-/*
- Copyright 2004-2005 Chris Tallon
-
- This file is part of VOMP.
-
- VOMP 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.
-
- VOMP 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 VOMP; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "playervideo.h"
-
-PlayerVideo::PlayerVideo(MessageQueue* messageQueue, UCHAR tIsRecording, UCHAR isRadio)
-: vfeed(this), afeed(this)
-{
- commandMessageQueue = messageQueue;
-
- logger = Log::getInstance();
- paused = 0;
- playing = 0;
- ffwd = 0;
- fbwd = 0;
- feedPosition = 0;
- feedMode = MODE_NORMAL;
- isRecording = tIsRecording;
- lastRescan = 0;
- startTS = 0;
- endTS = 0;
- startup = 1;
- threadBuffer = NULL;
-
- if (isRadio)
- {
- blockSize = 20000;
- startupBlockSize = 60000;
- }
- else
- {
- blockSize = 100000;
- startupBlockSize = 250000;
- }
-}
-
-PlayerVideo::~PlayerVideo()
-{
- if (initted) shutdown();
-}
-
-int PlayerVideo::init()
-{
- if (initted) return 0;
-
- video = Video::getInstance();
-
- if (!demuxer.init(this))
- {
- logger->log("Player", Log::ERR, "Demuxer failed to init");
- shutdown();
- return 0;
- }
-
- vfeed.init(video->getFD());
- afeed.init(audio->getFD());
-
- video->stop();
- video->blank();
- audio->stop();
-
- initted = 1;
- return 1;
-}
-
-int PlayerVideo::shutdown()
-{
- if (!initted) return 0;
- initted = 0;
-
- logger->log("Player", Log::DEBUG, "Player shutdown...");
-
- // copy of stop
- if (playing)
- {
- playing = 0;
- threadStop();
- video->stop();
- video->blank();
- audio->stop();
- vfeed.stop();
- afeed.stop();
- video->reset();
- demuxer.reset();
- feedPosition = 0;
- }
- logger->log("Player", Log::DEBUG, "Player shutdown done");
-
- return 1;
-}
-
-void PlayerVideo::resyncAudio()
-{
- // Temp hopefully
-
- if (!initted) return;
-
- audio->pause();
- usleep(500000); // SYNC
- audio->unPause();
-}
-
-int PlayerVideo::play()
-{
- if (!initted) return 0;
-
- // If we are just paused, unpause!
- if (paused)
- {
- togglePause();
- return 1;
- }
-
- // If we are fast forwarding, set to normal
- if (ffwd)
- {
- toggleFastForward();
- return 1;
- }
-
- // If we are fast backwarding, set to normal
- if (fbwd)
- {
- toggleFastBackward();
- return 1;
- }
-
- // If we are already playing, bail // FIXME - resync?
- if (playing)
- {
- logger->log("Player", Log::DEBUG, "DOING RESYNC");
-
-/*
- vfeed.stop();
- afeed.stop();
- video->reset();
- audio->reset();
- demuxer.flush();
- demuxer.seek();
- vfeed.start();
- afeed.start();
-
-
- video->play();
- audio->play();
- video->sync();
- audio->sync();
- call();
-*/
-
- // resync method 2..
-
- video->pause();
- usleep(500000);
- video->play();
- video->sync();
-
-
- return 1;
- }
-
- // Standard play start
-
- audio->reset();
- video->reset();
- demuxer.reset();
-
-// ------------------------ This one works, but doesn't allow any pre-buffering.
- threadStart();
- vfeed.start();
- afeed.start();
- audio->play();
- video->play();
- video->sync();
- audio->sync();
-
- video->pause();
- usleep(500000); // SYNC
- video->sync();
- video->unPause();
- video->sync();
-// ------------------------ This one doesn't work, but it should, and would allow for prebuffering.
-
-/*
- threadStart();
-// sleep(1);
-
-// struct timespec delay;
-// delay.tv_sec = 1;
-// delay.tv_nsec = 500000000;
-// nanosleep(&delay, NULL);
-
- vfeed.start();
- afeed.start();
- video->play();
- audio->play();
- video->sync();
- audio->sync();
-
- video->pause();
- usleep(500000); // SYNC
- video->sync();
- video->unPause();
- video->sync();
-*/
-
-// ------------------------------------------------------------------------------------------------
-
- playing = 1;
- return 1;
-}
-
-void PlayerVideo::stop()
-{
- if (!initted) return;
- if (!playing) return;
-
- if (ffwd || fbwd)
- {
- ffwd = 0;
- fbwd = 0;
- afeed.enable();
- video->unFastForward();
- audio->systemMuteOff();
- feedMode = MODE_NORMAL;
- }
-
- playing = 0;
- paused = 0;
-
- logger->log("PlayerVideo", Log::DEBUG, "Temp 1");
- threadStop();
- logger->log("PlayerVideo", Log::DEBUG, "Temp 2");
- video->stop();
- logger->log("PlayerVideo", Log::DEBUG, "Temp 3");
- video->blank();
- logger->log("PlayerVideo", Log::DEBUG, "Temp 4");
- audio->stop();
- logger->log("PlayerVideo", Log::DEBUG, "Temp 5");
- audio->unPause();
- logger->log("PlayerVideo", Log::DEBUG, "Temp 6");
- vfeed.stop();
- logger->log("PlayerVideo", Log::DEBUG, "Temp 7");
- afeed.stop();
- logger->log("PlayerVideo", Log::DEBUG, "Temp 8");
- video->reset();
- logger->log("PlayerVideo", Log::DEBUG, "Temp 9");
- demuxer.reset();
- logger->log("PlayerVideo", Log::DEBUG, "Temp 10");
-
- feedPosition = 0;
-}
-
-void PlayerVideo::togglePause()
-{
- if (!initted) return;
- if (!playing) return;
-
- if (ffwd) toggleFastForward();
- if (fbwd) toggleFastBackward();
-
- if (paused)
- {
- video->unPause();
- audio->unPause();
- paused = 0;
- }
- else
- {
- video->pause();
- audio->pause();
- paused = 1;
- }
-}
-
-void PlayerVideo::setPosition(ULLONG position)
-{
- feedPosition = position;
-}
-
-void PlayerVideo::setLength(ULLONG length)
-{
- lastRescan = time(NULL);
- streamLength = length;
- logger->log("PlayerVideo", Log::DEBUG, "Player has received length of %llu", streamLength);
-}
-
-void PlayerVideo::skipForward(int seconds)
-{
- // skip forward 1 minute
- logger->log("Player", Log::DEBUG, "SKIP FORWARD %i SECONDS", seconds);
-
- if (paused) togglePause();
-
- ULLONG moveBy = seconds * 500000;
-
- threadStop();
- vfeed.stop();
- afeed.stop();
- video->stop();
- video->reset();
- audio->reset();
- audio->doMuting(); // ???
- demuxer.flush();
- feedPosition += moveBy;
-
-// printf("Audio test %i\n", audio->test());
-
- vfeed.start();
- afeed.start();
- threadStart();
- audio->play();
- video->play();
- video->sync();
- audio->sync();
-
- video->pause();
- usleep(500000); // SYNC
- video->sync();
- video->unPause();
- video->sync();
-
-}
-
-void PlayerVideo::skipBackward(int seconds)
-{
- // skip forward 1 minute
- logger->log("Player", Log::DEBUG, "SKIP BACKWARD %i SECONDS", seconds);
-
- if (paused) togglePause();
-
- ULLONG moveBy = seconds * 500000;
-
- threadStop();
- vfeed.stop();
- afeed.stop();
- video->stop();
- audio->stop();
- video->reset();
- audio->reset();
- audio->doMuting(); // ???
- demuxer.flush();
- if (feedPosition > moveBy) feedPosition -= moveBy;
- vfeed.start();
- afeed.start();
- threadStart();
- audio->play();
- video->play();
- video->sync();
- audio->sync();
-
- video->pause();
- usleep(500000); // SYNC
- video->sync();
- video->unPause();
- video->sync();
-
-}
-
-void PlayerVideo::toggleFastForward()
-{
- if (!initted) return;
- if (!playing) return;
-
- if (paused) togglePause();
- if (fbwd) toggleFastBackward();
-
- if (ffwd)
- {
- ffwd = 0;
-// video->unFastForward();
-
-
- threadStop();
- vfeed.stop();
- afeed.stop();
- video->stop();
- audio->stop();
- video->reset();
- audio->reset();
- demuxer.flush();
-// demuxer.seek();
- vfeed.start();
- afeed.enable();
- afeed.start();
- threadStart();
- video->play();
- audio->play();
- video->sync();
- audio->sync();
-
- audio->systemMuteOff();
-
- video->pause();
- usleep(500000); // SYNC
- video->sync();
- video->unPause();
- video->sync();
-
-/*
- demuxer.flushAudio();
- audio->reset();
- afeed.enable();
- //video->reset();
- audio->play();
- video->play();
- video->sync();
- audio->sync();
- audio->systemMuteOff();
-*/
- }
- else
- {
- ffwd = 1;
- afeed.disable();
- audio->systemMuteOn();
- video->fastForward();
- }
-}
-
-void PlayerVideo::toggleFastBackward()
-{
- if (!initted) return;
- if (!playing) return;
-
- if (paused) togglePause();
- if (ffwd) toggleFastForward();
-
- if (fbwd)
- {
- fbwd = 0;
- afeed.enable();
- audio->systemMuteOff();
-
-// threadStop();
- feedMode = MODE_NORMAL;
-// threadStart();
- }
- else
- {
- fbwd = 1;
- afeed.disable();
- audio->systemMuteOn();
-
- threadStop();
- feedMode = MODE_BACKWARDS;
- video->reset();
- video->play();
- demuxer.flush();
- threadStart();
- }
-}
-
-void PlayerVideo::jumpToPercent(int percent)
-{
- if (paused) togglePause();
- if (ffwd) toggleFastForward();
-
- threadStop();
- vfeed.stop();
- afeed.stop();
- video->stop();
- audio->stop();
- video->reset();
- audio->reset();
- demuxer.flush();
- demuxer.seek();
- feedPosition = streamLength * percent / 100;
- vfeed.start();
- afeed.start();
- threadStart();
- audio->play();
- video->play();
- video->sync();
- audio->sync();
-
- video->pause();
- usleep(500000); // SYNC
- video->sync();
- video->unPause();
- video->sync();
-}
-
-ULLONG PlayerVideo::getPositionTS()
-{
- if (startup) return 0ULL;
- long long currentTS = video->getCurrentTimestamp() - startTS;
- if (currentTS < 0) currentTS += 8589934592ULL;
- return (ULLONG)currentTS;
-}
-
-ULLONG PlayerVideo::getEndTS()
-{
- long long rendTS = endTS - startTS;
- if (rendTS < 0) rendTS += 8589934592ULL;
- return (ULLONG)rendTS;
-}
-
-void PlayerVideo::call(void* caller)
-{
- if (caller == &demuxer)
- {
- logger->log("Player", Log::DEBUG, "Callback from demuxer");
-
- if (video->getTVsize() == Video::ASPECT4X3)
- {
- logger->log("Player", Log::DEBUG, "TV is 4:3, ignoring aspect switching");
- return;
- }
-
- int dxCurrentAspect = demuxer.getAspectRatio();
- if (dxCurrentAspect == Demuxer::ASPECT_4_3)
- {
- logger->log("Player", Log::DEBUG, "Demuxer said video is 4:3 aspect, switching TV");
- video->setAspectRatio(Video::ASPECT4X3);
- }
- else if (dxCurrentAspect == Demuxer::ASPECT_16_9)
- {
- logger->log("Player", Log::DEBUG, "Demuxer said video is 16:9 aspect, switching TV");
- video->setAspectRatio(Video::ASPECT16X9);
- }
- else
- {
- logger->log("Player", Log::DEBUG, "Demuxer said video is something else... ignoring");
- }
-
- }
- else
- {
- threadSignalNoLock();
- }
-}
-
-// Feed thread
-
-void PlayerVideo::threadMethod()
-{
- UINT thisRead;
- UINT writeLength;
- UINT thisWrite;
-
- VDR* vdr = VDR::getInstance();
-
- UINT askFor;
- while(1)
- {
- thisRead = 0;
- writeLength = 0;
- thisWrite = 0;
-
- threadCheckExit();
-
- // If we havn't rescanned for a while..
- if (isRecording && ((lastRescan + 60) < time(NULL)))
- {
- streamLength = vdr->rescanRecording();
- Log::getInstance()->log("PlayerVideo", Log::DEBUG, "Rescanned and reset length: %llu", streamLength);
- lastRescan = time(NULL);
- setEndTS();
- }
-
- if (streamLength) // is playing a recording
- {
- if (feedPosition >= streamLength) break; // finished playback
-
- if (startup)
- {
- if (startupBlockSize > streamLength)
- askFor = streamLength; // is a very small recording!
- else
- askFor = startupBlockSize; // normal, but a startup sized block to detect all the audio streams
- }
- else
- {
- if ((feedPosition + blockSize) > streamLength) // last block of recording
- askFor = streamLength - feedPosition;
- else // normal
- askFor = blockSize;
- }
- }
- else // is playing live
- {
- if (startup)
- askFor = startupBlockSize; // find audio streams sized block
- else
- askFor = blockSize; // normal
- }
-
- threadBuffer = vdr->getBlock(feedPosition, askFor, &thisRead);
- if (!threadBuffer) break;
-
- if (startup)
- {
- int a_stream = demuxer.scan(threadBuffer, thisRead);
- demuxer.setAudioStream(a_stream);
- Log::getInstance()->log("Player", Log::DEBUG, "Startup Audio stream chosen %x", a_stream);
-
- setStartTS(thisRead);
-
- if (isRecording) setEndTS();
-
- startup = 0;
- }
-
- if (feedMode == MODE_NORMAL)
- {
- feedPosition += thisRead;
- }
- else if (feedMode == MODE_BACKWARDS)
- {
- if (feedPosition >= blockSize)
- {
- feedPosition -= blockSize;
- demuxer.seek();
- }
- else
- {
- // got to the start of the recording.. revert to play mode? how?
- feedPosition += thisRead;
- }
- }
-
- threadCheckExit();
-
- while(writeLength < thisRead)
- {
- thisWrite = demuxer.put(threadBuffer + writeLength, thisRead - writeLength);
- writeLength += thisWrite;
-
- if (!thisWrite)
- {
-// Log::getInstance()->log("Player", Log::DEBUG, "DEMUXER FULL!!!");
- // demuxer is full and cant take anymore
- threadLock();
- threadWaitForSignal();
- threadUnlock();
-// Log::getInstance()->log("Player", Log::DEBUG, "BACK FROM WAIT");
- }
-
- threadCheckExit();
- }
-
- free(threadBuffer);
- threadBuffer = NULL;
-
- }
-
- // end of recording
- Log::getInstance()->log("Player", Log::DEBUG, "Recording playback ends");
- Message* m = new Message(); // Must be done after this thread finishes, and must break into master mutex
- if (streamLength) m->message = Message::STOP_PLAYBACK; // recording
- else m->message = Message::STREAM_END; // live
- Log::getInstance()->log("Player", Log::DEBUG, "Posting message to %p...", commandMessageQueue);
- commandMessageQueue->postMessage(m);
- Log::getInstance()->log("Player", Log::DEBUG, "Message posted...");
-}
-
-void PlayerVideo::threadPostStopCleanup()
-{
- Log::getInstance()->log("Player", Log::DEBUG, "Post stop cleanup 1");
- if (threadBuffer)
- {
- Log::getInstance()->log("Player", Log::DEBUG, "Post stop cleanup 2");
- free(threadBuffer);
- threadBuffer = NULL;
- }
-}
-
-void PlayerVideo::setStartTS(UINT dataInBuffer)
-{
- if (isRecording && feedPosition) // (feedPosition != 0)
- {
- // FIXME find out how much data need to get to find a TS
- // Need to get the actual start of the recording
-
- UINT thisRead;
- UCHAR* tempBuffer = VDR::getInstance()->getBlock(0, 100000, &thisRead);
- if (!tempBuffer) return;
- if (thisRead) demuxer.findVideoPTS(tempBuffer, thisRead, &startTS);
- free(tempBuffer);
- }
- else
- {
- demuxer.findVideoPTS(threadBuffer, dataInBuffer, &startTS);
- }
-}
-
-void PlayerVideo::setEndTS()
-{
- Log::getInstance()->log("Player", Log::DEBUG, "Setting end TS");
-
- UINT thisRead;
- UCHAR* tempBuffer = VDR::getInstance()->getBlock((streamLength - 100000), 100000, &thisRead);
- if (!tempBuffer) return;
- if (thisRead) demuxer.findVideoPTS(tempBuffer, thisRead, &endTS);
- free(tempBuffer);
- Log::getInstance()->log("Player", Log::DEBUG, "Set end TS");
-}
-
-#ifdef DEV
-void PlayerVideo::test1()
-{
- Log::getInstance()->log("Player", Log::DEBUG, "PLAYER TEST 1");
-}
-
-void PlayerVideo::test2()
-{
- Log::getInstance()->log("Player", Log::DEBUG, "PLAYER TEST 2");
-}
-#endif
+++ /dev/null
-/*
- Copyright 2004-2005 Chris Tallon
-
- This file is part of VOMP.
-
- VOMP 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.
-
- VOMP 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 VOMP; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef PLAYERVIDEO_H
-#define PLAYERVIDEO_H
-
-#include <stdio.h>
-
-#include "player.h"
-#include "audio.h"
-#include "video.h"
-#include "demuxer.h"
-#include "vfeed.h"
-#include "afeed.h"
-#include "remote.h"
-#include "thread.h"
-#include "vdr.h"
-#include "callback.h"
-#include "message.h"
-#include "messagequeue.h"
-
-class PlayerVideo : public Player
-{
- public:
- PlayerVideo(MessageQueue* messageQueue, UCHAR isRecording, UCHAR isRadio);
- virtual ~PlayerVideo();
-
- int init();
- int shutdown();
-
- int play();
- void stop();
- void togglePause();
- void toggleFastForward();
- void toggleFastBackward();
- void jumpToPercent(int percent);
- void skipForward(int seconds);
- void skipBackward(int seconds);
- void call(void*); // for callback interface
- void setPosition(ULLONG position);
- void setLength(ULLONG length);
- void resyncAudio();
- ULLONG getPositionTS();
- ULLONG getEndTS();
-
- bool isPaused() { return paused; }
- bool isFfwd() { return ffwd; }
- bool isFbwd() { return fbwd; }
-
-#ifdef DEV
- void test1();
- void test2();
-#endif
-
- void threadMethod();
- void threadPostStopCleanup();
-
- private:
- void setStartTS(UINT dataInBuffer);
- void setEndTS();
-
- MessageQueue* commandMessageQueue;
- Log* logger;
- Video* video;
- Demuxer demuxer;
- int startup;
- VFeed vfeed;
- AFeed afeed;
-
- ULLONG startTS;
- ULLONG endTS;
- ULLONG feedPosition;
- UCHAR feedMode;
- UCHAR isRecording;
- time_t lastRescan;
- UINT blockSize;
- UINT startupBlockSize;
- const static UCHAR MODE_NORMAL = 1;
- const static UCHAR MODE_BACKWARDS = 2;
- UCHAR* threadBuffer;
-
- UCHAR playing; // As in not stopped, (playing && paused) can == TRUE
- UCHAR paused; // Must be in playing state as well
- UCHAR ffwd; // Must be in playing state as well
- UCHAR fbwd; // Must be in playing state as well
-};
-
-#endif
initted = true;\r
logger = Log::getInstance();\r
\r
- logger->log("Timers", Log::DEBUG, "Timers init start");\r
-\r
threadLock(); // lock here, the thread loop will unlock and wait\r
//logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 1");\r
if (!threadStart())\r
return 0;\r
}\r
\r
- logger->log("Timers", Log::DEBUG, "Timers init end");\r
-\r
return 1;\r
}\r
\r
\r
if (nextTimer)\r
{\r
- logger->log("Timers", Log::DEBUG, "List size: %i. nextTimerClient: %p/%i. nextTime.tv_sec: %li. nextTime.tv_nsec: %li", timerList.size(), nextTimer->client, nextTimer->clientReference, nextTime.tv_sec, nextTime.tv_nsec);\r
+//## logger->log("Timers", Log::DEBUG, "List size: %i. nextTimerClient: %p/%i. nextTime.tv_sec: %li. nextTime.tv_nsec: %li", timerList.size(), nextTimer->client, nextTimer->clientReference, nextTime.tv_sec, nextTime.tv_nsec);\r
\r
\r
//logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX (1)");\r
\r
// timer ran out\r
\r
- Log::getInstance()->log("Timers", Log::DEBUG, "Timer firing for client %p ref %i", nextTimer->client, nextTimer->clientReference);\r
+//## Log::getInstance()->log("Timers", Log::DEBUG, "Timer firing for client %p ref %i", nextTimer->client, nextTimer->clientReference);\r
\r
// send this timer to the timer receiver, via the command message queue\r
// so that the gui mutex is locked when it happens\r
if (chan == NULL) return 2;
- // if (chan->type == VDR::RADIO) return 2;
-
VVideoLive* v = new VVideoLive(chanList, chan->type, this);
v->draw();
#include "vdr.h"
#include "channel.h"
#include "vvideolive.h"
-#include "vradiolive.h"
#include "colour.h"
#include "video.h"
#include "i18n.h"
{
d = new Directory();
d->setName(dirName);
- Log::getInstance()->log("VDR", Log::DEBUG, "Added a new directory = %s", d->name);
+// Log::getInstance()->log("VDR", Log::DEBUG, "Added a new directory = %s", d->name);
recDir->dirList.push_back(d);
}
recDir->recList.push_back(rec);
}
- Log::getInstance()->log("VDR", Log::DEBUG, "%s", rec->fileName);
+// Log::getInstance()->log("VDR", Log::DEBUG, "%s", rec->fileName);
}
freePacket();
vlen = Demuxer::getInstance()->writeVideo(fd); // FIXME
if (vlen)
{
- // Log::getInstance()->log("VFeed", Log::DEBUG, "Written %i", vlen);
+// Log::getInstance()->log("VFeed", Log::DEBUG, "Written %i", vlen);
cb.call(this);
}
else
{
+// Log::getInstance()->log("VFeed", Log::DEBUG, "No data delay");
nanosleep(&delayTime, NULL);
}
}
+++ /dev/null
-/*
- Copyright 2004-2005 Chris Tallon
-
- This file is part of VOMP.
-
- VOMP 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.
-
- VOMP 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 VOMP; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "vradiolive.h"
-
-VRadioLive::VRadioLive(ChannelList* tchanList)
-{
- player = new PlayerRadio();
- player->init();
- vdr = VDR::getInstance();
- chanList = tchanList;
- currentChannel = 0;
-
- create(100, 100);
- setBackgroundColour(Colour::VIEWBACKGROUND);
-}
-
-VRadioLive::~VRadioLive()
-{
- delete player;
-}
-
-void VRadioLive::draw()
-{
- View::draw();
-}
-
-int VRadioLive::handleCommand(int command)
-{
- switch(command)
- {
- case Remote::STOP:
- case Remote::BACK:
- case Remote::MENU:
- {
- player->stop();
- vdr->stopStreaming();
- return 4;
- }
- case Remote::DF_UP:
- case Remote::UP:
- {
- player->stop();
- vdr->stopStreaming();
- upChannel();
- vdr->streamChannel((*chanList)[currentChannel]->number);
- player->play();
- return 2;
- }
- case Remote::DF_DOWN:
- case Remote::DOWN:
- {
- player->stop();
- vdr->stopStreaming();
- downChannel();
- vdr->streamChannel((*chanList)[currentChannel]->number);
- player->play();
- return 2;
- }
- }
-
- return 1;
-}
-
-void VRadioLive::setChannel(UINT number)
-{
- currentChannel = channelIndexFromNumber(number);
- vdr->streamChannel((*chanList)[currentChannel]->number);
- player->play();
-}
-
-void VRadioLive::upChannel()
-{
- if (currentChannel == (chanList->size() - 1)) return; // at the end
-
- ++currentChannel;
-}
-
-void VRadioLive::downChannel()
-{
- if (currentChannel == 0) return; // at the start
-
- --currentChannel;
-}
-
-UINT VRadioLive::channelIndexFromNumber(int number)
-{
- for(UINT i = 0; i < chanList->size(); i++)
- {
- if ((*chanList)[i]->number == (UINT)number) return i;
- }
- return 0;
-}
-
+++ /dev/null
-/*
- Copyright 2004-2005 Chris Tallon
-
- This file is part of VOMP.
-
- VOMP 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.
-
- VOMP 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 VOMP; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef VRADIOLIVE_H
-#define VRADIOLIVE_H
-
-#include <stdio.h>
-#include <vector>
-
-#include "view.h"
-#include "playerradio.h"
-#include "vdr.h"
-#include "channel.h"
-#include "viewman.h"
-#include "remote.h"
-#include "colour.h"
-
-class VRadioLive : public View
-{
- public:
- VRadioLive(ChannelList* chanList);
- ~VRadioLive();
- void draw();
- int handleCommand(int command);
-
- void setChannel(UINT number);
-
- private:
- VDR* vdr;
- PlayerRadio* player;
- ChannelList* chanList;
- UINT currentChannel;
-
- void upChannel();
- void downChannel();
- UINT channelIndexFromNumber(int number);
-};
-
-#endif
unavailableView = NULL;
streamType = tstreamType;
videoMode = video->getMode();
- if (streamType == VDR::RADIO) player = new PlayerVideo(Command::getInstance(), 0, 1);
- else player = new PlayerVideo(Command::getInstance(), 0, 0);
+ if (streamType == VDR::RADIO) player = new Player(Command::getInstance(), 0, 1);
+ else player = new Player(Command::getInstance(), 0, 0);
player->init();
create(video->getScreenWidth(), video->getScreenHeight());
#include <vector>
#include "view.h"
-#include "playervideo.h"
-#include "playerradio.h"
+#include "player.h"
#include "vdr.h"
#include "channel.h"
#include "vlivebanner.h"
VVideoRec::VVideoRec(Recording* rec)
{
- player = new PlayerVideo(Command::getInstance(), 1, 0); // say 0 for radio because buffering will work anyway
- player->init();
vdr = VDR::getInstance();
video = Video::getInstance();
timers = Timers::getInstance();
+ player = new Player(Command::getInstance(), 1, 0); // say 0 for radio because buffering will work anyway
+ player->init();
+
videoMode = video->getMode();
myRec = rec;
+ playing = false;
+
+ startMargin = 0;
+ endMargin = 0;
+ char* cstartMargin = vdr->configLoad("Timers", "Start margin");
+ char* cendMargin = vdr->configLoad("Timers", "End margin");
+ if (!cstartMargin)
+ {
+ startMargin = 300; // 5 mins default
+ }
+ else
+ {
+ startMargin = atoi(cstartMargin) * 60;
+ delete[] cstartMargin;
+ }
+
+ if (!cendMargin)
+ {
+ endMargin = 300; // 5 mins default
+ }
+ else
+ {
+ endMargin = atoi(cendMargin) * 60;
+ delete[] cendMargin;
+ }
+
+ Log::getInstance()->log("VVideoRec", Log::DEBUG, "SM: %u EM: %u", startMargin, endMargin);
+
create(video->getScreenWidth(), video->getScreenHeight());
transparent.set(0, 0, 0, 0);
setBackgroundColour(transparent);
barRegion.w = video->getScreenWidth();
barRegion.h = 66;
- clocksRegion.x = barRegion.x + 180;
+ clocksRegion.x = barRegion.x + 160;
clocksRegion.y = barRegion.y + 12;
- clocksRegion.w = 200;
+ clocksRegion.w = 170;
clocksRegion.h = surface->getFontHeight();
barBlue.set(0, 0, 150, 150);
VVideoRec::~VVideoRec()
{
- Log::getInstance()->log("VVideoRec", Log::DEBUG, "Pre delete player");
- delete player;
- Log::getInstance()->log("VVideoRec", Log::DEBUG, "Post delete player");
+ if (playing) stopPlay();
Video::getInstance()->setDefaultAspect();
timers->cancelTimer(this, 1);
player->setLength(recLength);
player->setPosition(startPosition);
player->play();
+ playing = true;
}
else
{
{
case Remote::PLAY:
{
- player->play(); // do resync
+ player->play();
+ doBar(0);
return 2;
}
case Remote::BACK:
case Remote::MENU:
{
- Log::getInstance()->log("VVideoRec", Log::DEBUG, "Pre player stop");
-
- // FIXME work out a better soln for this
- // Fix a problem to do with thread sync here
- // because the bar gets a timer every 0.2s and it seems to take up to 0.1s,
- // (or maybe just the wrong thread being selected?) for the main loop to lock and process
- // the video stop message it is possible for a bar message to stack up after a stop message
- // when the bar message is finally processed the prog crashes because this is deleted by then
- removeBar();
- //
-
- player->stop();
- vdr->stopStreaming();
-
- Log::getInstance()->log("VVideoRec", Log::DEBUG, "Post player stop");
+ if (playing) stopPlay();
return 4;
}
case Remote::PAUSE:
case Remote::OK:
{
- doBar(0);
+ if (barShowing) removeBar();
+ else doBar(0);
return 2;
}
// return 2;
// }
- case Remote::ZERO: player->jumpToPercent(0); return 2;
- case Remote::ONE: player->jumpToPercent(10); return 2;
- case Remote::TWO: player->jumpToPercent(20); return 2;
- case Remote::THREE: player->jumpToPercent(30); return 2;
- case Remote::FOUR: player->jumpToPercent(40); return 2;
- case Remote::FIVE: player->jumpToPercent(50); return 2;
- case Remote::SIX: player->jumpToPercent(60); return 2;
- case Remote::SEVEN: player->jumpToPercent(70); return 2;
- case Remote::EIGHT: player->jumpToPercent(80); return 2;
- case Remote::NINE: player->jumpToPercent(90); return 2;
+ case Remote::ZERO: player->jumpToPercent(0); doBar(0); return 2;
+ case Remote::ONE: player->jumpToPercent(10); doBar(0); return 2;
+ case Remote::TWO: player->jumpToPercent(20); doBar(0); return 2;
+ case Remote::THREE: player->jumpToPercent(30); doBar(0); return 2;
+ case Remote::FOUR: player->jumpToPercent(40); doBar(0); return 2;
+ case Remote::FIVE: player->jumpToPercent(50); doBar(0); return 2;
+ case Remote::SIX: player->jumpToPercent(60); doBar(0); return 2;
+ case Remote::SEVEN: player->jumpToPercent(70); doBar(0); return 2;
+ case Remote::EIGHT: player->jumpToPercent(80); doBar(0); return 2;
+ case Remote::NINE: player->jumpToPercent(90); doBar(0); return 2;
#ifdef DEV
case Remote::RED:
return 1;
}
+void VVideoRec::stopPlay()
+{
+ Log::getInstance()->log("VVideoRec", Log::DEBUG, "Pre stopPlay");
+
+ // FIXME work out a better soln for this
+ // Fix a problem to do with thread sync here
+ // because the bar gets a timer every 0.2s and it seems to take up to 0.1s,
+ // (or maybe just the wrong thread being selected?) for the main loop to lock and process
+ // the video stop message it is possible for a bar message to stack up after a stop message
+ // when the bar message is finally processed the prog crashes because this is deleted by then
+ removeBar();
+ //
+
+ player->stop();
+ vdr->stopStreaming();
+ delete player;
+
+ playing = false;
+
+ Log::getInstance()->log("VVideoRec", Log::DEBUG, "Post stopPlay");
+}
+
void VVideoRec::toggleChopSides()
{
if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
snprintf(buffer, 99, "%01i:%02i:%02i / %01i:%02i:%02i", chours, cminutes, cseconds, ehours, eminutes, eseconds);
}
- drawText(buffer, barRegion.x + 180, barRegion.y + 12, Colour::LIGHTTEXT);
+ drawText(buffer, clocksRegion.x, clocksRegion.y, Colour::LIGHTTEXT);
+
+ // Draw progress bar
+
+ rectangle(barRegion.x + 350, barRegion.y + 12, 310, 24, Colour::LIGHTTEXT);
+ rectangle(barRegion.x + 352, barRegion.y + 14, 306, 20, barBlue);
+
+ if ((currentTS > 95441) || (!endTS)) return; // No values yet
+
+ double progress01 = (double)currentTS / (double)endTS;
+ // total width of bar = 302
+ int progressWidth = (int)(302 * progress01);
+
+ rectangle(barRegion.x + 354, barRegion.y + 16, progressWidth, 16, Colour::SELECTHIGHLIGHT);
+
+ // Now calc position for start margin blips
+ double pos01;
+ int posPix;
+
+ pos01 = (double)startMargin / (double)endTS;
+ posPix = (int)(302 * pos01);
+
+ rectangle(barRegion.x + 352 + posPix, barRegion.y + 12 - 2, 2, 2, Colour::LIGHTTEXT);
+ rectangle(barRegion.x + 352 + posPix, barRegion.y + 12 + 24, 2, 2, Colour::LIGHTTEXT);
+
+ pos01 = (double)(endTS - endMargin) / (double)endTS;
+ posPix = (int)(302 * pos01);
+
+ rectangle(barRegion.x + 352 + posPix, barRegion.y + 12 - 2, 2, 2, Colour::LIGHTTEXT);
+ rectangle(barRegion.x + 352 + posPix, barRegion.y + 12 + 24, 2, 2, Colour::LIGHTTEXT);
}
void VVideoRec::removeBar()
{
+ if (!barShowing) return;
timers->cancelTimer(this, 2);
barShowing = false;
rectangle(barRegion, transparent);
#include <stdio.h>
#include "view.h"
-#include "playervideo.h"
+#include "player.h"
#include "vdr.h"
#include "recording.h"
#include "command.h"
UCHAR videoMode;
void toggleChopSides();
+ bool playing;
bool barShowing;
void doBar(int action);
void drawBarClocks();
+ void stopPlay();
void removeBar();
Region barRegion;
Region clocksRegion;
+
+ UINT startMargin;
+ UINT endMargin;
};
#endif