air_mouse.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #include "air_mouse.h"
  2. #include <storage/storage.h>
  3. #include <furi.h>
  4. #include "tracking/imu/imu.h"
  5. #define TAG "AirMouseApp"
  6. enum AirMouseSubmenuIndex {
  7. AirMouseSubmenuIndexBtMouse,
  8. AirMouseSubmenuIndexUsbMouse,
  9. AirMouseSubmenuIndexCalibration,
  10. AirMouseSubmenuIndexRemovePairing,
  11. };
  12. void air_mouse_submenu_callback(void* context, uint32_t index) {
  13. furi_assert(context);
  14. AirMouse* app = context;
  15. if(index == AirMouseSubmenuIndexBtMouse) {
  16. app->view_id = AirMouseViewBtMouse;
  17. view_dispatcher_switch_to_view(app->view_dispatcher, AirMouseViewBtMouse);
  18. } else if(index == AirMouseSubmenuIndexUsbMouse) {
  19. app->view_id = AirMouseViewUsbMouse;
  20. view_dispatcher_switch_to_view(app->view_dispatcher, AirMouseViewUsbMouse);
  21. } else if(index == AirMouseSubmenuIndexCalibration) {
  22. app->view_id = AirMouseViewCalibration;
  23. view_dispatcher_switch_to_view(app->view_dispatcher, AirMouseViewCalibration);
  24. } else if(index == AirMouseSubmenuIndexRemovePairing) {
  25. bt_mouse_remove_pairing();
  26. }
  27. }
  28. void air_mouse_dialog_callback(DialogExResult result, void* context) {
  29. furi_assert(context);
  30. AirMouse* app = context;
  31. if(result == DialogExResultLeft) {
  32. view_dispatcher_switch_to_view(app->view_dispatcher, VIEW_NONE); // Exit
  33. } else if(result == DialogExResultRight) {
  34. view_dispatcher_switch_to_view(app->view_dispatcher, app->view_id); // Show last view
  35. } else if(result == DialogExResultCenter) {
  36. view_dispatcher_switch_to_view(app->view_dispatcher, AirMouseViewSubmenu); // Menu
  37. }
  38. }
  39. uint32_t air_mouse_exit_confirm_view(void* context) {
  40. UNUSED(context);
  41. return AirMouseViewExitConfirm;
  42. }
  43. uint32_t air_mouse_exit(void* context) {
  44. UNUSED(context);
  45. return VIEW_NONE;
  46. }
  47. AirMouse* air_mouse_app_alloc() {
  48. AirMouse* app = malloc(sizeof(AirMouse));
  49. Storage* storage = furi_record_open(RECORD_STORAGE);
  50. storage_simply_mkdir(storage, EXT_PATH("apps_data/air_mouse"));
  51. storage_common_migrate(
  52. storage, EXT_PATH(".calibration.data"), EXT_PATH("apps_data/air_mouse/calibration.data"));
  53. furi_record_close(RECORD_STORAGE);
  54. // Gui
  55. app->gui = furi_record_open(RECORD_GUI);
  56. // View dispatcher
  57. app->view_dispatcher = view_dispatcher_alloc();
  58. view_dispatcher_enable_queue(app->view_dispatcher);
  59. view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
  60. // Submenu view
  61. app->submenu = submenu_alloc();
  62. submenu_add_item(
  63. app->submenu, "Bluetooth", AirMouseSubmenuIndexBtMouse, air_mouse_submenu_callback, app);
  64. submenu_add_item(
  65. app->submenu, "USB", AirMouseSubmenuIndexUsbMouse, air_mouse_submenu_callback, app);
  66. submenu_add_item(
  67. app->submenu,
  68. "Calibration",
  69. AirMouseSubmenuIndexCalibration,
  70. air_mouse_submenu_callback,
  71. app);
  72. submenu_add_item(
  73. app->submenu,
  74. "Clear Bluetooth Pairings",
  75. AirMouseSubmenuIndexRemovePairing,
  76. air_mouse_submenu_callback,
  77. app);
  78. view_set_previous_callback(submenu_get_view(app->submenu), air_mouse_exit);
  79. view_dispatcher_add_view(
  80. app->view_dispatcher, AirMouseViewSubmenu, submenu_get_view(app->submenu));
  81. // Dialog views
  82. app->dialog = dialog_ex_alloc();
  83. dialog_ex_set_result_callback(app->dialog, air_mouse_dialog_callback);
  84. dialog_ex_set_context(app->dialog, app);
  85. dialog_ex_set_left_button_text(app->dialog, "Exit");
  86. dialog_ex_set_right_button_text(app->dialog, "Stay");
  87. dialog_ex_set_center_button_text(app->dialog, "Menu");
  88. dialog_ex_set_header(app->dialog, "Close Current App?", 16, 12, AlignLeft, AlignTop);
  89. view_dispatcher_add_view(
  90. app->view_dispatcher, AirMouseViewExitConfirm, dialog_ex_get_view(app->dialog));
  91. app->error_dialog = dialog_ex_alloc();
  92. dialog_ex_set_header(app->error_dialog, "Failed to init IMU", 63, 0, AlignCenter, AlignTop);
  93. dialog_ex_set_text(app->error_dialog, "Please connect sensor module", 63, 30, AlignCenter, AlignTop);
  94. view_set_previous_callback(dialog_ex_get_view(app->error_dialog), air_mouse_exit);
  95. view_dispatcher_add_view(
  96. app->view_dispatcher, AirMouseViewError, dialog_ex_get_view(app->error_dialog));
  97. // Bluetooth view
  98. app->bt_mouse = bt_mouse_alloc(app->view_dispatcher);
  99. view_set_previous_callback(bt_mouse_get_view(app->bt_mouse), air_mouse_exit_confirm_view);
  100. view_dispatcher_add_view(
  101. app->view_dispatcher, AirMouseViewBtMouse, bt_mouse_get_view(app->bt_mouse));
  102. // USB view
  103. app->usb_mouse = usb_mouse_alloc(app->view_dispatcher);
  104. view_set_previous_callback(usb_mouse_get_view(app->usb_mouse), air_mouse_exit_confirm_view);
  105. view_dispatcher_add_view(
  106. app->view_dispatcher, AirMouseViewUsbMouse, usb_mouse_get_view(app->usb_mouse));
  107. // Calibration view
  108. app->calibration = calibration_alloc(app->view_dispatcher);
  109. view_set_previous_callback(
  110. calibration_get_view(app->calibration), air_mouse_exit_confirm_view);
  111. view_dispatcher_add_view(
  112. app->view_dispatcher, AirMouseViewCalibration, calibration_get_view(app->calibration));
  113. app->view_id = AirMouseViewSubmenu;
  114. view_dispatcher_switch_to_view(app->view_dispatcher, app->view_id);
  115. return app;
  116. }
  117. void air_mouse_app_free(AirMouse* app) {
  118. furi_assert(app);
  119. // Free views
  120. view_dispatcher_remove_view(app->view_dispatcher, AirMouseViewSubmenu);
  121. submenu_free(app->submenu);
  122. view_dispatcher_remove_view(app->view_dispatcher, AirMouseViewExitConfirm);
  123. dialog_ex_free(app->dialog);
  124. view_dispatcher_remove_view(app->view_dispatcher, AirMouseViewError);
  125. dialog_ex_free(app->error_dialog);
  126. view_dispatcher_remove_view(app->view_dispatcher, AirMouseViewBtMouse);
  127. bt_mouse_free(app->bt_mouse);
  128. view_dispatcher_remove_view(app->view_dispatcher, AirMouseViewUsbMouse);
  129. usb_mouse_free(app->usb_mouse);
  130. view_dispatcher_remove_view(app->view_dispatcher, AirMouseViewCalibration);
  131. calibration_free(app->calibration);
  132. view_dispatcher_free(app->view_dispatcher);
  133. // Close records
  134. furi_record_close(RECORD_GUI);
  135. app->gui = NULL;
  136. // Free rest
  137. free(app);
  138. }
  139. int32_t air_mouse_app(void* p) {
  140. UNUSED(p);
  141. AirMouse* app = air_mouse_app_alloc();
  142. if(!imu_begin()) {
  143. view_dispatcher_switch_to_view(app->view_dispatcher, AirMouseViewError);
  144. }
  145. view_dispatcher_run(app->view_dispatcher);
  146. imu_end();
  147. air_mouse_app_free(app);
  148. return 0;
  149. }