xremote_signal_view.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /*!
  2. * @file flipper-xremote/views/xremote_signal_view.c
  3. @license This project is released under the GNU GPLv3 License
  4. * @copyright (c) 2023 Sandro Kalatozishvili (s.kalatoz@gmail.com)
  5. *
  6. * @brief Signal analyzer page view components and functionality.
  7. */
  8. #include "xremote_signal_view.h"
  9. #include "../xremote_analyzer.h"
  10. #include "../xremote_app.h"
  11. static void xremote_signal_view_draw_callback(Canvas* canvas, void* context) {
  12. furi_assert(context);
  13. XRemoteViewModel* model = context;
  14. XRemoteSignalAnalyzer* analyzer = model->context;
  15. XRemoteAppContext* app_ctx = xremote_signal_analyzer_get_app_context(analyzer);
  16. ViewOrientation orientation = app_ctx->app_settings->orientation;
  17. uint8_t y = orientation == ViewOrientationHorizontal ? 17 : 49;
  18. const char* text = "Press any\nbutton on\nthe remote.";
  19. xremote_canvas_draw_header(canvas, orientation, "Analyzer");
  20. elements_multiline_text_aligned(canvas, 0, y, AlignLeft, AlignTop, text);
  21. const char* exit_str = xremote_app_context_get_exit_str(app_ctx);
  22. xremote_canvas_draw_exit_footer(canvas, orientation, exit_str);
  23. }
  24. static void xremote_signal_success_view_draw_callback(Canvas* canvas, void* context) {
  25. furi_assert(context);
  26. XRemoteViewModel* model = context;
  27. XRemoteSignalAnalyzer* analyzer = model->context;
  28. XRemoteAppContext* app_ctx = xremote_signal_analyzer_get_app_context(analyzer);
  29. InfraredSignal* ir_signal = xremote_signal_analyzer_get_ir_signal(analyzer);
  30. xremote_canvas_draw_header(canvas, app_ctx->app_settings->orientation, "IR Signal");
  31. char signal_info[128];
  32. if(infrared_signal_is_raw(ir_signal)) {
  33. InfraredRawSignal* raw = infrared_signal_get_raw_signal(ir_signal);
  34. snprintf(
  35. signal_info,
  36. sizeof(signal_info),
  37. "Type: RAW\n"
  38. "T-Size: %u\n"
  39. "D-Cycle: %.2f\n",
  40. raw->timings_size,
  41. (double)raw->duty_cycle);
  42. } else {
  43. InfraredMessage* message = infrared_signal_get_message(ir_signal);
  44. const char* infrared_protocol = infrared_get_protocol_name(message->protocol);
  45. snprintf(
  46. signal_info,
  47. sizeof(signal_info),
  48. "Proto: %s\n"
  49. "Addr: 0x%lX\n"
  50. "Cmd: 0x%lX\n",
  51. infrared_protocol,
  52. message->address,
  53. message->command);
  54. }
  55. if(app_ctx->app_settings->orientation == ViewOrientationHorizontal) {
  56. elements_multiline_text_aligned(canvas, 0, 17, AlignLeft, AlignTop, signal_info);
  57. xremote_canvas_draw_button_wide(
  58. canvas, model->ok_pressed, 68, 26, "Send", XRemoteIconEnter);
  59. xremote_canvas_draw_button_wide(
  60. canvas, model->back_pressed, 68, 44, "Retry", XRemoteIconBack);
  61. } else {
  62. elements_multiline_text_aligned(canvas, 0, 39, AlignLeft, AlignTop, signal_info);
  63. xremote_canvas_draw_button_wide(
  64. canvas, model->ok_pressed, 0, 88, "Send", XRemoteIconEnter);
  65. xremote_canvas_draw_button_wide(
  66. canvas, model->back_pressed, 0, 106, "Retry", XRemoteIconBack);
  67. }
  68. }
  69. static void xremote_signal_success_view_process(XRemoteView* view, InputEvent* event) {
  70. with_view_model(
  71. xremote_view_get_view(view),
  72. XRemoteViewModel * model,
  73. {
  74. XRemoteSignalAnalyzer* analyzer = xremote_view_get_context(view);
  75. model->context = analyzer;
  76. if(event->type == InputTypePress) {
  77. if(event->key == InputKeyOk) {
  78. model->ok_pressed = true;
  79. xremote_signal_analyzer_send_event(analyzer, XRemoteEventSignalSend);
  80. } else if(event->key == InputKeyBack) {
  81. model->back_pressed = true;
  82. xremote_signal_analyzer_send_event(analyzer, XRemoteEventSignalRetry);
  83. }
  84. } else if(event->type == InputTypeRelease) {
  85. if(event->key == InputKeyOk)
  86. model->ok_pressed = false;
  87. else if(event->key == InputKeyBack)
  88. model->back_pressed = false;
  89. }
  90. },
  91. true);
  92. }
  93. static void xremote_signal_view_process(XRemoteView* view, InputEvent* event) {
  94. with_view_model(
  95. xremote_view_get_view(view),
  96. XRemoteViewModel * model,
  97. {
  98. XRemoteSignalAnalyzer* analyzer = xremote_view_get_context(view);
  99. XRemoteAppContext* app_ctx = xremote_view_get_app_context(view);
  100. XRemoteAppExit exit = app_ctx->app_settings->exit_behavior;
  101. model->context = analyzer;
  102. if((event->type == InputTypeShort || event->type == InputTypeLong) &&
  103. event->key == InputKeyBack) {
  104. if((event->type == InputTypeShort && exit == XRemoteAppExitPress) ||
  105. (event->type == InputTypeLong && exit == XRemoteAppExitHold)) {
  106. model->back_pressed = true;
  107. xremote_signal_analyzer_send_event(analyzer, XRemoteEventSignalExit);
  108. }
  109. } else if(event->type == InputTypeRelease) {
  110. if(event->key == InputKeyOk)
  111. model->ok_pressed = false;
  112. else if(event->key == InputKeyBack)
  113. model->back_pressed = false;
  114. else if(event->key == InputKeyRight)
  115. model->right_pressed = false;
  116. }
  117. },
  118. true);
  119. }
  120. static bool xremote_signal_success_view_input_callback(InputEvent* event, void* context) {
  121. furi_assert(context);
  122. XRemoteView* view = (XRemoteView*)context;
  123. xremote_signal_success_view_process(view, event);
  124. return true;
  125. }
  126. static bool xremote_signal_view_input_callback(InputEvent* event, void* context) {
  127. furi_assert(context);
  128. XRemoteView* view = (XRemoteView*)context;
  129. xremote_signal_view_process(view, event);
  130. return true;
  131. }
  132. XRemoteView* xremote_signal_success_view_alloc(void* app_ctx, void* analyzer) {
  133. XRemoteView* view = xremote_view_alloc(
  134. app_ctx,
  135. xremote_signal_success_view_input_callback,
  136. xremote_signal_success_view_draw_callback);
  137. xremote_view_set_context(view, analyzer, NULL);
  138. with_view_model(
  139. xremote_view_get_view(view),
  140. XRemoteViewModel * model,
  141. {
  142. model->context = analyzer;
  143. model->back_pressed = false;
  144. model->ok_pressed = false;
  145. },
  146. true);
  147. return view;
  148. }
  149. XRemoteView* xremote_signal_view_alloc(void* app_ctx, void* analyzer) {
  150. XRemoteView* view = xremote_view_alloc(
  151. app_ctx, xremote_signal_view_input_callback, xremote_signal_view_draw_callback);
  152. xremote_view_set_context(view, analyzer, NULL);
  153. with_view_model(
  154. xremote_view_get_view(view),
  155. XRemoteViewModel * model,
  156. {
  157. model->context = analyzer;
  158. model->back_pressed = false;
  159. },
  160. true);
  161. return view;
  162. }