Boot splash and more (#98)
* Boot splash and more - Added developer sdkconfig - Refactored the way FreeRTOS includes are included - Improved Gui/Loader logic - Implemented boot app with splash screen * Updated naming for Gui and Loader services * Renamed Screenshot service methods * Renames * Service renames
This commit is contained in:
committed by
GitHub
parent
3f62ec2efa
commit
0188ce721c
@@ -12,6 +12,8 @@ namespace tt::app {
|
||||
class App;
|
||||
|
||||
typedef enum {
|
||||
/** Boot screen, shown before desktop is launched. */
|
||||
TypeBoot,
|
||||
/** A desktop app sits at the root of the app stack managed by the Loader service */
|
||||
TypeDesktop,
|
||||
/** Apps that generally aren't started from the desktop (e.g. image viewer) */
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#include <Timer.h>
|
||||
#include <Check.h>
|
||||
#include <Thread.h>
|
||||
#include <Kernel.h>
|
||||
#include "Assets.h"
|
||||
#include "app/App.h"
|
||||
#include "lvgl.h"
|
||||
#include "service/loader/Loader.h"
|
||||
#include "lvgl/Style.h"
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "sdkconfig.h"
|
||||
#else
|
||||
#define CONFIG_TT_SPLASH_DURATION 0
|
||||
#endif
|
||||
|
||||
namespace tt::app::boot {
|
||||
|
||||
static int32_t threadCallback(void* context);
|
||||
|
||||
struct Data {
|
||||
Data() : thread("", 4096, threadCallback, this) {}
|
||||
|
||||
Thread thread;
|
||||
};
|
||||
|
||||
static int32_t threadCallback(TT_UNUSED void* context) {
|
||||
TickType_t start_time = tt::get_ticks();
|
||||
// Do stuff
|
||||
TickType_t end_time = tt::get_ticks();
|
||||
TickType_t ticks_passed = end_time - start_time;
|
||||
TickType_t minimum_ticks = (CONFIG_TT_SPLASH_DURATION / portTICK_PERIOD_MS);
|
||||
if (minimum_ticks > ticks_passed) {
|
||||
tt::delay_ticks(minimum_ticks - ticks_passed);
|
||||
}
|
||||
tt::service::loader::stopApp();
|
||||
tt::service::loader::startApp("Desktop");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void onShow(TT_UNUSED App& app, lv_obj_t* parent) {
|
||||
Data* data = (Data*)app.getData();
|
||||
|
||||
lv_obj_t* image = lv_image_create(parent);
|
||||
lv_obj_set_size(image, LV_PCT(100), LV_PCT(100));
|
||||
lv_image_set_src(image, TT_ASSETS_BOOT_LOGO);
|
||||
lvgl::obj_set_style_bg_blacken(parent);
|
||||
|
||||
data->thread.start();
|
||||
}
|
||||
|
||||
static void onStart(App& app) {
|
||||
Data* data = new Data();
|
||||
app.setData(data);
|
||||
}
|
||||
|
||||
static void onStop(App& app) {
|
||||
Data* data = (Data*)app.getData();
|
||||
data->thread.join();
|
||||
tt_assert(data);
|
||||
delete data;
|
||||
}
|
||||
|
||||
extern const Manifest manifest = {
|
||||
.id = "Boot",
|
||||
.name = "Boot",
|
||||
.type = TypeBoot,
|
||||
.onStart = onStart,
|
||||
.onStop = onStop,
|
||||
.onShow = onShow,
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@@ -11,7 +11,7 @@ static void on_app_pressed(lv_event_t* e) {
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if (code == LV_EVENT_CLICKED) {
|
||||
const auto* manifest = static_cast<const Manifest*>(lv_event_get_user_data(e));
|
||||
service::loader::start_app(manifest->id, false, Bundle());
|
||||
service::loader::startApp(manifest->id, false, Bundle());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ static void on_navigate_up_pressed(lv_event_t* event) {
|
||||
}
|
||||
|
||||
static void on_exit_app_pressed(TT_UNUSED lv_event_t* event) {
|
||||
service::loader::stop_app();
|
||||
service::loader::stopApp();
|
||||
}
|
||||
|
||||
static void view_file(const char* path, const char* filename) {
|
||||
@@ -84,7 +84,7 @@ static void view_file(const char* path, const char* filename) {
|
||||
// For PC we need to make the path relative to the current work directory,
|
||||
// because that's how LVGL maps its 'drive letter' to the file system.
|
||||
char* processed_filepath;
|
||||
if (get_platform() == PlatformPc) {
|
||||
if (get_platform() == PlatformSimulator) {
|
||||
char cwd[PATH_MAX];
|
||||
if (getcwd(cwd, sizeof(cwd)) == nullptr) {
|
||||
TT_LOG_E(TAG, "Failed to get current working directory");
|
||||
@@ -105,7 +105,7 @@ static void view_file(const char* path, const char* filename) {
|
||||
if (is_supported_image_file(filename)) {
|
||||
Bundle bundle;
|
||||
bundle.putString(IMAGE_VIEWER_FILE_ARGUMENT, processed_filepath);
|
||||
service::loader::start_app("ImageViewer", false, bundle);
|
||||
service::loader::startApp("ImageViewer", false, bundle);
|
||||
} else if (is_supported_text_file(filename)) {
|
||||
Bundle bundle;
|
||||
if (get_platform() == PlatformEsp) {
|
||||
@@ -114,7 +114,7 @@ static void view_file(const char* path, const char* filename) {
|
||||
// Remove forward slash, because we need a relative path
|
||||
bundle.putString(TEXT_VIEWER_FILE_ARGUMENT, processed_filepath + 1);
|
||||
}
|
||||
service::loader::start_app("TextViewer", false, bundle);
|
||||
service::loader::startApp("TextViewer", false, bundle);
|
||||
} else {
|
||||
TT_LOG_W(TAG, "opening files of this type is not supported");
|
||||
}
|
||||
@@ -199,7 +199,7 @@ static void on_show(App& app, lv_obj_t* parent) {
|
||||
static void on_start(App& app) {
|
||||
auto* data = data_alloc();
|
||||
// PC platform is bound to current work directory because of the LVGL file system mapping
|
||||
if (get_platform() == PlatformPc) {
|
||||
if (get_platform() == PlatformSimulator) {
|
||||
char cwd[PATH_MAX];
|
||||
if (getcwd(cwd, sizeof(cwd)) != nullptr) {
|
||||
data_set_entries_for_path(data, cwd);
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace tt::app::screenshot {
|
||||
|
||||
static void update_mode(ScreenshotUi* ui) {
|
||||
lv_obj_t* label = ui->start_stop_button_label;
|
||||
if (service::screenshot::is_started()) {
|
||||
if (service::screenshot::isStarted()) {
|
||||
lv_label_set_text(label, "Stop");
|
||||
} else {
|
||||
lv_label_set_text(label, "Start");
|
||||
@@ -34,7 +34,7 @@ static void on_mode_set(lv_event_t* event) {
|
||||
static void on_start_pressed(lv_event_t* event) {
|
||||
auto* ui = static_cast<ScreenshotUi*>(lv_event_get_user_data(event));
|
||||
|
||||
if (service::screenshot::is_started()) {
|
||||
if (service::screenshot::isStarted()) {
|
||||
TT_LOG_I(TAG, "Stop screenshot");
|
||||
service::screenshot::stop();
|
||||
} else {
|
||||
@@ -45,13 +45,13 @@ static void on_start_pressed(lv_event_t* event) {
|
||||
const char* delay_text = lv_textarea_get_text(ui->delay_textarea);
|
||||
int delay = atoi(delay_text);
|
||||
if (delay > 0) {
|
||||
service::screenshot::start_timed(path, delay, 1);
|
||||
service::screenshot::startTimed(path, delay, 1);
|
||||
} else {
|
||||
TT_LOG_W(TAG, "Ignored screenshot start because delay was 0");
|
||||
}
|
||||
} else {
|
||||
TT_LOG_I(TAG, "Start app screenshots");
|
||||
service::screenshot::start_apps(path);
|
||||
service::screenshot::startApps(path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ static void create_mode_setting_ui(ScreenshotUi* ui, lv_obj_t* parent) {
|
||||
lv_obj_align_to(mode_dropdown, mode_label, LV_ALIGN_OUT_RIGHT_MID, 8, 0);
|
||||
lv_obj_add_event_cb(mode_dropdown, on_mode_set, LV_EVENT_VALUE_CHANGED, ui);
|
||||
ui->mode_dropdown = mode_dropdown;
|
||||
service::screenshot::ScreenshotMode mode = service::screenshot::get_mode();
|
||||
service::screenshot::Mode mode = service::screenshot::getMode();
|
||||
if (mode == service::screenshot::ScreenshotModeApps) {
|
||||
lv_dropdown_set_selected(mode_dropdown, 1);
|
||||
}
|
||||
@@ -168,8 +168,8 @@ void create_ui(const App& app, ScreenshotUi* ui, lv_obj_t* parent) {
|
||||
create_path_ui(ui, wrapper);
|
||||
create_timer_settings_ui(ui, wrapper);
|
||||
|
||||
service::gui::keyboard_add_textarea(ui->delay_textarea);
|
||||
service::gui::keyboard_add_textarea(ui->path_textarea);
|
||||
service::gui::keyboardAddTextArea(ui->delay_textarea);
|
||||
service::gui::keyboardAddTextArea(ui->path_textarea);
|
||||
|
||||
update_mode(ui);
|
||||
}
|
||||
|
||||
@@ -49,11 +49,11 @@ static void onListItemSelected(lv_event_t* e) {
|
||||
if (code == LV_EVENT_CLICKED) {
|
||||
size_t index = (size_t)(e->user_data);
|
||||
TT_LOG_I(TAG, "Selected item at index %d", index);
|
||||
tt::app::App* app = service::loader::get_current_app();
|
||||
tt::app::App* app = service::loader::getCurrentApp();
|
||||
Bundle bundle;
|
||||
setResultIndex(bundle, (int32_t)index);
|
||||
app->setResult(app::ResultOk, bundle);
|
||||
service::loader::stop_app();
|
||||
service::loader::stopApp();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,12 +79,12 @@ static void onShow(App& app, lv_obj_t* parent) {
|
||||
if (items.empty() || items.front().empty()) {
|
||||
TT_LOG_E(TAG, "No items provided");
|
||||
app.setResult(ResultError);
|
||||
service::loader::stop_app();
|
||||
service::loader::stopApp();
|
||||
} else if (items.size() == 1) {
|
||||
Bundle result_bundle;
|
||||
setResultIndex(result_bundle, 0);
|
||||
app.setResult(ResultOk, result_bundle);
|
||||
service::loader::stop_app();
|
||||
service::loader::stopApp();
|
||||
TT_LOG_W(TAG, "Auto-selecting single item");
|
||||
} else {
|
||||
size_t index = 0;
|
||||
@@ -95,7 +95,7 @@ static void onShow(App& app, lv_obj_t* parent) {
|
||||
} else {
|
||||
TT_LOG_E(TAG, "No items provided");
|
||||
app.setResult(ResultError);
|
||||
service::loader::stop_app();
|
||||
service::loader::stopApp();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ static void on_app_pressed(lv_event_t* e) {
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if (code == LV_EVENT_CLICKED) {
|
||||
const auto* manifest = static_cast<const Manifest*>(lv_event_get_user_data(e));
|
||||
service::loader::start_app(manifest->id, false, Bundle());
|
||||
service::loader::startApp(manifest->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ static void on_connect(const service::wifi::settings::WifiApSettings* ap_setting
|
||||
static WifiConnect* wifi_connect_alloc() {
|
||||
auto* wifi = static_cast<WifiConnect*>(malloc(sizeof(WifiConnect)));
|
||||
|
||||
PubSub* wifi_pubsub = service::wifi::get_pubsub();
|
||||
PubSub* wifi_pubsub = service::wifi::getPubsub();
|
||||
wifi->wifi_subscription = tt_pubsub_subscribe(wifi_pubsub, &event_callback, wifi);
|
||||
wifi->mutex = tt_mutex_alloc(MutexTypeNormal);
|
||||
wifi->state = (WifiConnectState) {
|
||||
@@ -46,7 +46,7 @@ static WifiConnect* wifi_connect_alloc() {
|
||||
}
|
||||
|
||||
static void wifi_connect_free(WifiConnect* wifi) {
|
||||
PubSub* wifi_pubsub = service::wifi::get_pubsub();
|
||||
PubSub* wifi_pubsub = service::wifi::getPubsub();
|
||||
tt_pubsub_unsubscribe(wifi_pubsub, wifi->wifi_subscription);
|
||||
tt_mutex_free(wifi->mutex);
|
||||
|
||||
@@ -92,7 +92,7 @@ static void event_callback(const void* message, void* context) {
|
||||
case service::wifi::WifiEventTypeConnectionSuccess:
|
||||
if (wifi->state.is_connecting) {
|
||||
state_set_connecting(wifi, false);
|
||||
service::loader::stop_app();
|
||||
service::loader::stopApp();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -191,8 +191,8 @@ void view_create(const App& app, void* wifi, lv_obj_t* parent) {
|
||||
view_create_bottom_buttons(wifi_connect, wrapper);
|
||||
|
||||
// Keyboard bindings
|
||||
service::gui::keyboard_add_textarea(view->ssid_textarea);
|
||||
service::gui::keyboard_add_textarea(view->password_textarea);
|
||||
service::gui::keyboardAddTextArea(view->ssid_textarea);
|
||||
service::gui::keyboardAddTextArea(view->password_textarea);
|
||||
|
||||
// Init from app parameters
|
||||
const Bundle& bundle = app.getParameters();
|
||||
|
||||
@@ -26,7 +26,7 @@ static void on_connect(const char* ssid) {
|
||||
Bundle bundle;
|
||||
bundle.putString(WIFI_CONNECT_PARAM_SSID, ssid);
|
||||
bundle.putString(WIFI_CONNECT_PARAM_PASSWORD, "");
|
||||
service::loader::start_app("WifiConnect", false, bundle);
|
||||
service::loader::startApp("WifiConnect", false, bundle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ static void on_disconnect() {
|
||||
}
|
||||
|
||||
static void on_wifi_toggled(bool enabled) {
|
||||
service::wifi::set_enabled(enabled);
|
||||
service::wifi::setEnabled(enabled);
|
||||
}
|
||||
|
||||
static WifiManage* wifi_manage_alloc() {
|
||||
@@ -44,8 +44,8 @@ static WifiManage* wifi_manage_alloc() {
|
||||
wifi->wifi_subscription = nullptr;
|
||||
wifi->mutex = tt_mutex_alloc(MutexTypeNormal);
|
||||
wifi->state = (WifiManageState) {
|
||||
.scanning = service::wifi::is_scanning(),
|
||||
.radio_state = service::wifi::get_radio_state(),
|
||||
.scanning = service::wifi::isScanning(),
|
||||
.radio_state = service::wifi::getRadioState(),
|
||||
.connect_ssid = { 0 },
|
||||
.ap_records = { },
|
||||
.ap_records_count = 0
|
||||
@@ -94,8 +94,8 @@ void request_view_update(WifiManage* wifi) {
|
||||
static void wifi_manage_event_callback(const void* message, void* context) {
|
||||
auto* event = (service::wifi::WifiEvent*)message;
|
||||
auto* wifi = (WifiManage*)context;
|
||||
TT_LOG_I(TAG, "Update with state %d", service::wifi::get_radio_state());
|
||||
state_set_radio_state(wifi, service::wifi::get_radio_state());
|
||||
TT_LOG_I(TAG, "Update with state %d", service::wifi::getRadioState());
|
||||
state_set_radio_state(wifi, service::wifi::getRadioState());
|
||||
switch (event->type) {
|
||||
case tt::service::wifi::WifiEventTypeScanStarted:
|
||||
state_set_scanning(wifi, true);
|
||||
@@ -105,7 +105,7 @@ static void wifi_manage_event_callback(const void* message, void* context) {
|
||||
state_update_scanned_records(wifi);
|
||||
break;
|
||||
case tt::service::wifi::WifiEventTypeRadioStateOn:
|
||||
if (!service::wifi::is_scanning()) {
|
||||
if (!service::wifi::isScanning()) {
|
||||
service::wifi::scan();
|
||||
}
|
||||
break;
|
||||
@@ -119,12 +119,12 @@ static void wifi_manage_event_callback(const void* message, void* context) {
|
||||
static void app_show(App& app, lv_obj_t* parent) {
|
||||
auto* wifi = (WifiManage*)app.getData();
|
||||
|
||||
PubSub* wifi_pubsub = service::wifi::get_pubsub();
|
||||
PubSub* wifi_pubsub = service::wifi::getPubsub();
|
||||
wifi->wifi_subscription = tt_pubsub_subscribe(wifi_pubsub, &wifi_manage_event_callback, wifi);
|
||||
|
||||
// State update (it has its own locking)
|
||||
state_set_radio_state(wifi, service::wifi::get_radio_state());
|
||||
state_set_scanning(wifi, service::wifi::is_scanning());
|
||||
state_set_radio_state(wifi, service::wifi::getRadioState());
|
||||
state_set_scanning(wifi, service::wifi::isScanning());
|
||||
state_update_scanned_records(wifi);
|
||||
|
||||
// View update
|
||||
@@ -135,11 +135,11 @@ static void app_show(App& app, lv_obj_t* parent) {
|
||||
view_update(&wifi->view, &wifi->bindings, &wifi->state);
|
||||
unlock(wifi);
|
||||
|
||||
service::wifi::WifiRadioState radio_state = service::wifi::get_radio_state();
|
||||
service::wifi::WifiRadioState radio_state = service::wifi::getRadioState();
|
||||
bool can_scan = radio_state == service::wifi::WIFI_RADIO_ON ||
|
||||
radio_state == service::wifi::WIFI_RADIO_CONNECTION_PENDING ||
|
||||
radio_state == service::wifi::WIFI_RADIO_CONNECTION_ACTIVE;
|
||||
if (can_scan && !service::wifi::is_scanning()) {
|
||||
if (can_scan && !service::wifi::isScanning()) {
|
||||
service::wifi::scan();
|
||||
}
|
||||
}
|
||||
@@ -147,7 +147,7 @@ static void app_show(App& app, lv_obj_t* parent) {
|
||||
static void app_hide(App& app) {
|
||||
auto* wifi = (WifiManage*)app.getData();
|
||||
lock(wifi);
|
||||
PubSub* wifi_pubsub = service::wifi::get_pubsub();
|
||||
PubSub* wifi_pubsub = service::wifi::getPubsub();
|
||||
tt_pubsub_unsubscribe(wifi_pubsub, wifi->wifi_subscription);
|
||||
wifi->wifi_subscription = nullptr;
|
||||
wifi->view_enabled = false;
|
||||
|
||||
@@ -16,7 +16,7 @@ void state_set_radio_state(WifiManage* wifi, service::wifi::WifiRadioState state
|
||||
|
||||
void state_update_scanned_records(WifiManage* wifi) {
|
||||
lock(wifi);
|
||||
service::wifi::get_scan_results(
|
||||
service::wifi::getScanResults(
|
||||
wifi->state.ap_records,
|
||||
WIFI_SCAN_AP_RECORD_COUNT,
|
||||
&wifi->state.ap_records_count
|
||||
|
||||
@@ -43,7 +43,7 @@ static void connect(lv_event_t* event) {
|
||||
|
||||
static void create_network_button(WifiManageView* view, WifiManageBindings* bindings, service::wifi::WifiApRecord* record) {
|
||||
const char* ssid = (const char*)record->ssid;
|
||||
const char* icon = service::statusbar::get_status_icon_for_rssi(record->rssi, record->auth_mode != WIFI_AUTH_OPEN);
|
||||
const char* icon = service::statusbar::getWifiStatusIconForRssi(record->rssi, record->auth_mode != WIFI_AUTH_OPEN);
|
||||
lv_obj_t* ap_button = lv_list_add_btn(
|
||||
view->networks_list,
|
||||
icon,
|
||||
|
||||
Reference in New Issue
Block a user