Files
cardboy/Firmware/main/include/app_framework.hpp
2025-10-09 09:26:34 +02:00

73 lines
2.0 KiB
C++

#pragma once
#include "app_platform.hpp"
#include "input_state.hpp"
#include <cstdint>
#include <memory>
#include <string>
#include <string_view>
#include <vector>
class AppSystem;
template<typename FramebufferT, typename InputT, typename ClockT>
struct BasicAppContext {
using Framebuffer = FramebufferT;
using Input = InputT;
using Clock = ClockT;
BasicAppContext() = delete;
BasicAppContext(FramebufferT& fb, InputT& in, ClockT& clk) : framebuffer(fb), input(in), clock(clk) {}
FramebufferT& framebuffer;
InputT& input;
ClockT& clock;
AppSystem* system = nullptr;
void requestAppSwitchByIndex(std::size_t index) {
pendingAppIndex = index;
pendingAppName.clear();
pendingSwitchByName = false;
pendingSwitch = true;
}
void requestAppSwitchByName(std::string_view name) {
pendingAppName.assign(name.begin(), name.end());
pendingSwitchByName = true;
pendingSwitch = true;
}
bool hasPendingAppSwitch() const { return pendingSwitch; }
private:
friend class AppSystem;
bool pendingSwitch = false;
bool pendingSwitchByName = false;
std::size_t pendingAppIndex = 0;
std::string pendingAppName;
};
using AppContext = BasicAppContext<PlatformFramebuffer, PlatformInput, PlatformClock>;
struct AppSleepPlan {
uint32_t slow_ms = 0; // long sleep allowing battery/UI periodic refresh
uint32_t normal_ms = 0; // short sleep for responsiveness on input wake
};
class IApp {
public:
virtual ~IApp() = default;
virtual void onStart() {}
virtual void onStop() {}
virtual void step() = 0;
virtual AppSleepPlan sleepPlan(uint32_t now) const { return {}; }
};
class IAppFactory {
public:
virtual ~IAppFactory() = default;
virtual const char* name() const = 0;
virtual std::unique_ptr<IApp> create(AppContext& context) = 0;
};