xremote_learn_view.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*!
  2. * @file flipper-xremote/views/xremote_learn_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 Learn new remote page view components and functionality.
  7. */
  8. #include "xremote_learn_view.h"
  9. #include "../xremote_learn.h"
  10. #include "../xremote_app.h"
  11. static void xremote_learn_view_draw_callback(Canvas* canvas, void* context) {
  12. furi_assert(context);
  13. XRemoteViewModel* model = context;
  14. XRemoteLearnContext* learn_ctx = model->context;
  15. XRemoteAppContext* app_ctx = xremote_learn_get_app_context(learn_ctx);
  16. const char* button_name = xremote_learn_get_curr_button_name(learn_ctx);
  17. ViewOrientation orientation = app_ctx->app_settings->orientation;
  18. xremote_canvas_draw_header(canvas, orientation, "Learn");
  19. char info_text[128];
  20. snprintf(
  21. info_text,
  22. sizeof(info_text),
  23. "Press\n\"%s\"\nbutton on\nthe remote.",
  24. button_name != NULL ? button_name : "");
  25. if(orientation == ViewOrientationHorizontal) {
  26. elements_multiline_text_aligned(canvas, 0, 12, AlignLeft, AlignTop, info_text);
  27. xremote_canvas_draw_button_wide(
  28. canvas, model->ok_pressed, 68, 22, "Finish", XRemoteIconEnter);
  29. xremote_canvas_draw_button_wide(
  30. canvas, model->right_pressed, 68, 40, "Skip", XRemoteIconArrowRight);
  31. } else {
  32. elements_multiline_text_aligned(canvas, 0, 30, AlignLeft, AlignTop, info_text);
  33. xremote_canvas_draw_button_wide(
  34. canvas, model->ok_pressed, 0, 82, "Finish", XRemoteIconEnter);
  35. xremote_canvas_draw_button_wide(
  36. canvas, model->right_pressed, 0, 100, "Skip", XRemoteIconArrowRight);
  37. }
  38. const char* exit_str = xremote_app_context_get_exit_str(app_ctx);
  39. xremote_canvas_draw_exit_footer(canvas, orientation, exit_str);
  40. }
  41. static void xremote_learn_success_view_draw_callback(Canvas* canvas, void* context) {
  42. furi_assert(context);
  43. XRemoteViewModel* model = context;
  44. XRemoteLearnContext* learn_ctx = model->context;
  45. XRemoteAppContext* app_ctx = xremote_learn_get_app_context(learn_ctx);
  46. InfraredSignal* ir_signal = xremote_learn_get_ir_signal(learn_ctx);
  47. xremote_canvas_draw_header(canvas, app_ctx->app_settings->orientation, NULL);
  48. const char* button_name = xremote_learn_get_curr_button_name(learn_ctx);
  49. char signal_info[128];
  50. if(infrared_signal_is_raw(ir_signal)) {
  51. InfraredRawSignal* raw = infrared_signal_get_raw_signal(ir_signal);
  52. snprintf(
  53. signal_info,
  54. sizeof(signal_info),
  55. "Name: %s\n"
  56. "Type: RAW\n"
  57. "T-Size: %u\n"
  58. "D-Cycle: %.2f\n",
  59. button_name,
  60. raw->timings_size,
  61. (double)raw->duty_cycle);
  62. } else {
  63. InfraredMessage* message = infrared_signal_get_message(ir_signal);
  64. const char* infrared_protocol = infrared_get_protocol_name(message->protocol);
  65. snprintf(
  66. signal_info,
  67. sizeof(signal_info),
  68. "Name: %s\n"
  69. "Proto: %s\n"
  70. "Addr: 0x%lX\n"
  71. "Cmd: 0x%lX\n",
  72. button_name,
  73. infrared_protocol,
  74. message->address,
  75. message->command);
  76. }
  77. if(app_ctx->app_settings->orientation == ViewOrientationHorizontal) {
  78. canvas_draw_str_aligned(canvas, 0, 0, AlignLeft, AlignTop, "Received signal");
  79. elements_multiline_text_aligned(canvas, 0, 16, AlignLeft, AlignTop, signal_info);
  80. xremote_canvas_draw_button_wide(
  81. canvas, model->ok_pressed, 68, 12, "Finish", XRemoteIconEnter);
  82. xremote_canvas_draw_button_wide(
  83. canvas, model->right_pressed, 68, 30, "Next", XRemoteIconArrowRight);
  84. xremote_canvas_draw_button_wide(
  85. canvas, model->back_pressed, 68, 48, "Retry", XRemoteIconBack);
  86. } else {
  87. canvas_draw_str_aligned(canvas, 0, 12, AlignLeft, AlignTop, "Received signal");
  88. elements_multiline_text_aligned(canvas, 0, 27, AlignLeft, AlignTop, signal_info);
  89. xremote_canvas_draw_button_wide(
  90. canvas, model->ok_pressed, 0, 76, "Finish", XRemoteIconEnter);
  91. xremote_canvas_draw_button_wide(
  92. canvas, model->right_pressed, 0, 94, "Next", XRemoteIconArrowRight);
  93. xremote_canvas_draw_button_wide(
  94. canvas, model->back_pressed, 0, 112, "Retry", XRemoteIconBack);
  95. }
  96. }
  97. static void xremote_learn_success_view_process(XRemoteView* view, InputEvent* event) {
  98. with_view_model(
  99. xremote_view_get_view(view),
  100. XRemoteViewModel * model,
  101. {
  102. XRemoteLearnContext* learn_ctx = xremote_view_get_context(view);
  103. model->context = learn_ctx;
  104. if(event->type == InputTypePress) {
  105. if(event->key == InputKeyOk) {
  106. model->ok_pressed = true;
  107. xremote_learn_send_event(learn_ctx, XRemoteEventSignalFinish);
  108. } else if(event->key == InputKeyBack) {
  109. model->back_pressed = true;
  110. xremote_learn_send_event(learn_ctx, XRemoteEventSignalRetry);
  111. } else if(event->key == InputKeyRight) {
  112. model->right_pressed = true;
  113. xremote_learn_send_event(learn_ctx, XRemoteEventSignalSave);
  114. }
  115. } else if(event->type == InputTypeRelease) {
  116. if(event->key == InputKeyOk)
  117. model->ok_pressed = false;
  118. else if(event->key == InputKeyBack)
  119. model->back_pressed = false;
  120. else if(event->key == InputKeyRight)
  121. model->right_pressed = false;
  122. }
  123. },
  124. true);
  125. }
  126. static void xremote_learn_view_process(XRemoteView* view, InputEvent* event) {
  127. with_view_model(
  128. xremote_view_get_view(view),
  129. XRemoteViewModel * model,
  130. {
  131. XRemoteLearnContext* learn_ctx = xremote_view_get_context(view);
  132. XRemoteAppContext* app_ctx = xremote_view_get_app_context(view);
  133. XRemoteAppExit exit = app_ctx->app_settings->exit_behavior;
  134. model->context = learn_ctx;
  135. if(event->type == InputTypePress) {
  136. if(event->key == InputKeyOk && xremote_learn_has_buttons(learn_ctx)) {
  137. model->ok_pressed = true;
  138. xremote_learn_send_event(learn_ctx, XRemoteEventSignalFinish);
  139. } else if(event->key == InputKeyRight) {
  140. model->right_pressed = true;
  141. xremote_learn_send_event(learn_ctx, XRemoteEventSignalSkip);
  142. }
  143. } else if(
  144. (event->type == InputTypeShort || event->type == InputTypeLong) &&
  145. event->key == InputKeyBack) {
  146. if((event->type == InputTypeShort && exit == XRemoteAppExitPress) ||
  147. (event->type == InputTypeLong && exit == XRemoteAppExitHold)) {
  148. model->back_pressed = true;
  149. xremote_learn_send_event(learn_ctx, XRemoteEventSignalAskExit);
  150. }
  151. } else if(event->type == InputTypeRelease) {
  152. if(event->key == InputKeyOk)
  153. model->ok_pressed = false;
  154. else if(event->key == InputKeyBack)
  155. model->back_pressed = false;
  156. else if(event->key == InputKeyRight)
  157. model->right_pressed = false;
  158. }
  159. },
  160. true);
  161. }
  162. static bool xremote_learn_success_view_input_callback(InputEvent* event, void* context) {
  163. furi_assert(context);
  164. XRemoteView* view = (XRemoteView*)context;
  165. xremote_learn_success_view_process(view, event);
  166. return true;
  167. }
  168. static bool xremote_learn_view_input_callback(InputEvent* event, void* context) {
  169. furi_assert(context);
  170. XRemoteView* view = (XRemoteView*)context;
  171. xremote_learn_view_process(view, event);
  172. return true;
  173. }
  174. XRemoteView* xremote_learn_success_view_alloc(void* app_ctx, void* learn_ctx) {
  175. XRemoteView* view = xremote_view_alloc(
  176. app_ctx,
  177. xremote_learn_success_view_input_callback,
  178. xremote_learn_success_view_draw_callback);
  179. xremote_view_set_context(view, learn_ctx, NULL);
  180. with_view_model(
  181. xremote_view_get_view(view),
  182. XRemoteViewModel * model,
  183. {
  184. model->context = learn_ctx;
  185. model->right_pressed = false;
  186. model->back_pressed = false;
  187. model->ok_pressed = false;
  188. },
  189. true);
  190. return view;
  191. }
  192. XRemoteView* xremote_learn_view_alloc(void* app_ctx, void* learn_ctx) {
  193. XRemoteView* view = xremote_view_alloc(
  194. app_ctx, xremote_learn_view_input_callback, xremote_learn_view_draw_callback);
  195. xremote_view_set_context(view, learn_ctx, NULL);
  196. with_view_model(
  197. xremote_view_get_view(view),
  198. XRemoteViewModel * model,
  199. {
  200. model->context = learn_ctx;
  201. model->right_pressed = false;
  202. model->back_pressed = false;
  203. model->ok_pressed = false;
  204. },
  205. true);
  206. return view;
  207. }