FlightGear next
replay-internal.hxx
Go to the documentation of this file.
1/*
2 * SPDX-FileName: replay.hxx
3 * SPDX-FileComment: a system to record and replay FlightGear flights
4 * SPDX-FileCopyrightText: Copyright (C) 2003 Curtis L. Olson - http://www.flightgear.org/~curt
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8#pragma once
9
10#include <deque>
11#include <mutex>
12#include <vector>
13
14#include <simgear/compiler.h>
15#include <simgear/io/HTTPFileRequest.hxx>
16#include <simgear/io/iostreams/gzcontainerfile.hxx>
17#include <simgear/math/sg_types.hxx>
18#include <simgear/props/props.hxx>
19#include <simgear/structure/subsystem_mgr.hxx>
20
22
23
25
27extern const char* const FlightRecorderFileMagic;
28
29/* Data for a single frame. */
31 bool load_signals{false};
32 bool load_multiplayer{false};
34
35 double sim_time{0.0};
36
37 // Our aircraft state.
38 std::vector<char> raw_data;
39
40 // Incoming multiplayer messages, if any.
41 std::vector<std::shared_ptr<std::vector<char>>> multiplayer_messages;
42
43 // Serialised information about extra property changes, only used when
44 // making a Continuous recording - we write this raw data into frame data
45 // in the Continuous recording file.
46 std::vector<char> extra_properties;
47
48 // Information about extra property changes, only used when replaying. We
49 // populate these when loading a frame.
50 std::map<std::string, std::string> replay_extra_property_changes;
51 std::vector<std::string> replay_extra_property_removals;
52
53 // Updates static statistics defined below.
54 void UpdateStats();
55
56 // Resets out static property nodes; to be called by fgStartNewReset().
57 static void resetStatisticsProperties();
58
61
62 size_t m_bytes_raw_data = 0;
65
66 // Statistics about replay data, also properties /sim/replay/datastats_*.
67 static size_t s_num;
68 static size_t s_bytes_raw_data;
71 static SGPropertyNode_ptr s_prop_num;
72 static SGPropertyNode_ptr s_prop_bytes_raw_data;
73 static SGPropertyNode_ptr s_prop_bytes_multiplayer_messages;
74 static SGPropertyNode_ptr s_prop_num_multiplayer_messages;
75};
76
77typedef struct
78{
79 double sim_time;
80 std::string message;
81 std::string speaker;
83
89
90
91/* Index entry when replaying Continuous recording. */
93 size_t offset;
94 bool has_signals = false;
95 bool has_multiplayer = false;
97};
98
99std::ostream& operator<<(std::ostream& out, const FGFrameInfo& frame_info);
100
101
104 virtual ~FGReplayInternal();
105
106 /* Methods that implement the FGReplay API. */
107
108 void bind();
109 void init();
110 void reinit();
111 void unbind();
112 void update(double dt);
113
114 static const char* staticSubsystemClassId() { return "replay"; }
115
116 bool start(bool NewTape = false);
117
118 bool saveTape(const SGPropertyNode* ConfigData);
119 bool loadTape(const SGPropertyNode* ConfigData);
120
121 static int loadContinuousHeader(
122 const std::string& path,
123 std::istream* in,
124 SGPropertyNode* properties);
125
126 bool loadTape(
127 const SGPath& filename,
128 bool preview,
129 bool create_video,
130 double fixed_dt,
131 SGPropertyNode& meta_meta,
132 simgear::HTTP::FileRequestRef file_request = nullptr);
133
134 static std::string makeTapePath(const std::string& tape_name);
135
136
137 /* Callback for SGPropertyChangeListener. */
138 //void valueChanged(SGPropertyNode * node) override;
139
140 /* Internal state. */
141
143
149
150 std::deque<FGReplayData*> m_short_term;
151 std::deque<FGReplayData*> m_medium_term;
152 std::deque<FGReplayData*> m_long_term;
153 std::deque<FGReplayData*> m_recycler;
154
155 std::vector<FGReplayMessages> m_replay_messages;
156 std::vector<FGReplayMessages>::iterator m_current_msg;
157
158 SGPropertyNode_ptr m_disable_replay;
159 SGPropertyNode_ptr m_replay_master;
160 SGPropertyNode_ptr m_replay_master_eof;
161 SGPropertyNode_ptr m_replay_time;
162 SGPropertyNode_ptr m_replay_time_str;
163 SGPropertyNode_ptr m_replay_looped;
164 SGPropertyNode_ptr m_replay_duration_act;
165 SGPropertyNode_ptr m_speed_up;
166 SGPropertyNode_ptr m_replay_multiplayer;
167 SGPropertyNode_ptr m_recovery_period;
168 SGPropertyNode_ptr m_replay_error;
169 SGPropertyNode_ptr m_record_normal_begin; // Time of first in-memory recorded frame.
170 SGPropertyNode_ptr m_record_normal_end;
171 SGPropertyNode_ptr m_log_frame_times;
172
173 SGPropertyNode_ptr m_sim_startup_xpos;
174 SGPropertyNode_ptr m_sim_startup_ypos;
175 SGPropertyNode_ptr m_sim_startup_xsize;
176 SGPropertyNode_ptr m_sim_startup_ysize;
177 SGPropertyNode_ptr m_simple_time_enabled;
178
179 double m_replay_time_prev; // Used to detect jumps while replaying.
180
181 /* short term sample rate is as every frame. */
182 double m_high_res_time; // default: 60 secs of high res data
183 double m_medium_res_time; // default: 10 mins of 1 fps data
184 double m_low_res_time; // default: 1 hr of 10 spf data
185 double m_medium_sample_rate; // medium term sample rate (sec)
186 double m_long_sample_rate; // long term sample rate (sec)
187
188 std::shared_ptr<FGFlightRecorder> m_flight_recorder;
189
190 /* Things for Continuous recording/replay support. */
191 std::unique_ptr<struct Continuous> m_continuous;
192
194};
195
196
197/* Sets things up for writing to a normal or continuous fgtape file.
198
199 extra:
200 NULL or extra information when we are called from fgdata gui, e.g. with
201 the flight description entered by the user in the save dialogue.
202 path:
203 Path of fgtape file. We return nullptr if this file already exists.
204 duration:
205 Duration of recording. Zero if we are starting a continuous recording.
206 tape_type:
207 .
208 continuous_compression:
209 Whether to use compression if tape_type is FGTapeType_CONTINUOUS.
210 Returns:
211 A new SGPropertyNode suitable as prefix of recording. If
212 extra:user-data exists, it will appear as meta/user-data.
213*/
214SGPropertyNode_ptr saveSetup(
215 const SGPropertyNode* extra,
216 const SGPath& path,
217 double duration,
218 FGTapeType tape_type,
219 int continuous_compression = 0);
220
221/* Returns a path using different formats depending on <type>:
222
223 FGTapeType_NORMAL: <tape-directory>/<aircraft-type>-<date>-<time>.fgtape
224 FGTapeType_CONTINUOUS: <tape-directory>/<aircraft-type>-<date>-<time>-continuous.fgtape
225 FGTapeType_RECOVERY: <tape-directory>/<aircraft-type>-recovery.fgtape
226*/
227SGPath makeSavePath(FGTapeType type, SGPath* path_timeless = nullptr);
const char *const FlightRecorderFileMagic
Magic string to verify valid FG flight recorder tapes.
SGPropertyNode_ptr saveSetup(const SGPropertyNode *extra, const SGPath &path, double duration, FGTapeType tape_type, int continuous_compression=0)
std::ostream & operator<<(std::ostream &out, const FGFrameInfo &frame_info)
SGPath makeSavePath(FGTapeType type, SGPath *path_timeless=nullptr)
@ FGTapeType_NORMAL
@ FGTapeType_CONTINUOUS
@ FGTapeType_RECOVERY
size_t m_num_multiplayer_messages
std::vector< std::shared_ptr< std::vector< char > > > multiplayer_messages
static SGPropertyNode_ptr s_prop_num
std::vector< char > extra_properties
static size_t s_bytes_multiplayer_messages
static size_t s_num
static void resetStatisticsProperties()
std::map< std::string, std::string > replay_extra_property_changes
static size_t s_bytes_raw_data
static SGPropertyNode_ptr s_prop_bytes_raw_data
static SGPropertyNode_ptr s_prop_bytes_multiplayer_messages
std::vector< std::string > replay_extra_property_removals
std::vector< char > raw_data
size_t m_bytes_multiplayer_messages
static size_t s_num_multiplayer_messages
static SGPropertyNode_ptr s_prop_num_multiplayer_messages
SGPropertyNode_ptr m_sim_startup_xpos
FGMultiplayMgr * m_MultiplayMgr
SGPropertyNode_ptr m_recovery_period
SGPropertyNode_ptr m_replay_multiplayer
std::unique_ptr< struct Continuous > m_continuous
SGPropertyNode_ptr m_replay_time
SGPropertyNode_ptr m_record_normal_begin
SGPropertyNode_ptr m_replay_time_str
SGPropertyNode_ptr m_replay_duration_act
SGPropertyNode_ptr m_log_frame_times
SGPropertyNode_ptr m_replay_master
SGPropertyNode_ptr m_replay_master_eof
bool start(bool NewTape=false)
Start replay session.
SGPropertyNode_ptr m_record_normal_end
static const char * staticSubsystemClassId()
static int loadContinuousHeader(const std::string &path, std::istream *in, SGPropertyNode *properties)
SGPropertyNode_ptr m_speed_up
SGPropertyNode_ptr m_sim_startup_ypos
std::vector< FGReplayMessages >::iterator m_current_msg
std::deque< FGReplayData * > m_medium_term
std::deque< FGReplayData * > m_long_term
SGPropertyNode_ptr m_sim_startup_ysize
SGPropertyNode_ptr m_sim_startup_xsize
void update(double dt)
static std::string makeTapePath(const std::string &tape_name)
std::deque< FGReplayData * > m_short_term
std::shared_ptr< FGFlightRecorder > m_flight_recorder
bool loadTape(const SGPropertyNode *ConfigData)
Load a flight recorder tape from disk.
SGPropertyNode_ptr m_simple_time_enabled
SGPropertyNode_ptr m_replay_error
SGPropertyNode_ptr m_disable_replay
std::vector< FGReplayMessages > m_replay_messages
SGPropertyNode_ptr m_replay_looped
std::deque< FGReplayData * > m_recycler
bool saveTape(const SGPropertyNode *ConfigData)
Write flight recorder tape to disk.