aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorConfuSomu2021-08-11 19:01:10 -0400
committerConfuSomu2021-08-11 19:09:59 -0400
commit798241865d77c11e3f485a152853607759880163 (patch)
treea3c7e307cd78443d8539e6d3b509c47c26ec5997
parentd42b7faba24cdb14c556762200d586093570b2e5 (diff)
downloadpico-watch-798241865d77c11e3f485a152853607759880163.tar
pico-watch-798241865d77c11e3f485a152853607759880163.tar.gz
pico-watch-798241865d77c11e3f485a152853607759880163.zip
Allow apps to close and quit themselves via return
value when returning from render(), btnpressed() or bgrefresh(). This can help free system ressources when apps do not need to be running anymore. The AppAttributes::destroy_on_exit is currently ignored to give apps more freedom. The main_clock app has had some changes done to test the new features.
-rw-r--r--api.hpp6
-rw-r--r--app_manager.cpp60
-rw-r--r--app_manager.hpp10
-rw-r--r--apps/home_menu/main.cpp14
-rw-r--r--apps/home_menu/main.hpp6
-rw-r--r--apps/main_clock/main.cpp22
-rw-r--r--apps/main_clock/main.hpp8
-rw-r--r--apps/settings/main.cpp12
-rw-r--r--apps/settings/main.hpp6
-rw-r--r--base_app.hpp12
10 files changed, 108 insertions, 48 deletions
diff --git a/api.hpp b/api.hpp
index ad720e7..f162e58 100644
--- a/api.hpp
+++ b/api.hpp
@@ -22,12 +22,8 @@ class Api {
void gui_popup_intchoice_footer(int current_num, int min_num, int max_num);
void gui_popup_strchoice_footer(const char selection[]);
public:
- // Allow button press to be registed by app and for app_switch (when HOME). Set to false for in Api internal gui.
+ // Allow button press to be registed by app and for app_switch (when HOME). Set to false when displaying Api's internal GUI.
bool m_interpret_button_press = true;
- enum app_init_return_status {
- OK = 0,
- MALLOC_FAILED = 1
- };
enum perf_modes {
LOW_POWER,
NORMAL_PERF,
diff --git a/app_manager.cpp b/app_manager.cpp
index 34d4b32..db35037 100644
--- a/app_manager.cpp
+++ b/app_manager.cpp
@@ -23,6 +23,25 @@ BaseApp* app_mgr::app_check_if_init(int app_id) {
return nullptr;
}
+void app_mgr::app_act_on_return_value(BaseApp* app, BaseApp::AppReturnValues return_value) {
+ switch (return_value) {
+ case BaseApp::AppReturnValues::OK:
+ break;
+
+ case BaseApp::AppReturnValues::CLOSE:
+ g_s.foreground_app = open_apps.front(); // The app has to be in foreground as the current function is called by app_render and app_btnpress
+ break;
+
+ case BaseApp::AppReturnValues::QUIT:
+ app_destroy(app);
+ g_s.foreground_app = open_apps.front();
+ break;
+
+ default:
+ printf("Unidentified return value %d for app %d at %x", return_value, app->app_get_attributes().id, app);
+ }
+}
+
BaseApp* app_mgr::app_create(int app_id) {
BaseApp* new_app;
@@ -63,28 +82,53 @@ BaseApp* app_mgr::app_init(int app_id) {
return new_app;
}
-int app_mgr::app_render(BaseApp* app) {
- return app->render(&app_api);
+void app_mgr::app_render(BaseApp* app) {
+ app_act_on_return_value(app, app->render(&app_api));
}
-int app_mgr::app_btnpressed(BaseApp* app, uint gpio, unsigned long delta) {
- return app->btnpressed(&app_api, gpio, delta);
+void app_mgr::app_btnpressed(BaseApp* app, uint gpio, unsigned long delta) {
+ app_act_on_return_value(app, app->btnpressed(&app_api, gpio, delta));
}
-int app_mgr::app_destroy(BaseApp* to_erase) {
+void app_mgr::app_destroy(BaseApp* to_erase) {
auto erase_it = std::find(open_apps.begin(), open_apps.end(), to_erase); // "it" meaning iterator
if (erase_it != open_apps.end()) {
//assert(to_erase == erase_it);
delete to_erase;
open_apps.erase(erase_it);
}
-
- return 0;
}
void app_mgr::app_all_bgrefresh() {
+ std::vector<BaseApp*> to_erase;
+ bool do_erase = false;
+
for (auto app : open_apps) {
- app->bgrefresh(&app_api, app->app_get_attributes().id == g_s.foreground_app->app_get_attributes().id);
+ bool is_foreground = app->app_get_attributes().id == g_s.foreground_app->app_get_attributes().id;
+
+ switch (app->bgrefresh(&app_api, is_foreground)) {
+ case BaseApp::AppReturnValues::OK:
+ break;
+
+ case BaseApp::AppReturnValues::QUIT:
+ do_erase = true;
+ to_erase.push_back(app);
+ // No break here!
+
+ case BaseApp::AppReturnValues::CLOSE:
+ if (is_foreground)
+ g_s.foreground_app = open_apps.front();
+ break;
+
+ default:
+ printf("Unidentified return value in bgrefresh for app %d at %x", app->app_get_attributes().id, app);
+ }
+ }
+
+ if (do_erase) {
+ for (auto app : to_erase) {
+ app_destroy(app);
+ }
}
}
diff --git a/app_manager.hpp b/app_manager.hpp
index 3657d93..8dfbb88 100644
--- a/app_manager.hpp
+++ b/app_manager.hpp
@@ -11,10 +11,10 @@ namespace app_mgr {
BaseApp* app_init(int app_id);
// Allow the running app, referenced by app_id, to invoke its render routine.
- int app_render(BaseApp* app);
+ void app_render(BaseApp* app);
// Delta is in ms, from time_since_button_press()
- int app_btnpressed(BaseApp* app, uint gpio, unsigned long delta);
+ void app_btnpressed(BaseApp* app, uint gpio, unsigned long delta);
// This should only be called by pico-watch.cpp before app rendering, to chage the current app.
void app_switch(BaseApp* app, int new_appid);
@@ -26,13 +26,17 @@ namespace app_mgr {
void app_all_bgrefresh();
// Private functions following. I tried using anonymous namespaces but it was too complicated. I might come back to this later. Just don't use the following internal functions.
+
// Check if the specified app (via app_id) is already running.
// \return If app is init, pointer to app, else nullptr (more or less 0).
BaseApp* app_check_if_init(int app_id);
+ // Check the return value of the called application method and act on it.
+ void app_act_on_return_value(BaseApp* app, BaseApp::AppReturnValues return_value);
+
// Called by app_init to create the app object.
BaseApp* app_create(int app_id);
// Quit the app referenced by the app_id.
- int app_destroy(BaseApp* to_erase);
+ void app_destroy(BaseApp* to_erase);
}
diff --git a/apps/home_menu/main.cpp b/apps/home_menu/main.cpp
index ff8ae4d..4508e38 100644
--- a/apps/home_menu/main.cpp
+++ b/apps/home_menu/main.cpp
@@ -28,19 +28,19 @@ void app_home_menu::show_title(Api *app_api) {
}
// Rendering of app
-int app_home_menu::render(Api *app_api) {
+BaseApp::AppReturnValues app_home_menu::render(Api *app_api) {
show_title(app_api);
app_api->display_write_string(0,5,3, display_app_name, FONT_12x16, 0, 1);
- return 0;
+ return AppReturnValues::OK;
}
// Example of how button inputs could be interpreted.
// Drawing on screen should be done in the render function.
-int app_home_menu::btnpressed(Api *app_api, uint gpio, unsigned long delta) {
+BaseApp::AppReturnValues app_home_menu::btnpressed(Api *app_api, uint gpio, unsigned long delta) {
switch (gpio) {
case BUTTON_SELECT:
app_mgr::app_switch_request(selected_app);
- return 0;
+ return AppReturnValues::OK;
case BUTTON_DOWN:
selected_app--;
break;
@@ -55,7 +55,7 @@ int app_home_menu::btnpressed(Api *app_api, uint gpio, unsigned long delta) {
}
// Add spaces to avoid "ghost" characters from app names displayed before
snprintf(display_app_name, SIZE_APP_NAME, "%s ", APPS_NAME[selected_app]);
- return 0;
+ return AppReturnValues::OK;
}
// Initlisation of the app.
@@ -66,6 +66,6 @@ app_home_menu::app_home_menu(Api *app_api) {
}
// Processor intensive operations and functions related to drawing to the screen should only be done when the app is in_foreground(=1). This function is only called when the app is init.
-int app_home_menu::bgrefresh(Api *app_api, bool in_foreground) {
- return 1;
+BaseApp::AppReturnValues app_home_menu::bgrefresh(Api *app_api, bool in_foreground) {
+ return AppReturnValues::OK;
}
diff --git a/apps/home_menu/main.hpp b/apps/home_menu/main.hpp
index 155009b..d82e2a0 100644
--- a/apps/home_menu/main.hpp
+++ b/apps/home_menu/main.hpp
@@ -24,8 +24,8 @@ class app_home_menu : public BaseApp {
}
app_home_menu(Api *app_api);
- int render(Api *app_api);
- int btnpressed(Api *app_api, uint gpio, unsigned long delta);
- int bgrefresh(Api *app_api, bool in_foreground);
+ AppReturnValues render(Api *app_api);
+ AppReturnValues btnpressed(Api *app_api, uint gpio, unsigned long delta);
+ AppReturnValues bgrefresh(Api *app_api, bool in_foreground);
~app_home_menu();
};
diff --git a/apps/main_clock/main.cpp b/apps/main_clock/main.cpp
index 78be6fd..73a3103 100644
--- a/apps/main_clock/main.cpp
+++ b/apps/main_clock/main.cpp
@@ -52,7 +52,7 @@ void app_main_clock::show_datetime(Api *app_api) {
}
// Rendering of the app
-int app_main_clock::render(Api *app_api) {
+BaseApp::AppReturnValues app_main_clock::render(Api *app_api) {
app_api->gui_header_text("Test clock", 17);
show_datetime(app_api);
if (*ask_user_choice) {
@@ -60,14 +60,20 @@ int app_main_clock::render(Api *app_api) {
*ask_user_choice = false;
}
app_api->gui_footer_text(choices[*user_choice],0,1);
- return 0;
+
+ if (*user_choice == 1)
+ return AppReturnValues::CLOSE;
+ else if (*user_choice == 2)
+ return AppReturnValues::QUIT;
+
+ return AppReturnValues::OK;
}
// Interpretation of button inputs
-int app_main_clock::btnpressed(Api *app_api, uint gpio, unsigned long delta) {
+BaseApp::AppReturnValues app_main_clock::btnpressed(Api *app_api, uint gpio, unsigned long delta) {
if (gpio == BUTTON_MODE)
*ask_user_choice = true;
- return 0;
+ return AppReturnValues::OK;
}
// Initlisation of the app.
@@ -82,8 +88,12 @@ app_main_clock::app_main_clock(Api *app_api) {
}
// Processor intensive operations and functions related to drawing to the screen should only be done when the app is in_foreground(=1). This function is only called when the app is init.
-int app_main_clock::bgrefresh(Api *app_api, bool in_foreground) {
- return 1;
+BaseApp::AppReturnValues app_main_clock::bgrefresh(Api *app_api, bool in_foreground) {
+ if (*user_choice == 3)
+ return AppReturnValues::CLOSE;
+ else if (*user_choice == 4)
+ return AppReturnValues::QUIT;
+ return AppReturnValues::OK;
}
// Destruction of app, deinitlisation should be done here. This is only called if the app's APPS_DESTROY_ON_EXIT is set to 1. When it is not a "service" app.
diff --git a/apps/main_clock/main.hpp b/apps/main_clock/main.hpp
index f00958e..7c07cb3 100644
--- a/apps/main_clock/main.hpp
+++ b/apps/main_clock/main.hpp
@@ -9,7 +9,7 @@ class app_main_clock : public BaseApp {
private:
bool *ask_user_choice;
int *user_choice;
- const char *choices[26] = {"One", "Two", "Three!", "This is looong!", "make sure to choose me!:p"};
+ const char *choices[10] = {"One", "Close (fg)", "Quit (fg)", "Close (bg)", "Quit (bg)"};
void time_as_str(char *buf, uint buf_size, const datetime_t *t);
void date_as_str(char *buf, uint buf_size, const datetime_t *t);
@@ -22,8 +22,8 @@ class app_main_clock : public BaseApp {
}
app_main_clock(Api *app_api);
- int render(Api *app_api);
- int btnpressed(Api *app_api, uint gpio, unsigned long delta);
- int bgrefresh(Api *app_api, bool in_foreground);
+ AppReturnValues render(Api *app_api);
+ AppReturnValues btnpressed(Api *app_api, uint gpio, unsigned long delta);
+ AppReturnValues bgrefresh(Api *app_api, bool in_foreground);
~app_main_clock();
};
diff --git a/apps/settings/main.cpp b/apps/settings/main.cpp
index 555c2c1..d4c910a 100644
--- a/apps/settings/main.cpp
+++ b/apps/settings/main.cpp
@@ -119,7 +119,7 @@ void app_settings::set1_menu(Api *app_api) {
}
// Rendering of app
-int app_settings::render(Api *app_api) {
+BaseApp::AppReturnValues app_settings::render(Api *app_api) {
show_title(app_api);
app_api->display_write_string(0,0,3, display_setting_name, FONT_12x16, 0, 1);
@@ -135,10 +135,10 @@ int app_settings::render(Api *app_api) {
}
}
- return 0;
+ return AppReturnValues::OK;
}
-int app_settings::btnpressed(Api *app_api, uint gpio, unsigned long delta) {
+BaseApp::AppReturnValues app_settings::btnpressed(Api *app_api, uint gpio, unsigned long delta) {
switch (gpio) {
case BUTTON_SELECT:
selected = true;
@@ -157,7 +157,7 @@ int app_settings::btnpressed(Api *app_api, uint gpio, unsigned long delta) {
}
// Add spaces to avoid "ghost" characters from app names displayed before
snprintf(display_setting_name, SIZE_SETTING_NAME, "%s ", MAIN_SET_NAMES[selected_setting]);
- return 0;
+ return AppReturnValues::OK;
}
app_settings::app_settings(Api *app_api) {
@@ -168,8 +168,8 @@ app_settings::app_settings(Api *app_api) {
snprintf(display_setting_name, SIZE_SETTING_NAME, "%s", MAIN_SET_NAMES[0]);
}
-int app_settings::bgrefresh(Api *app_api, bool in_foreground) {
- return 1;
+BaseApp::AppReturnValues app_settings::bgrefresh(Api *app_api, bool in_foreground) {
+ return AppReturnValues::OK;
}
app_settings::~app_settings() {
diff --git a/apps/settings/main.hpp b/apps/settings/main.hpp
index 589be70..d53b8a9 100644
--- a/apps/settings/main.hpp
+++ b/apps/settings/main.hpp
@@ -20,9 +20,9 @@ class app_settings : public BaseApp {
}
app_settings(Api *app_api);
- int render(Api *app_api);
- int btnpressed(Api *app_api, uint gpio, unsigned long delta);
- int bgrefresh(Api *app_api, bool in_foreground);
+ AppReturnValues render(Api *app_api);
+ AppReturnValues btnpressed(Api *app_api, uint gpio, unsigned long delta);
+ AppReturnValues bgrefresh(Api *app_api, bool in_foreground);
~app_settings();
};
#include "strings-undef.hpp"
diff --git a/base_app.hpp b/base_app.hpp
index c9d8e85..06f608a 100644
--- a/base_app.hpp
+++ b/base_app.hpp
@@ -8,13 +8,19 @@ class BaseApp {
uint id = 0;
bool destroy_on_exit = true;
};
+ enum AppReturnValues {
+ OK = 0,
+ CLOSE, // Close app from foreground, not respecting AppAttribues::destroy_on_exit.
+ QUIT // Completely quit app; stop running in background
+ };
+
// CHECK: Following have to be overwritten by derived classes
virtual const AppAttributes& app_get_attributes() = 0;
// Could be implemented as:
// {return app_attributes;}
// where app_attribues is an instance of AppAttributes
- virtual int render(Api *app_api) = 0; // Has to be implemented
- virtual int btnpressed(Api *app_api, uint gpio, unsigned long delta) {};
- virtual int bgrefresh(Api *app_api, bool in_foreground) {};
+ virtual AppReturnValues render(Api *app_api) = 0; // Has to be implemented
+ virtual AppReturnValues btnpressed(Api *app_api, uint gpio, unsigned long delta) {return AppReturnValues::OK;};
+ virtual AppReturnValues bgrefresh(Api *app_api, bool in_foreground) {return AppReturnValues::OK;};
};