1 // TimeManager.hxx -- simulation-wide time management
2 //
3 // Written by James Turner, started July 2010.
4 //
5 // Copyright (C) 2010  Curtis L. Olson  - http://www.flightgear.org/~curt
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 
21 #ifndef FG_TIME_TIMEMANAGER_HXX
22 #define FG_TIME_TIMEMANAGER_HXX
23 
24 #include <simgear/props/props.hxx>
25 #include <simgear/structure/subsystem_mgr.hxx>
26 #include <simgear/math/SGVec3.hxx>
27 
28 // forward decls
29 class SGTime;
30 
31 class TimeManager : public SGSubsystem,
32                     public SGPropertyChangeListener
33 {
34 public:
35     TimeManager();
36     virtual ~TimeManager();
37 
38     // Subsystem API.
39     void init() override;
40     void postinit() override;
41     void reinit() override;
42     void shutdown() override;
43     void unbind() override;
44     void update(double dt) override;
45 
46     // Subsystem identification.
staticSubsystemClassId()47     static const char* staticSubsystemClassId() { return "time"; }
48 
49     void computeTimeDeltas(double& simDt, double& realDt);
50 
51     // SGPropertyChangeListener overrides
52     void valueChanged(SGPropertyNode *) override;
53 
54     void setTimeOffset(const std::string& offset_type, long int offset);
55 
getMPProtocolClockSec() const56     inline double getMPProtocolClockSec() const { return _mpProtocolClock; }
getSteadyClockSec() const57     inline double getSteadyClockSec() const { return _steadyClock; }
58 
59     double getSimSpeedUpFactor() const;
60 
61 private:
62     /**
63      * Ensure a consistent update-rate using a combination of
64      * sleep()-ing and busy-waiting.
65      */
66     void throttleUpdateRate();
67 
68     /**
69      * Compute frame (update) rate and write it to a property
70      */
71     void computeFrameRate();
72 
73     void updateLocalTime();
74 
75     void updateLocalTimeString();
76 
77     // set up a time offset (aka warp) if one is specified
78     void initTimeOffset();
79 
80     bool _inited;
81     SGTime* _impl;
82     SGTimeStamp _lastStamp;
83     SGTimeStamp _systemStamp;
84     bool _firstUpdate;
85     double _dtRemainder;
86     SGPropertyNode_ptr _maxDtPerFrame;
87     SGPropertyNode_ptr _clockFreeze;
88     SGPropertyNode_ptr _timeOverride;
89     SGPropertyNode_ptr _warp;
90     SGPropertyNode_ptr _warpDelta;
91     SGPropertyNode_ptr _simTimeFactor;
92     SGPropertyNode_ptr _mpProtocolClockNode;
93     SGPropertyNode_ptr _steadyClockNode;
94     SGPropertyNode_ptr _frameTimeOffsetNode;
95     SGPropertyNode_ptr _dtRemainderNode;
96     SGPropertyNode_ptr _mpClockOffset;
97     SGPropertyNode_ptr _steadyClockDrift;
98     SGPropertyNode_ptr _computeDrift;
99     SGPropertyNode_ptr _frameWait;
100     SGPropertyNode_ptr _maxFrameRate;
101     SGPropertyNode_ptr _localTimeStringNode;
102 
103     bool _lastClockFreeze;
104     bool _adjustWarpOnUnfreeze;
105 
106     // frame-rate / worst-case latency / update-rate counters
107     SGPropertyNode_ptr _frameRate;
108     SGPropertyNode_ptr _frameRateWorst;
109     SGPropertyNode_ptr _frameLatency;
110     time_t _lastFrameTime;
111     double _frameLatencyMax;
112     double _mpProtocolClock;
113     double _steadyClock;
114     int _frameCount;
115 
116     // we update TZ after moving more than a threshold distance
117     SGVec3d _lastTimeZoneCheckPosition;
118 
119     SGPropertyNode_ptr _sceneryLoaded;
120     SGPropertyNode_ptr _modelHz;
121     SGPropertyNode_ptr _timeDelta, _simTimeDelta;
122 };
123 
124 #endif // of FG_TIME_TIMEMANAGER_HXX
125