hid_ptt.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  1. #include "hid_ptt.h"
  2. #include "hid_ptt_menu.h"
  3. #include <gui/elements.h>
  4. #include <notification/notification_messages.h>
  5. #include <gui/modules/widget.h>
  6. #include "../hid.h"
  7. #include "../views.h"
  8. #include "hid_icons.h"
  9. #define TAG "HidPushToTalk"
  10. struct HidPushToTalk {
  11. View* view;
  12. Hid* hid;
  13. Widget* help;
  14. };
  15. typedef void (*PushToTalkActionCallback)(HidPushToTalk* hid_ptt);
  16. typedef struct {
  17. bool left_pressed;
  18. bool up_pressed;
  19. bool right_pressed;
  20. bool down_pressed;
  21. bool muted;
  22. bool ptt_pressed;
  23. bool mic_pressed;
  24. bool connected;
  25. FuriString *os;
  26. FuriString *app;
  27. size_t osIndex;
  28. size_t appIndex;
  29. size_t window_position;
  30. HidTransport transport;
  31. PushToTalkActionCallback callback_trigger_mute;
  32. PushToTalkActionCallback callback_trigger_camera;
  33. PushToTalkActionCallback callback_trigger_hand;
  34. PushToTalkActionCallback callback_start_ptt;
  35. PushToTalkActionCallback callback_stop_ptt;
  36. } HidPushToTalkModel;
  37. enum HidPushToTalkAppIndex {
  38. HidPushToTalkAppIndexDiscord,
  39. HidPushToTalkAppIndexFaceTime,
  40. HidPushToTalkAppIndexGoogleMeet,
  41. HidPushToTalkAppIndexGoogleHangouts,
  42. HidPushToTalkAppIndexJamulus,
  43. HidPushToTalkAppIndexSignal,
  44. HidPushToTalkAppIndexSkype,
  45. HidPushToTalkAppIndexSlackCall,
  46. HidPushToTalkAppIndexSlackHubble,
  47. HidPushToTalkAppIndexTeams,
  48. HidPushToTalkAppIndexTeamSpeak,
  49. HidPushToTalkAppIndexWebex,
  50. HidPushToTalkAppIndexZoom,
  51. HidPushToTalkAppIndexSize,
  52. };
  53. // meet, zoom
  54. static void hid_ptt_start_ptt_meet_zoom(HidPushToTalk* hid_ptt) {
  55. hid_hal_keyboard_press(hid_ptt->hid, HID_KEYBOARD_SPACEBAR);
  56. }
  57. static void hid_ptt_stop_ptt_meet_zoom(HidPushToTalk* hid_ptt) {
  58. hid_hal_keyboard_release(hid_ptt->hid, HID_KEYBOARD_SPACEBAR);
  59. }
  60. static void hid_ptt_trigger_mute_macos_meet(HidPushToTalk* hid_ptt) {
  61. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI | HID_KEYBOARD_D);
  62. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI | HID_KEYBOARD_D);
  63. }
  64. static void hid_ptt_trigger_mute_linux_meet(HidPushToTalk* hid_ptt) {
  65. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_D);
  66. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_D);
  67. }
  68. static void hid_ptt_trigger_camera_macos_meet(HidPushToTalk* hid_ptt) {
  69. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI | HID_KEYBOARD_E);
  70. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI | HID_KEYBOARD_E);
  71. }
  72. static void hid_ptt_trigger_camera_linux_meet(HidPushToTalk* hid_ptt) {
  73. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_E);
  74. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_E );
  75. }
  76. static void hid_ptt_trigger_hand_macos_meet(HidPushToTalk* hid_ptt) {
  77. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_CTRL |HID_KEYBOARD_H);
  78. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_CTRL |HID_KEYBOARD_H);
  79. }
  80. static void hid_ptt_trigger_hand_linux_meet(HidPushToTalk* hid_ptt) {
  81. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_LEFT_ALT |HID_KEYBOARD_H);
  82. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_LEFT_ALT |HID_KEYBOARD_H);
  83. }
  84. static void hid_ptt_trigger_mute_macos_zoom(HidPushToTalk* hid_ptt) {
  85. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_A);
  86. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_A);
  87. }
  88. static void hid_ptt_trigger_mute_linux_zoom(HidPushToTalk* hid_ptt) {
  89. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_ALT | HID_KEYBOARD_A);
  90. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_ALT | HID_KEYBOARD_A);
  91. }
  92. static void hid_ptt_trigger_camera_macos_zoom(HidPushToTalk* hid_ptt) {
  93. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_V);
  94. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_V);
  95. }
  96. static void hid_ptt_trigger_camera_linux_zoom(HidPushToTalk* hid_ptt) {
  97. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_ALT | HID_KEYBOARD_V);
  98. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_ALT | HID_KEYBOARD_V);
  99. }
  100. static void hid_ptt_trigger_hand_macos_zoom(HidPushToTalk* hid_ptt) {
  101. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI| HID_KEYBOARD_Y);
  102. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI| HID_KEYBOARD_Y);
  103. }
  104. static void hid_ptt_trigger_hand_linux_zoom(HidPushToTalk* hid_ptt) {
  105. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_ALT | HID_KEYBOARD_Y);
  106. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_ALT | HID_KEYBOARD_Y);
  107. }
  108. // this one is widely used across different apps
  109. static void hid_ptt_trigger_cmd_shift_m(HidPushToTalk* hid_ptt) {
  110. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M);
  111. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M);
  112. }
  113. // Hangouts HidPushToTalkAppIndexGoogleHangouts
  114. static void hid_ptt_trigger_mute_macos_hangouts(HidPushToTalk* hid_ptt) {
  115. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI | HID_KEYBOARD_D);
  116. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI | HID_KEYBOARD_D);
  117. }
  118. static void hid_ptt_trigger_mute_linux_hangouts(HidPushToTalk* hid_ptt) {
  119. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_D);
  120. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_D);
  121. }
  122. static void hid_ptt_trigger_camera_macos_hangouts(HidPushToTalk* hid_ptt) { // and hand in teams
  123. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI | HID_KEYBOARD_E);
  124. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI | HID_KEYBOARD_E);
  125. }
  126. static void hid_ptt_trigger_camera_linux_hangouts(HidPushToTalk* hid_ptt) { // and hand in teams
  127. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_E);
  128. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_E);
  129. }
  130. // Signal
  131. static void hid_ptt_trigger_mute_signal(HidPushToTalk* hid_ptt) {
  132. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M);
  133. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M);
  134. }
  135. static void hid_ptt_trigger_camera_signal(HidPushToTalk* hid_ptt) {
  136. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_V);
  137. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_V);
  138. }
  139. // skype
  140. static void hid_ptt_trigger_mute_linux_skype(HidPushToTalk* hid_ptt) { // and webex
  141. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_M);
  142. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL | HID_KEYBOARD_M);
  143. }
  144. static void hid_ptt_trigger_camera_macos_skype(HidPushToTalk* hid_ptt) { // and hand in teams
  145. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_K);
  146. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_K);
  147. }
  148. static void hid_ptt_trigger_camera_linux_skype(HidPushToTalk* hid_ptt) { // and hand in teams
  149. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_K);
  150. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_K);
  151. }
  152. // slack call
  153. static void hid_ptt_trigger_mute_slack_call(HidPushToTalk* hid_ptt) {
  154. hid_hal_keyboard_press( hid_ptt->hid, HID_KEYBOARD_M);
  155. hid_hal_keyboard_release(hid_ptt->hid, HID_KEYBOARD_M);
  156. }
  157. static void hid_ptt_trigger_camera_slack_call(HidPushToTalk* hid_ptt) {
  158. hid_hal_keyboard_press( hid_ptt->hid, HID_KEYBOARD_V);
  159. hid_hal_keyboard_release(hid_ptt->hid, HID_KEYBOARD_V);
  160. }
  161. // slack hubble
  162. static void hid_ptt_trigger_mute_macos_slack_hubble(HidPushToTalk* hid_ptt) {
  163. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_SPACEBAR);
  164. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_SPACEBAR);
  165. }
  166. static void hid_ptt_trigger_mute_linux_slack_hubble(HidPushToTalk* hid_ptt) {
  167. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_SPACEBAR);
  168. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_SPACEBAR);
  169. }
  170. // discord
  171. static void hid_ptt_trigger_mute_macos_discord(HidPushToTalk* hid_ptt) {
  172. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_RIGHT_GUI | KEY_MOD_RIGHT_ALT | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M);
  173. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_RIGHT_GUI | KEY_MOD_RIGHT_ALT | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M);
  174. }
  175. static void hid_ptt_start_ptt_macos_discord(HidPushToTalk* hid_ptt) { // and TeamSpeak
  176. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_RIGHT_GUI | KEY_MOD_RIGHT_ALT | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_P);
  177. }
  178. static void hid_ptt_stop_ptt_macos_discord(HidPushToTalk* hid_ptt) { // and TeamSpeak
  179. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_RIGHT_GUI | KEY_MOD_RIGHT_ALT | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_P);
  180. }
  181. static void hid_ptt_trigger_mute_linux_discord(HidPushToTalk* hid_ptt) {
  182. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_RIGHT_CTRL | KEY_MOD_RIGHT_ALT | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M);
  183. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_RIGHT_CTRL | KEY_MOD_RIGHT_ALT | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M);
  184. }
  185. static void hid_ptt_start_ptt_linux_discord(HidPushToTalk* hid_ptt) { // and TeamSpeak
  186. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_RIGHT_CTRL | KEY_MOD_RIGHT_ALT | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_P);
  187. }
  188. static void hid_ptt_stop_ptt_linux_discord(HidPushToTalk* hid_ptt) { // and TeamSpeak
  189. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_RIGHT_CTRL | KEY_MOD_RIGHT_ALT | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_P);
  190. }
  191. // teamspeak
  192. static void hid_ptt_trigger_mute_macos_teamspeak(HidPushToTalk* hid_ptt) {
  193. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_RIGHT_GUI | KEY_MOD_RIGHT_ALT | KEY_MOD_RIGHT_SHIFT | HID_KEYBOARD_M);
  194. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_RIGHT_GUI | KEY_MOD_RIGHT_ALT | KEY_MOD_RIGHT_SHIFT | HID_KEYBOARD_M);
  195. }
  196. static void hid_ptt_start_ptt_macos_teamspeak(HidPushToTalk* hid_ptt) {
  197. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_RIGHT_GUI | KEY_MOD_RIGHT_ALT | KEY_MOD_RIGHT_SHIFT | HID_KEYBOARD_P);
  198. }
  199. static void hid_ptt_stop_ptt_macos_teamspeak(HidPushToTalk* hid_ptt) {
  200. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_RIGHT_GUI | KEY_MOD_RIGHT_ALT | KEY_MOD_RIGHT_SHIFT | HID_KEYBOARD_P);
  201. }
  202. static void hid_ptt_trigger_mute_linux_teamspeak(HidPushToTalk* hid_ptt) {
  203. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_RIGHT_CTRL | KEY_MOD_RIGHT_ALT | KEY_MOD_RIGHT_SHIFT | HID_KEYBOARD_M);
  204. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_RIGHT_CTRL | KEY_MOD_RIGHT_ALT | KEY_MOD_RIGHT_SHIFT | HID_KEYBOARD_M);
  205. }
  206. static void hid_ptt_start_ptt_linux_teamspeak(HidPushToTalk* hid_ptt) {
  207. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_RIGHT_CTRL | KEY_MOD_RIGHT_ALT | KEY_MOD_RIGHT_SHIFT | HID_KEYBOARD_P);
  208. }
  209. static void hid_ptt_stop_ptt_linux_teamspeak(HidPushToTalk* hid_ptt) {
  210. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_RIGHT_CTRL | KEY_MOD_RIGHT_ALT | KEY_MOD_RIGHT_SHIFT | HID_KEYBOARD_P);
  211. }
  212. // teams
  213. static void hid_ptt_start_ptt_macos_teams(HidPushToTalk* hid_ptt) {
  214. hid_hal_keyboard_press(hid_ptt->hid, KEY_MOD_LEFT_GUI|HID_KEYBOARD_SPACEBAR);
  215. }
  216. static void hid_ptt_start_ptt_linux_teams(HidPushToTalk* hid_ptt) {
  217. hid_hal_keyboard_press(hid_ptt->hid, KEY_MOD_LEFT_CTRL|HID_KEYBOARD_SPACEBAR);
  218. }
  219. static void hid_ptt_stop_ptt_macos_teams(HidPushToTalk* hid_ptt) {
  220. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI|HID_KEYBOARD_SPACEBAR);
  221. }
  222. static void hid_ptt_stop_ptt_linux_teams(HidPushToTalk* hid_ptt) {
  223. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL|HID_KEYBOARD_SPACEBAR);
  224. }
  225. static void hid_ptt_trigger_mute_linux_teams(HidPushToTalk* hid_ptt) {
  226. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M);
  227. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_M);
  228. }
  229. static void hid_ptt_trigger_camera_macos_teams(HidPushToTalk* hid_ptt) {
  230. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_O);
  231. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_O);
  232. }
  233. static void hid_ptt_trigger_camera_linux_teams(HidPushToTalk* hid_ptt) {
  234. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_O);
  235. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_LEFT_SHIFT |HID_KEYBOARD_O);
  236. }
  237. // Jamulus
  238. static void hid_ptt_trigger_mute_jamulus(HidPushToTalk* hid_ptt) {
  239. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_ALT | HID_KEYBOARD_M);
  240. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_ALT | HID_KEYBOARD_M);
  241. }
  242. // webex
  243. static void hid_ptt_trigger_camera_webex(HidPushToTalk* hid_ptt) {
  244. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_V);
  245. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL| KEY_MOD_LEFT_SHIFT | HID_KEYBOARD_V);
  246. }
  247. static void hid_ptt_trigger_hand_macos_webex(HidPushToTalk* hid_ptt) {
  248. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_RIGHT_SHIFT | HID_KEYBOARD_R);
  249. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_GUI | KEY_MOD_RIGHT_SHIFT | HID_KEYBOARD_R);
  250. }
  251. static void hid_ptt_trigger_hand_linux_webex(HidPushToTalk* hid_ptt) {
  252. hid_hal_keyboard_press( hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_RIGHT_SHIFT | HID_KEYBOARD_R);
  253. hid_hal_keyboard_release(hid_ptt->hid, KEY_MOD_LEFT_CTRL | KEY_MOD_RIGHT_SHIFT | HID_KEYBOARD_R);
  254. }
  255. static void hid_ptt_menu_callback(void* context, uint32_t osIndex, FuriString* osLabel, uint32_t appIndex, FuriString* appLabel) {
  256. furi_assert(context);
  257. HidPushToTalk* hid_ptt = context;
  258. with_view_model(
  259. hid_ptt->view, HidPushToTalkModel * model, {
  260. furi_string_set(model->os, osLabel);
  261. furi_string_set(model->app, appLabel);
  262. model->osIndex = osIndex;
  263. model->appIndex = appIndex;
  264. model->callback_trigger_mute = NULL;
  265. model->callback_trigger_camera = NULL;
  266. model->callback_trigger_hand = NULL;
  267. model->callback_start_ptt = NULL;
  268. model->callback_stop_ptt = NULL;
  269. FURI_LOG_E(TAG, "appIndex: %lu", appIndex);
  270. if(osIndex == HidPushToTalkMacOS) {
  271. switch(appIndex) {
  272. case HidPushToTalkAppIndexDiscord:
  273. model->callback_trigger_mute = hid_ptt_trigger_mute_macos_discord;
  274. model->callback_start_ptt = hid_ptt_start_ptt_macos_discord;
  275. model->callback_stop_ptt = hid_ptt_stop_ptt_macos_discord;
  276. break;
  277. case HidPushToTalkAppIndexFaceTime:
  278. model->callback_trigger_mute = hid_ptt_trigger_cmd_shift_m;
  279. model->callback_start_ptt = hid_ptt_trigger_cmd_shift_m;
  280. model->callback_stop_ptt = hid_ptt_trigger_cmd_shift_m;
  281. break;
  282. case HidPushToTalkAppIndexGoogleHangouts:
  283. model->callback_trigger_mute = hid_ptt_trigger_mute_macos_hangouts;
  284. model->callback_trigger_camera = hid_ptt_trigger_camera_macos_hangouts;
  285. model->callback_start_ptt = hid_ptt_trigger_mute_macos_hangouts;
  286. model->callback_stop_ptt = hid_ptt_trigger_mute_macos_hangouts;
  287. break;
  288. case HidPushToTalkAppIndexGoogleMeet:
  289. model->callback_trigger_mute = hid_ptt_trigger_mute_macos_meet;
  290. model->callback_trigger_camera = hid_ptt_trigger_camera_macos_meet;
  291. model->callback_trigger_hand = hid_ptt_trigger_hand_macos_meet;
  292. model->callback_start_ptt = hid_ptt_start_ptt_meet_zoom;
  293. model->callback_stop_ptt = hid_ptt_stop_ptt_meet_zoom;
  294. break;
  295. case HidPushToTalkAppIndexJamulus:
  296. model->callback_trigger_mute = hid_ptt_trigger_mute_jamulus;
  297. model->callback_start_ptt = hid_ptt_trigger_mute_jamulus;
  298. model->callback_stop_ptt = hid_ptt_trigger_mute_jamulus;
  299. break;
  300. case HidPushToTalkAppIndexTeams:
  301. model->callback_trigger_mute = hid_ptt_trigger_cmd_shift_m;
  302. model->callback_trigger_camera = hid_ptt_trigger_camera_macos_teams;
  303. model->callback_trigger_hand = hid_ptt_trigger_camera_macos_skype;
  304. model->callback_start_ptt = hid_ptt_start_ptt_macos_teams;
  305. model->callback_stop_ptt = hid_ptt_stop_ptt_macos_teams;
  306. break;
  307. case HidPushToTalkAppIndexTeamSpeak:
  308. model->callback_trigger_mute = hid_ptt_trigger_mute_macos_teamspeak;
  309. model->callback_start_ptt = hid_ptt_start_ptt_macos_teamspeak;
  310. model->callback_stop_ptt = hid_ptt_stop_ptt_macos_teamspeak;
  311. break;
  312. case HidPushToTalkAppIndexSignal:
  313. model->callback_trigger_mute = hid_ptt_trigger_mute_signal;
  314. model->callback_trigger_camera = hid_ptt_trigger_camera_signal;
  315. model->callback_start_ptt = hid_ptt_trigger_mute_signal;
  316. model->callback_stop_ptt = hid_ptt_trigger_mute_signal;
  317. break;
  318. case HidPushToTalkAppIndexSkype:
  319. model->callback_trigger_mute = hid_ptt_trigger_cmd_shift_m;
  320. model->callback_trigger_camera = hid_ptt_trigger_camera_macos_skype;
  321. model->callback_start_ptt = hid_ptt_trigger_cmd_shift_m;
  322. model->callback_stop_ptt = hid_ptt_trigger_cmd_shift_m;
  323. break;
  324. case HidPushToTalkAppIndexSlackCall:
  325. model->callback_trigger_mute = hid_ptt_trigger_mute_slack_call;
  326. model->callback_trigger_camera = hid_ptt_trigger_camera_slack_call;
  327. model->callback_start_ptt = hid_ptt_trigger_mute_slack_call;
  328. model->callback_stop_ptt = hid_ptt_trigger_mute_slack_call;
  329. break;
  330. case HidPushToTalkAppIndexSlackHubble:
  331. model->callback_trigger_mute = hid_ptt_trigger_mute_macos_slack_hubble;
  332. model->callback_start_ptt = hid_ptt_trigger_mute_macos_slack_hubble;
  333. model->callback_stop_ptt = hid_ptt_trigger_mute_macos_slack_hubble;
  334. break;
  335. case HidPushToTalkAppIndexWebex:
  336. model->callback_trigger_mute = hid_ptt_trigger_cmd_shift_m;
  337. model->callback_trigger_camera = hid_ptt_trigger_camera_webex;
  338. model->callback_trigger_hand = hid_ptt_trigger_hand_macos_webex;
  339. model->callback_start_ptt = hid_ptt_trigger_cmd_shift_m;
  340. model->callback_stop_ptt = hid_ptt_trigger_cmd_shift_m;
  341. break;
  342. case HidPushToTalkAppIndexZoom:
  343. model->callback_trigger_mute = hid_ptt_trigger_mute_macos_zoom;
  344. model->callback_trigger_camera = hid_ptt_trigger_camera_macos_zoom;
  345. model->callback_trigger_hand = hid_ptt_trigger_hand_macos_zoom;
  346. model->callback_start_ptt = hid_ptt_start_ptt_meet_zoom;
  347. model->callback_stop_ptt = hid_ptt_stop_ptt_meet_zoom;
  348. break;
  349. }
  350. } else if (osIndex == HidPushToTalkLinux) {
  351. switch(appIndex) {
  352. case HidPushToTalkAppIndexDiscord:
  353. model->callback_trigger_mute = hid_ptt_trigger_mute_linux_discord;
  354. model->callback_start_ptt = hid_ptt_start_ptt_linux_discord;
  355. model->callback_stop_ptt = hid_ptt_stop_ptt_linux_discord;
  356. break;
  357. case HidPushToTalkAppIndexGoogleHangouts:
  358. model->callback_trigger_mute = hid_ptt_trigger_mute_linux_hangouts;
  359. model->callback_trigger_camera = hid_ptt_trigger_camera_linux_hangouts;
  360. model->callback_start_ptt = hid_ptt_trigger_mute_linux_hangouts;
  361. model->callback_stop_ptt = hid_ptt_trigger_mute_linux_hangouts;
  362. break;
  363. case HidPushToTalkAppIndexGoogleMeet:
  364. model->callback_trigger_mute = hid_ptt_trigger_mute_linux_meet;
  365. model->callback_trigger_camera = hid_ptt_trigger_camera_linux_meet;
  366. model->callback_trigger_hand = hid_ptt_trigger_hand_linux_meet;
  367. model->callback_start_ptt = hid_ptt_start_ptt_meet_zoom;
  368. model->callback_stop_ptt = hid_ptt_stop_ptt_meet_zoom;
  369. break;
  370. case HidPushToTalkAppIndexJamulus:
  371. model->callback_trigger_mute = hid_ptt_trigger_mute_jamulus;
  372. model->callback_start_ptt = hid_ptt_trigger_mute_jamulus;
  373. model->callback_stop_ptt = hid_ptt_trigger_mute_jamulus;
  374. break;
  375. case HidPushToTalkAppIndexTeams:
  376. model->callback_trigger_mute = hid_ptt_trigger_mute_linux_teams;
  377. model->callback_trigger_camera = hid_ptt_trigger_camera_linux_teams;
  378. model->callback_trigger_hand = hid_ptt_trigger_camera_linux_skype;
  379. model->callback_start_ptt = hid_ptt_start_ptt_linux_teams;
  380. model->callback_stop_ptt = hid_ptt_stop_ptt_linux_teams;
  381. break;
  382. case HidPushToTalkAppIndexTeamSpeak:
  383. model->callback_trigger_mute = hid_ptt_trigger_mute_linux_teamspeak;
  384. model->callback_start_ptt = hid_ptt_start_ptt_linux_teamspeak;
  385. model->callback_stop_ptt = hid_ptt_stop_ptt_linux_teamspeak;
  386. break;
  387. case HidPushToTalkAppIndexSignal:
  388. model->callback_trigger_mute = hid_ptt_trigger_mute_signal;
  389. model->callback_trigger_camera = hid_ptt_trigger_camera_signal;
  390. model->callback_start_ptt = hid_ptt_trigger_mute_signal;
  391. model->callback_stop_ptt = hid_ptt_trigger_mute_signal;
  392. break;
  393. case HidPushToTalkAppIndexSkype:
  394. model->callback_trigger_mute = hid_ptt_trigger_mute_linux_skype;
  395. model->callback_trigger_camera = hid_ptt_trigger_camera_linux_skype;
  396. model->callback_start_ptt = hid_ptt_trigger_mute_linux_skype;
  397. model->callback_stop_ptt = hid_ptt_trigger_mute_linux_skype;
  398. break;
  399. case HidPushToTalkAppIndexSlackCall:
  400. model->callback_trigger_mute = hid_ptt_trigger_mute_slack_call;
  401. model->callback_trigger_camera = hid_ptt_trigger_camera_slack_call;
  402. model->callback_start_ptt = hid_ptt_trigger_mute_slack_call;
  403. model->callback_stop_ptt = hid_ptt_trigger_mute_slack_call;
  404. break;
  405. case HidPushToTalkAppIndexSlackHubble:
  406. model->callback_trigger_mute = hid_ptt_trigger_mute_linux_slack_hubble;
  407. model->callback_start_ptt = hid_ptt_trigger_mute_linux_slack_hubble;
  408. model->callback_stop_ptt = hid_ptt_trigger_mute_linux_slack_hubble;
  409. break;
  410. case HidPushToTalkAppIndexZoom:
  411. model->callback_trigger_mute = hid_ptt_trigger_mute_linux_zoom;
  412. model->callback_trigger_camera = hid_ptt_trigger_camera_linux_zoom;
  413. model->callback_trigger_hand = hid_ptt_trigger_hand_linux_zoom;
  414. model->callback_start_ptt = hid_ptt_start_ptt_meet_zoom;
  415. model->callback_stop_ptt = hid_ptt_stop_ptt_meet_zoom;
  416. break;
  417. case HidPushToTalkAppIndexWebex:
  418. model->callback_trigger_mute = hid_ptt_trigger_mute_linux_skype;
  419. model->callback_trigger_camera = hid_ptt_trigger_camera_webex;
  420. model->callback_trigger_hand = hid_ptt_trigger_hand_linux_webex;
  421. model->callback_start_ptt = hid_ptt_trigger_mute_linux_skype;
  422. model->callback_stop_ptt = hid_ptt_trigger_mute_linux_skype;
  423. break;
  424. }
  425. }
  426. char *app_specific_help = "";
  427. switch(appIndex) {
  428. case HidPushToTalkAppIndexGoogleMeet:
  429. app_specific_help =
  430. "Google Meet:\n"
  431. "This feature is off by default in your audio settings "
  432. "and may not work for Windows users who use their screen "
  433. "reader. In this situation, the spacebar performs a different action.\n\n"
  434. ;
  435. break;
  436. case HidPushToTalkAppIndexDiscord:
  437. app_specific_help =
  438. "Discord:\n"
  439. "1. Under App Settings, click Voice & Video. Under Input Mode, "
  440. "check the box next to Push to Talk.\n"
  441. "2. Scroll down to SHORTCUT, click Record Keybinder.\n"
  442. "3. Press PTT in the app to bind it."
  443. "4. Go to Keybinds and assign mute button.\n\n"
  444. ;
  445. break;
  446. case HidPushToTalkAppIndexTeamSpeak:
  447. app_specific_help =
  448. "TeamSpeak:\n"
  449. "To make keys working bind them in TeamSpeak settings.\n\n"
  450. ;
  451. break;
  452. case HidPushToTalkAppIndexTeams:
  453. app_specific_help =
  454. "Teams:\n"
  455. "Go to Settings > Privacy. Make sure Keyboard shortcut to unmute is toggled on.\n\n"
  456. ;
  457. break;
  458. }
  459. FuriString *msg = furi_string_alloc();
  460. furi_string_cat_printf(msg,
  461. "%sGeneral:\n"
  462. "To operate properly flipper microphone "
  463. "status must be in sync with your computer.\n"
  464. "Hold > to change mic status.\n"
  465. "Hold < to open this help.\n"
  466. "Press BACK to switch mic on/off.\n"
  467. "Hold 'o' for PTT mode (mic will be off once you release 'o')\n"
  468. "Hold BACK to exit.", app_specific_help);
  469. widget_add_text_scroll_element(hid_ptt->help, 0, 0, 128, 64, furi_string_get_cstr(msg));
  470. furi_string_free(msg);
  471. }, true);
  472. view_dispatcher_switch_to_view(hid_ptt->hid->view_dispatcher, HidViewPushToTalk);
  473. }
  474. static void hid_ptt_draw_camera(Canvas* canvas, uint8_t x, uint8_t y) {
  475. canvas_draw_icon(canvas, x + 7, y, &I_ButtonLeft_4x7);
  476. canvas_draw_box(canvas, x, y, 7, 7);
  477. }
  478. static void hid_ptt_draw_text_centered(Canvas* canvas, uint8_t y, FuriString* str) {
  479. FuriString* disp_str;
  480. disp_str = furi_string_alloc_set(str);
  481. elements_string_fit_width(canvas, disp_str, canvas_width(canvas));
  482. uint8_t x_pos = (canvas_width(canvas) - canvas_string_width(canvas,furi_string_get_cstr(disp_str))) / 2;
  483. canvas_draw_str(canvas,x_pos,y,furi_string_get_cstr(disp_str));
  484. furi_string_free(disp_str);
  485. }
  486. static void hid_ptt_draw_callback(Canvas* canvas, void* context) {
  487. furi_assert(context);
  488. HidPushToTalkModel* model = context;
  489. // Header
  490. canvas_set_font(canvas, FontPrimary);
  491. if(model->transport == HidTransportBle) {
  492. if(model->connected) {
  493. canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
  494. } else {
  495. canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
  496. }
  497. }
  498. // OS and App labels
  499. canvas_set_font(canvas, FontSecondary);
  500. hid_ptt_draw_text_centered(canvas, 73, model->app);
  501. hid_ptt_draw_text_centered(canvas, 84, model->os);
  502. // Help label
  503. canvas_draw_icon(canvas, 0, 88, &I_Help_top_64x17);
  504. canvas_draw_line(canvas, 4, 105, 4, 114);
  505. canvas_draw_line(canvas, 63, 105, 63, 114);
  506. canvas_draw_icon(canvas, 7, 107, &I_Hold_15x5);
  507. canvas_draw_icon(canvas, 24, 105, &I_BtnLeft_9x9);
  508. canvas_draw_icon(canvas, 34, 108, &I_for_help_27x5);
  509. canvas_draw_icon(canvas, 0, 115, &I_Help_exit_64x9);
  510. canvas_draw_icon(canvas, 24, 115, &I_BtnBackV_9x9);
  511. const uint8_t x_1 = 0;
  512. const uint8_t x_2 = x_1 + 19 + 4;
  513. const uint8_t x_3 = x_1 + 19 * 2 + 8;
  514. const uint8_t y_1 = 3;
  515. const uint8_t y_2 = y_1 + 19;
  516. const uint8_t y_3 = y_2 + 19;
  517. // Up
  518. canvas_draw_icon(canvas, x_2, y_1, &I_Button_18x18);
  519. if(model->up_pressed) {
  520. elements_slightly_rounded_box(canvas, x_2 + 3, y_1 + 2, 13, 13);
  521. canvas_set_color(canvas, ColorWhite);
  522. }
  523. canvas_draw_icon(canvas, x_2 + 5, y_1 + 5, &I_Volup_8x6);
  524. canvas_set_color(canvas, ColorBlack);
  525. // Down
  526. canvas_draw_icon(canvas, x_2, y_3, &I_Button_18x18);
  527. if(model->down_pressed) {
  528. elements_slightly_rounded_box(canvas, x_2 + 3, y_3 + 2, 13, 13);
  529. canvas_set_color(canvas, ColorWhite);
  530. }
  531. canvas_draw_icon(canvas, x_2 + 6, y_3 + 5, &I_Voldwn_6x6);
  532. canvas_set_color(canvas, ColorBlack);
  533. // Left / Help
  534. canvas_draw_icon(canvas, x_1, y_2, &I_Button_18x18);
  535. if(model->left_pressed) {
  536. elements_slightly_rounded_box(canvas, x_1 + 3, y_2 + 2, 13, 13);
  537. canvas_set_color(canvas, ColorWhite);
  538. }
  539. if (model->callback_trigger_hand) {
  540. canvas_draw_icon(canvas, x_1 + 4, y_2 + 3, &I_Hand_8x10);
  541. } else {
  542. canvas_draw_icon(canvas, x_1 + 2, y_2 + 1, &I_BrokenButton_15x15);
  543. }
  544. canvas_set_color(canvas, ColorBlack);
  545. // Right / Camera
  546. canvas_draw_icon(canvas, x_3, y_2, &I_Button_18x18);
  547. if(model->right_pressed) {
  548. elements_slightly_rounded_box(canvas, x_3 + 3, y_2 + 2, 13, 13);
  549. canvas_set_color(canvas, ColorWhite);
  550. }
  551. if (model->callback_trigger_camera) {
  552. hid_ptt_draw_camera(canvas, x_3 + 4, y_2 + 5);
  553. } else {
  554. canvas_draw_icon(canvas, x_3 + 2, y_2 + 1, &I_BrokenButton_15x15);
  555. }
  556. canvas_set_color(canvas, ColorBlack);
  557. // Back / Mic
  558. const uint8_t x_mic = x_3;
  559. canvas_draw_icon(canvas, x_mic, 0, &I_RoundButtonUnpressed_16x16);
  560. if (!(!model->muted || (model->ptt_pressed))) {
  561. // show muted
  562. if(model->mic_pressed) {
  563. // canvas_draw_icon(canvas, x_mic + 1, 0, &I_MicrophonePressedCrossed_15x15);
  564. canvas_draw_icon(canvas, x_mic, 0, &I_MicrophonePressedCrossedBtn_16x16);
  565. } else {
  566. canvas_draw_icon(canvas, x_mic, 0, &I_MicrophoneCrossed_16x16);
  567. }
  568. } else {
  569. // show unmuted
  570. if(model->mic_pressed) {
  571. // canvas_draw_icon(canvas, x_mic + 1, 0, &I_MicrophonePressed_15x15);
  572. canvas_draw_icon(canvas, x_mic, 0, &I_MicrophonePressedBtn_16x16);
  573. } else {
  574. canvas_draw_icon(canvas, x_mic + 5, 2, &I_Mic_7x11);
  575. }
  576. }
  577. // Ok / PTT
  578. const uint8_t x_ptt_margin = 4;
  579. const uint8_t x_ptt_width = 17;
  580. const uint8_t x_ptt = x_1 + 19;
  581. canvas_draw_icon(canvas, x_ptt , y_2 , &I_BtnFrameLeft_3x18);
  582. canvas_draw_icon(canvas, x_ptt + x_ptt_width + 3 + x_ptt_margin, y_2 , &I_BtnFrameRight_2x18);
  583. canvas_draw_line(canvas, x_ptt + 3 , y_2 , x_ptt + x_ptt_width + 2 + x_ptt_margin, y_2);
  584. canvas_draw_line(canvas, x_ptt + 3 , y_2 + 16, x_ptt + x_ptt_width + 2 + x_ptt_margin, y_2 + 16);
  585. canvas_draw_line(canvas, x_ptt + 3 , y_2 + 17, x_ptt + x_ptt_width + 2 + x_ptt_margin, y_2 + 17);
  586. if (model->ptt_pressed) {
  587. elements_slightly_rounded_box(canvas, x_ptt + 3, y_2 + 2, x_ptt_width + x_ptt_margin, 13);
  588. canvas_set_color(canvas, ColorWhite);
  589. }
  590. canvas_set_font(canvas, FontPrimary);
  591. elements_multiline_text_aligned(canvas, x_ptt + 2 + x_ptt_margin / 2, y_2 + 13, AlignLeft, AlignBottom, "PTT");
  592. canvas_set_font(canvas, FontSecondary);
  593. canvas_set_color(canvas, ColorBlack);
  594. }
  595. static void hid_ptt_process(HidPushToTalk* hid_ptt, InputEvent* event) {
  596. with_view_model(
  597. hid_ptt->view,
  598. HidPushToTalkModel * model,
  599. {
  600. if(event->type == InputTypePress && !model->ptt_pressed) {
  601. if(event->key == InputKeyUp) {
  602. model->up_pressed = true;
  603. hid_hal_consumer_key_press(hid_ptt->hid, HID_CONSUMER_VOLUME_INCREMENT);
  604. } else if(event->key == InputKeyDown) {
  605. model->down_pressed = true;
  606. hid_hal_consumer_key_press(hid_ptt->hid, HID_CONSUMER_VOLUME_DECREMENT);
  607. } else if(event->key == InputKeyLeft) {
  608. model->left_pressed = true;
  609. } else if(event->key == InputKeyRight) {
  610. model->right_pressed = true;
  611. } else if(event->key == InputKeyOk) {
  612. model->ptt_pressed = true;
  613. if (!model->mic_pressed && model->muted){
  614. model->callback_start_ptt ? model->callback_start_ptt(hid_ptt):0;
  615. }
  616. } else if(event->key == InputKeyBack) {
  617. model->mic_pressed = true;
  618. }
  619. } else if(event->type == InputTypeRelease) {
  620. if(event->key == InputKeyUp) {
  621. model->up_pressed = false;
  622. if (!model->ptt_pressed){
  623. hid_hal_consumer_key_release(hid_ptt->hid, HID_CONSUMER_VOLUME_INCREMENT);
  624. }
  625. } else if(event->key == InputKeyDown) {
  626. model->down_pressed = false;
  627. if (!model->ptt_pressed){
  628. hid_hal_consumer_key_release(hid_ptt->hid, HID_CONSUMER_VOLUME_DECREMENT);
  629. }
  630. } else if(event->key == InputKeyLeft) {
  631. model->left_pressed = false;
  632. } else if(event->key == InputKeyRight) {
  633. model->right_pressed = false;
  634. } else if(event->key == InputKeyOk) {
  635. model->ptt_pressed = false;
  636. if(!model->mic_pressed) {
  637. if (model->muted) {
  638. model->callback_stop_ptt ? model->callback_stop_ptt(hid_ptt):0;
  639. } else {
  640. model->callback_trigger_mute ? model->callback_trigger_mute(hid_ptt):0;
  641. model->muted = true;
  642. }
  643. }
  644. } else if(event->key == InputKeyBack) {
  645. model->mic_pressed = false;
  646. }
  647. } else if(event->type == InputTypeShort && !model->ptt_pressed) {
  648. if(event->key == InputKeyBack ) { // no changes if PTT is pressed
  649. model->muted = !model->muted;
  650. model->callback_trigger_mute ? model->callback_trigger_mute(hid_ptt):0;
  651. } else if(event->key == InputKeyRight) {
  652. model->callback_trigger_camera ? model->callback_trigger_camera(hid_ptt):0;
  653. } else if(event->key == InputKeyLeft) {
  654. model->callback_trigger_hand ? model->callback_trigger_hand(hid_ptt):0;
  655. }
  656. } else if(event->type == InputTypeLong && event->key == InputKeyRight) {
  657. model->muted = !model->muted;
  658. notification_message(hid_ptt->hid->notifications, &sequence_single_vibro);
  659. } else if(event->type == InputTypeLong && event->key == InputKeyLeft) {
  660. notification_message(hid_ptt->hid->notifications, &sequence_single_vibro);
  661. model->left_pressed = false;
  662. view_dispatcher_switch_to_view(hid_ptt->hid->view_dispatcher, HidViewPushToTalkHelp);
  663. }
  664. //LED
  665. if (!model->muted || (model->ptt_pressed)) {
  666. notification_message(hid_ptt->hid->notifications, &sequence_set_red_255);
  667. } else {
  668. notification_message(hid_ptt->hid->notifications, &sequence_reset_red);
  669. }
  670. },
  671. true);
  672. }
  673. static bool hid_ptt_input_callback(InputEvent* event, void* context) {
  674. furi_assert(context);
  675. HidPushToTalk* hid_ptt = context;
  676. bool consumed = false;
  677. if(event->type == InputTypeLong && event->key == InputKeyBack) {
  678. hid_hal_keyboard_release_all(hid_ptt->hid);
  679. notification_message(hid_ptt->hid->notifications, &sequence_double_vibro);
  680. widget_reset(hid_ptt->help);
  681. } else {
  682. consumed = true;
  683. hid_ptt_process(hid_ptt, event);
  684. }
  685. return consumed;
  686. }
  687. View* hid_ptt_get_view(HidPushToTalk* hid_ptt) {
  688. furi_assert(hid_ptt);
  689. return hid_ptt->view;
  690. }
  691. static uint32_t hid_ptt_view(void* context) {
  692. UNUSED(context);
  693. return HidViewPushToTalk;
  694. }
  695. HidPushToTalk* hid_ptt_alloc(Hid* hid) {
  696. HidPushToTalk* hid_ptt = malloc(sizeof(HidPushToTalk));
  697. hid_ptt->hid = hid;
  698. hid_ptt->view = view_alloc();
  699. view_set_context(hid_ptt->view, hid_ptt);
  700. view_allocate_model(hid_ptt->view, ViewModelTypeLocking, sizeof(HidPushToTalkModel));
  701. view_set_draw_callback(hid_ptt->view, hid_ptt_draw_callback);
  702. view_set_input_callback(hid_ptt->view, hid_ptt_input_callback);
  703. view_set_orientation(hid_ptt->view, ViewOrientationVerticalFlip);
  704. with_view_model(
  705. hid_ptt->view, HidPushToTalkModel * model, {
  706. model->transport = hid->transport;
  707. model->muted = true; // assume we're muted
  708. model->os = furi_string_alloc();
  709. model->app = furi_string_alloc();
  710. }, true);
  711. FURI_LOG_I(TAG, "Calling adding list");
  712. ptt_menu_add_list(hid->hid_ptt_menu, "macOS", HidPushToTalkMacOS);
  713. ptt_menu_add_list(hid->hid_ptt_menu, "Win/Linux", HidPushToTalkLinux);
  714. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkMacOS, "Google Meet", HidPushToTalkAppIndexGoogleMeet, hid_ptt_menu_callback, hid_ptt);
  715. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkLinux, "Google Meet", HidPushToTalkAppIndexGoogleMeet, hid_ptt_menu_callback, hid_ptt);
  716. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkMacOS, "Google Hangouts", HidPushToTalkAppIndexGoogleHangouts, hid_ptt_menu_callback, hid_ptt);
  717. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkLinux, "Google Hangouts", HidPushToTalkAppIndexGoogleHangouts, hid_ptt_menu_callback, hid_ptt);
  718. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkMacOS, "Discord", HidPushToTalkAppIndexDiscord, hid_ptt_menu_callback, hid_ptt);
  719. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkLinux, "Discord", HidPushToTalkAppIndexDiscord, hid_ptt_menu_callback, hid_ptt);
  720. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkMacOS, "FaceTime", HidPushToTalkAppIndexFaceTime, hid_ptt_menu_callback, hid_ptt);
  721. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkMacOS, "Jamulus", HidPushToTalkAppIndexJamulus, hid_ptt_menu_callback, hid_ptt);
  722. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkLinux, "Jamulus", HidPushToTalkAppIndexJamulus, hid_ptt_menu_callback, hid_ptt);
  723. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkMacOS, "Signal", HidPushToTalkAppIndexSignal, hid_ptt_menu_callback, hid_ptt);
  724. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkLinux, "Signal", HidPushToTalkAppIndexSignal, hid_ptt_menu_callback, hid_ptt);
  725. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkMacOS, "Skype", HidPushToTalkAppIndexSkype, hid_ptt_menu_callback, hid_ptt);
  726. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkLinux, "Skype", HidPushToTalkAppIndexSkype, hid_ptt_menu_callback, hid_ptt);
  727. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkMacOS, "Slack Call", HidPushToTalkAppIndexSlackCall, hid_ptt_menu_callback, hid_ptt);
  728. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkLinux, "Slack Call", HidPushToTalkAppIndexSlackCall, hid_ptt_menu_callback, hid_ptt);
  729. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkMacOS, "Slack Hubble", HidPushToTalkAppIndexSlackHubble, hid_ptt_menu_callback, hid_ptt);
  730. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkLinux, "Slack Hubble", HidPushToTalkAppIndexSlackHubble, hid_ptt_menu_callback, hid_ptt);
  731. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkMacOS, "TeamSpeak", HidPushToTalkAppIndexTeamSpeak, hid_ptt_menu_callback, hid_ptt);
  732. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkLinux, "TeamSpeak", HidPushToTalkAppIndexTeamSpeak, hid_ptt_menu_callback, hid_ptt);
  733. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkMacOS, "Teams", HidPushToTalkAppIndexTeams, hid_ptt_menu_callback, hid_ptt);
  734. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkLinux, "Teams", HidPushToTalkAppIndexTeams, hid_ptt_menu_callback, hid_ptt);
  735. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkMacOS, "Zoom", HidPushToTalkAppIndexZoom, hid_ptt_menu_callback, hid_ptt);
  736. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkLinux, "Zoom", HidPushToTalkAppIndexZoom, hid_ptt_menu_callback, hid_ptt);
  737. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkMacOS, "Webex", HidPushToTalkAppIndexWebex, hid_ptt_menu_callback, hid_ptt);
  738. ptt_menu_add_item_to_list(hid->hid_ptt_menu, HidPushToTalkLinux, "Webex", HidPushToTalkAppIndexWebex, hid_ptt_menu_callback, hid_ptt);
  739. hid_ptt->help = widget_alloc();
  740. view_set_previous_callback(widget_get_view(hid_ptt->help), hid_ptt_view);
  741. view_dispatcher_add_view(hid->view_dispatcher, HidViewPushToTalkHelp, widget_get_view(hid_ptt->help));
  742. return hid_ptt;
  743. }
  744. void hid_ptt_free(HidPushToTalk* hid_ptt) {
  745. furi_assert(hid_ptt);
  746. notification_message(hid_ptt->hid->notifications, &sequence_reset_red);
  747. with_view_model(
  748. hid_ptt->view, HidPushToTalkModel * model, {
  749. furi_string_free(model->os);
  750. furi_string_free(model->app);
  751. }, true);
  752. view_dispatcher_remove_view(hid_ptt->hid->view_dispatcher, HidViewPushToTalkHelp);
  753. widget_free(hid_ptt->help);
  754. view_free(hid_ptt->view);
  755. free(hid_ptt);
  756. }
  757. void hid_ptt_set_connected_status(HidPushToTalk* hid_ptt, bool connected) {
  758. furi_assert(hid_ptt);
  759. with_view_model(
  760. hid_ptt->view, HidPushToTalkModel * model, {
  761. if (!connected && model->connected) {
  762. notification_message(hid_ptt->hid->notifications, &sequence_single_vibro);
  763. }
  764. model->connected = connected;
  765. }, true);
  766. }