RflySimSDK v3.05
RflySimSDK说明文档
载入中...
搜索中...
未找到
vrpn_FileConnection.h
1#ifndef VRPN_FILE_CONNECTION_H
2#define VRPN_FILE_CONNECTION_H
3
4// {{{ vrpn_File_Connection
5//
6// Tom Hudson, June 1998
7
8// This class *reads* a file written out by vrpn_Connection's logging hooks.
9
10// The interface exactly matches that of vrpn_Connection. To do things that
11// are meaningful on log replay but not on live networks, create a
12// vrpn_File_Controller and pass your vrpn_File_Connection to its constructor,
13// or just ask the Connection for its file connection pointer and do the
14// operations directly on the FileConnection if the pointer is non-NULL.
15
16// Logfiles are recorded as *sent*, not as translated by the receiver,
17// so we still need to have all the correct names for senders and types
18// registered.
19
20// September 1998: by default preloads the entire log file on startup.
21// This causes a delay (nontrivial for large logs) but should help smooth
22// playback.
23// }}}
24
25#include <stdio.h> // for NULL, FILE
26
27#include "vrpn_Configure.h" // for VRPN_API, VRPN_CALLBACK
28#include "vrpn_Connection.h" // for vrpn_LOGLIST (ptr only), etc
29#include "vrpn_Shared.h" // for timeval
30#include "vrpn_Types.h" // for vrpn_float32, vrpn_int32, etc
31
32struct timeval;
33
34// Global variable used to indicate whether File Connections should
35// pre-load all of their records into memory when opened. This is the
36// default behavior, but fails on very large files that eat up all
37// of the memory. This defaults to "true". User code should set this
38// to "false" before calling vrpn_get_connection_by_name() or creating
39// a new vrpn_File_Connection object if it wants that file connection
40// to not preload. The value is only checked at connection creation time;
41// the connection behaves consistently once created. This operation is
42// useful for applications that load large data files and don't want to
43// wait for them to pre-load.
44
45extern VRPN_API bool vrpn_FILE_CONNECTIONS_SHOULD_PRELOAD;
46
47// Global variable used to indicate whether File Connections should
48// keep already-read messages stored in memory. If not, then we have
49// to re-load the file starting at the beginning on rewind. This
50// defaults to "true". User code should set this
51// to "false" before calling vrpn_get_connection_by_name() or creating
52// a new vrpn_File_Connection object if it wants that file connection
53// to not preload. The value is only checked at connection creation time;
54// the connection behaves consistently once created. This operation is
55// useful for applications that read through large data files and
56// don't have enough memory to keep them in memory at once, or for applications
57// that read through only once and have no need to go back and check.
58
59extern VRPN_API bool vrpn_FILE_CONNECTIONS_SHOULD_ACCUMULATE;
60
61// Global variable used to indicate whether File Connections should
62// play through all system messages and get to the first user message
63// when opened or reset to the beginning. This defaults to "true".
64// User code should set this
65// to "false" before calling vrpn_get_connection_by_name() or creating
66// a new vrpn_File_Connection object if it wants that file connection
67// to not preload. The value is only checked at connection creation time;
68// the connection behaves consistently once created. Leaving this true
69// can help with offsets in time that happen at the beginning of files.
70
71extern VRPN_API bool vrpn_FILE_CONNECTIONS_SHOULD_SKIP_TO_USER_MESSAGES;
72
73class VRPN_API vrpn_File_Connection : public vrpn_Connection {
74public:
75 vrpn_File_Connection(const char *station_name,
76 const char *local_in_logfile_name = NULL,
77 const char *local_out_logfile_name = NULL);
78 virtual ~vrpn_File_Connection(void);
79
80 virtual int mainloop(const timeval *timeout = NULL);
81
82 // returns the elapsed time in the file
83 virtual int time_since_connection_open(timeval *elapsed_time);
84
85 // returns the current time in the file since the epoch (UTC time).
86 virtual timeval get_time() { return d_time; }
87
89
90 // Pretend to send pending report, really just clear the buffer.
91 virtual int send_pending_reports(void);
92
93 // {{{ fileconnections-specific methods (playback control)
94public:
95 // XXX the following should not be public if we want vrpn_File_Connection
96 // to have the same interface as vrpn_Connection
97 //
98 // If so handler functions for messages for these operations
99 // should be made, and functions added to vrpn_File_Controller which
100 // generate the messages. This seemed like it would be messy
101 // since most of these functions have return values
102
103 // rate of 0.0 is paused, 1.0 is normal speed
104 void set_replay_rate(vrpn_float32 rate)
105 {
106 d_filetime_accum.set_replay_rate(rate);
107 }
108
109 vrpn_float32 get_replay_rate() { return d_filetime_accum.replay_rate(); }
110
111 // resets to the beginning of the file
112 // returns 0 on success
113 int reset(void);
114
115 // returns 1 if we're at the end of file
116 int eof();
117
118 // end_time for play_to_time() is an elapsed time
119 // returns -1 on error or EOF, 0 on success
120 int play_to_time(vrpn_float64 end_time);
121 int play_to_time(timeval end_time);
122
123 // end_filetime is an absolute time, corresponding to the
124 // timestamps of the entries in the file,
125 // returns -1 on error or EOF, 0 on success
126 int play_to_filetime(const timeval end_filetime);
127
128 // plays the next entry, returns -1 or error or EOF, 0 otherwise
129 int playone();
130
131 // plays at most one entry, but won't play past end_filetime
132 // returns 0 on success, 1 if at end_filetime, -1 on error or EOF
133 int playone_to_filetime(timeval end_filetime);
134
135 // returns the elapsed time of the file
136 timeval get_length();
137 double get_length_secs();
138
139 // returns the timestamp of the earliest in time user message
140 timeval get_lowest_user_timestamp();
141
142 // returns the timestamp of the greatest-in-time user message
143 timeval get_highest_user_timestamp();
144
145 // returns the name of the file
146 const char *get_filename();
147
148 // jump_to_time sets the current position to the given elapsed time
149 // return 1 if we got to the specified time and 0 if we didn't
150 int jump_to_time(vrpn_float64 newtime);
151 int jump_to_time(timeval newtime);
152
153 // jump_to_filetime sets the current position to the given absolute time
154 // return 1 if we got to the specified time and 0 if we didn't
155 int jump_to_filetime(timeval absolute_time);
156
157 // Limits the number of messages played out on any one call to mainloop.
158 // 0 => no limit.
159 // Used to stop continuous callback-handling when messages arrive
160 // at a very high rate (such as from a vrpn_Imager) or to make sure
161 // that we are able to pause after each frame in frame-by-frame
162 // playback for tracking analysis programs.
163 void limit_messages_played_back(vrpn_uint32 max_playback)
164 {
165 Jane_stop_this_crazy_thing(max_playback);
166 };
167
168 // }}}
169 // {{{ tokens for VRPN control messages (data members)
170protected:
171 vrpn_int32 d_controllerId;
172
173 vrpn_int32 d_set_replay_rate_type;
174 vrpn_int32 d_reset_type;
175 vrpn_int32 d_play_to_time_type;
176 // long d_jump_to_time_type;
177
178 // }}}
179 // {{{ time-keeping
180protected:
181 timeval d_last_told; // Last time we printed error about no open file.
182 timeval d_time; // current time in file
183 timeval d_start_time; // time of first record in file
184 timeval d_earliest_user_time; // time of first user message
185 vrpn_bool d_earliest_user_time_valid;
186 timeval d_highest_user_time; // time of last user message
187 vrpn_bool d_highest_user_time_valid;
188
189 // finds the timestamps of the earliest and highest-time user messages
190 void find_superlative_user_times();
191
192 // these are to be used internally when jumping around in the
193 // stream (e.g., for finding the earliest and latest timed
194 // user messages). They assume
195 // 1) that only functions such as advance_currentLogEntry,
196 // read_entry and manual traversal of d_logHead/d_logTail
197 // will be used.
198 // the functions return false if they don't save or restore the bookmark
199 class VRPN_API vrpn_FileBookmark {
200 public:
203 bool valid;
204 timeval oldTime;
205 long int file_pos; // ftell result
206 vrpn_LOGLIST *oldCurrentLogEntryPtr; // just a pointer, useful for accum
207 // or preload
208 vrpn_LOGLIST *oldCurrentLogEntryCopy; // a deep copy, useful for
209 // no-accum, no-preload
210 };
211 bool store_stream_bookmark();
212 bool return_to_bookmark();
213 vrpn_FileBookmark d_bookmark;
214
215 // wallclock time at the (beginning of the) last call
216 // to mainloop that played back an event
217 timeval d_last_time; // XXX remove
218
219 class VRPN_API FileTime_Accumulator {
220 // accumulates the amount of time that we will advance
221 // filetime by when we next play back messages.
222 timeval d_filetime_accum_since_last_playback;
223
224 // wallclock time when d_filetime_accum_since_last_playback
225 // was last updated
226 timeval d_time_of_last_accum;
227
228 // scale factor between stream time and wallclock time
229 vrpn_float32 d_replay_rate;
230
231 public:
233
234 // return accumulated time since last reset
235 const timeval &accumulated(void)
236 {
237 return d_filetime_accum_since_last_playback;
238 }
239
240 // return last time accumulate_to was called
241 const timeval &time_of_last_accum(void) { return d_time_of_last_accum; }
242
243 vrpn_float32 replay_rate(void) { return d_replay_rate; }
244
245 // add (d_replay_rate * (now_time - d_time_of_last_accum))
246 // to d_filetime_accum_since_last_playback
247 // then set d_time_of_last_accum to now_time
248 void accumulate_to(const timeval &now_time);
249
250 // if current rate is non-zero, then time is accumulated
251 // before d_replay_rate is set to new_rate
252 void set_replay_rate(vrpn_float32 new_rate);
253
254 // set d_time_of_last_accum to now_time
255 // and set d_filetime_accum_since_last_playback to zero
256 void reset_at_time(const timeval &now_time);
257 };
258 FileTime_Accumulator d_filetime_accum;
259
260 // }}}
261 // {{{ actual mechanics of the logfile
262protected:
263 char *d_fileName;
264 FILE *d_file;
265
266 void play_to_user_message();
267
268 // helper function for mainloop()
269 int need_to_play(timeval filetime);
270
271 // checks the cookie at
272 // the head of the log file;
273 // exit on error!
274 virtual int read_cookie(void);
275
276 virtual int read_entry(void); // appends entry to d_logTail
277 // returns 0 on success, 1 on EOF, -1 on error
278
279 // Steps the currentLogEntry pointer forward one.
280 // It handles both cases of preload and non-preload.
281 // returns 0 on success, 1 on EOF, -1 on error
282 virtual int advance_currentLogEntry(void);
283
284 virtual int close_file(void);
285
286 // }}}
287 // {{{ handlers for VRPN control messages that might come from
288 // a File Controller object that wants to control this
289 // File Connection.
290protected:
291 static int VRPN_CALLBACK handle_set_replay_rate(void *, vrpn_HANDLERPARAM);
292 static int VRPN_CALLBACK handle_reset(void *, vrpn_HANDLERPARAM);
293 static int VRPN_CALLBACK handle_play_to_time(void *, vrpn_HANDLERPARAM);
294
295 // }}}
296 // {{{ Maintains a doubly-linked list structure that keeps
297 // copies of the messages from the file in memory. If
298 // d_accumulate is false, then there is only ever one entry
299 // in memory (d_currentLogEntry == d_logHead == d_logTail).
300 // If d_preload is true, then all of the records from the file
301 // are read into the list in the constructor and we merely step
302 // through memory when playing the streamfile. If d_preload is
303 // false and d_accumulate is true, then we have all of the
304 // records up the d_currentLogEntry in memory (d_logTail points
305 // to d_currentLogEntry but not to the last entry in the file
306 // until we get to the end of the file).
307 // The d_currentLogEntry should always be non-NULL unless we are
308 // past the end of all messages... we will either have preloaded
309 // all of them or else the read routine will attempt to load the
310 // next message each time one is played. The constructor fills it
311 // in with the first message, which makes it non-NULL initially.
312 // HOWEVER, if there are no user messages and we're asked to skip
313 // to the first user message then it can be NULL right after the
314 // constructor is called.
315protected:
316 vrpn_LOGLIST *d_logHead; // the first read-in record
317 vrpn_LOGLIST *d_logTail; // the last read-in record
318 vrpn_LOGLIST *d_currentLogEntry; // Message that we've just loaded, or are
319 // at right now
320 vrpn_LOGLIST *d_startEntry; // potentially after initial system messages
321 bool d_preload; // Should THIS File Connection pre-load?
322 bool d_accumulate; // Should THIS File Connection accumulate?
323 // }}}
324};
325
326#endif // VRPN_FILE_CONNECTION_H
Generic connection class not specific to the transport mechanism.
定义 vrpn_Connection.h:562
void Jane_stop_this_crazy_thing(vrpn_uint32 stop_looking_after)
定义 vrpn_Connection.h:689
virtual int mainloop(const struct timeval *timeout=NULL)=0
定义 vrpn_FileConnection.h:219
定义 vrpn_FileConnection.h:199
定义 vrpn_FileConnection.h:73
virtual timeval get_time()
定义 vrpn_FileConnection.h:86
virtual vrpn_File_Connection * get_File_Connection(void)
virtual int send_pending_reports(void)
virtual int time_since_connection_open(timeval *elapsed_time)
This structure is what is passed to a vrpn_Connection message callback.
定义 vrpn_Connection.h:41
Placed here so vrpn_FileConnection can use it too.
定义 vrpn_Connection.h:160