simple music player app (#240)
* split power-cli dependence * music_player application * add player to release mode * fix stupid error
This commit is contained in:
		
							parent
							
								
									3d5563b169
								
							
						
					
					
						commit
						3d6af91dd1
					
				| @ -36,6 +36,7 @@ void sd_card_test(void* p); | |||||||
| void application_vibro(void* p); | void application_vibro(void* p); | ||||||
| void app_gpio_test(void* p); | void app_gpio_test(void* p); | ||||||
| void cli_task(void* p); | void cli_task(void* p); | ||||||
|  | void music_player(void* p); | ||||||
| 
 | 
 | ||||||
| const FlipperStartupApp FLIPPER_STARTUP[] = { | const FlipperStartupApp FLIPPER_STARTUP[] = { | ||||||
| #ifdef APP_DISPLAY | #ifdef APP_DISPLAY | ||||||
| @ -121,6 +122,10 @@ const FlipperStartupApp FLIPPER_STARTUP[] = { | |||||||
|     {.app = sd_card_test, .name = "sd_card_test", .libs = {1, FURI_LIB{"gui_task"}}}, |     {.app = sd_card_test, .name = "sd_card_test", .libs = {1, FURI_LIB{"gui_task"}}}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #ifdef APP_MUSIC_PLAYER | ||||||
|  |     {.app = music_player, .name = "music player", .libs = {1, FURI_LIB{"gui_task"}}}, | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #ifdef APP_GPIO_DEMO | #ifdef APP_GPIO_DEMO | ||||||
|     { |     { | ||||||
|         .app = app_gpio_test, |         .app = app_gpio_test, | ||||||
| @ -169,4 +174,8 @@ const FlipperStartupApp FLIPPER_APPS[] = { | |||||||
| #ifdef BUILD_GPIO_DEMO | #ifdef BUILD_GPIO_DEMO | ||||||
|     {.app = app_gpio_test, .name = "gpio test", .libs = {1, FURI_LIB{"gui_task"}}}, |     {.app = app_gpio_test, .name = "gpio test", .libs = {1, FURI_LIB{"gui_task"}}}, | ||||||
| #endif | #endif | ||||||
|  | 
 | ||||||
|  | #ifdef BUILD_MUSIC_PLAYER | ||||||
|  |     {.app = music_player, .name = "music player", .libs = {1, FURI_LIB{"gui_task"}}}, | ||||||
|  | #endif | ||||||
| }; | }; | ||||||
| @ -23,6 +23,7 @@ BUILD_SPEAKER_DEMO = 1 | |||||||
| BUILD_VIBRO_DEMO = 1 | BUILD_VIBRO_DEMO = 1 | ||||||
| BUILD_SD_TEST = 1 | BUILD_SD_TEST = 1 | ||||||
| BUILD_GPIO_DEMO = 1 | BUILD_GPIO_DEMO = 1 | ||||||
|  | BUILD_MUSIC_PLAYER = 1 | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
| APP_NFC ?= 0 | APP_NFC ?= 0 | ||||||
| @ -246,6 +247,17 @@ CFLAGS		+= -DBUILD_GPIO_DEMO | |||||||
| C_SOURCES	+= $(wildcard $(APP_DIR)/gpio-tester/*.c) | C_SOURCES	+= $(wildcard $(APP_DIR)/gpio-tester/*.c) | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
|  | APP_MUSIC_PLAYER ?= 0 | ||||||
|  | ifeq ($(APP_MUSIC_PLAYER), 1) | ||||||
|  | CFLAGS		+= -DAPP_MUSIC_PLAYER | ||||||
|  | BUILD_MUSIC_PLAYER = 1 | ||||||
|  | endif | ||||||
|  | BUILD_MUSIC_PLAYER ?= 0 | ||||||
|  | ifeq ($(BUILD_MUSIC_PLAYER), 1) | ||||||
|  | CFLAGS		+= -DBUILD_MUSIC_PLAYER | ||||||
|  | C_SOURCES	+= $(wildcard $(APP_DIR)/music-player/*.c) | ||||||
|  | endif | ||||||
|  | 
 | ||||||
| # device drivers
 | # device drivers
 | ||||||
| 
 | 
 | ||||||
| APP_GUI	?= 0 | APP_GUI	?= 0 | ||||||
|  | |||||||
							
								
								
									
										444
									
								
								applications/music-player/music-player.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										444
									
								
								applications/music-player/music-player.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,444 @@ | |||||||
|  | #include "flipper_v2.h" | ||||||
|  | 
 | ||||||
|  | // TODO float note freq
 | ||||||
|  | typedef enum { | ||||||
|  |     // Delay
 | ||||||
|  |     N = 0, | ||||||
|  |     // Octave 4
 | ||||||
|  |     B4 = 494, | ||||||
|  |     // Octave 5
 | ||||||
|  |     C5 = 523, | ||||||
|  |     D5 = 587, | ||||||
|  |     E5 = 659, | ||||||
|  |     F_5 = 740, | ||||||
|  |     G5 = 784, | ||||||
|  |     A5 = 880, | ||||||
|  |     B5 = 988, | ||||||
|  |     // Octave 6
 | ||||||
|  |     C6 = 1046, | ||||||
|  |     D6 = 1175, | ||||||
|  |     E6 = 1319, | ||||||
|  | } MelodyEventNote; | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     L1 = 1, | ||||||
|  |     L2 = 2, | ||||||
|  |     L4 = 4, | ||||||
|  |     L8 = 8, | ||||||
|  |     L16 = 16, | ||||||
|  |     L32 = 32, | ||||||
|  |     L64 = 64, | ||||||
|  |     L128 = 128, | ||||||
|  | } MelodyEventLength; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     MelodyEventNote note; | ||||||
|  |     MelodyEventLength length; | ||||||
|  | } MelodyEventRecord; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     const MelodyEventRecord* record; | ||||||
|  |     int8_t loop_count; | ||||||
|  | } SongPattern; | ||||||
|  | 
 | ||||||
|  | const MelodyEventRecord melody_start[] = { | ||||||
|  |     {E6, L8}, {N, L8},   {E5, L8}, {B5, L8},  {N, L4},  {E5, L8},  {A5, L8},  {G5, L8}, {A5, L8}, | ||||||
|  |     {E5, L8}, {B5, L8},  {N, L8},  {G5, L8},  {A5, L8}, {D6, L8},  {N, L4},   {D5, L8}, {B5, L8}, | ||||||
|  |     {N, L4},  {D5, L8},  {A5, L8}, {G5, L8},  {A5, L8}, {D5, L8},  {F_5, L8}, {N, L8},  {G5, L8}, | ||||||
|  |     {A5, L8}, {D6, L8},  {N, L4},  {F_5, L8}, {B5, L8}, {N, L4},   {F_5, L8}, {D6, L8}, {C6, L8}, | ||||||
|  |     {B5, L8}, {F_5, L8}, {A5, L8}, {N, L8},   {G5, L8}, {F_5, L8}, {E5, L8},  {N, L8},  {C5, L8}, | ||||||
|  |     {E5, L8}, {B5, L8},  {B4, L8}, {C5, L8},  {D5, L8}, {D6, L8},  {C6, L8},  {B5, L8}, {F_5, L8}, | ||||||
|  |     {A5, L8}, {N, L8},   {G5, L8}, {A5, L8},  {E6, L8}}; | ||||||
|  | 
 | ||||||
|  | const MelodyEventRecord melody_loop[] = { | ||||||
|  |     {N, L4},   {E5, L8}, {B5, L8},  {N, L4},  {E5, L8},  {A5, L8},  {G5, L8}, {A5, L8},  {E5, L8}, | ||||||
|  |     {B5, L8},  {N, L8},  {G5, L8},  {A5, L8}, {D6, L8},  {N, L4},   {D5, L8}, {B5, L8},  {N, L4}, | ||||||
|  |     {D5, L8},  {A5, L8}, {G5, L8},  {A5, L8}, {D5, L8},  {F_5, L8}, {N, L8},  {G5, L8},  {A5, L8}, | ||||||
|  |     {D6, L8},  {N, L4},  {F_5, L8}, {B5, L8}, {N, L4},   {F_5, L8}, {D6, L8}, {C6, L8},  {B5, L8}, | ||||||
|  |     {F_5, L8}, {A5, L8}, {N, L8},   {G5, L8}, {F_5, L8}, {E5, L8},  {N, L8},  {C5, L8},  {E5, L8}, | ||||||
|  |     {B5, L8},  {B4, L8}, {C5, L8},  {D5, L8}, {D6, L8},  {C6, L8},  {B5, L8}, {F_5, L8}, {A5, L8}, | ||||||
|  |     {N, L8},   {G5, L8}, {A5, L8},  {E6, L8}}; | ||||||
|  | 
 | ||||||
|  | const MelodyEventRecord melody_chords_1bar[] = { | ||||||
|  |     {E6, L8},   {N, L8},    {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, | ||||||
|  |     {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, | ||||||
|  |     {B4, L128}, {E5, L128}, {B5, L8},   {N, L4},    {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, | ||||||
|  |     {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, | ||||||
|  |     {B4, L128}, {E5, L128}, {B4, L128}, {E5, L128}, {A5, L8}}; | ||||||
|  | 
 | ||||||
|  | const SongPattern song[] = {{melody_start, 1}, {melody_loop, -1}}; | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     EventTypeTick, | ||||||
|  |     EventTypeKey, | ||||||
|  |     EventTypeNote, | ||||||
|  |     // add your events type
 | ||||||
|  | } MusicDemoEventType; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     union { | ||||||
|  |         InputEvent input; | ||||||
|  |         const MelodyEventRecord* note_record; | ||||||
|  |     } value; | ||||||
|  |     MusicDemoEventType type; | ||||||
|  | } MusicDemoEvent; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     ValueMutex* state_mutex; | ||||||
|  |     osMessageQueueId_t event_queue; | ||||||
|  | 
 | ||||||
|  | } MusicDemoContext; | ||||||
|  | 
 | ||||||
|  | #define note_stack_size 4 | ||||||
|  | typedef struct { | ||||||
|  |     // describe state here
 | ||||||
|  |     const MelodyEventRecord* note_record; | ||||||
|  |     const MelodyEventRecord* note_stack[note_stack_size]; | ||||||
|  |     uint8_t volume_id; | ||||||
|  |     uint8_t volume_id_max; | ||||||
|  | } State; | ||||||
|  | 
 | ||||||
|  | float volumes[] = {0, 0.02, 0.05, 0.1, 0.5}; | ||||||
|  | 
 | ||||||
|  | bool is_white_note(const MelodyEventRecord* note_record, uint8_t id) { | ||||||
|  |     if(note_record == NULL) return false; | ||||||
|  | 
 | ||||||
|  |     switch(note_record->note) { | ||||||
|  |     case C5: | ||||||
|  |     case C6: | ||||||
|  |         if(id == 0) return true; | ||||||
|  |         break; | ||||||
|  |     case D5: | ||||||
|  |     case D6: | ||||||
|  |         if(id == 1) return true; | ||||||
|  |         break; | ||||||
|  |     case E5: | ||||||
|  |     case E6: | ||||||
|  |         if(id == 2) return true; | ||||||
|  |         break; | ||||||
|  |     case G5: | ||||||
|  |         if(id == 4) return true; | ||||||
|  |         break; | ||||||
|  |     case A5: | ||||||
|  |         if(id == 5) return true; | ||||||
|  |         break; | ||||||
|  |     case B4: | ||||||
|  |     case B5: | ||||||
|  |         if(id == 6) return true; | ||||||
|  |         break; | ||||||
|  |     default: | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool is_black_note(const MelodyEventRecord* note_record, uint8_t id) { | ||||||
|  |     if(note_record == NULL) return false; | ||||||
|  | 
 | ||||||
|  |     switch(note_record->note) { | ||||||
|  |     case F_5: | ||||||
|  |         if(id == 3) return true; | ||||||
|  |         break; | ||||||
|  |     default: | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const char* get_note_name(const MelodyEventRecord* note_record) { | ||||||
|  |     if(note_record == NULL) return ""; | ||||||
|  | 
 | ||||||
|  |     switch(note_record->note) { | ||||||
|  |     case N: | ||||||
|  |         return "---"; | ||||||
|  |         break; | ||||||
|  |     case B4: | ||||||
|  |         return "B4-"; | ||||||
|  |         break; | ||||||
|  |     case C5: | ||||||
|  |         return "C5-"; | ||||||
|  |         break; | ||||||
|  |     case D5: | ||||||
|  |         return "D5-"; | ||||||
|  |         break; | ||||||
|  |     case E5: | ||||||
|  |         return "E5-"; | ||||||
|  |         break; | ||||||
|  |     case F_5: | ||||||
|  |         return "F#5"; | ||||||
|  |         break; | ||||||
|  |     case G5: | ||||||
|  |         return "G5-"; | ||||||
|  |         break; | ||||||
|  |     case A5: | ||||||
|  |         return "A5-"; | ||||||
|  |         break; | ||||||
|  |     case B5: | ||||||
|  |         return "B5-"; | ||||||
|  |         break; | ||||||
|  |     case C6: | ||||||
|  |         return "C6-"; | ||||||
|  |         break; | ||||||
|  |     case D6: | ||||||
|  |         return "D6-"; | ||||||
|  |         break; | ||||||
|  |     case E6: | ||||||
|  |         return "E6-"; | ||||||
|  |         break; | ||||||
|  |     default: | ||||||
|  |         return "UNK"; | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | const char* get_note_len_name(const MelodyEventRecord* note_record) { | ||||||
|  |     if(note_record == NULL) return ""; | ||||||
|  | 
 | ||||||
|  |     switch(note_record->length) { | ||||||
|  |     case L1: | ||||||
|  |         return "1-"; | ||||||
|  |         break; | ||||||
|  |     case L2: | ||||||
|  |         return "2-"; | ||||||
|  |         break; | ||||||
|  |     case L4: | ||||||
|  |         return "4-"; | ||||||
|  |         break; | ||||||
|  |     case L8: | ||||||
|  |         return "8-"; | ||||||
|  |         break; | ||||||
|  |     case L16: | ||||||
|  |         return "16"; | ||||||
|  |         break; | ||||||
|  |     case L32: | ||||||
|  |         return "32"; | ||||||
|  |         break; | ||||||
|  |     case L64: | ||||||
|  |         return "64"; | ||||||
|  |         break; | ||||||
|  |     case L128: | ||||||
|  |         return "1+"; | ||||||
|  |         break; | ||||||
|  |     default: | ||||||
|  |         return "--"; | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void render_callback(CanvasApi* canvas, void* ctx) { | ||||||
|  |     State* state = (State*)acquire_mutex((ValueMutex*)ctx, 25); | ||||||
|  | 
 | ||||||
|  |     canvas->clear(canvas); | ||||||
|  |     canvas->set_color(canvas, ColorBlack); | ||||||
|  |     canvas->set_font(canvas, FontPrimary); | ||||||
|  |     canvas->draw_str(canvas, 0, 12, "MusicPlayer"); | ||||||
|  | 
 | ||||||
|  |     uint8_t x_pos = 0; | ||||||
|  |     uint8_t y_pos = 24; | ||||||
|  |     const uint8_t white_w = 10; | ||||||
|  |     const uint8_t white_h = 40; | ||||||
|  | 
 | ||||||
|  |     const int8_t black_x = 6; | ||||||
|  |     const int8_t black_y = -5; | ||||||
|  |     const uint8_t black_w = 8; | ||||||
|  |     const uint8_t black_h = 32; | ||||||
|  | 
 | ||||||
|  |     // white keys
 | ||||||
|  |     for(size_t i = 0; i < 7; i++) { | ||||||
|  |         if(is_white_note(state->note_record, i)) { | ||||||
|  |             canvas->draw_box(canvas, x_pos + white_w * i, y_pos, white_w + 1, white_h); | ||||||
|  |         } else { | ||||||
|  |             canvas->draw_frame(canvas, x_pos + white_w * i, y_pos, white_w + 1, white_h); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // black keys
 | ||||||
|  |     for(size_t i = 0; i < 7; i++) { | ||||||
|  |         if(i != 2 && i != 6) { | ||||||
|  |             canvas->set_color(canvas, ColorWhite); | ||||||
|  |             canvas->draw_box( | ||||||
|  |                 canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h); | ||||||
|  |             canvas->set_color(canvas, ColorBlack); | ||||||
|  |             if(is_black_note(state->note_record, i)) { | ||||||
|  |                 canvas->draw_box( | ||||||
|  |                     canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h); | ||||||
|  |             } else { | ||||||
|  |                 canvas->draw_frame( | ||||||
|  |                     canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // volume widget
 | ||||||
|  |     x_pos = 124; | ||||||
|  |     y_pos = 0; | ||||||
|  |     const uint8_t volume_h = (64 / (state->volume_id_max - 1)) * state->volume_id; | ||||||
|  |     canvas->draw_frame(canvas, x_pos, y_pos, 4, 64); | ||||||
|  |     canvas->draw_box(canvas, x_pos, y_pos + (64 - volume_h), 4, volume_h); | ||||||
|  | 
 | ||||||
|  |     // note stack widget
 | ||||||
|  |     x_pos = 73; | ||||||
|  |     y_pos = 0; | ||||||
|  |     canvas->set_color(canvas, ColorBlack); | ||||||
|  |     canvas->set_font(canvas, FontPrimary); | ||||||
|  |     canvas->draw_frame(canvas, x_pos, y_pos, 49, 64); | ||||||
|  |     canvas->draw_line(canvas, x_pos + 28, 0, x_pos + 28, 64); | ||||||
|  | 
 | ||||||
|  |     for(uint8_t i = 0; i < note_stack_size; i++) { | ||||||
|  |         if(i == 0) { | ||||||
|  |             canvas->draw_box(canvas, x_pos, y_pos + 48, 49, 16); | ||||||
|  |             canvas->set_color(canvas, ColorWhite); | ||||||
|  |         } else { | ||||||
|  |             canvas->set_color(canvas, ColorBlack); | ||||||
|  |         } | ||||||
|  |         canvas->draw_str(canvas, x_pos + 4, 64 - 16 * i - 3, get_note_name(state->note_stack[i])); | ||||||
|  |         canvas->draw_str( | ||||||
|  |             canvas, x_pos + 31, 64 - 16 * i - 3, get_note_len_name(state->note_stack[i])); | ||||||
|  |         canvas->draw_line(canvas, x_pos, 64 - 16 * i, x_pos + 48, 64 - 16 * i); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     release_mutex((ValueMutex*)ctx, state); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void input_callback(InputEvent* input_event, void* ctx) { | ||||||
|  |     osMessageQueueId_t event_queue = (QueueHandle_t)ctx; | ||||||
|  | 
 | ||||||
|  |     MusicDemoEvent event; | ||||||
|  |     event.type = EventTypeKey; | ||||||
|  |     event.value.input = *input_event; | ||||||
|  |     osMessageQueuePut(event_queue, &event, 0, 0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void process_note( | ||||||
|  |     const MelodyEventRecord* note_record, | ||||||
|  |     float bar_length_ms, | ||||||
|  |     MusicDemoContext* context) { | ||||||
|  |     MusicDemoEvent event; | ||||||
|  |     // send note event
 | ||||||
|  |     event.type = EventTypeNote; | ||||||
|  |     event.value.note_record = note_record; | ||||||
|  |     osMessageQueuePut(context->event_queue, &event, 0, 0); | ||||||
|  | 
 | ||||||
|  |     // read volume
 | ||||||
|  |     State* state = (State*)acquire_mutex(context->state_mutex, 25); | ||||||
|  |     float volume = volumes[state->volume_id]; | ||||||
|  |     release_mutex(context->state_mutex, state); | ||||||
|  | 
 | ||||||
|  |     // play note
 | ||||||
|  |     float note_delay = bar_length_ms / (float)note_record->length; | ||||||
|  |     if(note_record->note != N) { | ||||||
|  |         hal_pwm_set(volume, note_record->note, &SPEAKER_TIM, SPEAKER_CH); | ||||||
|  |     } | ||||||
|  |     delay(note_delay); | ||||||
|  |     hal_pwm_stop(&SPEAKER_TIM, SPEAKER_CH); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void music_player_thread(void* p) { | ||||||
|  |     MusicDemoContext* context = (MusicDemoContext*)p; | ||||||
|  | 
 | ||||||
|  |     const float bpm = 130.0f; | ||||||
|  |     // 4/4
 | ||||||
|  |     const float bar_length_ms = (60.0f * 1000.0f / bpm) * 4; | ||||||
|  |     const uint16_t melody_start_events_count = sizeof(melody_start) / sizeof(melody_start[0]); | ||||||
|  |     const uint16_t melody_loop_events_count = sizeof(melody_loop) / sizeof(melody_loop[0]); | ||||||
|  | 
 | ||||||
|  |     for(size_t i = 0; i < melody_start_events_count; i++) { | ||||||
|  |         process_note(&melody_start[i], bar_length_ms, context); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     while(1) { | ||||||
|  |         for(size_t i = 0; i < melody_loop_events_count; i++) { | ||||||
|  |             process_note(&melody_loop[i], bar_length_ms, context); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void music_player(void* p) { | ||||||
|  |     osMessageQueueId_t event_queue = osMessageQueueNew(1, sizeof(MusicDemoEvent), NULL); | ||||||
|  | 
 | ||||||
|  |     State _state; | ||||||
|  |     _state.note_record = NULL; | ||||||
|  |     for(size_t i = 0; i < note_stack_size; i++) { | ||||||
|  |         _state.note_stack[i] = NULL; | ||||||
|  |     } | ||||||
|  |     _state.volume_id = 1; | ||||||
|  |     _state.volume_id_max = sizeof(volumes) / sizeof(volumes[0]); | ||||||
|  | 
 | ||||||
|  |     ValueMutex state_mutex; | ||||||
|  |     if(!init_mutex(&state_mutex, &_state, sizeof(State))) { | ||||||
|  |         printf("cannot create mutex\n"); | ||||||
|  |         furiac_exit(NULL); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Widget* widget = widget_alloc(); | ||||||
|  |     widget_draw_callback_set(widget, render_callback, &state_mutex); | ||||||
|  |     widget_input_callback_set(widget, input_callback, event_queue); | ||||||
|  | 
 | ||||||
|  |     // Open GUI and register widget
 | ||||||
|  |     GuiApi* gui = (GuiApi*)furi_open("gui"); | ||||||
|  |     if(gui == NULL) { | ||||||
|  |         printf("gui is not available\n"); | ||||||
|  |         furiac_exit(NULL); | ||||||
|  |     } | ||||||
|  |     gui->add_widget(gui, widget, GuiLayerFullscreen); | ||||||
|  | 
 | ||||||
|  |     // open input record
 | ||||||
|  |     PubSub* input_events_record = furi_open("input_events"); | ||||||
|  |     // prepare "do nothing" event
 | ||||||
|  |     InputEvent input_event = {InputRight, true}; | ||||||
|  | 
 | ||||||
|  |     // start player thread
 | ||||||
|  |     // TODO change to fuirac_start
 | ||||||
|  |     osThreadAttr_t player_attr = {.name = "music_player_thread", .stack_size = 512}; | ||||||
|  |     MusicDemoContext context = {.state_mutex = &state_mutex, .event_queue = event_queue}; | ||||||
|  |     osThreadId_t player = osThreadNew(music_player_thread, &context, &player_attr); | ||||||
|  | 
 | ||||||
|  |     MusicDemoEvent event; | ||||||
|  |     while(1) { | ||||||
|  |         osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, 100); | ||||||
|  | 
 | ||||||
|  |         State* state = (State*)acquire_mutex_block(&state_mutex); | ||||||
|  | 
 | ||||||
|  |         if(event_status == osOK) { | ||||||
|  |             if(event.type == EventTypeKey) { | ||||||
|  |                 // press events
 | ||||||
|  |                 if(event.value.input.state && event.value.input.input == InputBack) { | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if(event.value.input.state && event.value.input.input == InputUp) { | ||||||
|  |                     if(state->volume_id < state->volume_id_max - 1) state->volume_id++; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if(event.value.input.state && event.value.input.input == InputDown) { | ||||||
|  |                     if(state->volume_id > 0) state->volume_id--; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if(event.value.input.state && event.value.input.input == InputLeft) { | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if(event.value.input.state && event.value.input.input == InputRight) { | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if(event.value.input.input == InputOk) { | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |             } else if(event.type == EventTypeNote) { | ||||||
|  |                 // send "do nothing" event to prevent display backlight off
 | ||||||
|  |                 notify_pubsub(input_events_record, &input_event); | ||||||
|  | 
 | ||||||
|  |                 state->note_record = event.value.note_record; | ||||||
|  | 
 | ||||||
|  |                 for(size_t i = note_stack_size - 1; i > 0; i--) { | ||||||
|  |                     state->note_stack[i] = state->note_stack[i - 1]; | ||||||
|  |                 } | ||||||
|  |                 state->note_stack[0] = state->note_record; | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             // event timeout
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         widget_update(widget); | ||||||
|  |         release_mutex(&state_mutex, state); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -57,7 +57,6 @@ Power* power_alloc() { | |||||||
|     furi_check(power->menu_vm); |     furi_check(power->menu_vm); | ||||||
| 
 | 
 | ||||||
|     power->cli = furi_open("cli"); |     power->cli = furi_open("cli"); | ||||||
|     furi_check(power->cli); |  | ||||||
| 
 | 
 | ||||||
|     power->menu = menu_item_alloc_menu("Power", NULL); |     power->menu = menu_item_alloc_menu("Power", NULL); | ||||||
|     menu_item_subitem_add( |     menu_item_subitem_add( | ||||||
| @ -97,7 +96,9 @@ void power_task(void* p) { | |||||||
|     (void)p; |     (void)p; | ||||||
|     Power* power = power_alloc(); |     Power* power = power_alloc(); | ||||||
| 
 | 
 | ||||||
|     cli_add_command(power->cli, "poweroff", power_cli_poweroff, power); |     if(power->cli) { | ||||||
|  |         cli_add_command(power->cli, "poweroff", power_cli_poweroff, power); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     FuriRecordSubscriber* gui_record = furi_open_deprecated("gui", false, false, NULL, NULL, NULL); |     FuriRecordSubscriber* gui_record = furi_open_deprecated("gui", false, false, NULL, NULL, NULL); | ||||||
|     assert(gui_record); |     assert(gui_record); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 DrZlo13
						DrZlo13