app-template.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. #pragma once
  2. #include "callback-connector.h"
  3. #include "flipper.h"
  4. #include "flipper_v2.h"
  5. // simple app class with template variables <state, events>
  6. template <class TState, class TEvent> class AppTemplate {
  7. public:
  8. Widget* widget;
  9. osMessageQueueId_t event_queue;
  10. TState state;
  11. ValueMutex state_mutex;
  12. Gui* gui;
  13. AppTemplate();
  14. ~AppTemplate();
  15. void input_callback(InputEvent* input_event, void* ctx);
  16. void draw_callback(Canvas* canvas, void* ctx);
  17. virtual void render(Canvas* canvas) = 0;
  18. void acquire_state(void);
  19. void release_state(void);
  20. bool get_event(TEvent* event, uint32_t timeout);
  21. void app_ready(void);
  22. void exit(void);
  23. void update_gui(void);
  24. };
  25. template <class TState, class TEvent> AppTemplate<TState, TEvent>::AppTemplate() {
  26. // allocate events queue
  27. event_queue = osMessageQueueNew(10, sizeof(TEvent), NULL);
  28. // allocate valuemutex
  29. // TODO: use plain os mutex?
  30. if(!init_mutex(&state_mutex, &state, sizeof(TState))) {
  31. printf("cannot create mutex\n");
  32. furiac_exit(NULL);
  33. }
  34. // open gui
  35. gui = (Gui*)furi_open("gui");
  36. if(gui == NULL) {
  37. printf("gui is not available\n");
  38. furiac_exit(NULL);
  39. }
  40. // allocate widget
  41. widget = widget_alloc();
  42. }
  43. template <class TState, class TEvent> AppTemplate<TState, TEvent>::~AppTemplate() {
  44. }
  45. // generic input callback
  46. template <class TState, class TEvent>
  47. void AppTemplate<TState, TEvent>::input_callback(InputEvent* input_event, void* ctx) {
  48. AppTemplate* app = static_cast<AppTemplate*>(ctx);
  49. TEvent event;
  50. event.type = TEvent::EventTypeKey;
  51. event.value.input = *input_event;
  52. osMessageQueuePut(app->event_queue, &event, 0, 0);
  53. }
  54. // generic draw callback
  55. template <class TState, class TEvent>
  56. void AppTemplate<TState, TEvent>::draw_callback(Canvas* canvas, void* ctx) {
  57. AppTemplate* app = static_cast<AppTemplate*>(ctx);
  58. app->acquire_state();
  59. canvas_clear(canvas);
  60. app->render(canvas);
  61. app->release_state();
  62. }
  63. template <class TState, class TEvent> void AppTemplate<TState, TEvent>::acquire_state(void) {
  64. acquire_mutex(&state_mutex, osWaitForever);
  65. }
  66. template <class TState, class TEvent> void AppTemplate<TState, TEvent>::release_state(void) {
  67. release_mutex(&state_mutex, &state);
  68. }
  69. template <class TState, class TEvent>
  70. bool AppTemplate<TState, TEvent>::get_event(TEvent* event, uint32_t timeout) {
  71. osStatus_t event_status = osMessageQueueGet(event_queue, event, NULL, timeout);
  72. return (event_status == osOK);
  73. }
  74. // signal that app is ready, and we can render something
  75. // also unblock dependent tasks
  76. template <class TState, class TEvent> void AppTemplate<TState, TEvent>::app_ready(void) {
  77. // connect widget with input callback
  78. auto input_cb_ref = cbc::obtain_connector(this, &AppTemplate::input_callback);
  79. widget_input_callback_set(widget, input_cb_ref, this);
  80. // connect widget with draw callback
  81. auto draw_cb_ref = cbc::obtain_connector(this, &AppTemplate::draw_callback);
  82. widget_draw_callback_set(widget, draw_cb_ref, this);
  83. // add widget
  84. gui_add_widget(gui, widget, GuiLayerFullscreen);
  85. // signal that our app ready to work
  86. furiac_ready();
  87. }
  88. template <class TState, class TEvent> void AppTemplate<TState, TEvent>::exit(void) {
  89. // TODO remove all widgets create by app
  90. widget_enabled_set(widget, false);
  91. furiac_exit(NULL);
  92. }
  93. template <class TState, class TEvent> void AppTemplate<TState, TEvent>::update_gui(void) {
  94. widget_update(widget);
  95. }