OBJECTS1 = command.o log.o tcp.o dsock.o thread.o timers.o i18n.o mutex.o \\r
message.o messagequeue.o udp.o \\r
- vdr.o recman.o recording.o channel.o rectimer.o event.o directory.o\\r
+ vdr.o recman.o recording.o recinfo.o channel.o rectimer.o event.o \\r
+ directory.o \\r
player.o vfeed.o afeed.o \\r
demuxer.o demuxervdr.o stream.o draintarget.o \\r
viewman.o box.o region.o colour.o view.o \\r
--- /dev/null
+/*
+ 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]);
+ }
+}
--- /dev/null
+/*
+ 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 <time.h>
+
+#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
#include "recording.h"
+Recording* Recording::recInfoFor = NULL;
+RecInfo* Recording::recInfo = NULL;
+
Recording::Recording()
{
start = 0;
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;
+}
#include <stdio.h>
#include <string.h>
#include "defines.h"
+#include "vdr.h"
+#include "recinfo.h"
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
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
*/
#include "vdr.h"
+#include "recman.h"
VDR* VDR::instance = NULL;
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;
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];
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;
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
freePacket();
MUTEX_UNLOCK(&mutex);
- // Sort the list
-
sort(recTimerList->begin(), recTimerList->end(), RecTimerSorter());
return recTimerList;
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;
+}
#include "channel.h"
#include "event.h"
#include "rectimer.h"
-#include "recman.h"
+#include "recinfo.h"
using namespace std;
}
};
+class RecMan;
class VDR
{
int connect();
void disconnect();
bool isConnected() { return connected; }
- ULONG getResumePoint(char* fileName); // uses configLoad
void setReceiveWindow(size_t size);
// getChannelSchedule
// getRecTimersList
// isConnected can be called after the following to determine if still ok
- // getRecordingSummary
// deleteRecording
// streamRecording
- // rescanRecording
// positionFromFrameNumber
// streamChannel
// getBlock
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);
const static ULONG VIDEO = 1;
const static ULONG RADIO = 2;
+
+
+
+ // obselete
+ ULLONG rescanRecording(ULONG* lengthFrames); // FIXME obselete
+
+
+
private:
static VDR* instance;
Log* logger;
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;
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();
Recording* toPlay = getCurrentOptionRecording();
if (toPlay)
{
+ toPlay->loadRecInfo();
VVideoRec* vidrec = new VVideoRec(toPlay);
vidrec->draw();
viewman->add(vidrec);
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;
}
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);
ViewMan::getInstance()->add(vi);
ViewMan::getInstance()->updateView(vi);
- if (summary) delete[] summary;
-
return 2;
}
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();
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()
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;