solitaire.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #include <furi.h>
  2. #include <notification/notification.h>
  3. #include <notification/notification_messages.h>
  4. #include "Game.h"
  5. typedef enum {
  6. EventTypeTick,
  7. EventTypeKey,
  8. } EventType;
  9. typedef struct {
  10. EventType type;
  11. InputEvent *input;
  12. } AppEvent;
  13. static FuriMutex *mutex;
  14. static void input_callback(InputEvent *input_event, FuriMessageQueue *event_queue) {
  15. furi_assert(event_queue);
  16. AppEvent event = {.type = EventTypeKey, .input = input_event};
  17. furi_message_queue_put(event_queue, &event, FuriWaitForever);
  18. }
  19. static void update_timer_callback(FuriMessageQueue *event_queue) {
  20. furi_assert(event_queue);
  21. AppEvent event = {.type = EventTypeTick, .input=nullptr};
  22. furi_message_queue_put(event_queue, &event, 0);
  23. }
  24. static void render_callback(Canvas *const canvas, void *ctx) {
  25. Game *g = (Game *) ctx;
  26. auto status = furi_mutex_acquire(mutex, 150);
  27. if (g == nullptr || status != FuriStatusOk) return;
  28. g->Render(canvas);
  29. UNUSED(canvas);
  30. UNUSED(g);
  31. furi_mutex_release(mutex);
  32. }
  33. #ifdef __cplusplus
  34. extern "C"
  35. {
  36. #endif
  37. int32_t solitaire_app(void *p) {
  38. UNUSED(p);
  39. FURI_LOG_D("MEMORY", "Free %i", memmgr_get_free_heap());
  40. int32_t return_code = 0;
  41. size_t start = memmgr_get_free_heap();
  42. Game *game = new Game;
  43. FuriMessageQueue *event_queue = furi_message_queue_alloc(8, sizeof(AppEvent));
  44. mutex = furi_mutex_alloc(FuriMutexTypeNormal);
  45. if (mutex) {
  46. bool processing = true;
  47. auto *notification = static_cast<NotificationApp *>(furi_record_open(RECORD_NOTIFICATION));
  48. notification_message_block(notification, &sequence_display_backlight_enforce_on);
  49. ViewPort *view_port = view_port_alloc();
  50. view_port_draw_callback_set(view_port, render_callback, game);
  51. view_port_input_callback_set(view_port, input_callback, event_queue);
  52. FuriTimer *timer = furi_timer_alloc(update_timer_callback, FuriTimerTypePeriodic, event_queue);
  53. furi_timer_start(timer, furi_kernel_get_tick_frequency() / 20);
  54. auto gui = static_cast<Gui *>(furi_record_open("gui"));
  55. gui_add_view_port(gui, view_port, GuiLayerFullscreen);
  56. AppEvent event;
  57. game->Reset();
  58. while (processing) {
  59. FuriStatus event_status = furi_message_queue_get(event_queue, &event, FuriWaitForever);
  60. furi_mutex_acquire(mutex, FuriWaitForever);
  61. if (event_status == FuriStatusOk) {
  62. if (event.type == EventTypeKey) {
  63. if (event.input->type == InputTypeLong) {
  64. switch (event.input->key) {
  65. case InputKeyUp:
  66. case InputKeyDown:
  67. case InputKeyRight:
  68. case InputKeyLeft:
  69. case InputKeyOk:
  70. game->LongPress(event.input->key);
  71. break;
  72. case InputKeyBack:
  73. processing = false;
  74. return_code = 1;
  75. default:
  76. break;
  77. }
  78. } else if (event.input->type == InputTypePress) {
  79. game->Press(event.input->key);
  80. }
  81. } else if (event.type == EventTypeTick) {
  82. game->Update();
  83. }
  84. }
  85. view_port_update(view_port);
  86. furi_mutex_release(mutex);
  87. }
  88. notification_message_block(notification, &sequence_display_backlight_enforce_auto);
  89. furi_timer_free(timer);
  90. view_port_enabled_set(view_port, false);
  91. gui_remove_view_port(gui, view_port);
  92. furi_record_close(RECORD_GUI);
  93. furi_record_close(RECORD_NOTIFICATION);
  94. view_port_free(view_port);
  95. } else {
  96. FURI_LOG_E("APP", "cannot create mutex\r\n");
  97. return_code = 255;
  98. }
  99. delete game;
  100. furi_mutex_free(mutex);
  101. furi_message_queue_free(event_queue);
  102. start = memmgr_get_free_heap()-start;
  103. if(start!=0)
  104. FURI_LOG_E("MEMORY", "Leak detected %i", start);
  105. return return_code;
  106. }
  107. #ifdef __cplusplus
  108. }
  109. #endif