#ifdef PANDA3DS_ENABLE_HTTP_SERVER #pragma once #include <array> #include <atomic> #include <condition_variable> #include <filesystem> #include <map> #include <memory> #include <mutex> #include <queue> #include <thread> #include "helpers.hpp" enum class HttpActionType { None, Screenshot, Key, TogglePause, Reset, LoadRom, Step }; class Emulator; namespace httplib { class Server; struct Response; } // Wrapper for httplib::Response that allows the HTTP server to wait for the response to be ready struct DeferredResponseWrapper { DeferredResponseWrapper(httplib::Response& response) : inner_response(response) {} httplib::Response& inner_response; std::mutex mutex; std::condition_variable cv; bool ready = false; }; // Actions derive from this class and are used to communicate with the HTTP server class HttpAction { HttpActionType type; public: HttpAction(HttpActionType type) : type(type) {} virtual ~HttpAction() = default; HttpActionType getType() const { return type; } static std::unique_ptr<HttpAction> createScreenshotAction(DeferredResponseWrapper& response); static std::unique_ptr<HttpAction> createKeyAction(u32 key, bool state); static std::unique_ptr<HttpAction> createLoadRomAction(DeferredResponseWrapper& response, const std::filesystem::path& path, bool paused); static std::unique_ptr<HttpAction> createTogglePauseAction(); static std::unique_ptr<HttpAction> createResetAction(); static std::unique_ptr<HttpAction> createStepAction(DeferredResponseWrapper& response, int frames); }; struct HttpServer { HttpServer(Emulator* emulator); ~HttpServer(); void processActions(); private: static constexpr const char* httpServerScreenshotPath = "screenshot.png"; Emulator* emulator; std::unique_ptr<httplib::Server> server; std::thread httpServerThread; std::queue<std::unique_ptr<HttpAction>> actionQueue; std::mutex actionQueueMutex; std::unique_ptr<HttpAction> currentStepAction {}; std::map<std::string, u32> keyMap; bool paused = false; int framesToRun = 0; void startHttpServer(); void pushAction(std::unique_ptr<HttpAction> action); std::string status(); u32 stringToKey(const std::string& key_name); HttpServer(const HttpServer&) = delete; HttpServer& operator=(const HttpServer&) = delete; }; #endif // PANDA3DS_ENABLE_HTTP_SERVER