117 lines
2.9 KiB
C++
117 lines
2.9 KiB
C++
#include "state_tracking.h"
|
|
#include <unistd.h>
|
|
#include <vector>
|
|
|
|
enum state_t {
|
|
STATE_IDLE = 0,
|
|
STATE_RECORDING = 1,
|
|
STATE_PLAYBACK = 2,
|
|
};
|
|
|
|
static std::vector<EventCB> event_cbs;
|
|
|
|
static bool should_close_recording_stream;
|
|
static FILE* recording_stream;
|
|
static uint32_t recording_start_time;
|
|
TaskHandle_t flush_file_task_handle;
|
|
|
|
static bool should_close_playback_stream;
|
|
static FILE* playback_stream;
|
|
static volatile state_t state = STATE_IDLE;
|
|
|
|
|
|
/// @brief Periodically flushes and syncs (if neccesary) the output stream.
|
|
/// @param arg unused.
|
|
static void flush_file_task(void* arg) {
|
|
while (state == STATE_RECORDING && recording_stream != nullptr) {
|
|
fflush(recording_stream);
|
|
|
|
int fd = fileno(recording_stream);
|
|
if (fd != -1) {
|
|
fsync(fd);
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(5000));
|
|
}
|
|
|
|
flush_file_task_handle = NULL;
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
void register_event_cb(const char* name, void (*replay_callback)(uint32_t, const char*)) {
|
|
EventCB event = {
|
|
.name = name,
|
|
.replay_callback = replay_callback,
|
|
};
|
|
event_cbs.push_back(event);
|
|
}
|
|
|
|
void event_occured(const char* name, const char* arg) {
|
|
if (state != STATE_RECORDING) return;
|
|
if (name == nullptr) return;
|
|
if (recording_stream == nullptr) {
|
|
ESP_LOGE("state_tracking", "We are in state recording, but recording stream is null");
|
|
return;
|
|
}
|
|
|
|
arg = (arg == nullptr) ? "" : arg;
|
|
uint32_t ticks = xTaskGetTickCount() - recording_start_time;
|
|
fprintf(recording_stream, "%ld,%s:%s\n", ticks, name, (arg == nullptr) ? "" : arg);
|
|
}
|
|
|
|
bool set_recording_source(FILE* stream, bool should_close) {
|
|
if (state == STATE_RECORDING) return false;
|
|
|
|
recording_stream = stream;
|
|
should_close_recording_stream = should_close;
|
|
return true;
|
|
}
|
|
|
|
bool set_playback_source(FILE* stream, bool should_close) {
|
|
if (state == STATE_PLAYBACK) return false;
|
|
|
|
playback_stream = stream;
|
|
should_close_playback_stream = should_close;
|
|
return true;
|
|
}
|
|
|
|
bool start_recording() {
|
|
if (state != STATE_IDLE) return false;
|
|
if (recording_stream == nullptr) return false;
|
|
|
|
state = STATE_RECORDING;
|
|
recording_start_time = xTaskGetTickCount();
|
|
xTaskCreate(flush_file_task, "flush_recording", 2048, NULL, 2, &flush_file_task_handle);
|
|
return true;
|
|
}
|
|
|
|
bool stop_recording() {
|
|
if (state != STATE_RECORDING) return false;
|
|
|
|
state = STATE_IDLE;
|
|
fflush(recording_stream);
|
|
if (should_close_recording_stream) {
|
|
fclose(recording_stream);
|
|
recording_stream = nullptr;
|
|
}
|
|
|
|
if (flush_file_task_handle != nullptr) {
|
|
vTaskDelete(flush_file_task_handle);
|
|
flush_file_task_handle = NULL;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool start_playback() {
|
|
// TODO: impl
|
|
return false;
|
|
}
|
|
|
|
bool stop_playback() {
|
|
// TODO: impl
|
|
return false;
|
|
}
|
|
|
|
bool is_state_tracking() {
|
|
return state == STATE_RECORDING;
|
|
}
|