multi_converter.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #include <furi.h>
  2. #include <gui/gui.h>
  3. #include <input/input.h>
  4. #include <stdlib.h>
  5. #include "multi_converter_definitions.h"
  6. #include "multi_converter_mode_display.h"
  7. #include "multi_converter_mode_select.h"
  8. static void multi_converter_render_callback(Canvas* const canvas, void* ctx) {
  9. furi_assert(ctx);
  10. const MultiConverterState* multi_converter_state = ctx;
  11. furi_mutex_acquire(multi_converter_state->mutex, FuriWaitForever);
  12. if(multi_converter_state->mode == ModeDisplay) {
  13. multi_converter_mode_display_draw(canvas, multi_converter_state);
  14. } else {
  15. multi_converter_mode_select_draw(canvas, multi_converter_state);
  16. }
  17. furi_mutex_release(multi_converter_state->mutex);
  18. }
  19. static void
  20. multi_converter_input_callback(InputEvent* input_event, void* ctx) {
  21. furi_assert(ctx);
  22. FuriMessageQueue* event_queue = ctx;
  23. MultiConverterEvent event = {.type = EventTypeKey, .input = *input_event};
  24. furi_message_queue_put(event_queue, &event, FuriWaitForever);
  25. }
  26. static void multi_converter_init(MultiConverterState* const multi_converter_state) {
  27. // initial default values
  28. multi_converter_state->buffer_orig[MULTI_CONVERTER_NUMBER_DIGITS] = '\0';
  29. multi_converter_state->buffer_dest[MULTI_CONVERTER_NUMBER_DIGITS] = '\0'; // null terminators
  30. multi_converter_state->unit_type_orig = UnitTypeDec;
  31. multi_converter_state->unit_type_dest = UnitTypeHex;
  32. multi_converter_state->keyboard_lock = 0;
  33. // init the display view
  34. multi_converter_mode_display_reset(multi_converter_state);
  35. // init the select view
  36. multi_converter_mode_select_reset(multi_converter_state);
  37. // set ModeDisplay as the current mode
  38. multi_converter_state->mode = ModeDisplay;
  39. }
  40. // main entry point
  41. int32_t multi_converter_app(void* p) {
  42. UNUSED(p);
  43. // get event queue
  44. FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(MultiConverterEvent));
  45. // allocate state
  46. MultiConverterState* multi_converter_state = malloc(sizeof(MultiConverterState));
  47. // set mutex for plugin state (different threads can access it)
  48. multi_converter_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
  49. if(!multi_converter_state->mutex) {
  50. FURI_LOG_E("MultiConverter", "cannot create mutex\r\n");
  51. furi_message_queue_free(event_queue);
  52. free(multi_converter_state);
  53. return 255;
  54. }
  55. // register callbacks for drawing and input processing
  56. ViewPort* view_port = view_port_alloc();
  57. view_port_draw_callback_set(view_port, multi_converter_render_callback, multi_converter_state);
  58. view_port_input_callback_set(view_port, multi_converter_input_callback, event_queue);
  59. // open GUI and register view_port
  60. Gui* gui = furi_record_open(RECORD_GUI);
  61. gui_add_view_port(gui, view_port, GuiLayerFullscreen);
  62. multi_converter_init(multi_converter_state);
  63. // main loop
  64. MultiConverterEvent event;
  65. for(bool processing = true; processing;) {
  66. FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
  67. furi_mutex_acquire(multi_converter_state->mutex, FuriWaitForever);
  68. if(event_status == FuriStatusOk) {
  69. // press events
  70. if(event.type == EventTypeKey && !multi_converter_state->keyboard_lock) {
  71. if(multi_converter_state->mode == ModeDisplay) {
  72. if(event.input.key == InputKeyBack) {
  73. if(event.input.type == InputTypePress) processing = false;
  74. } else if(event.input.key == InputKeyOk) { // the "ok" press can be short or long
  75. MultiConverterModeTrigger t = None;
  76. if(event.input.type == InputTypeLong)
  77. t = multi_converter_mode_display_ok(1, multi_converter_state);
  78. else if(event.input.type == InputTypeShort)
  79. t = multi_converter_mode_display_ok(0, multi_converter_state);
  80. if(t == Reset) {
  81. multi_converter_mode_select_reset(multi_converter_state);
  82. multi_converter_state->mode = ModeSelector;
  83. }
  84. } else {
  85. if(event.input.type == InputTypePress)
  86. multi_converter_mode_display_navigation(
  87. event.input.key, multi_converter_state);
  88. }
  89. } else { // ModeSelect
  90. if(event.input.type == InputTypePress) {
  91. switch(event.input.key) {
  92. default:
  93. break;
  94. case InputKeyBack:
  95. case InputKeyOk: {
  96. MultiConverterModeTrigger t = multi_converter_mode_select_exit(
  97. event.input.key == InputKeyOk ? 1 : 0, multi_converter_state);
  98. if(t == Reset) {
  99. multi_converter_mode_display_reset(multi_converter_state);
  100. } else if(t == Convert) {
  101. multi_converter_mode_display_convert(multi_converter_state);
  102. }
  103. multi_converter_state->keyboard_lock = 1;
  104. multi_converter_state->mode = ModeDisplay;
  105. break;
  106. }
  107. case InputKeyLeft:
  108. case InputKeyRight:
  109. multi_converter_mode_select_switch(multi_converter_state);
  110. break;
  111. case InputKeyUp:
  112. multi_converter_mode_select_change_unit(-1, multi_converter_state);
  113. break;
  114. case InputKeyDown:
  115. multi_converter_mode_select_change_unit(1, multi_converter_state);
  116. break;
  117. }
  118. }
  119. }
  120. } else if(multi_converter_state->keyboard_lock) {
  121. multi_converter_state->keyboard_lock = 0;
  122. }
  123. }
  124. furi_mutex_release(multi_converter_state->mutex);
  125. view_port_update(view_port);
  126. }
  127. view_port_enabled_set(view_port, false);
  128. gui_remove_view_port(gui, view_port);
  129. furi_record_close(RECORD_GUI);
  130. view_port_free(view_port);
  131. furi_message_queue_free(event_queue);
  132. furi_mutex_free(multi_converter_state->mutex);
  133. free(multi_converter_state);
  134. return 0;
  135. }