hid_ptt.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. #include "hid_ptt.h"
  2. #include <gui/elements.h>
  3. #include <notification/notification_messages.h>
  4. #include "../hid.h"
  5. #include "../views.h"
  6. #include "hid_icons.h"
  7. #define TAG "HidPtt"
  8. struct HidPtt {
  9. View* view;
  10. Hid* hid;
  11. };
  12. typedef struct {
  13. bool left_pressed;
  14. bool up_pressed;
  15. bool right_pressed;
  16. bool down_pressed;
  17. bool muted;
  18. bool ptt_pressed;
  19. bool mic_pressed;
  20. bool connected;
  21. bool is_mac_os;
  22. uint32_t appIndex;
  23. HidTransport transport;
  24. } HidPttModel;
  25. enum HidPttAppIndex {
  26. HidPttAppIndexGoogleMeet,
  27. HidPttAppIndexZoom,
  28. HidPttAppIndexFaceTime,
  29. HidPttAppIndexSkype,
  30. HidPttAppIndexSize,
  31. };
  32. static void hid_ptt_draw_callback(Canvas* canvas, void* context) {
  33. furi_assert(context);
  34. HidPttModel* model = context;
  35. // Header
  36. canvas_set_font(canvas, FontPrimary);
  37. if(model->transport == HidTransportBle) {
  38. if(model->connected) {
  39. canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
  40. } else {
  41. canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
  42. }
  43. }
  44. // App selection
  45. const uint8_t y_app = 78;
  46. canvas_set_font(canvas, FontSecondary);
  47. canvas_draw_icon(canvas, 0, y_app, &I_ButtonLeft_4x7);
  48. if(model->appIndex == HidPttAppIndexGoogleMeet) {
  49. elements_multiline_text_aligned(canvas, 7, y_app, AlignLeft, AlignTop, "Google Meet");
  50. } else if(model->appIndex == HidPttAppIndexZoom) {
  51. elements_multiline_text_aligned(canvas, 7, y_app, AlignLeft, AlignTop, "Zoom");
  52. } else if(model->appIndex == HidPttAppIndexFaceTime) {
  53. elements_multiline_text_aligned(canvas, 7, y_app, AlignLeft, AlignTop, "FaceTime");
  54. } else if(model->appIndex == HidPttAppIndexSkype) {
  55. elements_multiline_text_aligned(canvas, 7, y_app, AlignLeft, AlignTop, "Skype");
  56. }
  57. canvas_draw_icon(canvas, 60, y_app, &I_ButtonRight_4x7);
  58. // OS selection
  59. const uint8_t y_os = 88;
  60. const uint8_t x_os = 7;
  61. // elements_slightly_rounded_box(canvas, model->is_mac_os ? 0 : 26, y_os, model->is_mac_os ? 21 : 26, 11);
  62. elements_slightly_rounded_box(canvas, model->is_mac_os ? x_os : x_os + 26, y_os, model->is_mac_os ? 21 : 26, 11);
  63. canvas_set_color(canvas, model->is_mac_os ? ColorWhite : ColorBlack);
  64. elements_multiline_text_aligned(canvas, x_os + 2, y_os + 1, AlignLeft, AlignTop, "Mac");
  65. canvas_set_color(canvas, ColorBlack);
  66. if (model->appIndex != HidPttAppIndexFaceTime) {
  67. elements_multiline_text_aligned(canvas, x_os + 23, y_os + 2, AlignLeft, AlignTop, "|");
  68. canvas_set_color(canvas, model->is_mac_os ? ColorBlack : ColorWhite);
  69. elements_multiline_text_aligned(canvas, x_os + 28, y_os + 2, AlignLeft, AlignTop, "Linux");
  70. canvas_set_color(canvas, ColorBlack);
  71. }
  72. // Mic label
  73. const uint8_t y_mic = 102;
  74. canvas_draw_icon(canvas, 19, y_mic - 1, &I_Pin_back_arrow_rotated_8x10);
  75. elements_multiline_text_aligned(canvas, 0, y_mic, AlignLeft, AlignTop, "Hold to sync");
  76. elements_multiline_text_aligned(canvas, 20, y_mic+10, AlignLeft, AlignTop, "mic status");
  77. // Exit label
  78. canvas_draw_icon(canvas, 20, 121, &I_ButtonLeft_4x7);
  79. elements_multiline_text_aligned(canvas, 0, 121, AlignLeft, AlignTop, "Hold to exit");
  80. const uint8_t x_1 = 0;
  81. const uint8_t x_2 = x_1 + 19 + 4;
  82. const uint8_t x_3 = x_1 + 19 * 2 + 8;
  83. const uint8_t y_1 = 19;
  84. const uint8_t y_2 = y_1 + 19;
  85. const uint8_t y_3 = y_2 + 19;
  86. // Up
  87. canvas_draw_icon(canvas, x_2, y_1, &I_Button_18x18);
  88. if(model->up_pressed) {
  89. elements_slightly_rounded_box(canvas, x_2 + 3, y_1 + 2, 13, 13);
  90. canvas_set_color(canvas, ColorWhite);
  91. }
  92. if(model->ptt_pressed) {
  93. if (model->appIndex != HidPttAppIndexFaceTime) {
  94. elements_multiline_text_aligned(canvas, x_2 + 4, y_1 + 5, AlignLeft, AlignTop, "OS");
  95. }
  96. } else {
  97. canvas_draw_icon(canvas, x_2 + 5, y_1 + 5, &I_Volup_8x6);
  98. }
  99. canvas_set_color(canvas, ColorBlack);
  100. // Down
  101. canvas_draw_icon(canvas, x_2, y_3, &I_Button_18x18);
  102. if(model->down_pressed) {
  103. elements_slightly_rounded_box(canvas, x_2 + 3, y_3 + 2, 13, 13);
  104. canvas_set_color(canvas, ColorWhite);
  105. }
  106. if(!model->ptt_pressed) {
  107. canvas_draw_icon(canvas, x_2 + 6, y_3 + 5, &I_Voldwn_6x6);
  108. }
  109. canvas_set_color(canvas, ColorBlack);
  110. // Left
  111. canvas_draw_icon(canvas, x_1, y_2, &I_Button_18x18);
  112. if(model->left_pressed) {
  113. elements_slightly_rounded_box(canvas, x_1 + 3, y_2 + 2, 13, 13);
  114. canvas_set_color(canvas, ColorWhite);
  115. }
  116. if (model->ptt_pressed) {
  117. canvas_draw_icon(canvas, x_1 + 7, y_2 + 5, &I_ButtonLeft_4x7);
  118. } else {
  119. canvas_draw_icon(canvas, x_1 + 4, y_2 + 5, &I_Pin_back_arrow_10x8);
  120. }
  121. canvas_set_color(canvas, ColorBlack);
  122. // Right / Camera
  123. canvas_draw_icon(canvas, x_3, y_2, &I_Button_18x18);
  124. if(model->right_pressed) {
  125. elements_slightly_rounded_box(canvas, x_3 + 3, y_2 + 2, 13, 13);
  126. canvas_set_color(canvas, ColorWhite);
  127. }
  128. if(!model->ptt_pressed) {
  129. if (model->appIndex != HidPttAppIndexFaceTime) {
  130. canvas_draw_icon(canvas, x_3 + 11, y_2 + 5, &I_ButtonLeft_4x7);
  131. canvas_draw_box(canvas, x_3 + 4, y_2 + 5, 7, 7);
  132. }
  133. } else {
  134. canvas_draw_icon(canvas, x_3 + 8, y_2 + 5, &I_ButtonRight_4x7);
  135. }
  136. canvas_set_color(canvas, ColorBlack);
  137. // Back / Mic
  138. const uint8_t x_mic = x_3;
  139. canvas_draw_icon(canvas, x_mic, 0, &I_Button_18x18);
  140. if(model->mic_pressed) {
  141. elements_slightly_rounded_box(canvas, x_mic + 3, 0 + 2, 13, 13);
  142. canvas_set_color(canvas, ColorWhite);
  143. }
  144. canvas_draw_icon(canvas, x_mic + 5, 0 + 4, &I_Mic_btn_8x10);
  145. if(model->muted && !model->ptt_pressed) {
  146. canvas_draw_line(canvas, x_mic + 3, 2 , x_mic + 3 + 13, 2 + 13);
  147. canvas_draw_line(canvas, x_mic + 2, 2 , x_mic + 2 + 13, 2 + 13);
  148. canvas_draw_line(canvas, x_mic + 3, 2 + 13, x_mic + 3 + 13, 2);
  149. canvas_draw_line(canvas, x_mic + 2, 2 + 13, x_mic + 2 + 13, 2);
  150. }
  151. canvas_set_color(canvas, ColorBlack);
  152. // Ok / PTT
  153. const uint8_t x_ptt_margin = 4;
  154. const uint8_t x_ptt_width = 17;
  155. const uint8_t x_ptt = x_1 + 19;
  156. canvas_draw_icon(canvas, x_ptt , y_2 , &I_BtnFrameLeft_3x18);
  157. canvas_draw_icon(canvas, x_ptt + x_ptt_width + 3 + x_ptt_margin, y_2 , &I_BtnFrameRight_2x18);
  158. canvas_draw_line(canvas, x_ptt + 3 , y_2 , x_ptt + x_ptt_width + 2 + x_ptt_margin, y_2);
  159. canvas_draw_line(canvas, x_ptt + 3 , y_2 + 16, x_ptt + x_ptt_width + 2 + x_ptt_margin, y_2 + 16);
  160. canvas_draw_line(canvas, x_ptt + 3 , y_2 + 17, x_ptt + x_ptt_width + 2 + x_ptt_margin, y_2 + 17);
  161. if(model->ptt_pressed) {
  162. elements_slightly_rounded_box(canvas, x_ptt + 3, y_2 + 2, x_ptt_width + x_ptt_margin, 13);
  163. canvas_set_color(canvas, ColorWhite);
  164. }
  165. canvas_set_font(canvas, FontPrimary);
  166. elements_multiline_text_aligned(canvas, x_ptt + 2 + x_ptt_margin / 2, y_2 + 13, AlignLeft, AlignBottom, "PTT");
  167. canvas_set_font(canvas, FontSecondary);
  168. }
  169. static void hid_ptt_trigger_mute(HidPtt* hid_ptt, HidPttModel * model) {
  170. if(model->appIndex == HidPttAppIndexGoogleMeet && model->is_mac_os) {
  171. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI | HID_KEYBOARD_D);
  172. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI | HID_KEYBOARD_D );
  173. } else if(model->appIndex == HidPttAppIndexGoogleMeet && !model->is_mac_os) {
  174. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_D);
  175. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_D );
  176. } else if(model->appIndex == HidPttAppIndexZoom && model->is_mac_os) {
  177. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_A);
  178. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_A );
  179. } else if(model->appIndex == HidPttAppIndexFaceTime) {
  180. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M);
  181. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M );
  182. } else if(model->appIndex == HidPttAppIndexSkype && model->is_mac_os) {
  183. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M);
  184. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M );
  185. } else if(model->appIndex == HidPttAppIndexSkype && !model->is_mac_os) {
  186. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_M);
  187. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_M );
  188. }
  189. }
  190. static void hid_ptt_trigger_camera(HidPtt* hid_ptt, HidPttModel * model) {
  191. if(model->appIndex == HidPttAppIndexGoogleMeet && model->is_mac_os) {
  192. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI | HID_KEYBOARD_E);
  193. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI | HID_KEYBOARD_E );
  194. } else if(model->appIndex == HidPttAppIndexGoogleMeet && !model->is_mac_os) {
  195. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_E);
  196. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_E );
  197. } else if(model->appIndex == HidPttAppIndexZoom && model->is_mac_os) {
  198. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_V);
  199. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_V );
  200. } else if(model->appIndex == HidPttAppIndexZoom && !model->is_mac_os) {
  201. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_ALT | HID_KEYBOARD_V);
  202. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_ALT | HID_KEYBOARD_V );
  203. } else if(model->appIndex == HidPttAppIndexSkype && model->is_mac_os) {
  204. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_K);
  205. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_K );
  206. } else if(model->appIndex == HidPttAppIndexSkype && !model->is_mac_os) {
  207. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_K);
  208. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_K );
  209. }
  210. }
  211. static void hid_ptt_start_ptt(HidPtt* hid_ptt, HidPttModel * model) {
  212. if(model->appIndex == HidPttAppIndexGoogleMeet) {
  213. hid_hal_keyboard_press(hid_ptt->hid, HID_KEYBOARD_SPACEBAR);
  214. } else if(model->appIndex == HidPttAppIndexZoom) {
  215. hid_hal_keyboard_press(hid_ptt->hid, HID_KEYBOARD_SPACEBAR);
  216. } else if(model->appIndex == HidPttAppIndexFaceTime) {
  217. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M);
  218. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M );
  219. } else if(model->appIndex == HidPttAppIndexSkype && model->is_mac_os) {
  220. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M);
  221. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M );
  222. } else if(model->appIndex == HidPttAppIndexSkype && !model->is_mac_os) {
  223. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_M);
  224. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_M );
  225. }
  226. }
  227. static void hid_ptt_stop_ptt(HidPtt* hid_ptt, HidPttModel * model) {
  228. if(model->appIndex == HidPttAppIndexGoogleMeet) {
  229. hid_hal_keyboard_release(hid_ptt->hid, HID_KEYBOARD_SPACEBAR);
  230. } else if(model->appIndex == HidPttAppIndexZoom) {
  231. hid_hal_keyboard_release(hid_ptt->hid, HID_KEYBOARD_SPACEBAR);
  232. } else if(model->appIndex == HidPttAppIndexFaceTime) {
  233. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M);
  234. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M );
  235. } else if(model->appIndex == HidPttAppIndexSkype && model->is_mac_os) {
  236. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M);
  237. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M );
  238. } else if(model->appIndex == HidPttAppIndexSkype && !model->is_mac_os) {
  239. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_M);
  240. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_M );
  241. }
  242. }
  243. // Supports only ±1
  244. static void hid_ptt_shift_app(HidPttModel * model, int shift) {
  245. int i = (short) model->appIndex;
  246. if (i + shift >= HidPttAppIndexSize) {
  247. model->appIndex = 0;
  248. } else if(i + shift <= 0) {
  249. model->appIndex = HidPttAppIndexSize - 1;
  250. } else {
  251. model->appIndex += shift;
  252. }
  253. // Avoid showing facetime if not macos
  254. if (model->appIndex == HidPttAppIndexFaceTime && !model->is_mac_os) {
  255. hid_ptt_shift_app(model, shift);
  256. }
  257. }
  258. static void hid_ptt_process(HidPtt* hid_ptt, InputEvent* event) {
  259. with_view_model(
  260. hid_ptt->view,
  261. HidPttModel * model,
  262. {
  263. if(event->type == InputTypePress) {
  264. if(event->key == InputKeyUp) {
  265. model->up_pressed = true;
  266. if (!model->ptt_pressed){
  267. hid_hal_consumer_key_press(hid_ptt->hid, HID_CONSUMER_VOLUME_INCREMENT);
  268. } else {
  269. if (model->appIndex != HidPttAppIndexFaceTime) {
  270. model->is_mac_os = !model->is_mac_os;
  271. notification_message(hid_ptt->hid->notifications, &sequence_single_vibro);
  272. }
  273. }
  274. } else if(event->key == InputKeyDown) {
  275. model->down_pressed = true;
  276. if (!model->ptt_pressed){
  277. hid_hal_consumer_key_press(hid_ptt->hid, HID_CONSUMER_VOLUME_DECREMENT);
  278. } else {
  279. hid_ptt_shift_app(model, - 1);
  280. notification_message(hid_ptt->hid->notifications, &sequence_single_vibro);
  281. }
  282. } else if(event->key == InputKeyLeft) {
  283. model->left_pressed = true;
  284. if (model->ptt_pressed){
  285. hid_ptt_shift_app(model, 1);
  286. notification_message(hid_ptt->hid->notifications, &sequence_single_vibro);
  287. }
  288. } else if(event->key == InputKeyRight) {
  289. model->right_pressed = true;
  290. if (model->ptt_pressed){
  291. hid_ptt_shift_app(model, - 1);
  292. notification_message(hid_ptt->hid->notifications, &sequence_single_vibro);
  293. }
  294. } else if(event->key == InputKeyOk) {
  295. model->ptt_pressed = true;
  296. if (model->muted) {
  297. hid_ptt_start_ptt(hid_ptt, model);
  298. }
  299. } else if(event->key == InputKeyBack) {
  300. model->mic_pressed = true;
  301. }
  302. } else if(event->type == InputTypeRelease) {
  303. if(event->key == InputKeyUp) {
  304. model->up_pressed = false;
  305. if (!model->ptt_pressed){
  306. hid_hal_consumer_key_release(hid_ptt->hid, HID_CONSUMER_VOLUME_INCREMENT);
  307. }
  308. } else if(event->key == InputKeyDown) {
  309. model->down_pressed = false;
  310. if (!model->ptt_pressed){
  311. hid_hal_consumer_key_release(hid_ptt->hid, HID_CONSUMER_VOLUME_DECREMENT);
  312. }
  313. } else if(event->key == InputKeyLeft) {
  314. model->left_pressed = false;
  315. } else if(event->key == InputKeyRight) {
  316. model->right_pressed = false;
  317. } else if(event->key == InputKeyOk) {
  318. model->ptt_pressed = false;
  319. if (model->muted) {
  320. hid_ptt_stop_ptt(hid_ptt, model);
  321. } else {
  322. hid_ptt_trigger_mute(hid_ptt, model);
  323. model->muted = true;
  324. }
  325. } else if(event->key == InputKeyBack) {
  326. model->mic_pressed = false;
  327. }
  328. } else if(event->type == InputTypeShort) {
  329. if(event->key == InputKeyBack && !model->ptt_pressed ) { // no changes if PTT is pressed
  330. model->muted = !model->muted;
  331. hid_ptt_trigger_mute(hid_ptt, model);
  332. } else if(event->key == InputKeyRight) {
  333. if (!model->ptt_pressed){
  334. hid_ptt_trigger_camera(hid_ptt, model);
  335. }
  336. }
  337. } else if(event->type == InputTypeLong) {
  338. if(event->key == InputKeyLeft) {
  339. model->left_pressed = false;
  340. if (!model->ptt_pressed){
  341. hid_hal_keyboard_release_all(hid_ptt->hid);
  342. view_dispatcher_switch_to_view(hid_ptt->hid->view_dispatcher, HidViewSubmenu);
  343. // sequence_double_vibro to notify that we quit PTT
  344. notification_message(hid_ptt->hid->notifications, &sequence_double_vibro);
  345. }
  346. } else if(event->key == InputKeyBack && !model->ptt_pressed ) { // no changes if PTT is pressed
  347. // Change local mic status
  348. model->muted = !model->muted;
  349. notification_message(hid_ptt->hid->notifications, &sequence_single_vibro);
  350. }
  351. }
  352. //LED
  353. if (model->muted && !model->ptt_pressed) {
  354. notification_message(hid_ptt->hid->notifications, &sequence_reset_red);
  355. } else {
  356. notification_message(hid_ptt->hid->notifications, &sequence_set_red_255);
  357. }
  358. },
  359. true);
  360. }
  361. static bool hid_ptt_input_callback(InputEvent* event, void* context) {
  362. furi_assert(context);
  363. HidPtt* hid_ptt = context;
  364. bool consumed = true;
  365. hid_ptt_process(hid_ptt, event);
  366. return consumed;
  367. }
  368. HidPtt* hid_ptt_alloc(Hid* hid) {
  369. HidPtt* hid_ptt = malloc(sizeof(HidPtt));
  370. hid_ptt->view = view_alloc();
  371. hid_ptt->hid = hid;
  372. view_set_context(hid_ptt->view, hid_ptt);
  373. view_allocate_model(hid_ptt->view, ViewModelTypeLocking, sizeof(HidPttModel));
  374. view_set_draw_callback(hid_ptt->view, hid_ptt_draw_callback);
  375. view_set_input_callback(hid_ptt->view, hid_ptt_input_callback);
  376. view_set_orientation(hid_ptt->view, ViewOrientationVerticalFlip);
  377. with_view_model(
  378. hid_ptt->view, HidPttModel * model, {
  379. model->transport = hid->transport;
  380. model->muted = true; // assume we're muted
  381. model->is_mac_os = true;
  382. }, true);
  383. return hid_ptt;
  384. }
  385. void hid_ptt_free(HidPtt* hid_ptt) {
  386. furi_assert(hid_ptt);
  387. notification_message(hid_ptt->hid->notifications, &sequence_reset_red);
  388. view_free(hid_ptt->view);
  389. free(hid_ptt);
  390. }
  391. View* hid_ptt_get_view(HidPtt* hid_ptt) {
  392. furi_assert(hid_ptt);
  393. return hid_ptt->view;
  394. }
  395. void hid_ptt_set_connected_status(HidPtt* hid_ptt, bool connected) {
  396. furi_assert(hid_ptt);
  397. with_view_model(
  398. hid_ptt->view, HidPttModel * model, { model->connected = connected; }, true);
  399. }