Skip to content

Commit 60bc1a3

Browse files
new api
1 parent 1b0436f commit 60bc1a3

File tree

7 files changed

+151
-205
lines changed

7 files changed

+151
-205
lines changed

applications/debug/loader_chaining_a/loader_chaining_a.c

Lines changed: 18 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
#define TAG "LoaderChainingA"
99
#define CHAINING_TEST_B "/ext/apps/Debug/loader_chaining_b.fap"
10-
#define NONEXISTENT_APP "Some nonexistent app that will definitely trigger an error"
10+
#define NONEXISTENT_APP "Some nonexistent app"
1111

1212
typedef struct {
1313
Gui* gui;
@@ -24,52 +24,39 @@ typedef enum {
2424
LoaderChainingASubmenuLaunchBThenA,
2525
LoaderChainingASubmenuLaunchNonexistentSilent,
2626
LoaderChainingASubmenuLaunchNonexistentGui,
27-
LoaderChainingASubmenuLaunchNonexistentArgs,
28-
LoaderChainingASubmenuLaunchNonexistentGuiArgs,
2927
} LoaderChainingASubmenu;
3028

3129
static void loader_chaining_a_submenu_callback(void* context, uint32_t index) {
3230
LoaderChainingA* app = context;
3331

3432
switch(index) {
3533
case LoaderChainingASubmenuLaunchB:
36-
loader_launch_app_after_current(
37-
app->loader, CHAINING_TEST_B, "Hello", LoaderDeferredLaunchErrorReportGui);
34+
loader_enqueue_launch(app->loader, CHAINING_TEST_B, "Hello", LoaderDeferredLaunchFlagGui);
3835
view_dispatcher_stop(app->view_dispatcher);
3936
break;
4037

4138
case LoaderChainingASubmenuLaunchBThenA:
42-
loader_launch_app_after_current(
43-
app->loader, CHAINING_TEST_B, "Hello", LoaderDeferredLaunchErrorReportGui);
44-
loader_launch_current_app_after_deferred(
45-
app->loader, "Hello to you from the future", LoaderDeferredLaunchErrorReportGui);
46-
view_dispatcher_stop(app->view_dispatcher);
47-
break;
39+
loader_enqueue_launch(app->loader, CHAINING_TEST_B, "Hello", LoaderDeferredLaunchFlagGui);
4840

49-
case LoaderChainingASubmenuLaunchNonexistentSilent:
50-
loader_launch_app_after_current(
51-
app->loader, NONEXISTENT_APP, NULL, LoaderDeferredLaunchErrorReportDiscard);
52-
view_dispatcher_stop(app->view_dispatcher);
53-
break;
41+
FuriString* self_path = furi_string_alloc();
42+
furi_check(loader_get_application_launch_path(app->loader, self_path));
43+
loader_enqueue_launch(
44+
app->loader,
45+
furi_string_get_cstr(self_path),
46+
"Hello to you from the future",
47+
LoaderDeferredLaunchFlagGui);
48+
furi_string_free(self_path);
5449

55-
case LoaderChainingASubmenuLaunchNonexistentGui:
56-
loader_launch_app_after_current(
57-
app->loader, NONEXISTENT_APP, NULL, LoaderDeferredLaunchErrorReportGui);
5850
view_dispatcher_stop(app->view_dispatcher);
5951
break;
6052

61-
case LoaderChainingASubmenuLaunchNonexistentArgs:
62-
loader_launch_app_after_current(
63-
app->loader, NONEXISTENT_APP, NULL, LoaderDeferredLaunchErrorReportArgs);
53+
case LoaderChainingASubmenuLaunchNonexistentSilent:
54+
loader_enqueue_launch(app->loader, NONEXISTENT_APP, NULL, LoaderDeferredLaunchFlagNone);
6455
view_dispatcher_stop(app->view_dispatcher);
6556
break;
6657

67-
case LoaderChainingASubmenuLaunchNonexistentGuiArgs:
68-
loader_launch_app_after_current(
69-
app->loader,
70-
NONEXISTENT_APP,
71-
NULL,
72-
LoaderDeferredLaunchErrorReportGui | LoaderDeferredLaunchErrorReportArgs);
58+
case LoaderChainingASubmenuLaunchNonexistentGui:
59+
loader_enqueue_launch(app->loader, NONEXISTENT_APP, NULL, LoaderDeferredLaunchFlagGui);
7360
view_dispatcher_stop(app->view_dispatcher);
7461
break;
7562
}
@@ -113,18 +100,6 @@ LoaderChainingA* loader_chaining_a_alloc(void) {
113100
LoaderChainingASubmenuLaunchNonexistentGui,
114101
loader_chaining_a_submenu_callback,
115102
app);
116-
submenu_add_item(
117-
app->submenu,
118-
"Trigger error: Args",
119-
LoaderChainingASubmenuLaunchNonexistentArgs,
120-
loader_chaining_a_submenu_callback,
121-
app);
122-
submenu_add_item(
123-
app->submenu,
124-
"Trigger error: GUI+Args",
125-
LoaderChainingASubmenuLaunchNonexistentGuiArgs,
126-
loader_chaining_a_submenu_callback,
127-
app);
128103

129104
view_dispatcher_add_view(app->view_dispatcher, 0, submenu_get_view(app->submenu));
130105
view_dispatcher_set_navigation_event_callback(
@@ -152,20 +127,12 @@ int32_t chaining_test_app_a(const char* arg) {
152127

153128
if(arg) {
154129
if(strlen(arg)) {
155-
const char* loader_error_beginning = "loader:deferred_launch_err:";
156-
size_t beginning_len = strlen(loader_error_beginning);
157130
DialogMessage* message = dialog_message_alloc();
158131
FuriString* text;
159132

160-
if(strncmp(arg, loader_error_beginning, beginning_len) == 0) {
161-
dialog_message_set_header(message, "Hi, I am A", 64, 0, AlignCenter, AlignTop);
162-
text = furi_string_alloc_printf("Couldn't launch app:\n%s", arg + beginning_len);
163-
dialog_message_set_buttons(message, NULL, "ok :(", NULL);
164-
} else {
165-
dialog_message_set_header(message, "Hi, I am A", 64, 0, AlignCenter, AlignTop);
166-
text = furi_string_alloc_printf("Me from the past says:\n%s", arg);
167-
dialog_message_set_buttons(message, NULL, "ok!", NULL);
168-
}
133+
dialog_message_set_header(message, "Hi, I am A", 64, 0, AlignCenter, AlignTop);
134+
text = furi_string_alloc_printf("Me from the past says:\n%s", arg);
135+
dialog_message_set_buttons(message, NULL, "ok!", NULL);
169136

170137
dialog_message_set_text(
171138
message, furi_string_get_cstr(text), 64, 32, AlignCenter, AlignCenter);

applications/debug/loader_chaining_b/loader_chaining_b.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,8 @@ int32_t chaining_test_app_b(const char* arg) {
1818
furi_string_free(text);
1919

2020
if(result == DialogMessageButtonRight)
21-
furi_check(loader_launch_app_after_current(
22-
loader,
23-
"/ext/apps/Debug/loader_chaining_a.fap",
24-
NULL,
25-
LoaderDeferredLaunchErrorReportDiscard));
21+
loader_enqueue_launch(
22+
loader, "/ext/apps/Debug/loader_chaining_a.fap", NULL, LoaderDeferredLaunchFlagGui);
2623

2724
furi_record_close(RECORD_LOADER);
2825
furi_record_close(RECORD_DIALOGS);

applications/services/loader/loader.c

Lines changed: 55 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -292,24 +292,15 @@ bool loader_get_application_name(Loader* loader, FuriString* name) {
292292
return result.value;
293293
}
294294

295-
bool loader_launch_app_after_current(
296-
Loader* loader,
297-
const char* name,
298-
const char* args,
299-
LoaderDeferredLaunchErrorReport error_report) {
295+
bool loader_get_application_launch_path(Loader* loader, FuriString* name) {
300296
furi_check(loader);
301297

302298
LoaderMessageBoolResult result;
303299

304300
LoaderMessage message = {
305-
.type = LoaderMessageTypeRememberNextApp,
301+
.type = LoaderMessageTypeGetApplicationLaunchPath,
306302
.api_lock = api_lock_alloc_locked(),
307-
.defer_start =
308-
{
309-
.name = name,
310-
.args = args,
311-
.error_report = error_report,
312-
},
303+
.application_name = name,
313304
.bool_value = &result,
314305
};
315306

@@ -319,30 +310,38 @@ bool loader_launch_app_after_current(
319310
return result.value;
320311
}
321312

322-
bool loader_launch_current_app_after_deferred(
313+
void loader_enqueue_launch(
323314
Loader* loader,
315+
const char* name,
324316
const char* args,
325-
LoaderDeferredLaunchErrorReport error_report) {
317+
LoaderDeferredLaunchFlag flags) {
326318
furi_check(loader);
327319

328-
LoaderMessageBoolResult result;
329-
330320
LoaderMessage message = {
331-
.type = LoaderMessageTypeStartSelfAfterDeferred,
321+
.type = LoaderMessageTypeEnqueueLaunch,
332322
.api_lock = api_lock_alloc_locked(),
333323
.defer_start =
334324
{
335-
/* name unset */
325+
.name = name,
336326
.args = args,
337-
.error_report = error_report,
327+
.flags = flags,
338328
},
339-
.bool_value = &result,
340329
};
341330

342331
furi_message_queue_put(loader->queue, &message, FuriWaitForever);
343332
api_lock_wait_unlock_and_free(message.api_lock);
333+
}
344334

345-
return result.value;
335+
void loader_clear_launch_queue(Loader* loader) {
336+
furi_check(loader);
337+
338+
LoaderMessage message = {
339+
.type = LoaderMessageTypeClearLaunchQueue,
340+
.api_lock = api_lock_alloc_locked(),
341+
};
342+
343+
furi_message_queue_put(loader->queue, &message, FuriWaitForever);
344+
api_lock_wait_unlock_and_free(message.api_lock);
346345
}
347346

348347
// callbacks
@@ -377,26 +376,14 @@ static void
377376

378377
// implementation
379378

380-
static void loader_deferred_launch_data_init(LoaderDeferredLaunchData* data) {
381-
if(!data->name_or_path) data->name_or_path = furi_string_alloc();
382-
if(!data->args) data->args = furi_string_alloc();
383-
}
384-
385-
static void loader_deferred_launch_data_reset(LoaderDeferredLaunchData* data) {
386-
furi_string_free(data->name_or_path);
387-
furi_string_free(data->args);
388-
data->name_or_path = NULL;
389-
data->args = NULL;
390-
data->do_launch = false;
391-
}
392-
393379
static Loader* loader_alloc(void) {
394380
Loader* loader = malloc(sizeof(Loader));
395381
loader->pubsub = furi_pubsub_alloc();
396382
loader->queue = furi_message_queue_alloc(1, sizeof(LoaderMessage));
397383
loader->gui = furi_record_open(RECORD_GUI);
398384
loader->view_holder = view_holder_alloc();
399385
loader->loading = loading_alloc();
386+
LoaderDeferredLaunchRecordArray_init(loader->launch_queue);
400387
view_holder_attach_to_gui(loader->view_holder, loader->gui);
401388
return loader;
402389
}
@@ -741,39 +728,29 @@ static void loader_do_unlock(Loader* loader) {
741728
loader->app.thread = NULL;
742729
}
743730

744-
static bool loader_do_deferred_launch(
745-
Loader* loader,
746-
LoaderDeferredLaunchData* launch_data,
747-
LoaderDeferredLaunchData* error_report_launch_data) {
748-
furi_assert(launch_data);
731+
static bool loader_do_deferred_launch(Loader* loader, LoaderDeferredLaunchRecord* record) {
732+
furi_assert(loader);
733+
furi_assert(record);
749734

750735
bool is_successful = false;
751736
FuriString* error_message = furi_string_alloc();
752737
view_holder_set_view(loader->view_holder, loading_get_view(loader->loading));
753738
view_holder_send_to_front(loader->view_holder);
754739

755740
do {
756-
const char* app_name_str = furi_string_get_cstr(launch_data->name_or_path);
757-
const char* app_args = furi_string_get_cstr(launch_data->args);
758-
FURI_LOG_I(TAG, "Autonomous launch: %s", app_name_str);
741+
const char* app_name_str = furi_string_get_cstr(record->name_or_path);
742+
const char* app_args = furi_string_get_cstr(record->args);
743+
FURI_LOG_I(TAG, "Deferred launch: %s", app_name_str);
759744

760745
LoaderMessageLoaderStatusResult result =
761746
loader_do_start_by_name(loader, app_name_str, app_args, error_message);
762747
if(result.value == LoaderStatusOk) {
763748
is_successful = true;
749+
break;
764750
}
765751

766-
if(launch_data->error_report & LoaderDeferredLaunchErrorReportGui)
752+
if(record->flags & LoaderDeferredLaunchFlagGui)
767753
loader_show_gui_error(result, app_name_str, error_message);
768-
769-
if((launch_data->error_report & LoaderDeferredLaunchErrorReportArgs) &&
770-
error_report_launch_data) {
771-
furi_string_printf(
772-
error_report_launch_data->args,
773-
"loader:deferred_launch_err:%s",
774-
furi_string_get_cstr(error_message));
775-
loader_do_deferred_launch(loader, error_report_launch_data, NULL);
776-
}
777754
} while(false);
778755

779756
view_holder_set_view(loader->view_holder, NULL);
@@ -813,15 +790,10 @@ static void loader_do_app_closed(Loader* loader) {
813790
event.type = LoaderEventTypeApplicationStopped;
814791
furi_pubsub_publish(loader->pubsub, &event);
815792

816-
if(loader->chain.next.do_launch) {
817-
loader->chain.next.do_launch = false;
818-
if(!loader_do_deferred_launch(loader, &loader->chain.next, &loader->chain.previous))
819-
loader_deferred_launch_data_reset(&loader->chain.previous);
820-
loader_deferred_launch_data_reset(&loader->chain.next);
821-
} else if(loader->chain.previous.do_launch) {
822-
loader->chain.previous.do_launch = false;
823-
loader_do_deferred_launch(loader, &loader->chain.previous, NULL);
824-
loader_deferred_launch_data_reset(&loader->chain.previous);
793+
if(LoaderDeferredLaunchRecordArray_size(loader->launch_queue)) {
794+
loader_do_deferred_launch(
795+
loader, LoaderDeferredLaunchRecordArray_front(loader->launch_queue));
796+
LoaderDeferredLaunchRecordArray_pop_at(NULL, loader->launch_queue, 0);
825797
}
826798
}
827799

@@ -847,48 +819,25 @@ static bool loader_do_get_application_name(Loader* loader, FuriString* name) {
847819
return false;
848820
}
849821

850-
static bool loader_do_remember_next_app(Loader* loader, LoaderMessageDeferStart defer_start) {
851-
if(!loader_is_application_running(loader)) return false;
852-
if(!loader->chain.next.do_launch && loader->chain.previous.do_launch) return false;
853-
854-
if(defer_start.name) {
855-
loader_deferred_launch_data_init(&loader->chain.previous);
856-
loader_deferred_launch_data_init(&loader->chain.next);
857-
loader->chain.next.do_launch = true;
858-
859-
furi_string_set(loader->chain.previous.name_or_path, loader->app.launch_path);
860-
furi_string_set_str(loader->chain.next.name_or_path, defer_start.name);
861-
loader->chain.next.error_report = defer_start.error_report;
862-
863-
if(defer_start.args)
864-
furi_string_set_str(loader->chain.next.args, defer_start.args);
865-
else
866-
furi_string_reset(loader->chain.next.args);
867-
} else {
868-
loader_deferred_launch_data_reset(&loader->chain.previous);
869-
loader_deferred_launch_data_reset(&loader->chain.next);
822+
static bool loader_do_get_application_launch_path(Loader* loader, FuriString* path) {
823+
if(loader_is_application_running(loader)) {
824+
furi_string_set(path, loader->app.launch_path);
825+
return true;
870826
}
871827

872-
return true;
828+
return false;
873829
}
874830

875-
static bool
876-
loader_do_remember_to_launch_current(Loader* loader, LoaderMessageDeferStart defer_start) {
877-
if(!loader_is_application_running(loader)) return false;
878-
if(!loader->chain.next.do_launch) return false;
879-
if(defer_start.error_report & LoaderDeferredLaunchErrorReportArgs) return false;
880-
881-
loader_deferred_launch_data_init(&loader->chain.previous);
882-
loader->chain.previous.do_launch = true;
883-
884-
loader->chain.previous.error_report = defer_start.error_report;
831+
static void loader_do_enqueue_launch(Loader* loader, LoaderMessageDeferStart* data) {
832+
furi_check(LoaderDeferredLaunchRecordArray_size(loader->launch_queue) < LAUNCH_QUEUE_MAX_SIZE);
885833

886-
if(defer_start.args)
887-
furi_string_set_str(loader->chain.previous.args, defer_start.args);
888-
else
889-
furi_string_reset(loader->chain.previous.args);
890-
891-
return true;
834+
LoaderDeferredLaunchRecordArray_push_back(
835+
loader->launch_queue,
836+
(LoaderDeferredLaunchRecord){
837+
.name_or_path = furi_string_alloc_set_str(data->name),
838+
.args = data->args ? furi_string_alloc_set_str(data->args) : furi_string_alloc(),
839+
.flags = data->flags,
840+
});
892841
}
893842

894843
// app
@@ -961,14 +910,17 @@ int32_t loader_srv(void* p) {
961910
loader_do_get_application_name(loader, message.application_name);
962911
api_lock_unlock(message.api_lock);
963912
break;
964-
case LoaderMessageTypeRememberNextApp:
913+
case LoaderMessageTypeGetApplicationLaunchPath:
965914
message.bool_value->value =
966-
loader_do_remember_next_app(loader, message.defer_start);
915+
loader_do_get_application_launch_path(loader, message.application_name);
967916
api_lock_unlock(message.api_lock);
968917
break;
969-
case LoaderMessageTypeStartSelfAfterDeferred:
970-
message.bool_value->value =
971-
loader_do_remember_to_launch_current(loader, message.defer_start);
918+
case LoaderMessageTypeEnqueueLaunch:
919+
loader_do_enqueue_launch(loader, &message.defer_start);
920+
api_lock_unlock(message.api_lock);
921+
break;
922+
case LoaderMessageTypeClearLaunchQueue:
923+
LoaderDeferredLaunchRecordArray_reset(loader->launch_queue);
972924
api_lock_unlock(message.api_lock);
973925
break;
974926
}

0 commit comments

Comments
 (0)