[FL-3211][FL-3212] Debug apps: speaker, uart_echo with baudrate (#2812)
* Music player: move music_worker to library * Music player: drop cli * Debug: speaker debug app * Debug: baudrate arg in uart_echo app * Libs: add music_worker to api * Libs: add music_worker to targets linker_dependencies Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									e5ae3e22b3
								
							
						
					
					
						commit
						95c1585df6
					
				| @ -12,5 +12,6 @@ App( | |||||||
|         "display_test", |         "display_test", | ||||||
|         "text_box_test", |         "text_box_test", | ||||||
|         "file_browser_test", |         "file_browser_test", | ||||||
|  |         "speaker_debug", | ||||||
|     ], |     ], | ||||||
| ) | ) | ||||||
|  | |||||||
							
								
								
									
										11
									
								
								applications/debug/speaker_debug/application.fam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								applications/debug/speaker_debug/application.fam
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | App( | ||||||
|  |     appid="speaker_debug", | ||||||
|  |     name="Speaker Debug", | ||||||
|  |     apptype=FlipperAppType.DEBUG, | ||||||
|  |     entry_point="speaker_debug_app", | ||||||
|  |     requires=["gui", "notification"], | ||||||
|  |     stack_size=2 * 1024, | ||||||
|  |     order=10, | ||||||
|  |     fap_category="Debug", | ||||||
|  |     fap_libs=["music_worker"], | ||||||
|  | ) | ||||||
							
								
								
									
										120
									
								
								applications/debug/speaker_debug/speaker_debug.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								applications/debug/speaker_debug/speaker_debug.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,120 @@ | |||||||
|  | #include <furi.h> | ||||||
|  | #include <notification/notification.h> | ||||||
|  | #include <music_worker/music_worker.h> | ||||||
|  | #include <cli/cli.h> | ||||||
|  | #include <toolbox/args.h> | ||||||
|  | 
 | ||||||
|  | #define TAG "SpeakerDebug" | ||||||
|  | #define CLI_COMMAND "speaker_debug" | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     SpeakerDebugAppMessageTypeStop, | ||||||
|  | } SpeakerDebugAppMessageType; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     SpeakerDebugAppMessageType type; | ||||||
|  | } SpeakerDebugAppMessage; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     MusicWorker* music_worker; | ||||||
|  |     FuriMessageQueue* message_queue; | ||||||
|  |     Cli* cli; | ||||||
|  | } SpeakerDebugApp; | ||||||
|  | 
 | ||||||
