2026-10-16 00:54:13 +02:00

87 lines
2.4 KiB
C++

#include <Tactility/TactilityConfig.h>
#if TT_FEATURE_SCREENSHOT_ENABLED
#include <Tactility/lvgl/Lvgl.h>
#include <app/manifest.h>
#include <tactility/filesystem/fs.h>
#include <tactility/freertos/freertos.h>
#include <tactility/paths.h>
#include <lvgl/lvgl.h>
#include <lv_screenshot.h>
#include <cstdio>
#include <string>
namespace tt::app::screenshot {
namespace {
constexpr TickType_t LVGL_LOCK_TIMEOUT = pdMS_TO_TICKS(1000);
/** The default path is in the temp folder, so "tt screenshot" can pull and remove it */
bool getDefaultPath(char* out_path, size_t out_size) {
char temp_path[FILE_MAX_PATH_STRING_LENGTH];
if (paths_get_temp_path(temp_path, sizeof(temp_path)) != ERROR_NONE) {
return false;
}
if (!directory_exists(temp_path)) {
const error_t error = directory_make(temp_path, true);
if (error != ERROR_NONE && error != ERROR_ALREADY_EXISTS) {
return false;
}
}
const int written = snprintf(out_path, out_size, "%s/screenshot.png", temp_path);
return written > 0 && static_cast<size_t>(written) < out_size;
}
int32_t main(int argc, char* argv[]) {
if (argc > 2 || (argc == 2 && argv[1][0] != '/')) {
printf("usage: screenshot [absolute path of the .png file]\n");
return 1;
}
char path[FILE_MAX_PATH_STRING_LENGTH];
if (argc == 2) {
snprintf(path, sizeof(path), "%s", argv[1]);
} else if (!getDefaultPath(path, sizeof(path))) {
printf("screenshot: no storage available\n");
return 1;
}
if (!lvgl_try_lock(LVGL_LOCK_TIMEOUT)) {
printf("screenshot: the display is busy\n");
return 1;
}
// lv_screenshot writes through lv_fs, which requires the drive prefix
const std::string lvgl_path = std::string(lvgl::PATH_PREFIX) + path;
const bool success = lv_screenshot_create(lv_screen_active(), LV_100ASK_SCREENSHOT_SV_PNG, lvgl_path.c_str());
lvgl_unlock();
if (!success) {
printf("screenshot: failed to save %s\n", path);
return 1;
}
printf("%s\n", path);
return 0;
}
} // namespace
extern const ::AppManifest manifest = {
.id = "screenshot",
.name = "screenshot",
.category = APP_CATEGORY_SYSTEM,
.location = { .type = APP_LOCATION_MEMORY, .location = reinterpret_cast<void*>(main) },
.flags = APP_MANIFEST_FLAG_HEADLESS,
.stack = { .depth = 8192, .desired_memory_capability = 0 },
};
} // namespace tt::app::screenshot
#endif