2 Copyright 2004-2005 Chris Tallon
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "recplayer.h"
23 RecPlayer::RecPlayer(cRecording* rec)
25 log = Log::getInstance();
30 for(int i = 1; i < 1000; i++) segments[i] = NULL;
32 // FIXME find out max file path / name lengths
34 indexFile = new cIndexFile(recording->FileName(), false);
35 if (!indexFile) log->log("RecPlayer", Log::ERR, "Failed to create indexfile!");
40 void RecPlayer::scan()
42 if (file) fclose(file);
48 while(segments[i++]) delete segments[i];
51 for(i = 1; i < 1000; i++)
53 snprintf(fileName, 2047, "%s/%03i.vdr", recording->FileName(), i);
54 log->log("RecPlayer", Log::DEBUG, "FILENAME: %s", fileName);
55 file = fopen(fileName, "r");
58 segments[i] = new Segment();
59 segments[i]->start = totalLength;
60 fseek(file, 0, SEEK_END);
61 totalLength += ftell(file);
62 totalFrames = indexFile->Last();
63 log->log("RecPlayer", Log::DEBUG, "File %i found, totalLength now %llu, numFrames = %lu", i, totalLength, totalFrames);
64 segments[i]->end = totalLength;
71 RecPlayer::~RecPlayer()
73 log->log("RecPlayer", Log::DEBUG, "destructor");
75 while(segments[i++]) delete segments[i];
76 if (file) fclose(file);
79 int RecPlayer::openFile(int index)
81 if (file) fclose(file);
84 snprintf(fileName, 2047, "%s/%03i.vdr", recording->FileName(), index);
85 log->log("RecPlayer", Log::DEBUG, "openFile called for index %i string:%s", index, fileName);
87 file = fopen(fileName, "r");
90 log->log("RecPlayer", Log::DEBUG, "file failed to open");
98 ULLONG RecPlayer::getLengthBytes()
103 ULONG RecPlayer::getLengthFrames()
108 unsigned long RecPlayer::getBlock(unsigned char* buffer, ULLONG position, unsigned long amount)
110 if ((amount > totalLength) || (amount > 500000))
112 log->log("RecPlayer", Log::DEBUG, "Amount %lu requested and rejected", amount);
116 if (position >= totalLength)
118 log->log("RecPlayer", Log::DEBUG, "Client asked for data starting past end of recording!");
122 if ((position + amount) > totalLength)
124 log->log("RecPlayer", Log::DEBUG, "Client asked for some data past the end of recording, adjusting amount");
125 amount = totalLength - position;
128 // work out what block position is in
130 for(segmentNumber = 1; segmentNumber < 1000; segmentNumber++)
132 if ((position >= segments[segmentNumber]->start) && (position < segments[segmentNumber]->end)) break;
133 // position is in this block
136 // we could be seeking around
137 if (segmentNumber != fileOpen)
139 if (!openFile(segmentNumber)) return 0;
142 ULLONG currentPosition = position;
143 ULONG yetToGet = amount;
145 ULONG getFromThisSegment = 0;
152 // if(got) then we have already got some and we are back around
153 // advance the file pointer to the next file
154 if (!openFile(++segmentNumber)) return 0;
157 // is the request completely in this block?
158 if ((currentPosition + yetToGet) <= segments[segmentNumber]->end)
159 getFromThisSegment = yetToGet;
161 getFromThisSegment = segments[segmentNumber]->end - currentPosition;
163 filePosition = currentPosition - segments[segmentNumber]->start;
164 fseek(file, filePosition, SEEK_SET);
165 if (fread(&buffer[got], getFromThisSegment, 1, file) != 1) return 0; // umm, big problem.
167 got += getFromThisSegment;
168 currentPosition += getFromThisSegment;
169 yetToGet -= getFromThisSegment;
172 lastPosition = position;
176 ULLONG RecPlayer::getLastPosition()
181 cRecording* RecPlayer::getCurrentRecording()
186 ULLONG RecPlayer::positionFromFrameNumber(ULONG frameNumber)
188 if (!indexFile) return 0;
195 if (!indexFile->Get((int)frameNumber, &retFileNumber, &retFileOffset, &retPicType, &retLength))
200 // log->log("RecPlayer", Log::DEBUG, "FN: %u FO: %i", retFileNumber, retFileOffset);
201 if (!segments[retFileNumber]) return 0;
202 ULLONG position = segments[retFileNumber]->start + retFileOffset;
203 // log->log("RecPlayer", Log::DEBUG, "Pos: %llu", position);
208 ULONG RecPlayer::frameNumberFromPosition(ULLONG position)
210 if (!indexFile) return 0;
212 if (position >= totalLength)
214 log->log("RecPlayer", Log::DEBUG, "Client asked for data starting past end of recording!");
219 for(segmentNumber = 1; segmentNumber < 255; segmentNumber++)
221 if ((position >= segments[segmentNumber]->start) && (position < segments[segmentNumber]->end)) break;
222 // position is in this block
224 ULONG askposition = position - segments[segmentNumber]->start;
225 return indexFile->Get((int)segmentNumber, askposition);