From 63e9207c44d83471971a8a476bff1ca93721b11f Mon Sep 17 00:00:00 2001 From: gornekich Date: Wed, 26 May 2021 19:23:25 +0300 Subject: [PATCH] [FL-1308] Add API for starting applications with arguments (#486) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * app-loader: add API for starting applications with arguments * app-loader: add check if application is running * archive: rework starting app with app-loader API Co-authored-by: あく --- applications/app-loader/app-loader.c | 70 +++++++++++++++++++++------- applications/app-loader/app-loader.h | 15 ++++++ applications/archive/archive.c | 19 ++------ applications/archive/archive_i.h | 9 ++++ 4 files changed, 83 insertions(+), 30 deletions(-) mode change 100644 => 100755 applications/app-loader/app-loader.c create mode 100644 applications/app-loader/app-loader.h diff --git a/applications/app-loader/app-loader.c b/applications/app-loader/app-loader.c old mode 100644 new mode 100755 index 7c3532659..dfd93f15e --- a/applications/app-loader/app-loader.c +++ b/applications/app-loader/app-loader.c @@ -1,14 +1,11 @@ -#include -#include -#include "menu/menu.h" -#include "menu/menu_item.h" -#include "applications.h" -#include -#include +#include "app-loader.h" + +#define APP_LOADER_TAG "app_loader" typedef struct { FuriThread* thread; const FlipperApplication* current_app; + string_t args; Cli* cli; } AppLoaderState; @@ -21,10 +18,14 @@ static void app_loader_menu_callback(void* _ctx) { const FlipperApplication* flipper_app = (FlipperApplication*)_ctx; furi_assert(flipper_app->app); furi_assert(flipper_app->name); + + if(furi_thread_get_state(state.thread) != FuriThreadStateStopped) { + FURI_LOG_E(APP_LOADER_TAG, "Can't start app. %s is running", state.current_app->name); + return; + } api_hal_power_insomnia_enter(); - state.current_app = flipper_app; - + FURI_LOG_I(APP_LOADER_TAG, "Starting furi application: %s", state.current_app->name); furi_thread_set_name(state.thread, flipper_app->name); furi_thread_set_stack_size(state.thread, flipper_app->stack_size); furi_thread_set_callback(state.thread, flipper_app->app); @@ -37,19 +38,55 @@ static void app_loader_cli_callback(Cli* cli, string_t args, void* _ctx) { furi_assert(flipper_app->app); furi_assert(flipper_app->name); - if(!(furi_thread_get_state(state.thread) == FuriThreadStateStopped)) { + if(furi_thread_get_state(state.thread) != FuriThreadStateStopped) { printf("Can't start, furi application is running"); return; } - printf("Starting furi application %s", flipper_app->name); api_hal_power_insomnia_enter(); + state.current_app = flipper_app; + printf("Starting furi application %s", state.current_app->name); furi_thread_set_name(state.thread, flipper_app->name); furi_thread_set_stack_size(state.thread, flipper_app->stack_size); furi_thread_set_callback(state.thread, flipper_app->app); furi_thread_start(state.thread); } +bool app_loader_start(const char* name, const char* args) { + furi_assert(name); + + const FlipperApplication* flipper_app = NULL; + // Search for application + for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) { + if(!strcmp(FLIPPER_APPS[i].name, name)) { + flipper_app = &FLIPPER_APPS[i]; + break; + } + } + if(!flipper_app) { + FURI_LOG_E(APP_LOADER_TAG, "Can't find application with name %s", name); + return false; + } + if(furi_thread_get_state(state.thread) != FuriThreadStateStopped) { + FURI_LOG_E(APP_LOADER_TAG, "Can't start app. %s is running", state.current_app->name); + return false; + } + state.current_app = flipper_app; + if(args) { + string_set_str(state.args, args); + string_strim(state.args); + FURI_LOG_I(APP_LOADER_TAG, "Start %s app with args: %s", name, args); + } else { + string_clean(state.args); + FURI_LOG_I(APP_LOADER_TAG, "Start %s app with no args", name); + } + furi_thread_set_name(state.thread, flipper_app->name); + furi_thread_set_stack_size(state.thread, flipper_app->stack_size); + furi_thread_set_context(state.thread, (void*)string_get_cstr(state.args)); + furi_thread_set_callback(state.thread, flipper_app->app); + return furi_thread_start(state.thread); +} + void app_loader_thread_state_callback(FuriThreadState state, void* context) { furi_assert(context); if(state == FuriThreadStateStopped) { @@ -58,16 +95,17 @@ void app_loader_thread_state_callback(FuriThreadState state, void* context) { } int32_t app_loader(void* p) { - FURI_LOG_I("app-loader", "Starting"); + FURI_LOG_I(APP_LOADER_TAG, "Starting"); state.thread = furi_thread_alloc(); furi_thread_set_state_context(state.thread, &state); furi_thread_set_state_callback(state.thread, app_loader_thread_state_callback); + string_init(state.args); ValueMutex* menu_mutex = furi_record_open("menu"); state.cli = furi_record_open("cli"); // Main menu - FURI_LOG_I("app-loader", "Building main menu"); + FURI_LOG_I(APP_LOADER_TAG, "Building main menu"); with_value_mutex( menu_mutex, (Menu * menu) { for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) { @@ -94,7 +132,7 @@ int32_t app_loader(void* p) { }); // Plugins - FURI_LOG_I("app-loader", "Building plugins menu"); + FURI_LOG_I(APP_LOADER_TAG, "Building plugins menu"); with_value_mutex( menu_mutex, (Menu * menu) { MenuItem* menu_plugins = @@ -126,7 +164,7 @@ int32_t app_loader(void* p) { }); // Debug - FURI_LOG_I("app-loader", "Building debug menu"); + FURI_LOG_I(APP_LOADER_TAG, "Building debug menu"); with_value_mutex( menu_mutex, (Menu * menu) { MenuItem* menu_debug = @@ -162,7 +200,7 @@ int32_t app_loader(void* p) { (*FLIPPER_ON_SYSTEM_START[i])(); } - FURI_LOG_I("app-loader", "Started"); + FURI_LOG_I(APP_LOADER_TAG, "Started"); while(1) { osThreadSuspend(osThreadGetId()); diff --git a/applications/app-loader/app-loader.h b/applications/app-loader/app-loader.h new file mode 100644 index 000000000..8ba3631c3 --- /dev/null +++ b/applications/app-loader/app-loader.h @@ -0,0 +1,15 @@ +#include +#include +#include "menu/menu.h" +#include "menu/menu_item.h" +#include "applications.h" +#include +#include + +/** + * Start application + * @param name - application name + * @param args - application arguments + * @retval true on success + */ +bool app_loader_start(const char* name, const char* args); diff --git a/applications/archive/archive.c b/applications/archive/archive.c index 53fe414f9..9408c6364 100644 --- a/applications/archive/archive.c +++ b/applications/archive/archive.c @@ -290,21 +290,11 @@ static void archive_close_file_menu(ArchiveApp* archive) { view_commit_model(archive->view_archive_main, true); } -static void -archive_open_app(ArchiveApp* archive, const FlipperApplication* flipper_app, void* arg) { +static void archive_open_app(ArchiveApp* archive, const char* app_name, const char* args) { furi_assert(archive); - furi_assert(flipper_app); - furi_assert(flipper_app->app); - furi_assert(flipper_app->name); + furi_assert(app_name); - if(arg) { - // pass path to app? - } - - furi_thread_set_name(archive->app_thread, flipper_app->name); - furi_thread_set_stack_size(archive->app_thread, flipper_app->stack_size); - furi_thread_set_callback(archive->app_thread, flipper_app->app); - furi_thread_start(archive->app_thread); + app_loader_start(app_name, args); } static void archive_delete_file(ArchiveApp* archive, string_t name) { @@ -339,7 +329,8 @@ static void archive_file_menu_callback(ArchiveApp* archive) { switch(model->menu_idx) { case 0: if((selected->type != ArchiveFileTypeFolder && selected->type != ArchiveFileTypeUnknown)) { - archive_open_app(archive, &FLIPPER_APPS[selected->type], NULL); + archive_open_app( + archive, flipper_app_name[selected->type], string_get_cstr(selected->name)); } break; case 1: diff --git a/applications/archive/archive_i.h b/applications/archive/archive_i.h index d1d5c88d4..974282322 100644 --- a/applications/archive/archive_i.h +++ b/applications/archive/archive_i.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -33,6 +34,14 @@ typedef enum { ArchiveTabTotal, } ArchiveTabEnum; +static const char* flipper_app_name[] = { + [ArchiveFileTypeIButton] = "iButton", + [ArchiveFileTypeNFC] = "NFC", + [ArchiveFileTypeSubOne] = "Sub-1 GHz", + [ArchiveFileTypeLFRFID] = "125 kHz RFID", + [ArchiveFileTypeIrda] = "Infrared", +}; + static const char* known_ext[] = { [ArchiveFileTypeIButton] = ".ibtn", [ArchiveFileTypeNFC] = ".nfc",