15
15
#include < filesystem>
16
16
#include < fstream>
17
17
#include < cassert>
18
+ #include < thread>
18
19
19
20
#include < tape/TapePlayer.hpp>
20
21
#include < tape/tapeDefinitions.hpp>
23
24
24
25
namespace fs = std::filesystem;
25
26
26
- TapePlayer::TapePlayer (const char * path)
27
+ TapePlayer::TapePlayer (const char * path) : path(path)
27
28
{
28
- std::string pathYaml = fs::path (path).concat (YAML_EXTENSION).string ();
29
- std::string pathBin = fs::path (path).concat (BIN_EXTENSION).string ();
30
-
31
- playbackState = std::make_unique<PlaybackState>(pathBin.c_str ());
29
+ playbackState = std::make_unique<PlaybackState>(getBinPath ().c_str ());
32
30
33
- yamlRoot = YAML::LoadFile (pathYaml );
31
+ yamlRoot = YAML::LoadFile (getYamlPath () );
34
32
if (yamlRoot.IsNull ()) {
35
33
throw RecordError (" Invalid Tape: Empty YAML file detected" );
36
34
}
@@ -43,6 +41,10 @@ TapePlayer::TapePlayer(const char* path)
43
41
nextCallIdx = 0 ;
44
42
}
45
43
44
+ std::string TapePlayer::getBinPath () const { return fs::path (path).concat (BIN_EXTENSION).string (); }
45
+
46
+ std::string TapePlayer::getYamlPath () const { return fs::path (path).concat (YAML_EXTENSION).string (); }
47
+
46
48
void TapePlayer::checkTapeVersion ()
47
49
{
48
50
auto versionCallIdx = findFirst ({RGL_VERSION});
@@ -110,8 +112,6 @@ void TapePlayer::playUntil(std::optional<APICallIdx> breakpoint)
110
112
}
111
113
}
112
114
113
- void TapePlayer::rewindTo (APICallIdx nextCall) { this ->nextCallIdx = nextCall; }
114
-
115
115
void TapePlayer::playThis (APICallIdx idx)
116
116
{
117
117
const TapeCall& call = getTapeCall (idx);
@@ -121,15 +121,30 @@ void TapePlayer::playThis(APICallIdx idx)
121
121
tapeFunctions[call.getFnName ()](call.getArgsNode (), *playbackState);
122
122
}
123
123
124
- # include < thread >
125
- void TapePlayer::playRealtime ()
124
+
125
+ void TapePlayer::playApproximatelyRealtime ()
126
126
{
127
+ // Approximation comes from the fact that we don't account for the time it takes to execute the function
128
+ // This could be fixed by moving TAPE_HOOK to the beginning of the API call
129
+ // It might be a good idea to do so, because it would record failed calls.
127
130
auto beginTimestamp = std::chrono::steady_clock::now ();
128
- TapeCall nextCall = getTapeCall (nextCallIdx);
129
131
for (; nextCallIdx < yamlRoot.size (); ++nextCallIdx) {
132
+ TapeCall nextCall = getTapeCall (nextCallIdx);
130
133
auto nextCallNs = std::chrono::nanoseconds (nextCall.getTimestamp ().asNanoseconds ());
131
134
auto elapsed = std::chrono::steady_clock::now () - beginTimestamp;
132
135
std::this_thread::sleep_for (nextCallNs - elapsed);
133
136
playThis (nextCallIdx);
134
137
}
135
138
}
139
+
140
+ void TapePlayer::reset ()
141
+ {
142
+ auto status = rgl_cleanup ();
143
+ if (status != RGL_SUCCESS) {
144
+ const char * error = nullptr ;
145
+ rgl_get_last_error_string (&error);
146
+ throw RecordError (fmt::format (" Failed to reset playback state: {}" , error));
147
+ }
148
+ nextCallIdx = 0 ;
149
+ playbackState = std::make_unique<PlaybackState>(getBinPath ().c_str ());
150
+ }
0 commit comments