xremote_learn_view.c 9.0 KB

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