init_deinit.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. #include "init_deinit.h"
  2. #include "input_event.h"
  3. #include "diskop.h"
  4. #define AUDIO_MODES_COUNT 2
  5. static void tracker_redraw_update_model(void* context) {
  6. FlizzerTrackerApp* tracker = context;
  7. view_commit_model(tracker->tracker_view->view, true);
  8. }
  9. TrackerView* tracker_view_alloc(FlizzerTrackerApp* tracker) {
  10. TrackerView* tracker_view = malloc(sizeof(TrackerView));
  11. tracker_view->view = view_alloc();
  12. tracker_view->context = tracker;
  13. view_set_context(tracker_view->view, tracker_view);
  14. view_allocate_model(tracker_view->view, ViewModelTypeLockFree, sizeof(TrackerViewModel));
  15. view_set_draw_callback(tracker_view->view, draw_callback);
  16. view_set_input_callback(tracker_view->view, input_callback);
  17. view_dispatcher_set_event_callback_context(tracker->view_dispatcher, tracker);
  18. view_dispatcher_set_tick_event_callback(
  19. tracker->view_dispatcher, tracker_redraw_update_model, 250);
  20. return tracker_view;
  21. }
  22. void tracker_view_free(TrackerView* tracker_view) {
  23. furi_assert(tracker_view);
  24. view_free(tracker_view->view);
  25. free(tracker_view);
  26. }
  27. uint8_t my_value_index_bool(
  28. const bool value,
  29. const bool values[],
  30. uint8_t
  31. values_count) // why the fuck it gives unresolved symbol if I include it from toolbox???!!!
  32. {
  33. uint8_t index = 0;
  34. for(uint8_t i = 0; i < values_count; i++) {
  35. if(value == values[i]) {
  36. index = i;
  37. break;
  38. }
  39. }
  40. return index;
  41. }
  42. FlizzerTrackerApp* init_tracker(
  43. uint32_t sample_rate,
  44. uint8_t rate,
  45. bool external_audio_output,
  46. uint32_t audio_buffer_size) {
  47. FlizzerTrackerApp* tracker = malloc(sizeof(FlizzerTrackerApp));
  48. memset(tracker, 0, sizeof(FlizzerTrackerApp));
  49. tracker->external_audio = external_audio_output;
  50. sound_engine_init(
  51. &tracker->sound_engine, sample_rate, external_audio_output, audio_buffer_size);
  52. tracker_engine_init(&tracker->tracker_engine, rate, &tracker->sound_engine);
  53. tracker->tracker_engine.song = &tracker->song;
  54. tracker->current_note = MIDDLE_C;
  55. // Очередь событий на 8 элементов размера FlizzerTrackerEvent
  56. tracker->event_queue = furi_message_queue_alloc(8, sizeof(FlizzerTrackerEvent));
  57. tracker->gui = furi_record_open(RECORD_GUI);
  58. tracker->view_dispatcher = view_dispatcher_alloc();
  59. tracker->tracker_view = tracker_view_alloc(tracker);
  60. with_view_model(
  61. tracker->tracker_view->view, TrackerViewModel * model, { model->tracker = tracker; }, true);
  62. view_dispatcher_add_view(tracker->view_dispatcher, VIEW_TRACKER, tracker->tracker_view->view);
  63. view_dispatcher_attach_to_gui(
  64. tracker->view_dispatcher, tracker->gui, ViewDispatcherTypeFullscreen);
  65. tracker->storage = furi_record_open(RECORD_STORAGE);
  66. tracker->stream = file_stream_alloc(tracker->storage);
  67. tracker->text_input = text_input_alloc();
  68. view_dispatcher_add_view(
  69. tracker->view_dispatcher, VIEW_KEYBOARD, text_input_get_view(tracker->text_input));
  70. tracker->pattern_submenu = submenu_alloc();
  71. tracker->pattern_copypaste_submenu = submenu_alloc();
  72. tracker->instrument_submenu = submenu_alloc();
  73. view_set_previous_callback(submenu_get_view(tracker->pattern_submenu), submenu_exit_callback);
  74. view_set_previous_callback(
  75. submenu_get_view(tracker->pattern_copypaste_submenu), submenu_exit_callback);
  76. view_set_previous_callback(
  77. submenu_get_view(tracker->instrument_submenu), submenu_exit_callback);
  78. submenu_add_item(
  79. tracker->pattern_submenu,
  80. "Load song",
  81. SUBMENU_PATTERN_LOAD_SONG,
  82. submenu_callback,
  83. tracker);
  84. submenu_add_item(
  85. tracker->pattern_submenu,
  86. "Save song",
  87. SUBMENU_PATTERN_SAVE_SONG,
  88. submenu_callback,
  89. tracker);
  90. submenu_add_item(
  91. tracker->pattern_submenu, "Settings", SUBMENU_PATTERN_SETTINGS, submenu_callback, tracker);
  92. submenu_add_item(
  93. tracker->pattern_submenu, "Help", SUBMENU_PATTERN_HELP, submenu_callback, tracker);
  94. submenu_add_item(
  95. tracker->pattern_submenu, "Exit", SUBMENU_PATTERN_EXIT, submenu_callback, tracker);
  96. submenu_add_item(
  97. tracker->instrument_submenu,
  98. "Load instrument",
  99. SUBMENU_INSTRUMENT_LOAD,
  100. submenu_callback,
  101. tracker);
  102. submenu_add_item(
  103. tracker->instrument_submenu,
  104. "Save instrument",
  105. SUBMENU_INSTRUMENT_SAVE,
  106. submenu_callback,
  107. tracker);
  108. submenu_add_item(
  109. tracker->instrument_submenu, "Exit", SUBMENU_INSTRUMENT_EXIT, submenu_callback, tracker);
  110. submenu_add_item(
  111. tracker->pattern_copypaste_submenu,
  112. "Copy",
  113. SUBMENU_PATTERN_COPYPASTE_COPY,
  114. submenu_copypaste_callback,
  115. tracker);
  116. submenu_add_item(
  117. tracker->pattern_copypaste_submenu,
  118. "Paste",
  119. SUBMENU_PATTERN_COPYPASTE_PASTE,
  120. submenu_copypaste_callback,
  121. tracker);
  122. submenu_add_item(
  123. tracker->pattern_copypaste_submenu,
  124. "Cut",
  125. SUBMENU_PATTERN_COPYPASTE_CUT,
  126. submenu_copypaste_callback,
  127. tracker);
  128. submenu_add_item(
  129. tracker->pattern_copypaste_submenu,
  130. "Clear",
  131. SUBMENU_PATTERN_COPYPASTE_CLEAR,
  132. submenu_copypaste_callback,
  133. tracker);
  134. view_dispatcher_add_view(
  135. tracker->view_dispatcher,
  136. VIEW_SUBMENU_PATTERN,
  137. submenu_get_view(tracker->pattern_submenu));
  138. view_dispatcher_add_view(
  139. tracker->view_dispatcher,
  140. VIEW_SUBMENU_PATTERN_COPYPASTE,
  141. submenu_get_view(tracker->pattern_copypaste_submenu));
  142. view_dispatcher_add_view(
  143. tracker->view_dispatcher,
  144. VIEW_SUBMENU_INSTRUMENT,
  145. submenu_get_view(tracker->instrument_submenu));
  146. load_config(tracker);
  147. tracker->settings_list = variable_item_list_alloc();
  148. View* view = variable_item_list_get_view(tracker->settings_list);
  149. view_set_previous_callback(view, submenu_settings_exit_callback);
  150. VariableItem* item;
  151. uint8_t value_index;
  152. item = variable_item_list_add(
  153. tracker->settings_list,
  154. "Audio output",
  155. AUDIO_MODES_COUNT,
  156. audio_output_changed_callback,
  157. tracker);
  158. value_index =
  159. my_value_index_bool(tracker->external_audio, audio_modes_values, AUDIO_MODES_COUNT);
  160. variable_item_set_current_value_index(item, value_index);
  161. variable_item_set_current_value_text(item, audio_modes_text[value_index]);
  162. view_dispatcher_add_view(tracker->view_dispatcher, VIEW_SETTINGS, view);
  163. tracker->overwrite_file_widget = widget_alloc();
  164. widget_add_button_element(
  165. tracker->overwrite_file_widget,
  166. GuiButtonTypeLeft,
  167. "No",
  168. (ButtonCallback)overwrite_file_widget_no_input_callback,
  169. tracker);
  170. widget_add_button_element(
  171. tracker->overwrite_file_widget,
  172. GuiButtonTypeRight,
  173. "Yes",
  174. (ButtonCallback)overwrite_file_widget_yes_input_callback,
  175. tracker);
  176. widget_add_text_scroll_element(
  177. tracker->overwrite_file_widget,
  178. 0,
  179. 0,
  180. 128,
  181. 64,
  182. "This song file already exists,\n do you want to overwrite it?");
  183. view_dispatcher_add_view(
  184. tracker->view_dispatcher,
  185. VIEW_FILE_OVERWRITE,
  186. widget_get_view(tracker->overwrite_file_widget));
  187. tracker->overwrite_instrument_file_widget = widget_alloc();
  188. widget_add_button_element(
  189. tracker->overwrite_instrument_file_widget,
  190. GuiButtonTypeLeft,
  191. "No",
  192. (ButtonCallback)overwrite_instrument_file_widget_no_input_callback,
  193. tracker);
  194. widget_add_button_element(
  195. tracker->overwrite_instrument_file_widget,
  196. GuiButtonTypeRight,
  197. "Yes",
  198. (ButtonCallback)overwrite_instrument_file_widget_yes_input_callback,
  199. tracker);
  200. widget_add_text_scroll_element(
  201. tracker->overwrite_instrument_file_widget,
  202. 0,
  203. 0,
  204. 128,
  205. 64,
  206. "This instrument file already\nexists, do you want to\noverwrite it?");
  207. view_dispatcher_add_view(
  208. tracker->view_dispatcher,
  209. VIEW_INSTRUMENT_FILE_OVERWRITE,
  210. widget_get_view(tracker->overwrite_instrument_file_widget));
  211. tracker->notification = furi_record_open(RECORD_NOTIFICATION);
  212. notification_message(tracker->notification, &sequence_display_backlight_enforce_on);
  213. set_default_song(tracker);
  214. tracker->focus = EDIT_SONGINFO;
  215. tracker->source_pattern_index = -1;
  216. return tracker;
  217. }
  218. void deinit_tracker(FlizzerTrackerApp* tracker) {
  219. notification_message(tracker->notification, &sequence_display_backlight_enforce_auto);
  220. furi_record_close(RECORD_NOTIFICATION);
  221. // Специальная очистка памяти, занимаемой очередью
  222. furi_message_queue_free(tracker->event_queue);
  223. view_dispatcher_remove_view(tracker->view_dispatcher, VIEW_SETTINGS);
  224. view_dispatcher_remove_view(tracker->view_dispatcher, VIEW_FILE_OVERWRITE);
  225. view_dispatcher_remove_view(tracker->view_dispatcher, VIEW_SUBMENU_INSTRUMENT);
  226. view_dispatcher_remove_view(tracker->view_dispatcher, VIEW_INSTRUMENT_FILE_OVERWRITE);
  227. view_dispatcher_remove_view(tracker->view_dispatcher, VIEW_SUBMENU_PATTERN_COPYPASTE);
  228. view_dispatcher_remove_view(tracker->view_dispatcher, VIEW_SUBMENU_PATTERN);
  229. view_dispatcher_remove_view(tracker->view_dispatcher, VIEW_KEYBOARD);
  230. view_dispatcher_remove_view(tracker->view_dispatcher, VIEW_TRACKER);
  231. text_input_free(tracker->text_input);
  232. variable_item_list_free(tracker->settings_list);
  233. submenu_free(tracker->pattern_submenu);
  234. submenu_free(tracker->pattern_copypaste_submenu);
  235. submenu_free(tracker->instrument_submenu);
  236. widget_free(tracker->overwrite_file_widget);
  237. widget_free(tracker->overwrite_instrument_file_widget);
  238. view_dispatcher_free(tracker->view_dispatcher);
  239. tracker_view_free(tracker->tracker_view);
  240. furi_record_close(RECORD_GUI);
  241. stream_free(tracker->stream);
  242. furi_record_close(RECORD_STORAGE);
  243. sound_engine_deinit(&tracker->sound_engine);
  244. if(tracker->tracker_engine.song == NULL) {
  245. tracker_engine_set_song(&tracker->tracker_engine, &tracker->song);
  246. }
  247. tracker_engine_deinit(&tracker->tracker_engine, false);
  248. free(tracker);
  249. }