multi_converter.c 6.5 KB

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