From f5d2258b234f76c319e3a80a83922cae3caa337c Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Sat, 11 Mar 2006 18:17:01 +0000 Subject: [PATCH] Clean up of player system. Progress bar on recording playback --- Makefile | 3 +- afeed.cc | 3 +- command.cc | 8 +- messagequeue.cc | 2 +- player.cc | 652 ++++++++++++++++++++++++++++++++++++++++++- player.h | 98 +++++-- playerradio.cc | 383 ------------------------- playerradio.h | 79 ------ playervideo.cc | 727 ------------------------------------------------ playervideo.h | 105 ------- timers.cc | 8 +- vchannellist.cc | 2 - vchannellist.h | 1 - vdr.cc | 4 +- vfeed.cc | 3 +- vradiolive.cc | 111 -------- vradiolive.h | 56 ---- vvideolive.cc | 4 +- vvideolive.h | 3 +- vvideorec.cc | 138 ++++++--- vvideorec.h | 7 +- 21 files changed, 841 insertions(+), 1556 deletions(-) delete mode 100644 playerradio.cc delete mode 100644 playerradio.h delete mode 100644 playervideo.cc delete mode 100644 playervideo.h delete mode 100644 vradiolive.cc delete mode 100644 vradiolive.h diff --git a/Makefile b/Makefile index ae4b849..9df68d4 100644 --- a/Makefile +++ b/Makefile @@ -13,13 +13,12 @@ CROSSLIBS = ../jpeg-6b/libjpeg.a 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 diff --git a/afeed.cc b/afeed.cc index 8ff3f07..7035087 100644 --- a/afeed.cc +++ b/afeed.cc @@ -76,11 +76,12 @@ void AFeed::threadMethod() 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); } } diff --git a/command.cc b/command.cc index 6dbe17b..7409b30 100644 --- a/command.cc +++ b/command.cc @@ -575,9 +575,9 @@ void Command::doJustConnected(VConnect* vconnect) 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); } diff --git a/messagequeue.cc b/messagequeue.cc index d88d6ed..78d0b48 100644 --- a/messagequeue.cc +++ b/messagequeue.cc @@ -23,7 +23,7 @@ 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() diff --git a/player.cc b/player.cc index 3d07a1e..81cc055 100644 --- a/player.cc +++ b/player.cc @@ -20,14 +20,656 @@ #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 diff --git a/player.h b/player.h index 0032356..c490c0c 100644 --- a/player.h +++ b/player.h @@ -21,50 +21,88 @@ #ifndef PLAYER_H #define PLAYER_H +#include + +#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 diff --git a/playerradio.cc b/playerradio.cc deleted file mode 100644 index 419391e..0000000 --- a/playerradio.cc +++ /dev/null @@ -1,383 +0,0 @@ -/* - 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"); -*/ - } -} diff --git a/playerradio.h b/playerradio.h deleted file mode 100644 index c396976..0000000 --- a/playerradio.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - 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 - -#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 diff --git a/playervideo.cc b/playervideo.cc deleted file mode 100644 index cd805e3..0000000 --- a/playervideo.cc +++ /dev/null @@ -1,727 +0,0 @@ -/* - 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 diff --git a/playervideo.h b/playervideo.h deleted file mode 100644 index f94843e..0000000 --- a/playervideo.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - 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 - -#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 diff --git a/timers.cc b/timers.cc index 5b5b79f..e530759 100755 --- a/timers.cc +++ b/timers.cc @@ -45,8 +45,6 @@ int Timers::init() initted = true; logger = Log::getInstance(); - logger->log("Timers", Log::DEBUG, "Timers init start"); - threadLock(); // lock here, the thread loop will unlock and wait //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 1"); if (!threadStart()) @@ -55,8 +53,6 @@ int Timers::init() return 0; } - logger->log("Timers", Log::DEBUG, "Timers init end"); - return 1; } @@ -246,7 +242,7 @@ void Timers::threadMethod() if (nextTimer) { - 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); +//## 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); //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX (1)"); @@ -275,7 +271,7 @@ void Timers::threadMethod() // timer ran out - Log::getInstance()->log("Timers", Log::DEBUG, "Timer firing for client %p ref %i", nextTimer->client, nextTimer->clientReference); +//## Log::getInstance()->log("Timers", Log::DEBUG, "Timer firing for client %p ref %i", nextTimer->client, nextTimer->clientReference); // send this timer to the timer receiver, via the command message queue // so that the gui mutex is locked when it happens diff --git a/vchannellist.cc b/vchannellist.cc index 554cf72..eca6ae1 100644 --- a/vchannellist.cc +++ b/vchannellist.cc @@ -206,8 +206,6 @@ int VChannelList::handleCommand(int command) if (chan == NULL) return 2; - // if (chan->type == VDR::RADIO) return 2; - VVideoLive* v = new VVideoLive(chanList, chan->type, this); v->draw(); diff --git a/vchannellist.h b/vchannellist.h index 4feeb11..13c747e 100644 --- a/vchannellist.h +++ b/vchannellist.h @@ -33,7 +33,6 @@ #include "vdr.h" #include "channel.h" #include "vvideolive.h" -#include "vradiolive.h" #include "colour.h" #include "video.h" #include "i18n.h" diff --git a/vdr.cc b/vdr.cc index 2ce5514..3b12f9d 100644 --- a/vdr.cc +++ b/vdr.cc @@ -347,7 +347,7 @@ Directory* VDR::getRecordingsList() { 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); } @@ -358,7 +358,7 @@ Directory* VDR::getRecordingsList() recDir->recList.push_back(rec); } - Log::getInstance()->log("VDR", Log::DEBUG, "%s", rec->fileName); +// Log::getInstance()->log("VDR", Log::DEBUG, "%s", rec->fileName); } freePacket(); diff --git a/vfeed.cc b/vfeed.cc index 7ce9ad0..b7d6a26 100644 --- a/vfeed.cc +++ b/vfeed.cc @@ -60,11 +60,12 @@ void VFeed::threadMethod() 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); } } diff --git a/vradiolive.cc b/vradiolive.cc deleted file mode 100644 index 08b76cc..0000000 --- a/vradiolive.cc +++ /dev/null @@ -1,111 +0,0 @@ -/* - 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; -} - diff --git a/vradiolive.h b/vradiolive.h deleted file mode 100644 index 8457082..0000000 --- a/vradiolive.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - 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 -#include - -#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 diff --git a/vvideolive.cc b/vvideolive.cc index 7fb9685..b669598 100644 --- a/vvideolive.cc +++ b/vvideolive.cc @@ -38,8 +38,8 @@ VVideoLive::VVideoLive(ChannelList* tchanList, ULONG tstreamType, VChannelList* 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()); diff --git a/vvideolive.h b/vvideolive.h index 8d2d1c5..f4de463 100644 --- a/vvideolive.h +++ b/vvideolive.h @@ -25,8 +25,7 @@ #include #include "view.h" -#include "playervideo.h" -#include "playerradio.h" +#include "player.h" #include "vdr.h" #include "channel.h" #include "vlivebanner.h" diff --git a/vvideorec.cc b/vvideorec.cc index c97f984..d4d921e 100644 --- a/vvideorec.cc +++ b/vvideorec.cc @@ -22,15 +22,44 @@ 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); @@ -40,9 +69,9 @@ VVideoRec::VVideoRec(Recording* rec) 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); @@ -52,9 +81,7 @@ VVideoRec::VVideoRec(Recording* rec) 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); @@ -75,6 +102,7 @@ void VVideoRec::go(ULLONG startPosition) player->setLength(recLength); player->setPosition(startPosition); player->play(); + playing = true; } else { @@ -112,7 +140,8 @@ int VVideoRec::handleCommand(int command) { case Remote::PLAY: { - player->play(); // do resync + player->play(); + doBar(0); return 2; } @@ -120,21 +149,7 @@ int VVideoRec::handleCommand(int command) 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: @@ -182,7 +197,8 @@ int VVideoRec::handleCommand(int command) case Remote::OK: { - doBar(0); + if (barShowing) removeBar(); + else doBar(0); return 2; } @@ -193,16 +209,16 @@ int VVideoRec::handleCommand(int command) // 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: @@ -233,6 +249,28 @@ int VVideoRec::handleCommand(int command) 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 @@ -350,11 +388,41 @@ void VVideoRec::drawBarClocks() 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); diff --git a/vvideorec.h b/vvideorec.h index e8fbbae..482813b 100644 --- a/vvideorec.h +++ b/vvideorec.h @@ -24,7 +24,7 @@ #include #include "view.h" -#include "playervideo.h" +#include "player.h" #include "vdr.h" #include "recording.h" #include "command.h" @@ -61,12 +61,17 @@ class VVideoRec : public View, public TimerReceiver 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 -- 2.39.2