]> git.vomp.tv Git - vompserver.git/blob - recplayer.c
Frame number stuff
[vompserver.git] / recplayer.c
1 /*
2     Copyright 2004-2005 Chris Tallon
3
4     This file is part of VOMP.
5
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.
10
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.
15
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
19 */
20
21 #include "recplayer.h"
22
23 RecPlayer::RecPlayer(cRecording* rec)
24 {
25   log = Log::getInstance();
26   file = NULL;
27   fileOpen = 0;
28   lastPosition = 0;
29   recording = rec;
30   for(int i = 1; i < 1000; i++) segments[i] = NULL;
31
32   // FIXME find out max file path / name lengths
33
34   indexFile = new cIndexFile(recording->FileName(), false);
35   if (!indexFile) log->log("RecPlayer", Log::ERR, "Failed to create indexfile!");
36
37   scan();
38 }
39
40 void RecPlayer::scan()
41 {
42   if (file) fclose(file);
43   totalLength = 0;
44   fileOpen = 0;
45
46   int i = 1;
47   while(segments[i++]) delete segments[i];
48
49   char fileName[2048];
50   for(i = 1; i < 1000; i++)
51   {
52     snprintf(fileName, 2047, "%s/%03i.vdr", recording->FileName(), i);
53     log->log("RecPlayer", Log::DEBUG, "FILENAME: %s", fileName);
54     file = fopen(fileName, "r");
55     if (!file) break;
56
57     segments[i] = new Segment();
58     segments[i]->start = totalLength;
59     fseek(file, 0, SEEK_END);
60     totalLength += ftell(file);
61     log->log("RecPlayer", Log::DEBUG, "File %i found, totalLength now %llu", i, totalLength);
62     segments[i]->end = totalLength;
63     fclose(file);
64   }
65
66   file = NULL;
67 }
68
69 RecPlayer::~RecPlayer()
70 {
71   log->log("RecPlayer", Log::DEBUG, "destructor");
72   int i = 1;
73   while(segments[i++]) delete segments[i];
74   if (file) fclose(file);
75 }
76
77 int RecPlayer::openFile(int index)
78 {
79   if (file) fclose(file);
80
81   char fileName[2048];
82   snprintf(fileName, 2047, "%s/%03i.vdr", recording->FileName(), index);
83   log->log("RecPlayer", Log::DEBUG, "openFile called for index %i string:%s", index, fileName);
84
85   file = fopen(fileName, "r");
86   if (!file)
87   {
88     log->log("RecPlayer", Log::DEBUG, "file failed to open");
89     fileOpen = 0;
90     return 0;
91   }
92   fileOpen = index;
93   return 1;
94 }
95
96 ULLONG RecPlayer::getTotalLength()
97 {
98   return totalLength;
99 }
100
101 unsigned long RecPlayer::getBlock(unsigned char* buffer, ULLONG position, unsigned long amount)
102 {
103   if ((amount > totalLength) || (amount > 500000))
104   {
105     log->log("RecPlayer", Log::DEBUG, "Amount %lu requested and rejected", amount);
106     return 0;
107   }
108
109   if (position >= totalLength)
110   {
111     log->log("RecPlayer", Log::DEBUG, "Client asked for data starting past end of recording!");
112     return 0;
113   }
114
115   if ((position + amount) > totalLength)
116   {
117     log->log("RecPlayer", Log::DEBUG, "Client asked for some data past the end of recording, adjusting amount");
118     amount = totalLength - position;
119   }
120
121   // work out what block position is in
122   int segmentNumber;
123   for(segmentNumber = 1; segmentNumber < 1000; segmentNumber++)
124   {
125     if ((position >= segments[segmentNumber]->start) && (position < segments[segmentNumber]->end)) break;
126     // position is in this block
127   }
128
129   // we could be seeking around
130   if (segmentNumber != fileOpen)
131   {
132     if (!openFile(segmentNumber)) return 0;
133   }
134
135   ULLONG currentPosition = position;
136   ULONG yetToGet = amount;
137   ULONG got = 0;
138   ULONG getFromThisSegment = 0;
139   ULONG filePosition;
140
141   while(got < amount)
142   {
143     if (got)
144     {
145       // if(got) then we have already got some and we are back around
146       // advance the file pointer to the next file
147       if (!openFile(++segmentNumber)) return 0;
148     }
149
150     // is the request completely in this block?
151     if ((currentPosition + yetToGet) <= segments[segmentNumber]->end)
152       getFromThisSegment = yetToGet;
153     else
154       getFromThisSegment = segments[segmentNumber]->end - currentPosition;
155
156     filePosition = currentPosition - segments[segmentNumber]->start;
157     fseek(file, filePosition, SEEK_SET);
158     if (fread(&buffer[got], getFromThisSegment, 1, file) != 1) return 0; // umm, big problem.
159
160     got += getFromThisSegment;
161     currentPosition += getFromThisSegment;
162     yetToGet -= getFromThisSegment;
163   }
164
165   lastPosition = position;
166   return got;
167 }
168
169 ULLONG RecPlayer::getLastPosition()
170 {
171   return lastPosition;
172 }
173
174 cRecording* RecPlayer::getCurrentRecording()
175 {
176   return recording;
177 }
178
179 ULLONG RecPlayer::positionFromFrameNumber(ULONG frameNumber)
180 {
181   if (!indexFile) return 0;
182
183   uchar retFileNumber;
184   int retFileOffset;
185   uchar retPicType;
186   int retLength;
187
188   if (!indexFile->Get((int)frameNumber, &retFileNumber, &retFileOffset, &retPicType, &retLength))
189   {
190     return 0;
191   }
192
193 //  log->log("RecPlayer", Log::DEBUG, "FN: %u FO: %i", retFileNumber, retFileOffset);
194   if (!segments[retFileNumber]) return 0;
195   ULLONG position = segments[retFileNumber]->start + retFileOffset;
196 //  log->log("RecPlayer", Log::DEBUG, "Pos: %llu", position);
197
198   return position;
199 }