blob: 6381a166462d98261ce6c23ba0e837e4c8144853 [file] [log] [blame]
Constantin Kaplinsky729598c2006-05-25 05:12:25 +00001/* Copyright (C) 2004 TightVNC Team. All Rights Reserved.
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18
19// -=- FbsInputStream class
20
21#include <windows.h>
22
23#include <rfb/Exception.h>
24
25#include <rfbplayer/FbsInputStream.h>
26
27FbsInputStream::FbsInputStream(char* FileName) {
28 bufferSize = 0;
29 ptr = end = start = NULL;
30
31 timeOffset = 0;
32 seekOffset = -1;
33 startTime = GetTickCount();
34
35 playbackSpeed = 1.0;
36 seekBackwards = false;
37 paused = false;
38
39 interruptDelay = false;
40
41 fbsFile = fopen(FileName, "rb");
42 if (fbsFile == NULL) {
43 char *msg = new char[12 + sizeof(FileName)];
44 strcpy(msg, "Can't open ");
45 strcat(msg, FileName);
46 throw rfb::Exception(msg);
47 }
48
49 U8 b[12];
50 readNByte(b, 12);
51
52 if (b[0] != 'F' || b[1] != 'B' || b[2] != 'S' || b[3] != ' ' ||
53 b[4] != '0' || b[5] != '0' || b[6] != '1' || b[7] != '.' ||
54 b[8] < '0' || b[8] > '9' || b[9] < '0' || b[9] > '9' ||
55 b[10] < '0' || b[10] > '9' || b[11] != '\n') {
56 throw rfb::Exception("Incorrect protocol version");
57 }
58}
59
60FbsInputStream::~FbsInputStream() {
61 if (start != NULL)
62 delete [] start;
63 ptr = end = start = NULL;
64 fclose(fbsFile);
65}
66
67int FbsInputStream::pos() {
68 return ptr - start;
69}
70
71//
72// Close FbsInputStream and free data buffer
73//
74
75void FbsInputStream::close() {
76 fclose(fbsFile);
77
78 startTime = -1;
79 timeOffset = 0;
80 seekOffset = -1;
81 seekBackwards = false;
82 paused = false;
83 playbackSpeed = 1.0;
84
85 if (start != NULL)
86 delete [] start;
87 ptr = end = start = NULL;
88 bufferSize = 0;
89}
90
91//
92// Fill data buffer from the session file (InStream::overrun() override)
93//
94
95int FbsInputStream::overrun(int itemSize, int nItems, bool wait=true) {
96 // Just wait unless we are performing playback OR seeking.
97 waitWhilePaused();
98
99 // Perform backwardSeek (throws the special exception)
100 if (seekBackwards) {
101 throw rfb::Exception("[REWIND]");
102 }
103
104 // Save a tail of data
105 U8 *tmp;
106 int n = end - ptr;
107 if (n) {
108 tmp = new U8[n];
109 memmove(tmp, ptr, n);
110 }
111
112 bufferSize = (int)readUnsigned32();
113 if (bufferSize >= 0) {
114 if (start != NULL)
115 delete [] start;
116 int realSize = (bufferSize + 3) & 0xFFFFFFFC; // padding to multiple of 32-bits
117 ptr = start = new U8[realSize + n];
118 end = ptr + bufferSize + n;
119 if (n) {
120 memmove(start, tmp, n);
121 delete [] tmp;
122 }
123 readNByte(start + n, realSize);
124 timeOffset = (long)(readUnsigned32() / playbackSpeed);
125
126 if (itemSize * nItems > bufferSize)
127 nItems = bufferSize / itemSize;
128 }
129
130 if (bufferSize < 0 || timeOffset < 0) {
131 if (start != NULL)
132 delete [] start;
133 ptr = end = start = NULL;
134 bufferSize = 0;
135 return 0;
136 }
137
138 if (seekOffset >= 0) {
139 if (timeOffset >= seekOffset) {
140 startTime = GetTickCount() - seekOffset;
141 seekOffset = -1;
142 } else {
143 return nItems;
144 }
145 }
146
147 while (!interruptDelay) {
148 long timeDiff = startTime + timeOffset - GetTickCount();
149 if (timeDiff <= 0) {
150 break;
151 }
152 Sleep(min(20, timeDiff));
153 waitWhilePaused();
154 }
155 interruptDelay = false;
156
157 return nItems;
158}
159
160int FbsInputStream::readUnsigned32() {
161 U8 buf[4];
162 if (!readNByte(buf, 4))
163 return -1;
164
165 return ((long)(buf[0] & 0xFF) << 24 |
166 (buf[1] & 0xFF) << 16 |
167 (buf[2] & 0xFF) << 8 |
168 (buf[3] & 0xFF));
169}
170
171//
172// Read n-bytes from the session file
173//
174
175bool FbsInputStream::readNByte(U8 b[], int n) {
176 int off = 0;
177
178 while (off != n) {
179 int count = fread(b, 1, n - off, fbsFile);
180 if (count < n) {
181 if (ferror(fbsFile))
182 throw rfb::Exception("Read error from session file");
183 if (feof(fbsFile))
184 throw rfb::Exception("[End Of File]");
185 }
186 off += count;
187 }
188 return true;
189}
190
191void FbsInputStream::waitWhilePaused() {
192 while (paused && !isSeeking()) {
193 // A small delay helps to decrease the cpu usage
194 Sleep(20);
195 }
196}
197
198void FbsInputStream::interruptFrameDelay() {
199 interruptDelay = true;
200}
201
202//
203// Methods providing additional functionality.
204//
205
206long FbsInputStream::getTimeOffset() {
207 //long off = max(seekOffset, timeOffset);
208 return (long)(timeOffset * playbackSpeed);
209}
210
211void FbsInputStream::setTimeOffset(long pos) {
212 seekOffset = (long)(pos / playbackSpeed);
213 if (seekOffset < timeOffset) {
214 seekBackwards = true;
215 }
216}
217
218void FbsInputStream::setSpeed(double newSpeed) {
219 long newOffset = (long)(timeOffset * playbackSpeed / newSpeed);
220 startTime += timeOffset - newOffset;
221 timeOffset = newOffset;
222 if (isSeeking()) {
223 seekOffset = (long)(seekOffset * playbackSpeed / newSpeed);
224 }
225 playbackSpeed = newSpeed;
226}
227
228double FbsInputStream::getSpeed() {
229 return playbackSpeed;
230}
231
232bool FbsInputStream::isSeeking() {
233 return (seekOffset >= 0);
234}
235
236long FbsInputStream::getSeekOffset() {
237 return (long)(seekOffset * playbackSpeed);
238}
239
240bool FbsInputStream::isPaused() {
241 return paused;
242}
243
244void FbsInputStream::pausePlayback() {
245 paused = true;
246}
247
248void FbsInputStream::resumePlayback() {
249 paused = false;
250 startTime = GetTickCount() - timeOffset;
251}