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