xremote_analyzer.c 5.9 KB

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