#include "state_tracking.h" #include #include enum state_t { STATE_IDLE = 0, STATE_RECORDING = 1, STATE_PLAYBACK = 2, }; static std::vector 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; }