From ef6ec1a0b626cc7dfda7204778e1c9ab8bf2db9c Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Sun, 1 Oct 2006 23:36:33 +0000 Subject: [PATCH] New recinfo system - not finished just yet! --- objects.mk | 3 +- recinfo.cc | 103 ++++++++++++++++++++++ recinfo.h | 56 ++++++++++++ recording.cc | 19 ++++ recording.h | 11 +++ udp.cc | 3 + vdr.cc | 217 ++++++++++++++++++++++++---------------------- vdr.h | 22 +++-- vrecordinglist.cc | 5 +- vrecordingmenu.cc | 15 ++-- vvideorec.cc | 16 ++-- 11 files changed, 337 insertions(+), 133 deletions(-) create mode 100644 recinfo.cc create mode 100644 recinfo.h diff --git a/objects.mk b/objects.mk index aed0e6d..1eb44f8 100644 --- a/objects.mk +++ b/objects.mk @@ -1,6 +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 channel.o rectimer.o event.o directory.o\ + vdr.o recman.o recording.o recinfo.o channel.o rectimer.o event.o \ + directory.o \ player.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/recinfo.cc b/recinfo.cc new file mode 100644 index 0000000..84eb111 --- /dev/null +++ b/recinfo.cc @@ -0,0 +1,103 @@ +/* + Copyright 2006 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 "recinfo.h" + +RecInfo::RecInfo() +{ + timerStart = 0; + timerEnd = 0; + resumePoint = 0; + summary = NULL; + + numComponents = 0; + streams = NULL; + types = NULL; + languages = NULL; + descriptions = NULL; +} + +RecInfo::~RecInfo() +{ + if (summary) delete[] summary; + + for (ULONG i = 0; i < numComponents; i++) + { + delete[] languages[i]; + delete[] descriptions[i]; + } + + if (numComponents) + { + delete[] languages; + delete[] descriptions; + + delete[] streams; + delete[] types; + } + + timerStart = 0; + timerEnd = 0; + resumePoint = 0; + summary = NULL; + + numComponents = 0; + streams = NULL; + types = NULL; + languages = NULL; + descriptions = NULL; +} + +void RecInfo::setNumComponents(ULONG tnumComponents) +{ + numComponents = tnumComponents; + languages = new char*[numComponents]; + descriptions = new char*[numComponents]; + streams = new UCHAR[numComponents]; + types = new UCHAR[numComponents]; +} + +void RecInfo::addComponent(ULONG componentNum, UCHAR tstream, UCHAR ttype, char* tlanguage, char* tdescription) +{ + if (componentNum >= numComponents) return; + streams[componentNum] = tstream; + types[componentNum] = ttype; + languages[componentNum] = tlanguage; + descriptions[componentNum] = tdescription; +} + +void RecInfo::print() +{ + Log* logger = Log::getInstance(); + + logger->log("RecInfo", Log::DEBUG, "timerStart %lu", timerStart); + logger->log("RecInfo", Log::DEBUG, "timerEnd %lu", timerEnd); + logger->log("RecInfo", Log::DEBUG, "resumePoint %lu", resumePoint); + logger->log("RecInfo", Log::DEBUG, "Summary: %s", summary); + logger->log("RecInfo", Log::DEBUG, "numComponents: %lu", numComponents); + + for (ULONG i = 0; i < numComponents; i++) + { + logger->log("RecInfo", Log::DEBUG, "streams[%lu]: %u", i, streams[i]); + logger->log("RecInfo", Log::DEBUG, "types[%lu]: %u", i, types[i]); + logger->log("RecInfo", Log::DEBUG, "languages[%lu]: %s", i, languages[i]); + logger->log("RecInfo", Log::DEBUG, "descriptions[%lu]: %s", i, descriptions[i]); + } +} diff --git a/recinfo.h b/recinfo.h new file mode 100644 index 0000000..880d9ab --- /dev/null +++ b/recinfo.h @@ -0,0 +1,56 @@ +/* + Copyright 2006 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 RECINFO_H +#define RECINFO_H + +#include + +#include "defines.h" +#include "log.h" + +class RecInfo +{ + public: + RecInfo(); + ~RecInfo(); + + time_t timerStart; + time_t timerEnd; + ULONG resumePoint; + char* summary; + + ULONG numComponents; + UCHAR* streams; + UCHAR* types; + char** languages; + char** descriptions; + + void setNumComponents(ULONG); + void addComponent(ULONG componentNum, UCHAR tstream, UCHAR ttype, char* tlanguage, char* tdescription); + // addComponent accepts a pointer to a buffer that RecInfo will free, not the caller + + void print(); + + private: + +}; + +#endif diff --git a/recording.cc b/recording.cc index 8272fd7..2842347 100644 --- a/recording.cc +++ b/recording.cc @@ -20,6 +20,9 @@ #include "recording.h" +Recording* Recording::recInfoFor = NULL; +RecInfo* Recording::recInfo = NULL; + Recording::Recording() { start = 0; @@ -70,3 +73,19 @@ void Recording::setFileName(char* tFileName) fileName = new char[strlen(tFileName) + 1]; if (fileName) strcpy(fileName, tFileName); } + +void Recording::loadRecInfo() +{ + if (recInfoFor == this) return; // it already is loaded + + if (recInfo) delete recInfo; + recInfoFor = this; + recInfo = VDR::getInstance()->getRecInfo(fileName); +} + +void Recording::dropRecInfo() +{ + if (recInfo) delete recInfo; + recInfo = NULL; + recInfoFor = NULL; +} diff --git a/recording.h b/recording.h index ddbd593..03dbc63 100644 --- a/recording.h +++ b/recording.h @@ -24,6 +24,8 @@ #include #include #include "defines.h" +#include "vdr.h" +#include "recinfo.h" class Recording { @@ -41,11 +43,20 @@ class Recording int index; + void loadRecInfo(); + void dropRecInfo(); + + static RecInfo* recInfo; + private: ULONG start; char* progName; char* fileName; + // I only want 1 RecInfo loaded at a time + // if (recInfoFor == this) then recInfo is valid + // else delete recInfo and reload for this recording + static Recording* recInfoFor; }; #endif diff --git a/udp.cc b/udp.cc index 2ff6c56..e8e5a75 100755 --- a/udp.cc +++ b/udp.cc @@ -74,12 +74,15 @@ int UDP::run(MessageQueue* tcommandMessageQueue) void UDP::threadMethod() { + threadSetKillable(); + int retval; while(1) { #ifndef WIN32 retval = ds->waitforMessage(0); #else + log->log("UDP", Log::DEBUG, "Wait for packet"); threadCheckExit(); retval = ds->waitforMessage(1); #endif diff --git a/vdr.cc b/vdr.cc index 0158797..6ea9178 100644 --- a/vdr.cc +++ b/vdr.cc @@ -19,6 +19,7 @@ */ #include "vdr.h" +#include "recman.h" VDR* VDR::instance = NULL; @@ -216,6 +217,14 @@ char* VDR::extractString() return str; } +UCHAR VDR::extractUCHAR() +{ + if ((packetPos + sizeof(UCHAR)) > packetLength) return 0; + UCHAR uc = packet[packetPos]; + packetPos += sizeof(UCHAR); + return uc; +} + ULONG VDR::extractULONG() { if ((packetPos + sizeof(ULONG)) > packetLength) return 0; @@ -455,40 +464,6 @@ char* VDR::moveRecording(char* fileName, char* newPath) return toReturn; } -char* VDR::getRecordingSummary(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_GETSUMMARY); - 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; - } - char* toReturn = extractString(); - freePacket(); - MUTEX_UNLOCK(&mutex); - - return toReturn; -} - ChannelList* VDR::getChannelsList(ULONG type) { UCHAR buffer[8]; @@ -691,44 +666,6 @@ ULLONG VDR::streamRecording(char* fileName, ULONG* totalFrames) return lengthBytes; } -ULLONG VDR::rescanRecording(ULONG* totalFrames) -{ - unsigned long totalLength = 8; - UCHAR* buffer = new UCHAR[totalLength]; - - *(unsigned long*)&buffer[0] = htonl(totalLength - 4); - *(unsigned long*)&buffer[4] = htonl(VDR_RESCANRECORDING); - - 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 0; - } - - if (!getPacket()) - { - MUTEX_UNLOCK(&mutex); - return 0; - } - - ULLONG lengthBytes = extractULLONG(); - ULONG lengthFrames = extractULONG(); - freePacket(); - MUTEX_UNLOCK(&mutex); - - Log::getInstance()->log("VDR", Log::DEBUG, "VDR said length is: %llu %lu", lengthBytes, lengthFrames); - - *totalFrames = lengthFrames; - return lengthBytes; -} - ULLONG VDR::positionFromFrameNumber(ULONG frameNumber) { unsigned long totalLength = 12; @@ -908,45 +845,15 @@ EventList* VDR::getChannelSchedule(ULONG number, time_t start, ULONG duration) event->subtitle = extractString(); event->description = extractString(); eventList->push_back(event); -// eventList->next(); } freePacket(); MUTEX_UNLOCK(&mutex); Log::getInstance()->log("VDR", Log::DEBUG, "Success got to end of getChannelSchedule"); - - - // debug -/* - Log* l = Log::getInstance(); - - - l->log("VDR", Log::DEBUG, "datalength = %i count = %i", dataLength, count); - - Event* currentEvent; - for(eventList->reset(); !eventList->eol(); eventList->next()) - { - currentEvent = (Event*)eventList->getCurrent(); - l->log("VDR", Log::DEBUG, "%lu %lu %lu %s %s %s", currentEvent->id, currentEvent->time, currentEvent->duration, currentEvent->title, currentEvent->subtitle, currentEvent->description); - } -*/ - return eventList; } -ULONG VDR::getResumePoint(char* fileName) -{ - if (!connected) return 0; - - char* resumeString = configLoad("ResumeData", fileName); - if (!resumeString) return 0; - - ULONG toReturn = STRTOUL(resumeString, NULL, 10); - delete[] resumeString; - return toReturn; -} - int VDR::configSave(char* section, char* key, const char* value) { ULONG totalLength = 8 + strlen(section) + strlen(key) + strlen(value) + 3; // 8 for headers, 3 for nulls @@ -1086,8 +993,6 @@ RecTimerList* VDR::getRecTimersList() freePacket(); MUTEX_UNLOCK(&mutex); - // Sort the list - sort(recTimerList->begin(), recTimerList->end(), RecTimerSorter()); return recTimerList; @@ -1127,3 +1032,107 @@ ULONG VDR::setEventTimer(char* timerString) return toReturn; } + +RecInfo* VDR::getRecInfo(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_GETRECINFO); + strcpy((char*)&buffer[8], fileName); + + MUTEX_LOCK(&mutex); + if (!connected) { MUTEX_UNLOCK(&mutex); return NULL; } + + 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()) + { + Log::getInstance()->log("VDR", Log::DEBUG, "Could not get rec info"); + freePacket(); + MUTEX_UNLOCK(&mutex); + return NULL; + } + + TCP::dump(packet, packetLength); + + RecInfo* recInfo = new RecInfo(); + + recInfo->timerStart = extractULONG(); + recInfo->timerEnd = extractULONG(); + recInfo->resumePoint = extractULONG(); + recInfo->summary = extractString(); + + ULONG numComponents = extractULONG(); + if (numComponents) + { + recInfo->setNumComponents(numComponents); + for (ULONG i = 0; i < numComponents; i++) + { + recInfo->streams[i] = extractUCHAR(); + recInfo->types[i] = extractUCHAR(); + recInfo->languages[i] = extractString(); + recInfo->descriptions[i] = extractString(); + } + } + + recInfo->print(); + + freePacket(); + MUTEX_UNLOCK(&mutex); + return recInfo; +} + +// FIXME obselete +ULLONG VDR::rescanRecording(ULONG* totalFrames) +{ + unsigned long totalLength = 8; + UCHAR* buffer = new UCHAR[totalLength]; + + *(unsigned long*)&buffer[0] = htonl(totalLength - 4); + *(unsigned long*)&buffer[4] = htonl(VDR_RESCANRECORDING); + + 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 0; + } + + if (!getPacket()) + { + MUTEX_UNLOCK(&mutex); + return 0; + } + + ULLONG lengthBytes = extractULLONG(); + ULONG lengthFrames = extractULONG(); + freePacket(); + MUTEX_UNLOCK(&mutex); + + Log::getInstance()->log("VDR", Log::DEBUG, "VDR said length is: %llu %lu", lengthBytes, lengthFrames); + + *totalFrames = lengthFrames; + return lengthBytes; +} diff --git a/vdr.h b/vdr.h index c3d9f8a..5d512e1 100644 --- a/vdr.h +++ b/vdr.h @@ -38,7 +38,7 @@ #include "channel.h" #include "event.h" #include "rectimer.h" -#include "recman.h" +#include "recinfo.h" using namespace std; @@ -69,6 +69,7 @@ struct ServerSorter } }; +class RecMan; class VDR { @@ -87,7 +88,6 @@ class VDR int connect(); void disconnect(); bool isConnected() { return connected; } - ULONG getResumePoint(char* fileName); // uses configLoad void setReceiveWindow(size_t size); @@ -99,10 +99,8 @@ class VDR // getChannelSchedule // getRecTimersList // isConnected can be called after the following to determine if still ok - // getRecordingSummary // deleteRecording // streamRecording - // rescanRecording // positionFromFrameNumber // streamChannel // getBlock @@ -114,11 +112,10 @@ class VDR int doLogin(); bool getRecordingsList(RecMan* recman); - char* getRecordingSummary(char* fileName); + RecInfo* getRecInfo(char* fileName); int deleteRecording(char* fileName); char* moveRecording(char* fileName, char* newPath); ULLONG streamRecording(char* fileName, ULONG* lengthFrames); - ULLONG rescanRecording(ULONG* lengthFrames); ULLONG positionFromFrameNumber(ULONG frameNumber); ULONG frameNumberFromPosition(ULLONG position); bool getNextIFrame(ULONG frameNumber, ULONG direction, ULLONG* rfilePosition, ULONG* rframeNumber, ULONG* rframeLength); @@ -142,6 +139,14 @@ class VDR const static ULONG VIDEO = 1; const static ULONG RADIO = 2; + + + + // obselete + ULLONG rescanRecording(ULONG* lengthFrames); // FIXME obselete + + + private: static VDR* instance; Log* logger; @@ -164,7 +169,6 @@ class VDR const static ULONG VDR_LOGIN = 1; const static ULONG VDR_GETRECORDINGLIST = 2; const static ULONG VDR_DELETERECORDING = 3; - const static ULONG VDR_GETSUMMARY = 4; const static ULONG VDR_GETCHANNELLIST = 5; const static ULONG VDR_STREAMCHANNEL = 6; const static ULONG VDR_GETBLOCK = 7; @@ -173,18 +177,20 @@ class VDR const static ULONG VDR_GETCHANNELSCHEDULE = 10; const static ULONG VDR_CONFIGSAVE = 11; const static ULONG VDR_CONFIGLOAD = 12; - const static ULONG VDR_RESCANRECORDING = 13; + const static ULONG VDR_RESCANRECORDING = 13; // FIXME obselete const static ULONG VDR_GETTIMERS = 14; const static ULONG VDR_SETTIMER = 15; const static ULONG VDR_POSFROMFRAME = 16; const static ULONG VDR_FRAMEFROMPOS = 17; const static ULONG VDR_MOVERECORDING = 18; const static ULONG VDR_GETNEXTIFRAME = 19; + const static ULONG VDR_GETRECINFO = 20; int getPacket(); void freePacket(); int serverError(); char* extractString(); + UCHAR extractUCHAR(); ULONG extractULONG(); ULLONG extractULLONG(); long extractLONG(); diff --git a/vrecordinglist.cc b/vrecordinglist.cc index dd6ae8d..ec4bcd2 100644 --- a/vrecordinglist.cc +++ b/vrecordinglist.cc @@ -296,6 +296,7 @@ int VRecordingList::doPlay() Recording* toPlay = getCurrentOptionRecording(); if (toPlay) { + toPlay->loadRecInfo(); VVideoRec* vidrec = new VVideoRec(toPlay); vidrec->draw(); viewman->add(vidrec); @@ -313,13 +314,13 @@ int VRecordingList::doResume() if (toResume) { - ULLONG position = VDR::getInstance()->getResumePoint(toResume->getFileName()); + toResume->loadRecInfo(); VVideoRec* vidrec = new VVideoRec(toResume); vidrec->draw(); viewman->add(vidrec); viewman->updateView(vidrec); - vidrec->go(position); + vidrec->go(toResume->recInfo->resumePoint); return 1; } diff --git a/vrecordingmenu.cc b/vrecordingmenu.cc index 6997844..60880b4 100644 --- a/vrecordingmenu.cc +++ b/vrecordingmenu.cc @@ -115,19 +115,16 @@ int VRecordingMenu::handleCommand(int command) if (sl.getCurrentOptionData() == 3) { - char* summary = VDR::getInstance()->getRecordingSummary(rec->getFileName()); - if (!summary && !VDR::getInstance()->isConnected()) - { - Command::getInstance()->connectionLost(); - return 2; - } + rec->loadRecInfo(); VInfo* vi = new VInfo(); vi->setTitleText(tr("Programme summary")); vi->setBorderOn(1); vi->setExitable(); - if (summary) vi->setMainText(summary); - else vi->setMainText(tr("Summary unavailable")); + if (strlen(rec->recInfo->summary)) + vi->setMainText(rec->recInfo->summary); + else + vi->setMainText(tr("Summary unavailable")); if (Video::getInstance()->getFormat() == Video::PAL) { vi->setScreenPos(120, 130); @@ -141,8 +138,6 @@ int VRecordingMenu::handleCommand(int command) ViewMan::getInstance()->add(vi); ViewMan::getInstance()->updateView(vi); - if (summary) delete[] summary; - return 2; } diff --git a/vvideorec.cc b/vvideorec.cc index bea2e33..e506573 100644 --- a/vvideorec.cc +++ b/vvideorec.cc @@ -26,7 +26,9 @@ VVideoRec::VVideoRec(Recording* rec) video = Video::getInstance(); timers = Timers::getInstance(); - player = new Player(Command::getInstance(), true, false); // say 0 for radio because buffering will work anyway + // TODO Work out if is a radio stream + + player = new Player(Command::getInstance(), true, false); player->init(); videoMode = video->getMode(); @@ -87,6 +89,11 @@ VVideoRec::~VVideoRec() timers->cancelTimer(this, 1); timers->cancelTimer(this, 2); + + // kill recInfo in case resumePoint has changed (likely) + myRec->dropRecInfo(); + // FIXME - do this properly - save the resume point back to the server manually and update + // rec->recInfo->resumePoint - this will fix the ~10s offset problem as well } void VVideoRec::draw() @@ -220,13 +227,6 @@ int VVideoRec::handleCommand(int command) return 2; } - -// case Remote::REVERSE: -// { -// player->toggleFastBackward(); -// 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; -- 2.39.5