desktop_scene_main.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #include <furi.h>
  2. #include <furi_hal.h>
  3. #include <applications.h>
  4. #include <assets_icons.h>
  5. #include <loader/loader.h>
  6. #include "../desktop_i.h"
  7. #include "../views/desktop_events.h"
  8. #include "../views/desktop_view_main.h"
  9. #include "desktop_scene.h"
  10. #include "desktop_scene_i.h"
  11. #define TAG "DesktopSrv"
  12. #define MUSIC_PLAYER_APP EXT_PATH("/apps/Media/music_player.fap")
  13. #define SNAKE_GAME_APP EXT_PATH("/apps/Games/snake_game.fap")
  14. #define CLOCK_APP EXT_PATH("/apps/Tools/clock.fap")
  15. static void desktop_scene_main_new_idle_animation_callback(void* context) {
  16. furi_assert(context);
  17. Desktop* desktop = context;
  18. view_dispatcher_send_custom_event(
  19. desktop->view_dispatcher, DesktopAnimationEventNewIdleAnimation);
  20. }
  21. static void desktop_scene_main_check_animation_callback(void* context) {
  22. furi_assert(context);
  23. Desktop* desktop = context;
  24. view_dispatcher_send_custom_event(
  25. desktop->view_dispatcher, DesktopAnimationEventCheckAnimation);
  26. }
  27. static void desktop_scene_main_interact_animation_callback(void* context) {
  28. furi_assert(context);
  29. Desktop* desktop = context;
  30. view_dispatcher_send_custom_event(
  31. desktop->view_dispatcher, DesktopAnimationEventInteractAnimation);
  32. }
  33. #ifdef APP_ARCHIVE
  34. static void desktop_switch_to_app(Desktop* desktop, const FlipperApplication* flipper_app) {
  35. furi_assert(desktop);
  36. furi_assert(flipper_app);
  37. furi_assert(flipper_app->app);
  38. furi_assert(flipper_app->name);
  39. if(furi_thread_get_state(desktop->scene_thread) != FuriThreadStateStopped) {
  40. FURI_LOG_E("Desktop", "Thread is already running");
  41. return;
  42. }
  43. FuriHalRtcHeapTrackMode mode = furi_hal_rtc_get_heap_track_mode();
  44. if(mode > FuriHalRtcHeapTrackModeNone) {
  45. furi_thread_enable_heap_trace(desktop->scene_thread);
  46. } else {
  47. furi_thread_disable_heap_trace(desktop->scene_thread);
  48. }
  49. furi_thread_set_name(desktop->scene_thread, flipper_app->name);
  50. furi_thread_set_stack_size(desktop->scene_thread, flipper_app->stack_size);
  51. furi_thread_set_callback(desktop->scene_thread, flipper_app->app);
  52. furi_thread_start(desktop->scene_thread);
  53. }
  54. #endif
  55. static void desktop_scene_main_open_app_or_profile(Desktop* desktop, const char* path) {
  56. do {
  57. LoaderStatus status = loader_start(desktop->loader, FAP_LOADER_APP_NAME, path);
  58. if(status == LoaderStatusOk) break;
  59. FURI_LOG_E(TAG, "loader_start failed: %d", status);
  60. status = loader_start(desktop->loader, "Passport", NULL);
  61. if(status != LoaderStatusOk) {
  62. FURI_LOG_E(TAG, "loader_start failed: %d", status);
  63. }
  64. } while(false);
  65. }
  66. void desktop_scene_main_callback(DesktopEvent event, void* context) {
  67. Desktop* desktop = (Desktop*)context;
  68. if(desktop->in_transition) return;
  69. view_dispatcher_send_custom_event(desktop->view_dispatcher, event);
  70. }
  71. void desktop_scene_main_on_enter(void* context) {
  72. Desktop* desktop = (Desktop*)context;
  73. DesktopMainView* main_view = desktop->main_view;
  74. animation_manager_set_context(desktop->animation_manager, desktop);
  75. animation_manager_set_new_idle_callback(
  76. desktop->animation_manager, desktop_scene_main_new_idle_animation_callback);
  77. animation_manager_set_check_callback(
  78. desktop->animation_manager, desktop_scene_main_check_animation_callback);
  79. animation_manager_set_interact_callback(
  80. desktop->animation_manager, desktop_scene_main_interact_animation_callback);
  81. desktop_main_set_callback(main_view, desktop_scene_main_callback, desktop);
  82. view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdMain);
  83. }
  84. bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
  85. Desktop* desktop = (Desktop*)context;
  86. bool consumed = false;
  87. if(event.type == SceneManagerEventTypeCustom) {
  88. switch(event.event) {
  89. case DesktopMainEventOpenMenu: {
  90. Loader* loader = furi_record_open(RECORD_LOADER);
  91. loader_show_menu(loader);
  92. furi_record_close(RECORD_LOADER);
  93. consumed = true;
  94. } break;
  95. case DesktopMainEventOpenLockMenu:
  96. scene_manager_next_scene(desktop->scene_manager, DesktopSceneLockMenu);
  97. consumed = true;
  98. break;
  99. case DesktopMainEventOpenDebug:
  100. scene_manager_next_scene(desktop->scene_manager, DesktopSceneDebug);
  101. consumed = true;
  102. break;
  103. case DesktopMainEventOpenArchive:
  104. #ifdef APP_ARCHIVE
  105. desktop_switch_to_app(desktop, &FLIPPER_ARCHIVE);
  106. #endif
  107. consumed = true;
  108. break;
  109. case DesktopMainEventOpenPowerOff: {
  110. LoaderStatus status = loader_start(desktop->loader, "Power", "off");
  111. if(status != LoaderStatusOk) {
  112. FURI_LOG_E(TAG, "loader_start failed: %d", status);
  113. }
  114. consumed = true;
  115. break;
  116. }
  117. case DesktopMainEventOpenFavoritePrimary:
  118. DESKTOP_SETTINGS_LOAD(&desktop->settings);
  119. if(desktop->settings.favorite_primary.is_external) {
  120. LoaderStatus status = loader_start(
  121. desktop->loader,
  122. FAP_LOADER_APP_NAME,
  123. desktop->settings.favorite_primary.name_or_path);
  124. if(status != LoaderStatusOk) {
  125. FURI_LOG_E(TAG, "loader_start failed: %d", status);
  126. }
  127. } else {
  128. LoaderStatus status = loader_start(
  129. desktop->loader, desktop->settings.favorite_primary.name_or_path, NULL);
  130. if(status != LoaderStatusOk) {
  131. FURI_LOG_E(TAG, "loader_start failed: %d", status);
  132. }
  133. }
  134. consumed = true;
  135. break;
  136. case DesktopMainEventOpenFavoriteSecondary:
  137. DESKTOP_SETTINGS_LOAD(&desktop->settings);
  138. if(desktop->settings.favorite_secondary.is_external) {
  139. LoaderStatus status = loader_start(
  140. desktop->loader,
  141. FAP_LOADER_APP_NAME,
  142. desktop->settings.favorite_secondary.name_or_path);
  143. if(status != LoaderStatusOk) {
  144. FURI_LOG_E(TAG, "loader_start failed: %d", status);
  145. }
  146. } else {
  147. LoaderStatus status = loader_start(
  148. desktop->loader, desktop->settings.favorite_secondary.name_or_path, NULL);
  149. if(status != LoaderStatusOk) {
  150. FURI_LOG_E(TAG, "loader_start failed: %d", status);
  151. }
  152. }
  153. consumed = true;
  154. break;
  155. case DesktopAnimationEventCheckAnimation:
  156. animation_manager_check_blocking_process(desktop->animation_manager);
  157. consumed = true;
  158. break;
  159. case DesktopAnimationEventNewIdleAnimation:
  160. animation_manager_new_idle_process(desktop->animation_manager);
  161. consumed = true;
  162. break;
  163. case DesktopAnimationEventInteractAnimation:
  164. if(!animation_manager_interact_process(desktop->animation_manager)) {
  165. LoaderStatus status = loader_start(desktop->loader, "Passport", NULL);
  166. if(status != LoaderStatusOk) {
  167. FURI_LOG_E(TAG, "loader_start failed: %d", status);
  168. }
  169. }
  170. consumed = true;
  171. break;
  172. case DesktopMainEventOpenPassport: {
  173. LoaderStatus status = loader_start(desktop->loader, "Passport", NULL);
  174. if(status != LoaderStatusOk) {
  175. FURI_LOG_E(TAG, "loader_start failed: %d", status);
  176. }
  177. break;
  178. }
  179. case DesktopMainEventOpenGame: {
  180. desktop_scene_main_open_app_or_profile(desktop, SNAKE_GAME_APP);
  181. break;
  182. }
  183. case DesktopMainEventOpenClock: {
  184. desktop_scene_main_open_app_or_profile(desktop, CLOCK_APP);
  185. break;
  186. }
  187. case DesktopMainEventOpenMusicPlayer: {
  188. desktop_scene_main_open_app_or_profile(desktop, MUSIC_PLAYER_APP);
  189. break;
  190. }
  191. case DesktopLockedEventUpdate:
  192. desktop_view_locked_update(desktop->locked_view);
  193. consumed = true;
  194. break;
  195. default:
  196. break;
  197. }
  198. }
  199. return consumed;
  200. }
  201. void desktop_scene_main_on_exit(void* context) {
  202. Desktop* desktop = (Desktop*)context;
  203. animation_manager_set_new_idle_callback(desktop->animation_manager, NULL);
  204. animation_manager_set_check_callback(desktop->animation_manager, NULL);
  205. animation_manager_set_interact_callback(desktop->animation_manager, NULL);
  206. animation_manager_set_context(desktop->animation_manager, desktop);
  207. }