This commit is contained in:
Willy-JL
2024-06-11 22:46:09 +02:00
62 changed files with 1625 additions and 1133 deletions

View File

@@ -23,7 +23,6 @@ Cli* cli_alloc(void) {
cli->session = NULL;
cli->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
furi_check(cli->mutex);
cli->idle_sem = furi_semaphore_alloc(1, 0);

View File

@@ -100,8 +100,8 @@ void dolphin_event_send_async(Dolphin* dolphin, DolphinEvent* event) {
void dolphin_event_send_wait(Dolphin* dolphin, DolphinEvent* event) {
furi_assert(dolphin);
furi_assert(event);
event->flag = furi_event_flag_alloc();
furi_check(event->flag);
furi_check(
furi_message_queue_put(dolphin->event_queue, event, FuriWaitForever) == FuriStatusOk);
furi_check(

View File

@@ -112,7 +112,6 @@ Popup* popup_alloc(void) {
Popup* popup = malloc(sizeof(Popup));
popup->view = view_alloc();
popup->timer = furi_timer_alloc(popup_timer_callback, FuriTimerTypeOnce, popup);
furi_assert(popup->timer);
popup->timer_period_in_ms = 1000;
popup->timer_enabled = false;

View File

@@ -83,7 +83,6 @@ void view_allocate_model(View* view, ViewModelType type, size_t size) {
} else if(view->model_type == ViewModelTypeLocking) {
ViewModelLocking* model = malloc(sizeof(ViewModelLocking));
model->mutex = furi_mutex_alloc(FuriMutexTypeRecursive);
furi_check(model->mutex);
model->data = malloc(size);
view->model = model;
} else {

View File

@@ -31,8 +31,23 @@ void view_dispatcher_free(ViewDispatcher* view_dispatcher) {
// Free ViewPort
view_port_free(view_dispatcher->view_port);
// Free internal queue
if(view_dispatcher->queue) {
furi_message_queue_free(view_dispatcher->queue);
if(view_dispatcher->input_queue) {
furi_event_loop_message_queue_unsubscribe(
view_dispatcher->event_loop, view_dispatcher->input_queue);
furi_message_queue_free(view_dispatcher->input_queue);
}
if(view_dispatcher->ascii_queue) {
furi_event_loop_message_queue_unsubscribe(
view_dispatcher->event_loop, view_dispatcher->ascii_queue);
furi_message_queue_free(view_dispatcher->ascii_queue);
}
if(view_dispatcher->event_queue) {
furi_event_loop_message_queue_unsubscribe(
view_dispatcher->event_loop, view_dispatcher->event_queue);
furi_message_queue_free(view_dispatcher->event_queue);
}
if(view_dispatcher->event_loop) {
furi_event_loop_free(view_dispatcher->event_loop);
}
// Free dispatcher
free(view_dispatcher);
@@ -40,8 +55,33 @@ void view_dispatcher_free(ViewDispatcher* view_dispatcher) {
void view_dispatcher_enable_queue(ViewDispatcher* view_dispatcher) {
furi_check(view_dispatcher);
furi_check(view_dispatcher->queue == NULL);
view_dispatcher->queue = furi_message_queue_alloc(16, sizeof(ViewDispatcherMessage));
furi_check(view_dispatcher->event_loop == NULL);
view_dispatcher->event_loop = furi_event_loop_alloc();
view_dispatcher->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
furi_event_loop_message_queue_subscribe(
view_dispatcher->event_loop,
view_dispatcher->input_queue,
FuriEventLoopEventIn,
view_dispatcher_run_input_callback,
view_dispatcher);
view_dispatcher->ascii_queue = furi_message_queue_alloc(8, sizeof(AsciiEvent));
furi_event_loop_message_queue_subscribe(
view_dispatcher->event_loop,
view_dispatcher->ascii_queue,
FuriEventLoopEventIn,
view_dispatcher_run_ascii_callback,
view_dispatcher);
view_dispatcher->event_queue = furi_message_queue_alloc(8, sizeof(uint32_t));
furi_event_loop_message_queue_subscribe(
view_dispatcher->event_loop,
view_dispatcher->event_queue,
FuriEventLoopEventIn,
view_dispatcher_run_event_callback,
view_dispatcher);
}
void view_dispatcher_set_event_callback_context(ViewDispatcher* view_dispatcher, void* context) {
@@ -72,50 +112,45 @@ void view_dispatcher_set_tick_event_callback(
view_dispatcher->tick_period = tick_period;
}
FuriEventLoop* view_dispatcher_get_event_loop(ViewDispatcher* view_dispatcher) {
furi_check(view_dispatcher);
furi_check(view_dispatcher->event_loop);
return view_dispatcher->event_loop;
}
void view_dispatcher_run(ViewDispatcher* view_dispatcher) {
furi_check(view_dispatcher);
furi_check(view_dispatcher->queue);
furi_check(view_dispatcher->event_loop);
uint32_t tick_period = view_dispatcher->tick_period == 0 ? FuriWaitForever :
view_dispatcher->tick_period;
ViewDispatcherMessage message;
while(1) {
if(furi_message_queue_get(view_dispatcher->queue, &message, tick_period) != FuriStatusOk) {
view_dispatcher_handle_tick_event(view_dispatcher);
continue;
}
if(message.type == ViewDispatcherMessageTypeStop) {
break;
} else if(message.type == ViewDispatcherMessageTypeInput) {
view_dispatcher_handle_input(view_dispatcher, &message.input);
} else if(message.type == ViewDispatcherMessageTypeAscii) {
view_dispatcher_handle_ascii(view_dispatcher, &message.ascii);
} else if(message.type == ViewDispatcherMessageTypeCustomEvent) {
view_dispatcher_handle_custom_event(view_dispatcher, message.custom_event);
}
}
furi_event_loop_tick_set(
view_dispatcher->event_loop,
tick_period,
view_dispatcher_handle_tick_event,
view_dispatcher);
furi_event_loop_run(view_dispatcher->event_loop);
// Wait till all input events delivered
InputEvent input;
while(view_dispatcher->ongoing_input) {
furi_message_queue_get(view_dispatcher->queue, &message, FuriWaitForever);
if(message.type == ViewDispatcherMessageTypeInput) {
uint8_t key_bit = (1 << message.input.key);
if(message.input.type == InputTypePress) {
view_dispatcher->ongoing_input |= key_bit;
} else if(message.input.type == InputTypeRelease) {
view_dispatcher->ongoing_input &= ~key_bit;
}
furi_message_queue_get(view_dispatcher->input_queue, &input, FuriWaitForever);
uint8_t key_bit = (1 << input.key);
if(input.type == InputTypePress) {
view_dispatcher->ongoing_input |= key_bit;
} else if(input.type == InputTypeRelease) {
view_dispatcher->ongoing_input &= ~key_bit;
}
}
}
void view_dispatcher_stop(ViewDispatcher* view_dispatcher) {
furi_check(view_dispatcher);
furi_check(view_dispatcher->queue);
ViewDispatcherMessage message;
message.type = ViewDispatcherMessageTypeStop;
furi_check(
furi_message_queue_put(view_dispatcher->queue, &message, FuriWaitForever) == FuriStatusOk);
furi_check(view_dispatcher->event_loop);
furi_event_loop_stop(view_dispatcher->event_loop);
}
void view_dispatcher_add_view(ViewDispatcher* view_dispatcher, uint32_t view_id, View* view) {
@@ -222,12 +257,9 @@ void view_dispatcher_draw_callback(Canvas* canvas, void* context) {
void view_dispatcher_input_callback(InputEvent* event, void* context) {
ViewDispatcher* view_dispatcher = context;
if(view_dispatcher->queue) {
ViewDispatcherMessage message;
message.type = ViewDispatcherMessageTypeInput;
message.input = *event;
if(view_dispatcher->input_queue) {
furi_check(
furi_message_queue_put(view_dispatcher->queue, &message, FuriWaitForever) ==
furi_message_queue_put(view_dispatcher->input_queue, event, FuriWaitForever) ==
FuriStatusOk);
} else {
view_dispatcher_handle_input(view_dispatcher, event);
@@ -239,12 +271,9 @@ bool view_dispatcher_ascii_callback(AsciiEvent* event, void* context) {
// So instead ViewDispatcher tells ViewPort that all events are consumed
// Then ViewDispatcher handles fallbacks the same way as ViewPort would have done
ViewDispatcher* view_dispatcher = context;
if(view_dispatcher->queue) {
ViewDispatcherMessage message;
message.type = ViewDispatcherMessageTypeAscii;
message.ascii = *event;
if(view_dispatcher->ascii_queue) {
furi_check(
furi_message_queue_put(view_dispatcher->queue, &message, FuriWaitForever) ==
furi_message_queue_put(view_dispatcher->ascii_queue, event, FuriWaitForever) ==
FuriStatusOk);
} else {
view_dispatcher_handle_ascii(view_dispatcher, event);
@@ -351,7 +380,8 @@ void view_dispatcher_handle_ascii(ViewDispatcher* view_dispatcher, AsciiEvent* e
}
}
void view_dispatcher_handle_tick_event(ViewDispatcher* view_dispatcher) {
void view_dispatcher_handle_tick_event(void* context) {
ViewDispatcher* view_dispatcher = context;
if(view_dispatcher->tick_event_callback) {
view_dispatcher->tick_event_callback(view_dispatcher->event_context);
}
@@ -370,14 +400,11 @@ void view_dispatcher_handle_custom_event(ViewDispatcher* view_dispatcher, uint32
void view_dispatcher_send_custom_event(ViewDispatcher* view_dispatcher, uint32_t event) {
furi_check(view_dispatcher);
furi_check(view_dispatcher->queue);
ViewDispatcherMessage message;
message.type = ViewDispatcherMessageTypeCustomEvent;
message.custom_event = event;
furi_check(view_dispatcher->event_loop);
furi_check(
furi_message_queue_put(view_dispatcher->queue, &message, FuriWaitForever) == FuriStatusOk);
furi_message_queue_put(view_dispatcher->event_queue, &event, FuriWaitForever) ==
FuriStatusOk);
}
static const ViewPortOrientation view_dispatcher_view_port_orientation_table[] = {
@@ -409,7 +436,7 @@ void view_dispatcher_set_current_view(ViewDispatcher* view_dispatcher, View* vie
view_port_update(view_dispatcher->view_port);
} else {
view_port_enabled_set(view_dispatcher->view_port, false);
if(view_dispatcher->queue) {
if(view_dispatcher->event_loop) {
view_dispatcher_stop(view_dispatcher);
}
}
@@ -425,3 +452,39 @@ void view_dispatcher_update(View* view, void* context) {
view_port_update(view_dispatcher->view_port);
}
}
bool view_dispatcher_run_event_callback(FuriMessageQueue* queue, void* context) {
furi_assert(context);
ViewDispatcher* instance = context;
furi_assert(instance->event_queue == queue);
uint32_t event;
furi_check(furi_message_queue_get(instance->event_queue, &event, 0) == FuriStatusOk);
view_dispatcher_handle_custom_event(instance, event);
return true;
}
bool view_dispatcher_run_input_callback(FuriMessageQueue* queue, void* context) {
furi_assert(context);
ViewDispatcher* instance = context;
furi_assert(instance->input_queue == queue);
InputEvent input;
furi_check(furi_message_queue_get(instance->input_queue, &input, 0) == FuriStatusOk);
view_dispatcher_handle_input(instance, &input);
return true;
}
bool view_dispatcher_run_ascii_callback(FuriMessageQueue* queue, void* context) {
furi_assert(context);
ViewDispatcher* instance = context;
furi_assert(instance->ascii_queue == queue);
AsciiEvent ascii;
furi_check(furi_message_queue_get(instance->ascii_queue, &ascii, 0) == FuriStatusOk);
view_dispatcher_handle_ascii(instance, &ascii);
return true;
}

View File

@@ -47,8 +47,8 @@ void view_dispatcher_free(ViewDispatcher* view_dispatcher);
/** Enable queue support
*
* If queue enabled all input and custom events will be dispatched throw
* internal queue
* Allocates event_loop, input and event message queues. Must be used with
* `view_dispatcher_run`
*
* @param view_dispatcher ViewDispatcher instance
*/
@@ -101,6 +101,20 @@ void view_dispatcher_set_tick_event_callback(
*/
void view_dispatcher_set_event_callback_context(ViewDispatcher* view_dispatcher, void* context);
/** Get event_loop instance
*
* event_loop instance is allocated on `view_dispatcher_enable_queue` and used
* in view_dispatcher_run.
*
* You can add your objects into event_loop instance, but don't run the loop on
* your side it will cause issues with input processing on dispatcher stop.
*
* @param view_dispatcher ViewDispatcher instance
*
* @return The event_loop instance.
*/
FuriEventLoop* view_dispatcher_get_event_loop(ViewDispatcher* view_dispatcher);
/** Run ViewDispatcher
*
* Use only after queue enabled

View File

@@ -5,7 +5,6 @@
#pragma once
#include <furi.h>
#include <m-dict.h>
#include "view_dispatcher.h"
@@ -15,7 +14,11 @@
DICT_DEF2(ViewDict, uint32_t, M_DEFAULT_OPLIST, View*, M_PTR_OPLIST)
struct ViewDispatcher {
FuriMessageQueue* queue;
FuriEventLoop* event_loop;
FuriMessageQueue* input_queue;
FuriMessageQueue* ascii_queue;
FuriMessageQueue* event_queue;
Gui* gui;
ViewPort* view_port;
ViewDict_t views;
@@ -32,22 +35,6 @@ struct ViewDispatcher {
void* event_context;
};
typedef enum {
ViewDispatcherMessageTypeInput,
ViewDispatcherMessageTypeAscii,
ViewDispatcherMessageTypeCustomEvent,
ViewDispatcherMessageTypeStop,
} ViewDispatcherMessageType;
typedef struct {
ViewDispatcherMessageType type;
union {
InputEvent input;
AsciiEvent ascii;
uint32_t custom_event;
};
} ViewDispatcherMessage;
/** ViewPort Draw Callback */
void view_dispatcher_draw_callback(Canvas* canvas, void* context);
@@ -64,7 +51,7 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e
void view_dispatcher_handle_ascii(ViewDispatcher* view_dispatcher, AsciiEvent* event);
/** Tick handler */
void view_dispatcher_handle_tick_event(ViewDispatcher* view_dispatcher);
void view_dispatcher_handle_tick_event(void* context);
/** Custom event handler */
void view_dispatcher_handle_custom_event(ViewDispatcher* view_dispatcher, uint32_t event);
@@ -74,3 +61,12 @@ void view_dispatcher_set_current_view(ViewDispatcher* view_dispatcher, View* vie
/** ViewDispatcher update event */
void view_dispatcher_update(View* view, void* context);
/** ViewDispatcher run event loop event callback */
bool view_dispatcher_run_event_callback(FuriMessageQueue* queue, void* context);
/** ViewDispatcher run event loop input callback */
bool view_dispatcher_run_input_callback(FuriMessageQueue* queue, void* context);
/** ViewDispatcher run event loop ascii callback */
bool view_dispatcher_run_ascii_callback(FuriMessageQueue* queue, void* context);