ocarina.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #include <furi.h>
  2. #include <furi_hal.h>
  3. #include <gui/gui.h>
  4. #include <input/input.h>
  5. #include <stdlib.h>
  6. #define NOTE_UP 587.33f
  7. #define NOTE_LEFT 493.88f
  8. #define NOTE_RIGHT 440.00f
  9. #define NOTE_DOWN 349.23
  10. #define NOTE_OK 293.66f
  11. typedef struct {
  12. FuriMutex* model_mutex;
  13. FuriMessageQueue* event_queue;
  14. ViewPort* view_port;
  15. Gui* gui;
  16. } Ocarina;
  17. void draw_callback(Canvas* canvas, void* ctx) {
  18. Ocarina* ocarina = ctx;
  19. furi_check(furi_mutex_acquire(ocarina->model_mutex, FuriWaitForever) == FuriStatusOk);
  20. //canvas_draw_box(canvas, ocarina->model->x, ocarina->model->y, 4, 4);
  21. canvas_draw_frame(canvas, 0, 0, 128, 64);
  22. canvas_draw_str(canvas, 50, 10, "Ocarina");
  23. canvas_draw_str(canvas, 30, 20, "OK button for A");
  24. furi_mutex_release(ocarina->model_mutex);
  25. }
  26. void input_callback(InputEvent* input, void* ctx) {
  27. Ocarina* ocarina = ctx;
  28. // Puts input onto event queue with priority 0, and waits until completion.
  29. furi_message_queue_put(ocarina->event_queue, input, FuriWaitForever);
  30. }
  31. Ocarina* ocarina_alloc() {
  32. Ocarina* instance = malloc(sizeof(Ocarina));
  33. instance->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
  34. instance->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
  35. instance->view_port = view_port_alloc();
  36. view_port_draw_callback_set(instance->view_port, draw_callback, instance);
  37. view_port_input_callback_set(instance->view_port, input_callback, instance);
  38. instance->gui = furi_record_open("gui");
  39. gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen);
  40. return instance;
  41. }
  42. void ocarina_free(Ocarina* instance) {
  43. view_port_enabled_set(instance->view_port, false); // Disabsles our ViewPort
  44. gui_remove_view_port(instance->gui, instance->view_port); // Removes our ViewPort from the Gui
  45. furi_record_close("gui"); // Closes the gui record
  46. view_port_free(instance->view_port); // Frees memory allocated by view_port_alloc
  47. furi_message_queue_free(instance->event_queue);
  48. furi_mutex_free(instance->model_mutex);
  49. if(furi_hal_speaker_is_mine()) {
  50. furi_hal_speaker_stop();
  51. furi_hal_speaker_release();
  52. }
  53. free(instance);
  54. }
  55. int32_t ocarina_app(void* p) {
  56. UNUSED(p);
  57. Ocarina* ocarina = ocarina_alloc();
  58. InputEvent event;
  59. for(bool processing = true; processing;) {
  60. // Pops a message off the queue and stores it in `event`.
  61. // No message priority denoted by NULL, and 100 ticks of timeout.
  62. FuriStatus status = furi_message_queue_get(ocarina->event_queue, &event, 100);
  63. furi_check(furi_mutex_acquire(ocarina->model_mutex, FuriWaitForever) == FuriStatusOk);
  64. float volume = 1.0f;
  65. if(status == FuriStatusOk) {
  66. if(event.type == InputTypePress) {
  67. switch(event.key) {
  68. case InputKeyUp:
  69. if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(1000)) {
  70. furi_hal_speaker_start(NOTE_UP, volume);
  71. }
  72. break;
  73. case InputKeyDown:
  74. if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(1000)) {
  75. furi_hal_speaker_start(NOTE_DOWN, volume);
  76. }
  77. break;
  78. case InputKeyLeft:
  79. if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(1000)) {
  80. furi_hal_speaker_start(NOTE_LEFT, volume);
  81. }
  82. break;
  83. case InputKeyRight:
  84. if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(1000)) {
  85. furi_hal_speaker_start(NOTE_RIGHT, volume);
  86. }
  87. break;
  88. case InputKeyOk:
  89. if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(1000)) {
  90. furi_hal_speaker_start(NOTE_OK, volume);
  91. }
  92. break;
  93. case InputKeyBack:
  94. processing = false;
  95. break;
  96. default:
  97. break;
  98. }
  99. } else if(event.type == InputTypeRelease) {
  100. if(furi_hal_speaker_is_mine()) {
  101. furi_hal_speaker_stop();
  102. furi_hal_speaker_release();
  103. }
  104. }
  105. }
  106. furi_mutex_release(ocarina->model_mutex);
  107. view_port_update(ocarina->view_port); // signals our draw callback
  108. }
  109. ocarina_free(ocarina);
  110. return 0;
  111. }