xremote_analyzer.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*!
  2. * @file flipper-xremote/xremote_analyzer.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 Infrared remote singnal analyzer and custom view events.
  7. */
  8. #include "xremote_analyzer.h"
  9. #include "views/xremote_signal_view.h"
  10. struct XRemoteSignalAnalyzer {
  11. XRemoteSignalReceiver* ir_receiver;
  12. XRemoteClearCallback on_clear;
  13. XRemoteAppContext* app_ctx;
  14. InfraredSignal* ir_signal;
  15. XRemoteView* signal_view;
  16. void* context;
  17. bool pause;
  18. };
  19. InfraredSignal* xremote_signal_analyzer_get_ir_signal(XRemoteSignalAnalyzer* analyzer) {
  20. xremote_app_assert(analyzer, NULL);
  21. return analyzer->ir_signal;
  22. }
  23. XRemoteSignalReceiver* xremote_signal_analyzer_get_ir_receiver(XRemoteSignalAnalyzer* analyzer) {
  24. xremote_app_assert(analyzer, NULL);
  25. return analyzer->ir_receiver;
  26. }
  27. XRemoteAppContext* xremote_signal_analyzer_get_app_context(XRemoteSignalAnalyzer* analyzer) {
  28. xremote_app_assert(analyzer, NULL);
  29. return analyzer->app_ctx;
  30. }
  31. void xremote_signal_analyzer_send_event(XRemoteSignalAnalyzer* analyzer, XRemoteEvent event) {
  32. xremote_app_assert_void(analyzer);
  33. ViewDispatcher* view_disp = analyzer->app_ctx->view_dispatcher;
  34. view_dispatcher_send_custom_event(view_disp, event);
  35. }
  36. static void
  37. xremote_signal_analyzer_switch_to_view(XRemoteSignalAnalyzer* analyzer, XRemoteViewID view_id) {
  38. xremote_app_assert_void(analyzer);
  39. ViewDispatcher* view_disp = analyzer->app_ctx->view_dispatcher;
  40. view_dispatcher_switch_to_view(view_disp, view_id);
  41. }
  42. static void xremote_signal_analyzer_rx_stop(XRemoteSignalAnalyzer* analyzer) {
  43. xremote_app_assert_void(analyzer);
  44. analyzer->pause = true;
  45. xremote_signal_receiver_stop(analyzer->ir_receiver);
  46. }
  47. static void xremote_signal_analyzer_rx_start(XRemoteSignalAnalyzer* analyzer) {
  48. xremote_app_assert_void(analyzer);
  49. analyzer->pause = false;
  50. xremote_signal_receiver_start(analyzer->ir_receiver);
  51. }
  52. static uint32_t xremote_signal_analyzer_view_exit_callback(void* context) {
  53. UNUSED(context);
  54. return XRemoteViewAnalyzer;
  55. }
  56. static void xremote_signal_analyzer_signal_callback(void* context, InfraredSignal* signal) {
  57. XRemoteSignalAnalyzer* analyzer = context;
  58. xremote_app_assert_void(!analyzer->pause);
  59. analyzer->pause = true;
  60. infrared_signal_set_signal(analyzer->ir_signal, signal);
  61. xremote_signal_analyzer_send_event(analyzer, XRemoteEventSignalReceived);
  62. }
  63. static bool xremote_signal_analyzer_custom_event_callback(void* context, uint32_t event) {
  64. xremote_app_assert(context, false);
  65. XRemoteSignalAnalyzer* analyzer = context;
  66. if(event == XRemoteEventSignalExit) {
  67. xremote_signal_analyzer_rx_stop(analyzer);
  68. xremote_signal_analyzer_switch_to_view(analyzer, XRemoteViewSubmenu);
  69. } else if(event == XRemoteEventSignalReceived) {
  70. xremote_signal_analyzer_rx_stop(analyzer);
  71. xremote_signal_analyzer_switch_to_view(analyzer, XRemoteViewSignal);
  72. } else if(event == XRemoteEventSignalRetry) {
  73. xremote_signal_analyzer_rx_start(analyzer);
  74. xremote_signal_analyzer_switch_to_view(analyzer, XRemoteViewAnalyzer);
  75. } else if(event == XRemoteEventSignalSend) {
  76. XRemoteAppContext* app_ctx = analyzer->app_ctx;
  77. xremote_app_send_signal(app_ctx, analyzer->ir_signal);
  78. }
  79. return true;
  80. }
  81. static XRemoteSignalAnalyzer* xremote_signal_analyzer_alloc(XRemoteAppContext* app_ctx) {
  82. XRemoteSignalAnalyzer* analyzer = malloc(sizeof(XRemoteSignalAnalyzer));
  83. analyzer->ir_signal = infrared_signal_alloc();
  84. analyzer->app_ctx = app_ctx;
  85. analyzer->pause = false;
  86. analyzer->signal_view = xremote_signal_success_view_alloc(app_ctx, analyzer);
  87. View* view = xremote_view_get_view(analyzer->signal_view);
  88. view_set_previous_callback(view, xremote_signal_analyzer_view_exit_callback);
  89. view_dispatcher_add_view(app_ctx->view_dispatcher, XRemoteViewSignal, view);
  90. view_dispatcher_set_custom_event_callback(
  91. app_ctx->view_dispatcher, xremote_signal_analyzer_custom_event_callback);
  92. view_dispatcher_set_event_callback_context(app_ctx->view_dispatcher, analyzer);
  93. analyzer->ir_receiver = xremote_signal_receiver_alloc(app_ctx);
  94. xremote_signal_receiver_set_context(analyzer->ir_receiver, analyzer, NULL);
  95. xremote_signal_receiver_set_rx_callback(
  96. analyzer->ir_receiver, xremote_signal_analyzer_signal_callback);
  97. return analyzer;
  98. }
  99. static void xremote_signal_analyzer_free(XRemoteSignalAnalyzer* analyzer) {
  100. xremote_app_assert_void(analyzer);
  101. xremote_signal_receiver_stop(analyzer->ir_receiver);
  102. ViewDispatcher* view_disp = analyzer->app_ctx->view_dispatcher;
  103. view_dispatcher_set_custom_event_callback(view_disp, NULL);
  104. view_dispatcher_set_event_callback_context(view_disp, NULL);
  105. view_dispatcher_remove_view(view_disp, XRemoteViewSignal);
  106. xremote_view_free(analyzer->signal_view);
  107. xremote_signal_receiver_free(analyzer->ir_receiver);
  108. infrared_signal_free(analyzer->ir_signal);
  109. free(analyzer);
  110. }
  111. static void xremote_signal_analyzer_clear_callback(void* context) {
  112. XRemoteSignalAnalyzer* analyzer = context;
  113. xremote_signal_analyzer_free(analyzer);
  114. }
  115. XRemoteApp* xremote_analyzer_alloc(XRemoteAppContext* app_ctx) {
  116. XRemoteApp* app = xremote_app_alloc(app_ctx);
  117. app->view_id = XRemoteViewAnalyzer;
  118. XRemoteSignalAnalyzer* analyzer = xremote_signal_analyzer_alloc(app_ctx);
  119. app->view_ctx = xremote_signal_view_alloc(app->app_ctx, analyzer);
  120. View* view = xremote_view_get_view(app->view_ctx);
  121. ViewDispatcher* view_disp = app_ctx->view_dispatcher;
  122. view_dispatcher_add_view(view_disp, app->view_id, view);
  123. xremote_app_view_set_previous_callback(app, xremote_signal_analyzer_view_exit_callback);
  124. xremote_app_set_view_context(app, analyzer, xremote_signal_analyzer_clear_callback);
  125. xremote_signal_receiver_start(analyzer->ir_receiver);
  126. return app;
  127. }