14 #include "recordreader.h"
16 #include "primarydriver.h"
23 #define IFSMODE std::ios::in
24 #define SPEED_FASTEST "Fastest"
25 #define SPEED_FAST "Fast"
26 #define SPEED_NORMAL "Normal"
27 #define SPEED_SLOW "Slow"
29 #define RECORDREADER_DELAY 20
30 #define RECORD_READER_NUM_THREADS 1
32 XRawStreamRecordReader::XIOError::XIOError(
const char *file,
int line)
33 : XRecordError(i18n(
"IO Error"), file, line) {}
34 XRawStreamRecordReader::XIOError::XIOError(
const XString &msg,
const char *file,
int line)
35 : XRecordError(msg, file, line) {}
36 XRawStreamRecordReader::XBufferOverflowError::XBufferOverflowError(
const char *file,
int line)
37 : XIOError(i18n(
"Buffer Overflow Error"), file, line) {}
38 XRawStreamRecordReader::XBrokenRecordError::XBrokenRecordError(
const char *file,
int line)
39 : XRecordError(i18n(
"Broken Record Error"), file, line) {}
40 XRawStreamRecordReader::XNoDriverError::
41 XNoDriverError(
const XString &driver_name,
const char *file,
int line)
42 : XRecordError(i18n(
"No Driver Error: ") + driver_name, file, line),
45 XRawStreamRecordReader::XRawStreamRecordReader(
const char *name,
bool runtime,
const shared_ptr<XDriverList> &driverlist)
47 m_speed(create<
XComboNode>(
"Speed", true, true)),
48 m_fastForward(create<
XBoolNode>(
"FastForward", true)),
49 m_rewind(create<
XBoolNode>(
"Rewind", true)),
54 m_posString(create<
XStringNode>(
"PosString", true)),
58 tr[ *m_speed].add(SPEED_FASTEST);
59 tr[ *m_speed].add(SPEED_FAST);
60 tr[ *m_speed].add(SPEED_NORMAL);
61 tr[ *m_speed].add(SPEED_SLOW);
62 tr[ *m_speed] = SPEED_FAST;
64 m_lsnOnOpen = tr[ *filename()].onValueChanged().connectWeakly(
65 shared_from_this(), &XRawStreamRecordReader::onOpen);
66 m_lsnFirst = tr[ *m_first].onTouch().connectWeakly(
67 shared_from_this(), &XRawStreamRecordReader::onFirst,
68 XListener::FLAG_MAIN_THREAD_CALL | XListener::FLAG_AVOID_DUP | XListener::FLAG_DELAY_ADAPTIVE);
69 m_lsnBack = tr[ *m_back].onTouch().connectWeakly(
70 shared_from_this(), &XRawStreamRecordReader::onBack,
71 XListener::FLAG_MAIN_THREAD_CALL | XListener::FLAG_AVOID_DUP | XListener::FLAG_DELAY_ADAPTIVE);
72 m_lsnNext = tr[ *m_next].onTouch().connectWeakly(
73 shared_from_this(), &XRawStreamRecordReader::onNext,
74 XListener::FLAG_MAIN_THREAD_CALL | XListener::FLAG_AVOID_DUP | XListener::FLAG_DELAY_ADAPTIVE);
75 m_lsnStop = tr[ *m_stop].onTouch().connectWeakly(
76 shared_from_this(), &XRawStreamRecordReader::onStop,
77 XListener::FLAG_MAIN_THREAD_CALL | XListener::FLAG_AVOID_DUP | XListener::FLAG_DELAY_ADAPTIVE);
78 m_lsnPlayCond = tr[ *m_fastForward].onValueChanged().connectWeakly(
80 &XRawStreamRecordReader::onPlayCondChanged,
81 XListener::FLAG_MAIN_THREAD_CALL | XListener::FLAG_AVOID_DUP | XListener::FLAG_DELAY_ADAPTIVE);
82 tr[ *m_rewind].onValueChanged().connect(m_lsnPlayCond);
83 tr[ *m_speed].onValueChanged().connect(m_lsnPlayCond);
86 m_threads.resize(RECORD_READER_NUM_THREADS);
87 for(
auto it = m_threads.begin(); it != m_threads.end(); it++) {
89 &XRawStreamRecordReader::execute));
96 m_pGFD = gzopen(QString(( **filename())->to_str()).toLocal8Bit().data(),
"rb");
99 XRawStreamRecordReader::readHeader(
void *_fd)
101 gzFile fd =
static_cast<gzFile
>(_fd);
104 throw XIOError(__FILE__, __LINE__);
109 std::vector<char> buf(size);
111 if(gzread(fd, &buf[0], size) == -1)
throw XIOError(__FILE__, __LINE__);
112 m_allsize = reader.pop<uint32_t>();
113 long sec = reader.pop<int32_t>();
114 long usec = reader.pop<int32_t>();
115 m_time =
XTime(sec, usec);
120 gzFile fd =
static_cast<gzFile
>(_fd);
123 char name[256], sup[256];
124 gzgetline(fd, (
unsigned char*)name, 256,
'\0');
125 gzgetline(fd, (
unsigned char*)sup, 256,
'\0');
126 if(strlen(name) == 0) {
129 shared_ptr<XNode> driver_precast = m_drivers->getChild(name);
130 auto driver = dynamic_pointer_cast<
XPrimaryDriver>(driver_precast);
143 trans( *m_posString) = time.getTimeStr();
144 if( !driver || (size > MAX_RAW_RECORD_SIZE)) {
145 if(gzseek(fd, size +
sizeof(uint32_t), SEEK_CUR) == -1)
150 throw XNoDriverError(formatString_tr(I18N_NOOP(
"Typemismatch: %s"), name),
155 auto rawdata = std::make_shared<XPrimaryDriver::RawData>();
157 rawdata->resize(size);
158 if(gzread(fd, &rawdata->at(0), size) == -1)
160 std::vector<char> buf(
sizeof(uint32_t));
161 if(gzread(fd, &buf[0],
sizeof(uint32_t)) == -1)
164 uint32_t footer_allsize = reader.
pop<uint32_t>();
165 if(footer_allsize != m_allsize)
169 driver->finishWritingRaw(rawdata,
XTime(),
XTime());
174 driver->finishWritingRaw(rawdata, XTime::now(), time);
178 XRawStreamRecordReader::gzgetline(
void* _fd,
unsigned char*buf,
unsigned int len,
int del)
180 gzFile fd =
static_cast<gzFile
>(_fd);
183 for(
unsigned int i = 0; i < len; i++) {
185 if(c == -1)
throw XIOError(__FILE__, __LINE__);
186 *(buf++) = (
unsigned char)c;
189 throw XBufferOverflowError(__FILE__, __LINE__);
194 gzrewind(static_cast<gzFile>(fd));
197 XRawStreamRecordReader::previous_(
void *fd)
199 if(gzseek(static_cast<gzFile>(fd), -
sizeof(uint32_t), SEEK_CUR) == -1)
throw XIOError(__FILE__, __LINE__);
203 XRawStreamRecordReader::next_(
void *fd)
206 uint32_t headersize =
sizeof(uint32_t)
209 if(gzseek(static_cast<gzFile>(fd), m_allsize - headersize, SEEK_CUR) == -1)
throw XIOError(__FILE__, __LINE__);
212 XRawStreamRecordReader::goToHeader(
void *_fd)
214 gzFile fd =
static_cast<gzFile
>(_fd);
216 if(gzeof(fd))
throw XIOError(__FILE__, __LINE__);
217 std::vector<char> buf(
sizeof(uint32_t));
219 if(gzread(fd, &buf[0],
sizeof(uint32_t)) == Z_NULL)
throw XIOError(__FILE__, __LINE__);
220 int allsize = reader.pop<uint32_t>();
221 if(gzseek(fd, -allsize, SEEK_CUR) == -1)
throw XIOError(__FILE__, __LINE__);
224 XRawStreamRecordReader::terminate() {
226 for(
auto &&x: m_threads) {
233 XRawStreamRecordReader::join() {
234 for(
auto &&x: m_threads) {
243 if(shot_this[ *m_speed].to_str() == SPEED_FASTEST) ms = 0.1;
244 if(shot_this[ *m_speed].to_str() == SPEED_FAST) ms = 10.0;
245 if(shot_this[ *m_speed].to_str() == SPEED_NORMAL) ms = 30.0;
246 if(shot_this[ *m_speed].to_str() == SPEED_SLOW) ms = 100.0;
247 if( !shot_this[ *m_fastForward] && !shot_this[ *m_rewind]) ms = 0;
248 if(shot_this[ *m_rewind]) ms = -ms;
256 g_statusPrinter->printMessage(i18n(
"Stopped"));
258 tr[ *m_fastForward] =
false;
259 tr[ *m_rewind] =
false;
260 tr.unmark(m_lsnPlayCond);
270 g_statusPrinter->printMessage(i18n(
"First"));
272 catch (XRecordError &e) {
273 m_filemutex.unlock();
274 e.print(i18n(
"No Record, because "));
284 g_statusPrinter->printMessage(i18n(
"Next"));
286 catch (XRecordError &e) {
287 m_filemutex.unlock();
288 e.print(i18n(
"No Record, because "));
300 g_statusPrinter->printMessage(i18n(
"Previous"));
302 catch (XRecordError &e) {
303 m_filemutex.unlock();
304 e.print(i18n(
"No Record, because "));
309 void *XRawStreamRecordReader::execute(
const atomic<bool> &terminated) {
310 while( !terminated) {
314 while((fabs((ms = m_periodicTerm)) < 1e-4) && !terminated)
318 if(terminated)
break;
328 catch (XNoDriverError &e) {
329 m_filemutex.unlock();
330 e.print(i18n(
"No such driver :") + e.name);
332 catch (XRecordError &e) {
333 m_periodicTerm = 0.0;
335 tr[ *m_fastForward] =
false;
336 tr[ *m_rewind] =
false;
337 tr.unmark(m_lsnPlayCond);
339 m_filemutex.unlock();
340 e.print(i18n(
"No Record, because "));
343 msecsleep(lrint(fabs(ms)));