dtmf_dolphin_dialer.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. #include "dtmf_dolphin_dialer.h"
  2. #include <gui/elements.h>
  3. typedef struct DTMFDolphinDialer {
  4. View* view;
  5. DTMFDolphinDialerOkCallback callback;
  6. void* context;
  7. } DTMFDolphinDialer;
  8. typedef struct {
  9. uint8_t row;
  10. uint8_t col;
  11. float *freq;
  12. } DTMFDolphinDialerModel;
  13. static bool dtmf_dolphin_dialer_process_up(DTMFDolphinDialer* dtmf_dolphin_dialer);
  14. static bool dtmf_dolphin_dialer_process_down(DTMFDolphinDialer* dtmf_dolphin_dialer);
  15. static bool dtmf_dolphin_dialer_process_left(DTMFDolphinDialer* dtmf_dolphin_dialer);
  16. static bool dtmf_dolphin_dialer_process_right(DTMFDolphinDialer* dtmf_dolphin_dialer);
  17. static bool dtmf_dolphin_dialer_process_ok(DTMFDolphinDialer* dtmf_dolphin_dialer, InputEvent* event);
  18. void draw_button(Canvas* canvas, uint8_t row, uint8_t col, bool invert) {
  19. uint8_t left = DTMF_DOLPHIN_NUMPAD_X + \
  20. // ((col + 1) * DTMF_DOLPHIN_BUTTON_PADDING) +
  21. (col * DTMF_DOLPHIN_BUTTON_WIDTH);
  22. // (col * DTMF_DOLPHIN_BUTTON_PADDING);
  23. uint8_t top = DTMF_DOLPHIN_NUMPAD_Y + \
  24. // ((row + 1) * DTMF_DOLPHIN_BUTTON_PADDING) +
  25. (row * DTMF_DOLPHIN_BUTTON_HEIGHT);
  26. // (row * DTMF_DOLPHIN_BUTTON_PADDING);
  27. uint8_t span = dtmf_dolphin_get_tone_span(row, col, DTMF_DOLPHIN_TONE_BLOCK_DIALER);
  28. canvas_set_color(canvas, ColorBlack);
  29. if (invert)
  30. canvas_draw_rbox(canvas, left, top,
  31. (DTMF_DOLPHIN_BUTTON_WIDTH * span) - (DTMF_DOLPHIN_BUTTON_PADDING * 2),
  32. DTMF_DOLPHIN_BUTTON_HEIGHT - (DTMF_DOLPHIN_BUTTON_PADDING * 2),
  33. 2);
  34. else
  35. canvas_draw_rframe(canvas, left, top,
  36. (DTMF_DOLPHIN_BUTTON_WIDTH * span) - (DTMF_DOLPHIN_BUTTON_PADDING * 2),
  37. DTMF_DOLPHIN_BUTTON_HEIGHT- (DTMF_DOLPHIN_BUTTON_PADDING * 2),
  38. 2);
  39. if (invert)
  40. canvas_invert_color(canvas);
  41. canvas_set_font(canvas, FontSecondary);
  42. // canvas_set_color(canvas, invert ? ColorWhite : ColorBlack);
  43. canvas_draw_str_aligned(canvas,
  44. left - 1 + (int) ((DTMF_DOLPHIN_BUTTON_WIDTH * span) / 2),
  45. top + (int) (DTMF_DOLPHIN_BUTTON_HEIGHT / 2),
  46. AlignCenter,
  47. AlignCenter,
  48. dtmf_dolphin_get_tone_name(row, col, DTMF_DOLPHIN_TONE_BLOCK_DIALER));
  49. if (invert)
  50. canvas_invert_color(canvas);
  51. }
  52. void draw_dialer(Canvas* canvas, void* _model) {
  53. DTMFDolphinDialerModel* model = _model;
  54. uint8_t max_rows;
  55. uint8_t max_cols;
  56. uint8_t max_span;
  57. dtmf_dolphin_tone_get_max_pos(&max_rows, &max_cols, &max_span, DTMF_DOLPHIN_TONE_BLOCK_DIALER);
  58. canvas_set_font(canvas, FontSecondary);
  59. for (int r = 0; r < max_rows; r++) {
  60. for (int c = 0; c < max_cols; c++) {
  61. if (model->row == r && model->col == c)
  62. draw_button(canvas, r, c, true);
  63. else
  64. draw_button(canvas, r, c, false);
  65. }
  66. }
  67. }
  68. void update_frequencies(DTMFDolphinDialerModel *model) {
  69. dtmf_dolphin_get_tone_frequencies(model->freq, model->row, model->col, DTMF_DOLPHIN_TONE_BLOCK_DIALER);
  70. }
  71. static void dtmf_dolphin_dialer_draw_callback(Canvas* canvas, void* _model) {
  72. DTMFDolphinDialerModel* model = _model;
  73. uint8_t max_rows;
  74. uint8_t max_cols;
  75. uint8_t max_span;
  76. dtmf_dolphin_tone_get_max_pos(&max_rows, &max_cols, &max_span, DTMF_DOLPHIN_TONE_BLOCK_DIALER);
  77. canvas_set_font(canvas, FontPrimary);
  78. elements_multiline_text(canvas, 2, 10, "Dialer");
  79. canvas_draw_line(canvas,
  80. (max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 1, 0,
  81. (max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 1, canvas_height(canvas));
  82. elements_multiline_text(canvas, (max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 4, 10, "Detail");
  83. canvas_draw_line(canvas, 0, DTMF_DOLPHIN_NUMPAD_Y - 3, canvas_width(canvas), DTMF_DOLPHIN_NUMPAD_Y - 3);
  84. // elements_multiline_text_aligned(canvas, 64, 2, AlignCenter, AlignTop, "Dialer Mode");
  85. draw_dialer(canvas, model);
  86. string_t output;
  87. string_init(output);
  88. string_cat_printf(
  89. output,
  90. "F1: %u Hz\nF2: %u Hz",
  91. model->freq[0] ? (unsigned int) model->freq[0] : 0,
  92. model->freq[1] ? (unsigned int) model->freq[1] : 0);
  93. canvas_set_font(canvas, FontSecondary);
  94. canvas_set_color(canvas, ColorBlack);
  95. elements_multiline_text(canvas, (max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 4, 21, string_get_cstr(output));
  96. string_clear(output);
  97. }
  98. static bool dtmf_dolphin_dialer_input_callback(InputEvent* event, void* context) {
  99. furi_assert(context);
  100. DTMFDolphinDialer* dtmf_dolphin_dialer = context;
  101. bool consumed = false;
  102. if(event->type == InputTypeShort) {
  103. if(event->key == InputKeyRight) {
  104. consumed = dtmf_dolphin_dialer_process_right(dtmf_dolphin_dialer);
  105. } else if(event->key == InputKeyLeft) {
  106. consumed = dtmf_dolphin_dialer_process_left(dtmf_dolphin_dialer);
  107. } else if(event->key == InputKeyUp) {
  108. consumed = dtmf_dolphin_dialer_process_up(dtmf_dolphin_dialer);
  109. } else if(event->key == InputKeyDown) {
  110. consumed = dtmf_dolphin_dialer_process_down(dtmf_dolphin_dialer);
  111. }
  112. } else if(event->key == InputKeyOk) {
  113. consumed = dtmf_dolphin_dialer_process_ok(dtmf_dolphin_dialer, event);
  114. }
  115. return consumed;
  116. }
  117. static bool dtmf_dolphin_dialer_process_up(DTMFDolphinDialer* dtmf_dolphin_dialer) {
  118. with_view_model(
  119. dtmf_dolphin_dialer->view, (DTMFDolphinDialerModel * model) {
  120. if(model->row > 0) {
  121. model->row--;
  122. update_frequencies(model);
  123. }
  124. return true;
  125. });
  126. return true;
  127. }
  128. static bool dtmf_dolphin_dialer_process_down(DTMFDolphinDialer* dtmf_dolphin_dialer) {
  129. uint8_t max_rows = 0;
  130. uint8_t max_cols = 0;
  131. uint8_t max_span = 0;
  132. dtmf_dolphin_tone_get_max_pos(&max_rows, &max_cols, &max_span, DTMF_DOLPHIN_TONE_BLOCK_DIALER);
  133. with_view_model(
  134. dtmf_dolphin_dialer->view, (DTMFDolphinDialerModel * model) {
  135. if(model->row < max_rows - 1) {
  136. model->row++;
  137. update_frequencies(model);
  138. }
  139. return true;
  140. });
  141. return true;
  142. }
  143. static bool dtmf_dolphin_dialer_process_left(DTMFDolphinDialer* dtmf_dolphin_dialer) {
  144. with_view_model(
  145. dtmf_dolphin_dialer->view, (DTMFDolphinDialerModel * model) {
  146. if(model->col > 0) {
  147. model->col--;
  148. update_frequencies(model);
  149. }
  150. return true;
  151. });
  152. return true;
  153. }
  154. static bool dtmf_dolphin_dialer_process_right(DTMFDolphinDialer* dtmf_dolphin_dialer) {
  155. uint8_t max_rows = 0;
  156. uint8_t max_cols = 0;
  157. uint8_t max_span = 0;
  158. dtmf_dolphin_tone_get_max_pos(&max_rows, &max_cols, &max_span, DTMF_DOLPHIN_TONE_BLOCK_DIALER);
  159. with_view_model(
  160. dtmf_dolphin_dialer->view, (DTMFDolphinDialerModel * model) {
  161. if(model->col < max_cols - 1) {
  162. model->col++;
  163. update_frequencies(model);
  164. }
  165. return true;
  166. });
  167. return true;
  168. }
  169. static bool dtmf_dolphin_dialer_process_ok(DTMFDolphinDialer* dtmf_dolphin_dialer, InputEvent* event) {
  170. bool consumed = false;
  171. with_view_model(
  172. dtmf_dolphin_dialer->view, (DTMFDolphinDialerModel * model) {
  173. if (event->type == InputTypePress) {
  174. dtmf_dolphin_player_play_tones(model->freq);
  175. } else if (event->type == InputTypeRelease) {
  176. dtmf_dolphin_player_stop_tones();
  177. }
  178. return true;
  179. });
  180. return consumed;
  181. }
  182. DTMFDolphinDialer* dtmf_dolphin_dialer_alloc() {
  183. DTMFDolphinDialer* dtmf_dolphin_dialer = malloc(sizeof(DTMFDolphinDialer));
  184. dtmf_dolphin_dialer->view = view_alloc();
  185. view_allocate_model(dtmf_dolphin_dialer->view, ViewModelTypeLocking, sizeof(DTMFDolphinDialerModel));
  186. with_view_model(
  187. dtmf_dolphin_dialer->view, (DTMFDolphinDialerModel * model) {
  188. model->col = 0;
  189. model->row = 0;
  190. model->freq = malloc(sizeof(float) * 2);
  191. update_frequencies(model);
  192. return true;
  193. }
  194. );
  195. view_set_context(dtmf_dolphin_dialer->view, dtmf_dolphin_dialer);
  196. view_set_draw_callback(dtmf_dolphin_dialer->view, dtmf_dolphin_dialer_draw_callback);
  197. view_set_input_callback(dtmf_dolphin_dialer->view, dtmf_dolphin_dialer_input_callback);
  198. return dtmf_dolphin_dialer;
  199. }
  200. void dtmf_dolphin_dialer_free(DTMFDolphinDialer* dtmf_dolphin_dialer) {
  201. furi_assert(dtmf_dolphin_dialer);
  202. with_view_model(
  203. dtmf_dolphin_dialer->view, (DTMFDolphinDialerModel * model) {
  204. free(model->freq);
  205. return true;
  206. }
  207. );
  208. view_free(dtmf_dolphin_dialer->view);
  209. free(dtmf_dolphin_dialer);
  210. }
  211. View* dtmf_dolphin_dialer_get_view(DTMFDolphinDialer* dtmf_dolphin_dialer) {
  212. furi_assert(dtmf_dolphin_dialer);
  213. return dtmf_dolphin_dialer->view;
  214. }
  215. // void dtmf_dolphin_dialer_set_ok_callback(DTMFDolphinDialer* dtmf_dolphin_dialer, DTMFDolphinDialerOkCallback callback, void* context) {
  216. // furi_assert(dtmf_dolphin_dialer);
  217. // furi_assert(callback);
  218. // with_view_model(
  219. // dtmf_dolphin_dialer->view, (DTMFDolphinDialerModel * model) {
  220. // UNUSED(model);
  221. // dtmf_dolphin_dialer->callback = callback;
  222. // dtmf_dolphin_dialer->context = context;
  223. // return false;
  224. // });
  225. // }