From 6165fa1e7826eb95dedf93acb12135fb4a6cbd38 Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Wed, 13 Dec 2006 16:11:12 +0000 Subject: [PATCH] Cut marks support --- mark.cc | 30 ++++++++++++++++ mark.h | 37 ++++++++++++++++++++ objects.mk | 2 +- player.cc | 8 +++++ player.h | 1 + readme.win | 3 ++ recording.cc | 81 ++++++++++++++++++++++++++++++++++++++++--- recording.h | 14 +++++++- vdr.cc | 51 +++++++++++++++++++++++++++ vdr.h | 4 +++ vrecordinglist.cc | 1 + vvideorec.cc | 87 ++++++++++++++++++++++++++++++++++++++++++----- 12 files changed, 305 insertions(+), 14 deletions(-) create mode 100644 mark.cc create mode 100644 mark.h diff --git a/mark.cc b/mark.cc new file mode 100644 index 0000000..7590f58 --- /dev/null +++ b/mark.cc @@ -0,0 +1,30 @@ +/* + 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 "mark.h" + +Mark::Mark() +{ + pos = 0; +} + +Mark::~Mark() +{ +} diff --git a/mark.h b/mark.h new file mode 100644 index 0000000..7dbc0d5 --- /dev/null +++ b/mark.h @@ -0,0 +1,37 @@ +/* + 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 MARK_H +#define MARK_H + +#include + +#include "defines.h" + + +class Mark +{ + public: + Mark(); + ~Mark(); + int pos; +}; + +#endif diff --git a/objects.mk b/objects.mk index 001562e..039988e 100644 --- a/objects.mk +++ b/objects.mk @@ -1,7 +1,7 @@ OBJECTS1 = command.o log.o tcp.o dsock.o thread.o timers.o i18n.o mutex.o \ message.o messagequeue.o udp.o \ vdr.o recman.o recording.o recinfo.o channel.o rectimer.o event.o \ - directory.o \ + directory.o mark.o \ player.o playerradio.o vfeed.o afeed.o \ demuxer.o demuxervdr.o stream.o draintarget.o \ viewman.o box.o region.o colour.o view.o \ diff --git a/player.cc b/player.cc index f35a8a2..e613ca2 100644 --- a/player.cc +++ b/player.cc @@ -256,6 +256,14 @@ void Player::jumpToPercent(int percent) // unLock(); - let thread unlock this } +void Player::jumpToMark(int mark) +{ + lock(); + logger->log("Player", Log::DEBUG, "JUMP TO MARK %i%%", mark); + switchState(S_JUMP, mark); +// unLock(); - let thread unlock this +} + void Player::skipForward(int seconds) { lock(); diff --git a/player.h b/player.h index 3de7e5a..2731d37 100644 --- a/player.h +++ b/player.h @@ -66,6 +66,7 @@ class Player : public Thread_TYPE, public Callback void jumpToPercent(int percent); void skipForward(int seconds); void skipBackward(int seconds); + void jumpToMark(int mark); UCHAR getState() { return state; } ULONG getCurrentFrameNum(); diff --git a/readme.win b/readme.win index 898a99e..5019a2f 100644 --- a/readme.win +++ b/readme.win @@ -29,6 +29,7 @@ Compatibility List for MPEG2 Decoders Compatible MPEG2 decoders: * Cyberlink PowerDVD 6 +* Nero Showtime 2 (from Nero Suite 6) Incompatible MPEG2 decoders: * Cyperlink PowerDVD 4 @@ -91,6 +92,8 @@ PREVCHANNEL | Not implemented STAR | * HASH | Not implemented +Use Alt-Enter to toggle full screen mode. + Remote Controls tested with vomp on windows =========================================== diff --git a/recording.cc b/recording.cc index 67aee09..5f7b381 100644 --- a/recording.cc +++ b/recording.cc @@ -25,10 +25,14 @@ RecInfo* Recording::recInfo = NULL; Recording::Recording() { + logger = Log::getInstance(); + vdr = VDR::getInstance(); + start = 0; progName = NULL; fileName = NULL; index = -1; + markList = NULL; } Recording::~Recording() @@ -36,6 +40,18 @@ Recording::~Recording() if (progName) { delete[] progName; progName = NULL; } if (fileName) { delete[] fileName; fileName = NULL; } index = -1; // just in case + + if (markList && markList->size()) + { + for(UINT i = 0; i < markList->size(); i++) + { + delete (*markList)[i]; + } + markList->clear(); + Log::getInstance()->log("Recording", Log::DEBUG, "Recording destructor, marks list deleted"); + } + + if (markList) delete markList; } ULONG Recording::getStartTime() const @@ -80,7 +96,7 @@ void Recording::loadRecInfo() if (recInfo) delete recInfo; recInfoFor = this; - recInfo = VDR::getInstance()->getRecInfo(fileName); + recInfo = vdr->getRecInfo(fileName); Log::getInstance()->log("Recording", Log::DEBUG, "Recording has loaded recInfo %p", recInfo); } @@ -91,11 +107,13 @@ void Recording::dropRecInfo() recInfoFor = NULL; } -bool Recording::isRadio() +void Recording::loadMarks() { - VDR* vdr = VDR::getInstance(); - if (!vdr) return false; + markList = vdr->getMarks(fileName); +} +bool Recording::isRadio() +{ ULONG lengthFrames = 0; ULLONG lengthBytes = vdr->streamRecording(getFileName(), &lengthFrames); if (!lengthBytes || !lengthFrames) return false; @@ -123,3 +141,58 @@ bool Recording::isRadio() return false; } +int Recording::getPrevMark(int currentFrame) +{ + MarkList::reverse_iterator i; + Mark* loopMark = NULL; + + if (!markList || !markList->size()) return 0; + + for(i = markList->rbegin(); i != markList->rend(); i++) + { + loopMark = *i; + logger->log("Recording", Log::NOTICE, "findprev:comparing Frame %i with current Frame %i",loopMark->pos,currentFrame); + + if (loopMark->pos < currentFrame) + { + logger->log("Recording", Log::NOTICE, "findprev:setting pos %i to jumpframe_target",loopMark->pos); + return loopMark->pos; + } + } + + // No previous mark + return 0; +} + +int Recording::getNextMark(int currentFrame) +{ + MarkList::iterator i; + Mark* loopMark = NULL; + + if (!markList || !markList->size()) return 0; + + for(i = markList->begin(); i != markList->end(); i++) + { + loopMark = *i; + logger->log("Recording", Log::NOTICE, "findnext:comparing Frame %i with current Frame %i",loopMark->pos,currentFrame); + + if (loopMark->pos > currentFrame) + { + logger->log("Recording", Log::NOTICE, "findnext:setting pos %i to jumpframe_target",loopMark->pos); + return loopMark->pos; + } + } + + // No next mark + return 0; +} + +bool Recording::hasMarks() +{ + return (markList && markList->size()); +} + +MarkList* Recording::getMarkList() +{ + return markList; +} diff --git a/recording.h b/recording.h index e1eaba5..14b6c0f 100644 --- a/recording.h +++ b/recording.h @@ -26,7 +26,8 @@ #include "defines.h" #include "vdr.h" #include "recinfo.h" - +#include "mark.h" +#include "log.h" #include "demuxer.h" class Recording @@ -50,9 +51,18 @@ class Recording bool isRadio(); + void loadMarks(); + int getPrevMark(int currentFrame); + int getNextMark(int currentFrame); + bool hasMarks(); + MarkList* getMarkList(); + static RecInfo* recInfo; private: + Log* logger; + VDR* vdr; + ULONG start; char* progName; char* fileName; @@ -61,6 +71,8 @@ class Recording // if (recInfoFor == this) then recInfo is valid // else delete recInfo and reload for this recording static Recording* recInfoFor; + + MarkList* markList; }; #endif diff --git a/vdr.cc b/vdr.cc index 6ea9178..b98c9fc 100644 --- a/vdr.cc +++ b/vdr.cc @@ -1136,3 +1136,54 @@ ULLONG VDR::rescanRecording(ULONG* totalFrames) *totalFrames = lengthFrames; return lengthBytes; } + +MarkList* VDR::getMarks(char* fileName) +{ + unsigned long totalLength = 8 + strlen(fileName) + 1; + UCHAR* buffer = new UCHAR[totalLength]; + + *(unsigned long*)&buffer[0] = htonl(totalLength - 4); + *(unsigned long*)&buffer[4] = htonl(VDR_GETMARKS); + strcpy((char*)&buffer[8], fileName); + + MUTEX_LOCK(&mutex); + if (!connected) { MUTEX_UNLOCK(&mutex); return 0; } + + unsigned int a = tcp->sendPacket(buffer, totalLength); + delete []buffer; + + if (a != totalLength) + { + disconnect(); + MUTEX_UNLOCK(&mutex); + return NULL; + } + + if (!getPacket()) + { + MUTEX_UNLOCK(&mutex); + return NULL; + } + + if (serverError()) + { + MUTEX_UNLOCK(&mutex); + return NULL; + } + + MarkList* markList = new MarkList(); + + while (packetPos < packetLength) + { + Mark* mark = new Mark(); + mark->pos = extractULONG(); + + markList->push_back(mark); + Log::getInstance()->log("VDR", Log::DEBUG, "Have added a mark to list. %lu", mark->pos); + } + + freePacket(); + MUTEX_UNLOCK(&mutex); + + return markList; +} diff --git a/vdr.h b/vdr.h index 6133d8b..bb1a16e 100644 --- a/vdr.h +++ b/vdr.h @@ -39,12 +39,14 @@ #include "event.h" #include "rectimer.h" #include "recinfo.h" +#include "mark.h" using namespace std; typedef vector EventList; typedef vector ChannelList; typedef vector RecTimerList; +typedef vector MarkList; struct VDRServer { @@ -120,6 +122,7 @@ class VDR ULONG frameNumberFromPosition(ULLONG position); bool getNextIFrame(ULONG frameNumber, ULONG direction, ULLONG* rfilePosition, ULONG* rframeNumber, ULONG* rframeLength); // Direction: 0=backwards, 1=forwards + MarkList* getMarks(char* fileName); ChannelList* getChannelsList(ULONG type); int streamChannel(ULONG number); @@ -185,6 +188,7 @@ class VDR const static ULONG VDR_MOVERECORDING = 18; const static ULONG VDR_GETNEXTIFRAME = 19; const static ULONG VDR_GETRECINFO = 20; + const static ULONG VDR_GETMARKS = 21; int getPacket(); void freePacket(); diff --git a/vrecordinglist.cc b/vrecordinglist.cc index 46d46db..943b17a 100644 --- a/vrecordinglist.cc +++ b/vrecordinglist.cc @@ -297,6 +297,7 @@ int VRecordingList::doPlay(bool resume) if (toPlay) { toPlay->loadRecInfo(); // check if still need this + toPlay->loadMarks(); bool isRadio = toPlay->isRadio(); diff --git a/vvideorec.cc b/vvideorec.cc index 47aa832..40bc248 100644 --- a/vvideorec.cc +++ b/vvideorec.cc @@ -239,12 +239,60 @@ int VVideoRec::handleCommand(int command) return 2; } case Remote::YELLOW: + { + if (myRec->hasMarks()) + { + // skip to previous mark + Log* logger = Log::getInstance(); + int currentFrame = (player->getCurrentFrameNum()); // get current Frame + currentFrame -= 5 * video->getFPS(); // subtrack 5 seconds, else you cannot skip more than once back .. + + int prevMark = myRec->getPrevMark(currentFrame); // find previous Frame + if (prevMark) + { + logger->log("VVideoRec", Log::NOTICE, "jump back from pos %i to mark at %i",currentFrame,prevMark); + player->jumpToMark(prevMark); + } + doBar(4); + } + else + { + doBar(2); + player->skipBackward(10); + } + return 2; + } + case Remote::BLUE: + { + if (myRec->hasMarks()) + { + // skip to next mark + Log* logger = Log::getInstance(); + int currentFrame = (player->getCurrentFrameNum()); + + int nextMark = myRec->getNextMark(currentFrame); + + if (nextMark) + { + logger->log("VVideoRec", Log::NOTICE, "jump forward from pos %i to mark at %i",currentFrame,nextMark); + player->jumpToMark(nextMark); + } + doBar(3); + } + else + { + doBar(1); + player->skipForward(10); + } + return 2; + } + case Remote::STAR: { doBar(2); player->skipBackward(10); return 2; } - case Remote::BLUE: + case Remote::HASH: { doBar(1); player->skipForward(10); @@ -630,18 +678,41 @@ void VVideoRec::drawBarClocks() rectangle(barRegion.x + progBarXbase + 4 + 302 - nrWidth, barRegion.y + 16, nrWidth, 16, Colour::RED); } - // Now calc position for start margin blips int posPix; + // Now calc position for blips - posPix = 302 * startMargin * video->getFPS() / lengthFrames; + if (myRec->hasMarks()) + { + // Draw blips where there are cut marks + MarkList* markList = myRec->getMarkList(); + MarkList::iterator i; + Mark* loopMark = NULL; - rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 - 2, 2, 2, Colour::LIGHTTEXT); - rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 + 24, 2, 2, Colour::LIGHTTEXT); + for(i = markList->begin(); i != markList->end(); i++) + { + loopMark = *i; + if (loopMark->pos) + { + logger->log("VVideoRec", Log::DEBUG, "Drawing mark at frame %i", loopMark->pos); + posPix = 302 * loopMark->pos / lengthFrames; + rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 - 2, 3, 28, Colour::DANGER); + } + } + } + else + { + // Draw blips where start and end margins probably are + + posPix = 302 * startMargin * video->getFPS() / lengthFrames; - posPix = 302 * (lengthFrames - endMargin * video->getFPS()) / lengthFrames; + rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 - 2, 2, 2, Colour::LIGHTTEXT); + rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 + 24, 2, 2, Colour::LIGHTTEXT); - rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 - 2, 2, 2, Colour::LIGHTTEXT); - rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 + 24, 2, 2, Colour::LIGHTTEXT); + posPix = 302 * (lengthFrames - endMargin * video->getFPS()) / lengthFrames; + + rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 - 2, 2, 2, Colour::LIGHTTEXT); + rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 + 24, 2, 2, Colour::LIGHTTEXT); + } } void VVideoRec::removeBar() -- 2.39.2