Files
tactility/Tactility/Source/settings/DisplaySettings.cpp
Adolfo Reyna e3eb3fd415 feat(mcp): restore MCP system with native log.h
- MCP 3.3K LOC: McpSystem 1899 + McpHandler 1029 + McpScreensaver + 2 apps
- Uses native tactility/log.h TAG macros, no old Logger.h
- DisplaySettings McpScreen enum, WebServer coexistence (MCP enabled starts HTTP)
- DisplayIdle: startMcpScreensaver + isDeviceCharging + lock inversion fix 3629ffef
- LVGL 512K PSRAM cache retained from previous perf patch
- Audio kept upstream es8311-module per note we might not need custom
2026-07-18 17:29:37 -04:00

198 lines
8.2 KiB
C++

#include <Tactility/settings/DisplaySettings.h>
#include <Tactility/file/File.h>
#include <Tactility/file/PropertiesFile.h>
#include <Tactility/Paths.h>
#include <tactility/hal/Device.h>
#include <Tactility/hal/display/DisplayDevice.h>
#include <map>
#include <string>
#include <utility>
namespace tt::settings::display {
static std::string getSettingsFilePath() {
return getUserDataPath() + "/settings/display.properties";
}
constexpr auto* SETTINGS_KEY_ORIENTATION = "orientation";
constexpr auto* SETTINGS_KEY_GAMMA_CURVE = "gammaCurve";
constexpr auto* SETTINGS_KEY_BACKLIGHT_DUTY = "backlightDuty";
constexpr auto* SETTINGS_KEY_TIMEOUT_ENABLED = "backlightTimeoutEnabled";
constexpr auto* SETTINGS_KEY_TIMEOUT_MS = "backlightTimeoutMs";
constexpr auto* SETTINGS_KEY_SCREENSAVER_TYPE = "screensaverType";
constexpr auto* SETTINGS_KEY_DISABLE_WHEN_CHARGING = "disableScreensaverWhenCharging";
static Orientation getDefaultOrientation() {
auto* display = lv_display_get_default();
if (display == nullptr) {
return Orientation::Landscape;
}
if (lv_display_get_physical_horizontal_resolution(display) > lv_display_get_physical_vertical_resolution(display)) {
return Orientation::Landscape;
} else {
return Orientation::Portrait;
}
}
static std::string toString(Orientation orientation) {
switch (orientation) {
using enum Orientation;
case Portrait: return "Portrait";
case Landscape: return "Landscape";
case PortraitFlipped: return "PortraitFlipped";
case LandscapeFlipped: return "LandscapeFlipped";
default: std::unreachable();
}
}
static bool fromString(const std::string& str, Orientation& orientation) {
if (str == "Portrait") { orientation = Orientation::Portrait; return true; }
else if (str == "Landscape") { orientation = Orientation::Landscape; return true; }
else if (str == "PortraitFlipped") { orientation = Orientation::PortraitFlipped; return true; }
else if (str == "LandscapeFlipped") { orientation = Orientation::LandscapeFlipped; return true; }
else { return false; }
}
static std::string toString(ScreensaverType type) {
switch (type) {
using enum ScreensaverType;
case None: return "None";
case BouncingBalls: return "BouncingBalls";
case Mystify: return "Mystify";
case MatrixRain: return "MatrixRain";
case StackChan: return "StackChan";
case McpScreen: return "McpScreen";
case Count: return "None";
default: std::unreachable();
}
}
static bool fromString(const std::string& str, ScreensaverType& type) {
if (str == "None") { type = ScreensaverType::None; return true; }
else if (str == "BouncingBalls") { type = ScreensaverType::BouncingBalls; return true; }
else if (str == "Mystify") { type = ScreensaverType::Mystify; return true; }
else if (str == "MatrixRain") { type = ScreensaverType::MatrixRain; return true; }
else if (str == "StackChan") { type = ScreensaverType::StackChan; return true; }
else if (str == "McpScreen") { type = ScreensaverType::McpScreen; return true; }
else { return false; }
}
bool load(DisplaySettings& settings) {
auto settings_path = getSettingsFilePath();
if (!file::isFile(settings_path)) { return false; }
std::map<std::string, std::string> map;
if (!file::loadPropertiesFile(settings_path, map)) { return false; }
auto orientation_entry = map.find(SETTINGS_KEY_ORIENTATION);
Orientation orientation;
if (orientation_entry == map.end() || !fromString(orientation_entry->second, orientation)) {
orientation = getDefaultOrientation();
}
auto gamma_entry = map.find(SETTINGS_KEY_GAMMA_CURVE);
int gamma_curve = 0;
if (gamma_entry != map.end()) { gamma_curve = atoi(gamma_entry->second.c_str()); }
auto backlight_duty_entry = map.find(SETTINGS_KEY_BACKLIGHT_DUTY);
int backlight_duty = 200;
if (backlight_duty_entry != map.end()) {
backlight_duty = atoi(backlight_duty_entry->second.c_str());
if (backlight_duty_entry->second != "0" && backlight_duty == 0) backlight_duty = 200;
}
bool timeout_enabled = false;
auto timeout_enabled_entry = map.find(SETTINGS_KEY_TIMEOUT_ENABLED);
if (timeout_enabled_entry != map.end()) {
timeout_enabled = (timeout_enabled_entry->second == "1" || timeout_enabled_entry->second == "true" || timeout_enabled_entry->second == "True");
}
uint32_t timeout_ms = 60000;
auto timeout_ms_entry = map.find(SETTINGS_KEY_TIMEOUT_MS);
if (timeout_ms_entry != map.end()) {
timeout_ms = static_cast<uint32_t>(std::strtoul(timeout_ms_entry->second.c_str(), nullptr, 10));
}
auto screensaver_entry = map.find(SETTINGS_KEY_SCREENSAVER_TYPE);
ScreensaverType screensaver_type = ScreensaverType::BouncingBalls;
if (screensaver_entry != map.end()) { fromString(screensaver_entry->second, screensaver_type); }
bool disable_when_charging = false;
auto charging_entry = map.find(SETTINGS_KEY_DISABLE_WHEN_CHARGING);
if (charging_entry != map.end()) {
disable_when_charging = (charging_entry->second == "1" || charging_entry->second == "true");
}
settings.orientation = orientation;
settings.gammaCurve = gamma_curve;
settings.backlightDuty = backlight_duty;
settings.backlightTimeoutEnabled = timeout_enabled;
settings.backlightTimeoutMs = timeout_ms;
settings.screensaverType = screensaver_type;
settings.disableScreensaverWhenCharging = disable_when_charging;
return true;
}
DisplaySettings getDefault() {
return DisplaySettings {
.orientation = getDefaultOrientation(),
.gammaCurve = 1,
.backlightDuty = 200,
.backlightTimeoutEnabled = false,
.backlightTimeoutMs = 60000,
.screensaverType = ScreensaverType::BouncingBalls,
.disableScreensaverWhenCharging = false
};
}
DisplaySettings loadOrGetDefault() {
DisplaySettings settings;
if (!load(settings)) { settings = getDefault(); }
return settings;
}
bool save(const DisplaySettings& settings) {
std::map<std::string, std::string> map;
map[SETTINGS_KEY_BACKLIGHT_DUTY] = std::to_string(settings.backlightDuty);
map[SETTINGS_KEY_GAMMA_CURVE] = std::to_string(settings.gammaCurve);
map[SETTINGS_KEY_ORIENTATION] = toString(settings.orientation);
map[SETTINGS_KEY_TIMEOUT_ENABLED] = settings.backlightTimeoutEnabled ? "1" : "0";
map[SETTINGS_KEY_TIMEOUT_MS] = std::to_string(settings.backlightTimeoutMs);
map[SETTINGS_KEY_SCREENSAVER_TYPE] = toString(settings.screensaverType);
map[SETTINGS_KEY_DISABLE_WHEN_CHARGING] = settings.disableScreensaverWhenCharging ? "1" : "0";
auto settings_path = getSettingsFilePath();
if (!file::findOrCreateParentDirectory(settings_path, 0755)) { return false; }
return file::savePropertiesFile(settings_path, map);
}
lv_display_rotation_t toLvglDisplayRotation(Orientation orientation) {
auto* lvgl_display = lv_display_get_default();
auto rotation = lv_display_get_rotation(lvgl_display);
bool is_originally_landscape;
if (rotation == LV_DISPLAY_ROTATION_0 || rotation == LV_DISPLAY_ROTATION_180) {
is_originally_landscape = lv_display_get_physical_horizontal_resolution(lvgl_display) > lv_display_get_physical_vertical_resolution(lvgl_display);
} else {
is_originally_landscape = lv_display_get_physical_horizontal_resolution(lvgl_display) < lv_display_get_physical_vertical_resolution(lvgl_display);
}
if (is_originally_landscape) {
switch (orientation) {
case Orientation::Landscape: return LV_DISPLAY_ROTATION_0;
case Orientation::Portrait: return LV_DISPLAY_ROTATION_90;
case Orientation::LandscapeFlipped: return LV_DISPLAY_ROTATION_180;
case Orientation::PortraitFlipped: return LV_DISPLAY_ROTATION_270;
default: return LV_DISPLAY_ROTATION_0;
}
} else {
switch (orientation) {
case Orientation::Landscape: return LV_DISPLAY_ROTATION_90;
case Orientation::Portrait: return LV_DISPLAY_ROTATION_0;
case Orientation::LandscapeFlipped: return LV_DISPLAY_ROTATION_270;
case Orientation::PortraitFlipped: return LV_DISPLAY_ROTATION_180;
default: return LV_DISPLAY_ROTATION_0;
}
}
}
} // namespace