|  | static SpeakerDebugApp* speaker_app_alloc() { | ||||||
|  |     SpeakerDebugApp* app = (SpeakerDebugApp*)malloc(sizeof(SpeakerDebugApp)); | ||||||
|  |     app->music_worker = music_worker_alloc(); | ||||||
|  |     app->message_queue = furi_message_queue_alloc(8, sizeof(SpeakerDebugAppMessage)); | ||||||
|  |     app->cli = furi_record_open(RECORD_CLI); | ||||||
|  |     return app; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void speaker_app_free(SpeakerDebugApp* app) { | ||||||
|  |     music_worker_free(app->music_worker); | ||||||
|  |     furi_message_queue_free(app->message_queue); | ||||||
|  |     furi_record_close(RECORD_CLI); | ||||||
|  |     free(app); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void speaker_app_cli(Cli* cli, FuriString* args, void* context) { | ||||||
|  |     UNUSED(cli); | ||||||
|  | 
 | ||||||
|  |     SpeakerDebugApp* app = (SpeakerDebugApp*)context; | ||||||
|  |     SpeakerDebugAppMessage message; | ||||||
|  |     FuriString* cmd = furi_string_alloc(); | ||||||
|  | 
 | ||||||
|  |     if(!args_read_string_and_trim(args, cmd)) { | ||||||
|  |         furi_string_free(cmd); | ||||||
|  |         printf("Usage:\r\n"); | ||||||
|  |         printf("\t" CLI_COMMAND " stop\r\n"); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if(furi_string_cmp(cmd, "stop") == 0) { | ||||||
|  |         message.type = SpeakerDebugAppMessageTypeStop; | ||||||
|  |         FuriStatus status = furi_message_queue_put(app->message_queue, &message, 100); | ||||||
|  |         if(status != FuriStatusOk) { | ||||||
|  |             printf("Failed to send message\r\n"); | ||||||
|  |         } else { | ||||||
|  |             printf("Stopping\r\n"); | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         printf("Usage:\r\n"); | ||||||
|  |         printf("\t" CLI_COMMAND " stop\r\n"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     furi_string_free(cmd); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool speaker_app_music_play(SpeakerDebugApp* app, const char* rtttl) { | ||||||
|  |     if(music_worker_is_playing(app->music_worker)) { | ||||||
|  |         music_worker_stop(app->music_worker); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if(!music_worker_load_rtttl_from_string(app->music_worker, rtttl)) { | ||||||
|  |         FURI_LOG_E(TAG, "Failed to load RTTTL"); | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     music_worker_set_volume(app->music_worker, 1.0f); | ||||||
|  |     music_worker_start(app->music_worker); | ||||||
|  | 
 | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void speaker_app_music_stop(SpeakerDebugApp* app) { | ||||||
|  |     if(music_worker_is_playing(app->music_worker)) { | ||||||
|  |         music_worker_stop(app->music_worker); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void speaker_app_run(SpeakerDebugApp* app, const char* arg) { | ||||||
|  |     if(!arg || !speaker_app_music_play(app, arg)) { | ||||||
|  |         FURI_LOG_E(TAG, "Provided RTTTL is invalid"); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     cli_add_command(app->cli, CLI_COMMAND, CliCommandFlagParallelSafe, speaker_app_cli, app); | ||||||
|  | 
 | ||||||
|  |     SpeakerDebugAppMessage message; | ||||||
|  |     FuriStatus status; | ||||||
|  |     while(true) { | ||||||
|  |         status = furi_message_queue_get(app->message_queue, &message, FuriWaitForever); | ||||||
|  | 
 | ||||||
|  |         if(status == FuriStatusOk) { | ||||||
|  |             if(message.type == SpeakerDebugAppMessageTypeStop) { | ||||||
|  |                 speaker_app_music_stop(app); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     cli_delete_command(app->cli, CLI_COMMAND); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int32_t speaker_debug_app(void* arg) { | ||||||
|  |     SpeakerDebugApp* app = speaker_app_alloc(); | ||||||
|  |     speaker_app_run(app, arg); | ||||||
|  |     speaker_app_free(app); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
| @ -10,6 +10,8 @@ | |||||||
| 
 | 
 | ||||||
| #define LINES_ON_SCREEN 6 | #define LINES_ON_SCREEN 6 | ||||||
| #define COLUMNS_ON_SCREEN 21 | #define COLUMNS_ON_SCREEN 21 | ||||||
|  | #define TAG "UartEcho" | ||||||
|  | #define DEFAULT_BAUD_RATE 230400 | ||||||
| 
 | 
 | ||||||
| typedef struct UartDumpModel UartDumpModel; | typedef struct UartDumpModel UartDumpModel; | ||||||
| 
 | 
 | ||||||
| @ -179,7 +181,7 @@ static int32_t uart_echo_worker(void* context) { | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static UartEchoApp* uart_echo_app_alloc() { | static UartEchoApp* uart_echo_app_alloc(uint32_t baudrate) { | ||||||
|     UartEchoApp* app = malloc(sizeof(UartEchoApp)); |     UartEchoApp* app = malloc(sizeof(UartEchoApp)); | ||||||
| 
 | 
 | ||||||
|     app->rx_stream = furi_stream_buffer_alloc(2048, 1); |     app->rx_stream = furi_stream_buffer_alloc(2048, 1); | ||||||
| @ -220,7 +222,7 @@ static UartEchoApp* uart_echo_app_alloc() { | |||||||
| 
 | 
 | ||||||
|     // Enable uart listener
 |     // Enable uart listener
 | ||||||
|     furi_hal_console_disable(); |     furi_hal_console_disable(); | ||||||
|     furi_hal_uart_set_br(FuriHalUartIdUSART1, 115200); |     furi_hal_uart_set_br(FuriHalUartIdUSART1, baudrate); | ||||||
|     furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_echo_on_irq_cb, app); |     furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_echo_on_irq_cb, app); | ||||||
| 
 | 
 | ||||||
|     return app; |     return app; | ||||||
| @ -263,8 +265,18 @@ static void uart_echo_app_free(UartEchoApp* app) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t uart_echo_app(void* p) { | int32_t uart_echo_app(void* p) { | ||||||
|     UNUSED(p); |     uint32_t baudrate = DEFAULT_BAUD_RATE; | ||||||
|     UartEchoApp* app = uart_echo_app_alloc(); |     if(p) { | ||||||
|  |         const char* baudrate_str = p; | ||||||
|  |         if(sscanf(baudrate_str, "%lu", &baudrate) != 1) { | ||||||
|  |             FURI_LOG_E(TAG, "Invalid baudrate: %s", baudrate_str); | ||||||
|  |             baudrate = DEFAULT_BAUD_RATE; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     FURI_LOG_I(TAG, "Using baudrate: %lu", baudrate); | ||||||
|  | 
 | ||||||
|  |     UartEchoApp* app = uart_echo_app_alloc(baudrate); | ||||||
|     view_dispatcher_run(app->view_dispatcher); |     view_dispatcher_run(app->view_dispatcher); | ||||||
|     uart_echo_app_free(app); |     uart_echo_app_free(app); | ||||||
|     return 0; |     return 0; | ||||||
|  | |||||||
| @ -7,18 +7,10 @@ App( | |||||||
|         "gui", |         "gui", | ||||||
|         "dialogs", |         "dialogs", | ||||||
|     ], |     ], | ||||||
|     provides=["music_player_start"], |  | ||||||
|     stack_size=2 * 1024, |     stack_size=2 * 1024, | ||||||
|     order=20, |     order=20, | ||||||
|     fap_icon="icons/music_10px.png", |     fap_icon="icons/music_10px.png", | ||||||
|     fap_category="Media", |     fap_category="Media", | ||||||
|     fap_icon_assets="icons", |     fap_icon_assets="icons", | ||||||
| ) |     fap_libs=["music_worker"], | ||||||
| 
 |  | ||||||
| App( |  | ||||||
|     appid="music_player_start", |  | ||||||
|     apptype=FlipperAppType.STARTUP, |  | ||||||
|     entry_point="music_player_on_system_start", |  | ||||||
|     requires=["music_player"], |  | ||||||
|     order=30, |  | ||||||
| ) | ) | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| #include "music_player_worker.h" | #include <music_worker/music_worker.h> | ||||||
| 
 | 
 | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include <furi_hal.h> | #include <furi_hal.h> | ||||||
| @ -34,7 +34,7 @@ typedef struct { | |||||||
|     ViewPort* view_port; |     ViewPort* view_port; | ||||||
|     Gui* gui; |     Gui* gui; | ||||||
| 
 | 
 | ||||||
|     MusicPlayerWorker* worker; |     MusicWorker* worker; | ||||||
| } MusicPlayer; | } MusicPlayer; | ||||||
| 
 | 
 | ||||||
| static const float MUSIC_PLAYER_VOLUMES[] = {0, .25, .5, .75, 1}; | static const float MUSIC_PLAYER_VOLUMES[] = {0, .25, .5, .75, 1}; | ||||||
| @ -218,7 +218,7 @@ static void input_callback(InputEvent* input_event, void* ctx) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void music_player_worker_callback( | static void music_worker_callback( | ||||||
|     uint8_t semitone, |     uint8_t semitone, | ||||||
|     uint8_t dots, |     uint8_t dots, | ||||||
|     uint8_t duration, |     uint8_t duration, | ||||||
| @ -250,7 +250,7 @@ static void music_player_worker_callback( | |||||||
| void music_player_clear(MusicPlayer* instance) { | void music_player_clear(MusicPlayer* instance) { | ||||||
|     memset(instance->model->duration_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); |     memset(instance->model->duration_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); | ||||||
|     memset(instance->model->semitone_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); |     memset(instance->model->semitone_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); | ||||||
|     music_player_worker_clear(instance->worker); |     music_worker_clear(instance->worker); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MusicPlayer* music_player_alloc() { | MusicPlayer* music_player_alloc() { | ||||||
| @ -263,10 +263,9 @@ MusicPlayer* music_player_alloc() { | |||||||
| 
 | 
 | ||||||
|     instance->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); |     instance->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); | ||||||
| 
 | 
 | ||||||
|     instance->worker = music_player_worker_alloc(); |     instance->worker = music_worker_alloc(); | ||||||
|     music_player_worker_set_volume( |     music_worker_set_volume(instance->worker, MUSIC_PLAYER_VOLUMES[instance->model->volume]); | ||||||
|         instance->worker, MUSIC_PLAYER_VOLUMES[instance->model->volume]); |     music_worker_set_callback(instance->worker, music_worker_callback, instance); | ||||||
|     music_player_worker_set_callback(instance->worker, music_player_worker_callback, instance); |  | ||||||
| 
 | 
 | ||||||
|     music_player_clear(instance); |     music_player_clear(instance); | ||||||
| 
 | 
 | ||||||
| @ -286,7 +285,7 @@ void music_player_free(MusicPlayer* instance) { | |||||||
|     furi_record_close(RECORD_GUI); |     furi_record_close(RECORD_GUI); | ||||||
|     view_port_free(instance->view_port); |     view_port_free(instance->view_port); | ||||||
| 
 | 
 | ||||||
|     music_player_worker_free(instance->worker); |     music_worker_free(instance->worker); | ||||||
| 
 | 
 | ||||||
|     furi_message_queue_free(instance->input_queue); |     furi_message_queue_free(instance->input_queue); | ||||||
| 
 | 
 | ||||||
| @ -330,12 +329,12 @@ int32_t music_player_app(void* p) { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if(!music_player_worker_load(music_player->worker, furi_string_get_cstr(file_path))) { |         if(!music_worker_load(music_player->worker, furi_string_get_cstr(file_path))) { | ||||||
|             FURI_LOG_E(TAG, "Unable to load file"); |             FURI_LOG_E(TAG, "Unable to load file"); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         music_player_worker_start(music_player->worker); |         music_worker_start(music_player->worker); | ||||||
| 
 | 
 | ||||||
|         InputEvent input; |         InputEvent input; | ||||||
|         while(furi_message_queue_get(music_player->input_queue, &input, FuriWaitForever) == |         while(furi_message_queue_get(music_player->input_queue, &input, FuriWaitForever) == | ||||||
| @ -349,11 +348,11 @@ int32_t music_player_app(void* p) { | |||||||
|             } else if(input.key == InputKeyUp) { |             } else if(input.key == InputKeyUp) { | ||||||
|                 if(music_player->model->volume < COUNT_OF(MUSIC_PLAYER_VOLUMES) - 1) |                 if(music_player->model->volume < COUNT_OF(MUSIC_PLAYER_VOLUMES) - 1) | ||||||
|                     music_player->model->volume++; |                     music_player->model->volume++; | ||||||
|                 music_player_worker_set_volume( |                 music_worker_set_volume( | ||||||
|                     music_player->worker, MUSIC_PLAYER_VOLUMES[music_player->model->volume]); |                     music_player->worker, MUSIC_PLAYER_VOLUMES[music_player->model->volume]); | ||||||
|             } else if(input.key == InputKeyDown) { |             } else if(input.key == InputKeyDown) { | ||||||
|                 if(music_player->model->volume > 0) music_player->model->volume--; |                 if(music_player->model->volume > 0) music_player->model->volume--; | ||||||
|                 music_player_worker_set_volume( |                 music_worker_set_volume( | ||||||
|                     music_player->worker, MUSIC_PLAYER_VOLUMES[music_player->model->volume]); |                     music_player->worker, MUSIC_PLAYER_VOLUMES[music_player->model->volume]); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @ -361,7 +360,7 @@ int32_t music_player_app(void* p) { | |||||||
|             view_port_update(music_player->view_port); |             view_port_update(music_player->view_port); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         music_player_worker_stop(music_player->worker); |         music_worker_stop(music_player->worker); | ||||||
|         if(p && strlen(p)) break; // Exit instead of going to browser if launched with arg
 |         if(p && strlen(p)) break; // Exit instead of going to browser if launched with arg
 | ||||||
|         music_player_clear(music_player); |         music_player_clear(music_player); | ||||||
|     } while(1); |     } while(1); | ||||||
|  | |||||||
| @ -1,48 +0,0 @@ | |||||||
| #include <furi.h> |  | ||||||
| #include <cli/cli.h> |  | ||||||
| #include <storage/storage.h> |  | ||||||
| #include "music_player_worker.h" |  | ||||||
| 
 |  | ||||||
| static void music_player_cli(Cli* cli, FuriString* args, void* context) { |  | ||||||
|     UNUSED(context); |  | ||||||
|     MusicPlayerWorker* music_player_worker = music_player_worker_alloc(); |  | ||||||
|     Storage* storage = furi_record_open(RECORD_STORAGE); |  | ||||||
| 
 |  | ||||||
|     do { |  | ||||||
|         if(storage_common_stat(storage, furi_string_get_cstr(args), NULL) == FSE_OK) { |  | ||||||
|             if(!music_player_worker_load(music_player_worker, furi_string_get_cstr(args))) { |  | ||||||
|                 printf("Failed to open file %s\r\n", furi_string_get_cstr(args)); |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             if(!music_player_worker_load_rtttl_from_string( |  | ||||||
|                    music_player_worker, furi_string_get_cstr(args))) { |  | ||||||
|                 printf("Argument is not a file or RTTTL\r\n"); |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         printf("Press CTRL+C to stop\r\n"); |  | ||||||
|         music_player_worker_set_volume(music_player_worker, 1.0f); |  | ||||||
|         music_player_worker_start(music_player_worker); |  | ||||||
|         while(!cli_cmd_interrupt_received(cli)) { |  | ||||||
|             furi_delay_ms(50); |  | ||||||
|         } |  | ||||||
|         music_player_worker_stop(music_player_worker); |  | ||||||
|     } while(0); |  | ||||||
| 
 |  | ||||||
|     furi_record_close(RECORD_STORAGE); |  | ||||||
|     music_player_worker_free(music_player_worker); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void music_player_on_system_start() { |  | ||||||
| #ifdef SRV_CLI |  | ||||||
|     Cli* cli = furi_record_open(RECORD_CLI); |  | ||||||
| 
 |  | ||||||
|     cli_add_command(cli, "music_player", CliCommandFlagDefault, music_player_cli, NULL); |  | ||||||
| 
 |  | ||||||
|     furi_record_close(RECORD_CLI); |  | ||||||
| #else |  | ||||||
|     UNUSED(music_player_cli); |  | ||||||
| #endif |  | ||||||
| } |  | ||||||
| @ -1,38 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include <stdbool.h> |  | ||||||
| #include <stdint.h> |  | ||||||
| 
 |  | ||||||
| typedef void (*MusicPlayerWorkerCallback)( |  | ||||||
|     uint8_t semitone, |  | ||||||
|     uint8_t dots, |  | ||||||
|     uint8_t duration, |  | ||||||
|     float position, |  | ||||||
|     void* context); |  | ||||||
| 
 |  | ||||||
| typedef struct MusicPlayerWorker MusicPlayerWorker; |  | ||||||
| 
 |  | ||||||
| MusicPlayerWorker* music_player_worker_alloc(); |  | ||||||
| 
 |  | ||||||
| void music_player_worker_clear(MusicPlayerWorker* instance); |  | ||||||
| 
 |  | ||||||
| void music_player_worker_free(MusicPlayerWorker* instance); |  | ||||||
| 
 |  | ||||||
| bool music_player_worker_load(MusicPlayerWorker* instance, const char* file_path); |  | ||||||
| 
 |  | ||||||
| bool music_player_worker_load_fmf_from_file(MusicPlayerWorker* instance, const char* file_path); |  | ||||||
| 
 |  | ||||||
| bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const char* file_path); |  | ||||||
| 
 |  | ||||||
| bool music_player_worker_load_rtttl_from_string(MusicPlayerWorker* instance, const char* string); |  | ||||||
| 
 |  | ||||||
| void music_player_worker_set_callback( |  | ||||||
|     MusicPlayerWorker* instance, |  | ||||||
|     MusicPlayerWorkerCallback callback, |  | ||||||
|     void* context); |  | ||||||
| 
 |  | ||||||
| void music_player_worker_set_volume(MusicPlayerWorker* instance, float volume); |  | ||||||
| 
 |  | ||||||
| void music_player_worker_start(MusicPlayerWorker* instance); |  | ||||||
| 
 |  | ||||||
| void music_player_worker_stop(MusicPlayerWorker* instance); |  | ||||||
| @ -1,5 +1,5 @@ | |||||||
| entry,status,name,type,params | entry,status,name,type,params | ||||||
| Version,+,31.2,, | Version,+,31.3,, | ||||||
| Header,+,applications/services/bt/bt_service/bt.h,, | Header,+,applications/services/bt/bt_service/bt.h,, | ||||||
| Header,+,applications/services/cli/cli.h,, | Header,+,applications/services/cli/cli.h,, | ||||||
| Header,+,applications/services/cli/cli_vcp.h,, | Header,+,applications/services/cli/cli_vcp.h,, | ||||||
| @ -128,6 +128,7 @@ Header,+,lib/mlib/m-list.h,, | |||||||
| Header,+,lib/mlib/m-rbtree.h,, | Header,+,lib/mlib/m-rbtree.h,, | ||||||
| Header,+,lib/mlib/m-tuple.h,, | Header,+,lib/mlib/m-tuple.h,, | ||||||
| Header,+,lib/mlib/m-variant.h,, | Header,+,lib/mlib/m-variant.h,, | ||||||
|  | Header,+,lib/music_worker/music_worker.h,, | ||||||
| Header,+,lib/one_wire/maxim_crc.h,, | Header,+,lib/one_wire/maxim_crc.h,, | ||||||
| Header,+,lib/one_wire/one_wire_host.h,, | Header,+,lib/one_wire/one_wire_host.h,, | ||||||
| Header,+,lib/one_wire/one_wire_slave.h,, | Header,+,lib/one_wire/one_wire_slave.h,, | ||||||
| @ -1519,6 +1520,18 @@ Function,-,mkstemps,int,"char*, int" | |||||||
| Function,-,mktemp,char*,char* | Function,-,mktemp,char*,char* | ||||||
| Function,-,mktime,time_t,tm* | Function,-,mktime,time_t,tm* | ||||||
| Function,-,mrand48,long, | Function,-,mrand48,long, | ||||||
|  | Function,-,music_worker_alloc,MusicWorker*, | ||||||
|  | Function,-,music_worker_clear,void,MusicWorker* | ||||||
|  | Function,-,music_worker_free,void,MusicWorker* | ||||||
|  | Function,-,music_worker_is_playing,_Bool,MusicWorker* | ||||||
|  | Function,-,music_worker_load,_Bool,"MusicWorker*, const char*" | ||||||
|  | Function,-,music_worker_load_fmf_from_file,_Bool,"MusicWorker*, const char*" | ||||||
|  | Function,-,music_worker_load_rtttl_from_file,_Bool,"MusicWorker*, const char*" | ||||||
|  | Function,-,music_worker_load_rtttl_from_string,_Bool,"MusicWorker*, const char*" | ||||||
|  | Function,-,music_worker_set_callback,void,"MusicWorker*, MusicWorkerCallback, void*" | ||||||
|  | Function,-,music_worker_set_volume,void,"MusicWorker*, float" | ||||||
|  | Function,-,music_worker_start,void,MusicWorker* | ||||||
|  | Function,-,music_worker_stop,void,MusicWorker* | ||||||
| Function,+,notification_internal_message,void,"NotificationApp*, const NotificationSequence*" | Function,+,notification_internal_message,void,"NotificationApp*, const NotificationSequence*" | ||||||
| Function,+,notification_internal_message_block,void,"NotificationApp*, const NotificationSequence*" | Function,+,notification_internal_message_block,void,"NotificationApp*, const NotificationSequence*" | ||||||
| Function,+,notification_message,void,"NotificationApp*, const NotificationSequence*" | Function,+,notification_message,void,"NotificationApp*, const NotificationSequence*" | ||||||
|  | |||||||
| 
 | 
| @ -25,6 +25,7 @@ | |||||||
|         "appframe", |         "appframe", | ||||||
|         "assets", |         "assets", | ||||||
|         "one_wire", |         "one_wire", | ||||||
|  |         "music_worker", | ||||||
|         "misc", |         "misc", | ||||||
|         "flipper_application", |         "flipper_application", | ||||||
|         "flipperformat", |         "flipperformat", | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| entry,status,name,type,params | entry,status,name,type,params | ||||||
| Version,+,31.2,, | Version,+,31.3,, | ||||||
| Header,+,applications/services/bt/bt_service/bt.h,, | Header,+,applications/services/bt/bt_service/bt.h,, | ||||||
| Header,+,applications/services/cli/cli.h,, | Header,+,applications/services/cli/cli.h,, | ||||||
| Header,+,applications/services/cli/cli_vcp.h,, | Header,+,applications/services/cli/cli_vcp.h,, | ||||||
| @ -146,6 +146,7 @@ Header,+,lib/mlib/m-list.h,, | |||||||
| Header,+,lib/mlib/m-rbtree.h,, | Header,+,lib/mlib/m-rbtree.h,, | ||||||
| Header,+,lib/mlib/m-tuple.h,, | Header,+,lib/mlib/m-tuple.h,, | ||||||
| Header,+,lib/mlib/m-variant.h,, | Header,+,lib/mlib/m-variant.h,, | ||||||
|  | Header,+,lib/music_worker/music_worker.h,, | ||||||
| Header,+,lib/nfc/nfc_device.h,, | Header,+,lib/nfc/nfc_device.h,, | ||||||
| Header,+,lib/nfc/protocols/nfc_util.h,, | Header,+,lib/nfc/protocols/nfc_util.h,, | ||||||
| Header,+,lib/one_wire/maxim_crc.h,, | Header,+,lib/one_wire/maxim_crc.h,, | ||||||
| @ -1220,12 +1221,12 @@ Function,+,furi_hal_mpu_protect_disable,void,FuriHalMpuRegion | |||||||
| Function,+,furi_hal_mpu_protect_no_access,void,"FuriHalMpuRegion, uint32_t, FuriHalMPURegionSize" | Function,+,furi_hal_mpu_protect_no_access,void,"FuriHalMpuRegion, uint32_t, FuriHalMPURegionSize" | ||||||
| Function,+,furi_hal_mpu_protect_read_only,void,"FuriHalMpuRegion, uint32_t, FuriHalMPURegionSize" | Function,+,furi_hal_mpu_protect_read_only,void,"FuriHalMpuRegion, uint32_t, FuriHalMPURegionSize" | ||||||
| Function,+,furi_hal_nfc_activate_nfca,_Bool,"uint32_t, uint32_t*" | Function,+,furi_hal_nfc_activate_nfca,_Bool,"uint32_t, uint32_t*" | ||||||
| Function,+,furi_hal_nfc_field_is_present,_Bool, |  | ||||||
| Function,+,furi_hal_nfc_field_detect_start,void, |  | ||||||
| Function,-,furi_hal_nfc_deinit,void, | Function,-,furi_hal_nfc_deinit,void, | ||||||
| Function,+,furi_hal_nfc_detect,_Bool,"FuriHalNfcDevData*, uint32_t" | Function,+,furi_hal_nfc_detect,_Bool,"FuriHalNfcDevData*, uint32_t" | ||||||
| Function,+,furi_hal_nfc_emulate_nfca,_Bool,"uint8_t*, uint8_t, uint8_t*, uint8_t, FuriHalNfcEmulateCallback, void*, uint32_t" | Function,+,furi_hal_nfc_emulate_nfca,_Bool,"uint8_t*, uint8_t, uint8_t*, uint8_t, FuriHalNfcEmulateCallback, void*, uint32_t" | ||||||
| Function,+,furi_hal_nfc_exit_sleep,void, | Function,+,furi_hal_nfc_exit_sleep,void, | ||||||
|  | Function,+,furi_hal_nfc_field_detect_start,void, | ||||||
|  | Function,+,furi_hal_nfc_field_is_present,_Bool, | ||||||
| Function,+,furi_hal_nfc_field_off,void, | Function,+,furi_hal_nfc_field_off,void, | ||||||
| Function,+,furi_hal_nfc_field_on,void, | Function,+,furi_hal_nfc_field_on,void, | ||||||
| Function,-,furi_hal_nfc_init,void, | Function,-,furi_hal_nfc_init,void, | ||||||
| @ -1307,9 +1308,9 @@ Function,-,furi_hal_resources_init_early,void, | |||||||
| Function,+,furi_hal_rfid_comp_set_callback,void,"FuriHalRfidCompCallback, void*" | Function,+,furi_hal_rfid_comp_set_callback,void,"FuriHalRfidCompCallback, void*" | ||||||
| Function,+,furi_hal_rfid_comp_start,void, | Function,+,furi_hal_rfid_comp_start,void, | ||||||
| Function,+,furi_hal_rfid_comp_stop,void, | Function,+,furi_hal_rfid_comp_stop,void, | ||||||
| Function,+,furi_hal_rfid_field_is_present,_Bool,uint32_t* |  | ||||||
| Function,+,furi_hal_rfid_field_detect_start,void, | Function,+,furi_hal_rfid_field_detect_start,void, | ||||||
| Function,+,furi_hal_rfid_field_detect_stop,void, | Function,+,furi_hal_rfid_field_detect_stop,void, | ||||||
|  | Function,+,furi_hal_rfid_field_is_present,_Bool,uint32_t* | ||||||
| Function,-,furi_hal_rfid_init,void, | Function,-,furi_hal_rfid_init,void, | ||||||
| Function,+,furi_hal_rfid_pin_pull_pulldown,void, | Function,+,furi_hal_rfid_pin_pull_pulldown,void, | ||||||
| Function,+,furi_hal_rfid_pin_pull_release,void, | Function,+,furi_hal_rfid_pin_pull_release,void, | ||||||
| @ -2063,6 +2064,18 @@ Function,-,modf,double,"double, double*" | |||||||
| Function,-,modff,float,"float, float*" | Function,-,modff,float,"float, float*" | ||||||
| Function,-,modfl,long double,"long double, long double*" | Function,-,modfl,long double,"long double, long double*" | ||||||
| Function,-,mrand48,long, | Function,-,mrand48,long, | ||||||
|  | Function,-,music_worker_alloc,MusicWorker*, | ||||||
|  | Function,-,music_worker_clear,void,MusicWorker* | ||||||
|  | Function,-,music_worker_free,void,MusicWorker* | ||||||
|  | Function,-,music_worker_is_playing,_Bool,MusicWorker* | ||||||
|  | Function,-,music_worker_load,_Bool,"MusicWorker*, const char*" | ||||||
|  | Function,-,music_worker_load_fmf_from_file,_Bool,"MusicWorker*, const char*" | ||||||
|  | Function,-,music_worker_load_rtttl_from_file,_Bool,"MusicWorker*, const char*" | ||||||
|  | Function,-,music_worker_load_rtttl_from_string,_Bool,"MusicWorker*, const char*" | ||||||
|  | Function,-,music_worker_set_callback,void,"MusicWorker*, MusicWorkerCallback, void*" | ||||||
|  | Function,-,music_worker_set_volume,void,"MusicWorker*, float" | ||||||
|  | Function,-,music_worker_start,void,MusicWorker* | ||||||
|  | Function,-,music_worker_stop,void,MusicWorker* | ||||||
| Function,-,nan,double,const char* | Function,-,nan,double,const char* | ||||||
| Function,-,nanf,float,const char* | Function,-,nanf,float,const char* | ||||||
| Function,-,nanl,long double,const char* | Function,-,nanl,long double,const char* | ||||||
|  | |||||||
| 
 | 
| @ -38,6 +38,7 @@ | |||||||
|         "assets", |         "assets", | ||||||
|         "one_wire", |         "one_wire", | ||||||
|         "ibutton", |         "ibutton", | ||||||
|  |         "music_worker", | ||||||
|         "misc", |         "misc", | ||||||
|         "mbedtls", |         "mbedtls", | ||||||
|         "lfrfid", |         "lfrfid", | ||||||
|  | |||||||
| @ -15,6 +15,7 @@ env.Append( | |||||||
|         Dir("u8g2"), |         Dir("u8g2"), | ||||||
|         Dir("update_util"), |         Dir("update_util"), | ||||||
|         Dir("print"), |         Dir("print"), | ||||||
|  |         Dir("music_worker"), | ||||||
|     ], |     ], | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -100,6 +101,7 @@ libs = env.BuildModules( | |||||||
|         "misc", |         "misc", | ||||||
|         "lfrfid", |         "lfrfid", | ||||||
|         "flipper_application", |         "flipper_application", | ||||||
|  |         "music_worker", | ||||||
|     ], |     ], | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										27
									
								
								lib/music_worker/SConscript
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								lib/music_worker/SConscript
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | |||||||
|  | Import("env") | ||||||
|  | 
 | ||||||
|  | env.Append( | ||||||
|  |     CPPPATH=[ | ||||||
|  |         "#/lib/music_worker", | ||||||
|  |     ], | ||||||
|  |     SDK_HEADERS=[ | ||||||
|  |         File("music_worker.h"), | ||||||
|  |     ], | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | libenv = env.Clone(FW_LIB_NAME="music_worker") | ||||||
|  | libenv.ApplyLibFlags() | ||||||
|  | 
 | ||||||
|  | libenv.AppendUnique( | ||||||
|  |     CCFLAGS=[ | ||||||
|  |         # Required for lib to be linkable with .faps | ||||||
|  |         "-mword-relocations", | ||||||
|  |         "-mlong-calls", | ||||||
|  |     ], | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | sources = libenv.GlobRecursive("*.c*") | ||||||
|  | 
 | ||||||
|  | lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) | ||||||
|  | libenv.Install("${LIB_DIST_DIR}", lib) | ||||||
|  | Return("lib") | ||||||
| @ -1,4 +1,4 @@ | |||||||
| #include "music_player_worker.h" | #include "music_worker.h" | ||||||
| 
 | 
 | ||||||
| #include <furi_hal.h> | #include <furi_hal.h> | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
| @ -9,7 +9,7 @@ | |||||||
| #include <math.h> | #include <math.h> | ||||||
| #include <m-array.h> | #include <m-array.h> | ||||||
| 
 | 
 | ||||||
| #define TAG "MusicPlayerWorker" | #define TAG "MusicWorker" | ||||||
| 
 | 
 | ||||||
| #define MUSIC_PLAYER_FILETYPE "Flipper Music Format" | #define MUSIC_PLAYER_FILETYPE "Flipper Music Format" | ||||||
| #define MUSIC_PLAYER_VERSION 0 | #define MUSIC_PLAYER_VERSION 0 | ||||||
| @ -28,11 +28,11 @@ typedef struct { | |||||||
| 
 | 
 | ||||||
| ARRAY_DEF(NoteBlockArray, NoteBlock, M_POD_OPLIST); | ARRAY_DEF(NoteBlockArray, NoteBlock, M_POD_OPLIST); | ||||||
| 
 | 
 | ||||||
| struct MusicPlayerWorker { | struct MusicWorker { | ||||||
|     FuriThread* thread; |     FuriThread* thread; | ||||||
|     bool should_work; |     bool should_work; | ||||||
| 
 | 
 | ||||||
|     MusicPlayerWorkerCallback callback; |     MusicWorkerCallback callback; | ||||||
|     void* callback_context; |     void* callback_context; | ||||||
| 
 | 
 | ||||||
|     float volume; |     float volume; | ||||||
| @ -42,9 +42,9 @@ struct MusicPlayerWorker { | |||||||
|     NoteBlockArray_t notes; |     NoteBlockArray_t notes; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static int32_t music_player_worker_thread_callback(void* context) { | static int32_t music_worker_thread_callback(void* context) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     MusicPlayerWorker* instance = context; |     MusicWorker* instance = context; | ||||||
| 
 | 
 | ||||||
|     NoteBlockArray_it_t it; |     NoteBlockArray_it_t it; | ||||||
|     NoteBlockArray_it(it, instance->notes); |     NoteBlockArray_it(it, instance->notes); | ||||||
| @ -97,24 +97,24 @@ static int32_t music_player_worker_thread_callback(void* context) { | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MusicPlayerWorker* music_player_worker_alloc() { | MusicWorker* music_worker_alloc() { | ||||||
|     MusicPlayerWorker* instance = malloc(sizeof(MusicPlayerWorker)); |     MusicWorker* instance = malloc(sizeof(MusicWorker)); | ||||||
| 
 | 
 | ||||||
|     NoteBlockArray_init(instance->notes); |     NoteBlockArray_init(instance->notes); | ||||||
| 
 | 
 | ||||||
|     instance->thread = furi_thread_alloc_ex( |     instance->thread = | ||||||
|         "MusicPlayerWorker", 1024, music_player_worker_thread_callback, instance); |         furi_thread_alloc_ex("MusicWorker", 1024, music_worker_thread_callback, instance); | ||||||
| 
 | 
 | ||||||
|     instance->volume = 1.0f; |     instance->volume = 1.0f; | ||||||
| 
 | 
 | ||||||
|     return instance; |     return instance; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void music_player_worker_clear(MusicPlayerWorker* instance) { | void music_worker_clear(MusicWorker* instance) { | ||||||
|     NoteBlockArray_reset(instance->notes); |     NoteBlockArray_reset(instance->notes); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void music_player_worker_free(MusicPlayerWorker* instance) { | void music_worker_free(MusicWorker* instance) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     furi_thread_free(instance->thread); |     furi_thread_free(instance->thread); | ||||||
|     NoteBlockArray_clear(instance->notes); |     NoteBlockArray_clear(instance->notes); | ||||||
| @ -186,11 +186,8 @@ static size_t skip_till(const char* string, const char symbol) { | |||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool music_player_worker_add_note( | static bool | ||||||
|     MusicPlayerWorker* instance, |     music_worker_add_note(MusicWorker* instance, uint8_t semitone, uint8_t duration, uint8_t dots) { | ||||||
|     uint8_t semitone, |  | ||||||
|     uint8_t duration, |  | ||||||
|     uint8_t dots) { |  | ||||||
|     NoteBlock note_block; |     NoteBlock note_block; | ||||||
| 
 | 
 | ||||||
|     note_block.semitone = semitone; |     note_block.semitone = semitone; | ||||||
| @ -228,7 +225,7 @@ static int8_t note_to_semitone(const char note) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool music_player_worker_parse_notes(MusicPlayerWorker* instance, const char* string) { | static bool music_worker_parse_notes(MusicWorker* instance, const char* string) { | ||||||
|     const char* cursor = string; |     const char* cursor = string; | ||||||
|     bool result = true; |     bool result = true; | ||||||
| 
 | 
 | ||||||
| @ -286,7 +283,7 @@ static bool music_player_worker_parse_notes(MusicPlayerWorker* instance, const c | |||||||
|                 semitone += sharp_char == '#' ? 1 : 0; |                 semitone += sharp_char == '#' ? 1 : 0; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if(music_player_worker_add_note(instance, semitone, duration, dots)) { |             if(music_worker_add_note(instance, semitone, duration, dots)) { | ||||||
|                 FURI_LOG_D( |                 FURI_LOG_D( | ||||||
|                     TAG, |                     TAG, | ||||||
|                     "Added note: %c%c%lu.%lu = %u %lu", |                     "Added note: %c%c%lu.%lu = %u %lu", | ||||||
| @ -316,20 +313,20 @@ static bool music_player_worker_parse_notes(MusicPlayerWorker* instance, const c | |||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool music_player_worker_load(MusicPlayerWorker* instance, const char* file_path) { | bool music_worker_load(MusicWorker* instance, const char* file_path) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     furi_assert(file_path); |     furi_assert(file_path); | ||||||
| 
 | 
 | ||||||
|     bool ret = false; |     bool ret = false; | ||||||
|     if(strcasestr(file_path, ".fmf")) { |     if(strcasestr(file_path, ".fmf")) { | ||||||
|         ret = music_player_worker_load_fmf_from_file(instance, file_path); |         ret = music_worker_load_fmf_from_file(instance, file_path); | ||||||
|     } else { |     } else { | ||||||
|         ret = music_player_worker_load_rtttl_from_file(instance, file_path); |         ret = music_worker_load_rtttl_from_file(instance, file_path); | ||||||
|     } |     } | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool music_player_worker_load_fmf_from_file(MusicPlayerWorker* instance, const char* file_path) { | bool music_worker_load_fmf_from_file(MusicWorker* instance, const char* file_path) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     furi_assert(file_path); |     furi_assert(file_path); | ||||||
| 
 | 
 | ||||||
| @ -369,7 +366,7 @@ bool music_player_worker_load_fmf_from_file(MusicPlayerWorker* instance, const c | |||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if(!music_player_worker_parse_notes(instance, furi_string_get_cstr(temp_str))) { |         if(!music_worker_parse_notes(instance, furi_string_get_cstr(temp_str))) { | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -383,7 +380,7 @@ bool music_player_worker_load_fmf_from_file(MusicPlayerWorker* instance, const c | |||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const char* file_path) { | bool music_worker_load_rtttl_from_file(MusicWorker* instance, const char* file_path) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     furi_assert(file_path); |     furi_assert(file_path); | ||||||
| 
 | 
 | ||||||
| @ -414,7 +411,7 @@ bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const | |||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if(!music_player_worker_load_rtttl_from_string(instance, furi_string_get_cstr(content))) { |         if(!music_worker_load_rtttl_from_string(instance, furi_string_get_cstr(content))) { | ||||||
|             FURI_LOG_E(TAG, "Invalid file content"); |             FURI_LOG_E(TAG, "Invalid file content"); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| @ -429,7 +426,7 @@ bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const | |||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool music_player_worker_load_rtttl_from_string(MusicPlayerWorker* instance, const char* string) { | bool music_worker_load_rtttl_from_string(MusicWorker* instance, const char* string) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
| 
 | 
 | ||||||
|     const char* cursor = string; |     const char* cursor = string; | ||||||
| @ -470,28 +467,25 @@ bool music_player_worker_load_rtttl_from_string(MusicPlayerWorker* instance, con | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|     cursor++; |     cursor++; | ||||||
|     if(!music_player_worker_parse_notes(instance, cursor)) { |     if(!music_worker_parse_notes(instance, cursor)) { | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void music_player_worker_set_callback( | void music_worker_set_callback(MusicWorker* instance, MusicWorkerCallback callback, void* context) { | ||||||
|     MusicPlayerWorker* instance, |  | ||||||
|     MusicPlayerWorkerCallback callback, |  | ||||||
|     void* context) { |  | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     instance->callback = callback; |     instance->callback = callback; | ||||||
|     instance->callback_context = context; |     instance->callback_context = context; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void music_player_worker_set_volume(MusicPlayerWorker* instance, float volume) { | void music_worker_set_volume(MusicWorker* instance, float volume) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     instance->volume = volume; |     instance->volume = volume; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void music_player_worker_start(MusicPlayerWorker* instance) { | void music_worker_start(MusicWorker* instance) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     furi_assert(instance->should_work == false); |     furi_assert(instance->should_work == false); | ||||||
| 
 | 
 | ||||||
| @ -499,10 +493,15 @@ void music_player_worker_start(MusicPlayerWorker* instance) { | |||||||
|     furi_thread_start(instance->thread); |     furi_thread_start(instance->thread); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void music_player_worker_stop(MusicPlayerWorker* instance) { | void music_worker_stop(MusicWorker* instance) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     furi_assert(instance->should_work == true); |     furi_assert(instance->should_work == true); | ||||||
| 
 | 
 | ||||||
|     instance->should_work = false; |     instance->should_work = false; | ||||||
|     furi_thread_join(instance->thread); |     furi_thread_join(instance->thread); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | bool music_worker_is_playing(MusicWorker* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     return instance->should_work; | ||||||
|  | } | ||||||
							
								
								
									
										37
									
								
								lib/music_worker/music_worker.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								lib/music_worker/music_worker.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | 
 | ||||||
|  | typedef void (*MusicWorkerCallback)( | ||||||
|  |     uint8_t semitone, | ||||||
|  |     uint8_t dots, | ||||||
|  |     uint8_t duration, | ||||||
|  |     float position, | ||||||
|  |     void* context); | ||||||
|  | 
 | ||||||
|  | typedef struct MusicWorker MusicWorker; | ||||||
|  | 
 | ||||||
|  | MusicWorker* music_worker_alloc(); | ||||||
|  | 
 | ||||||
|  | void music_worker_clear(MusicWorker* instance); | ||||||
|  | 
 | ||||||
|  | void music_worker_free(MusicWorker* instance); | ||||||
|  | 
 | ||||||
|  | bool music_worker_load(MusicWorker* instance, const char* file_path); | ||||||
|  | 
 | ||||||
|  | bool music_worker_load_fmf_from_file(MusicWorker* instance, const char* file_path); | ||||||
|  | 
 | ||||||
|  | bool music_worker_load_rtttl_from_file(MusicWorker* instance, const char* file_path); | ||||||
|  | 
 | ||||||
|  | bool music_worker_load_rtttl_from_string(MusicWorker* instance, const char* string); | ||||||
|  | 
 | ||||||
|  | void music_worker_set_callback(MusicWorker* instance, MusicWorkerCallback callback, void* context); | ||||||
|  | 
 | ||||||
|  | void music_worker_set_volume(MusicWorker* instance, float volume); | ||||||
|  | 
 | ||||||
|  | void music_worker_start(MusicWorker* instance); | ||||||
|  | 
 | ||||||
|  | void music_worker_stop(MusicWorker* instance); | ||||||
|  | 
 | ||||||
|  | bool music_worker_is_playing(MusicWorker* instance); | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Sergey Gavrilov
						Sergey Gavrilov