xremote_analyzer.c 5.9 KB

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