]> git.vomp.tv Git - vompserver.git/blob - recplayer.c
Fix for chasing playback by allowing the client to rescan the length
[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   scan();
35 }
36
37 void RecPlayer::scan()
38 {
39   if (file) fclose(file);
40   totalLength = 0;
41   fileOpen = 0;
42
43   int i = 1;
44   while(segments[i++]) delete segments[i];
45
46   char fileName[2048];
47   for(i = 1; i < 1000; i++)
48   {
49     snprintf(fileName, 2047, "%s/%03i.vdr", recording->FileName(), i);
50     log->log("RecPlayer", Log::DEBUG, "FILENAME: %s", fileName);
51     file = fopen(fileName, "r");
52     if (!file) break;
53
54     segments[i] = new Segment();
55     segments[i]->start = totalLength;
56     fseek(file, 0, SEEK_END);
57     totalLength += ftell(file);
58     log->log("RecPlayer", Log::DEBUG, "File %i found, totalLength now %llu", i, totalLength);
59     segments[i]->end = totalLength;
60     fclose(file);
61   }
62
63   file = NULL;
64 }
65
66 RecPlayer::~RecPlayer()
67 {
68   log->log("RecPlayer", Log::DEBUG, "destructor");
69   int i = 1;
70   while(segments[i++]) delete segments[i];
71   if (file) fclose(file);
72 }
73
74 int RecPlayer::openFile(int index)
75 {
76   if (file) fclose(file);
77
78   char fileName[2048];
79   snprintf(fileName, 2047, "%s/%03i.vdr", recording->FileName(), index);
80   log->log("RecPlayer", Log::DEBUG, "openFile called for index %i string:%s", index, fileName);
81
82   file = fopen(fileName, "r");
83   if (!file)
84   {
85     log->log("RecPlayer", Log::DEBUG, "file failed to open");
86     fileOpen = 0;
87     return 0;
88   }
89   fileOpen = index;
90   return 1;
91 }
92
93 ULLONG RecPlayer::getTotalLength()
94 {
95   return totalLength;
96 }
97
98 unsigned long RecPlayer::getBlock(unsigned char* buffer, ULLONG position, unsigned long amount)
99 {
100   if ((amount > totalLength) || (amount > 100000))
101   {
102     log->log("RecPlayer", Log::DEBUG, "Amount %lu requested and rejected", amount);
103     return 0;
104   }
105
106   if (position >= totalLength)
107   {
108     log->log("RecPlayer", Log::DEBUG, "Client asked for data starting past end of recording!");
109     return 0;
110   }
111
112   if ((position + amount) > totalLength)
113   {
114     log->log("RecPlayer", Log::DEBUG, "Client asked for some data past the end of recording, adjusting amount");
115     amount = totalLength - position;
116   }
117
118   // work out what block position is in
119   int segmentNumber;
120   for(segmentNumber = 1; segmentNumber < 1000; segmentNumber++)
121   {
122     if ((position >= segments[segmentNumber]->start) && (position < segments[segmentNumber]->end)) break;
123     // position is in this block
124   }
125
126   // we could be seeking around
127   if (segmentNumber != fileOpen)
128   {
129     if (!openFile(segmentNumber)) return 0;
130   }
131
132   ULLONG currentPosition = position;
133   ULONG yetToGet = amount;
134   ULONG got = 0;
135   ULONG getFromThisSegment = 0;
136   ULONG filePosition;
137
138   while(got < amount)
139   {
140     if (got)
141     {
142       // if(got) then we have already got some and we are back around
143       // advance the file pointer to the next file
144       if (!openFile(++segmentNumber)) return 0;
145     }
146
147     // is the request completely in this block?
148     if ((currentPosition + yetToGet) <= segments[segmentNumber]->end)
149       getFromThisSegment = yetToGet;
150     else
151       getFromThisSegment = segments[segmentNumber]->end - currentPosition;
152
153     filePosition = currentPosition - segments[segmentNumber]->start;
154     fseek(file, filePosition, SEEK_SET);
155     if (fread(&buffer[got], getFromThisSegment, 1, file) != 1) return 0; // umm, big problem.
156
157     got += getFromThisSegment;
158     currentPosition += getFromThisSegment;
159     yetToGet -= getFromThisSegment;
160   }
161
162   lastPosition = position;
163   return got;
164 }
165
166 ULLONG RecPlayer::getLastPosition()
167 {
168   return lastPosition;
169 }
170
171 cRecording* RecPlayer::getCurrentRecording()
172 {
173   return recording;
174 }