mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-10 06:54:19 +00:00
[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
16 changed files with 295 additions and 153 deletions
|
@ -12,5 +12,6 @@ App(
|
|||
"display_test",
|
||||
"text_box_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 COLUMNS_ON_SCREEN 21
|
||||
#define TAG "UartEcho"
|
||||
#define DEFAULT_BAUD_RATE 230400
|
||||
|
||||
typedef struct UartDumpModel UartDumpModel;
|
||||
|
||||
|
@ -179,7 +181,7 @@ static int32_t uart_echo_worker(void* context) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static UartEchoApp* uart_echo_app_alloc() {
|
||||
static UartEchoApp* uart_echo_app_alloc(uint32_t baudrate) {
|
||||
UartEchoApp* app = malloc(sizeof(UartEchoApp));
|
||||
|
||||
app->rx_stream = furi_stream_buffer_alloc(2048, 1);
|
||||
|
@ -220,7 +222,7 @@ static UartEchoApp* uart_echo_app_alloc() {
|
|||
|
||||
// Enable uart listener
|
||||
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);
|
||||
|
||||
return app;
|
||||
|
@ -263,8 +265,18 @@ static void uart_echo_app_free(UartEchoApp* app) {
|
|||
}
|
||||
|
||||
int32_t uart_echo_app(void* p) {
|
||||
UNUSED(p);
|
||||
UartEchoApp* app = uart_echo_app_alloc();
|
||||
uint32_t baudrate = DEFAULT_BAUD_RATE;
|
||||
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);
|
||||
uart_echo_app_free(app);
|
||||
return 0;
|
||||
|
|
|
@ -7,18 +7,10 @@ App(
|
|||
"gui",
|
||||
"dialogs",
|
||||
],
|
||||
provides=["music_player_start"],
|
||||
stack_size=2 * 1024,
|
||||
order=20,
|
||||
fap_icon="icons/music_10px.png",
|
||||
fap_category="Media",
|
||||
fap_icon_assets="icons",
|
||||
)
|
||||
|
||||
App(
|
||||
appid="music_player_start",
|
||||
apptype=FlipperAppType.STARTUP,
|
||||
entry_point="music_player_on_system_start",
|
||||
requires=["music_player"],
|
||||
order=30,
|
||||
fap_libs=["music_worker"],
|
||||
)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "music_player_worker.h"
|
||||
#include <music_worker/music_worker.h>
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
@ -34,7 +34,7 @@ typedef struct {
|
|||
ViewPort* view_port;
|
||||
Gui* gui;
|
||||
|
||||
MusicPlayerWorker* worker;
|
||||
MusicWorker* worker;
|
||||
} MusicPlayer;
|
||||
|
||||
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 dots,
|
||||
uint8_t duration,
|
||||
|
@ -250,7 +250,7 @@ static void music_player_worker_callback(
|
|||
void music_player_clear(MusicPlayer* instance) {
|
||||
memset(instance->model->duration_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() {
|
||||
|
@ -263,10 +263,9 @@ MusicPlayer* music_player_alloc() {
|
|||
|
||||
instance->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
|
||||
|
||||
instance->worker = music_player_worker_alloc();
|
||||
music_player_worker_set_volume(
|
||||
instance->worker, MUSIC_PLAYER_VOLUMES[instance->model->volume]);
|
||||
music_player_worker_set_callback(instance->worker, music_player_worker_callback, instance);
|
||||
instance->worker = music_worker_alloc();
|
||||
music_worker_set_volume(instance->worker, MUSIC_PLAYER_VOLUMES[instance->model->volume]);
|
||||
music_worker_set_callback(instance->worker, music_worker_callback, instance);
|
||||
|
||||
music_player_clear(instance);
|
||||
|
||||
|
@ -286,7 +285,7 @@ void music_player_free(MusicPlayer* instance) {
|
|||
furi_record_close(RECORD_GUI);
|
||||
view_port_free(instance->view_port);
|
||||
|
||||
music_player_worker_free(instance->worker);
|
||||
music_worker_free(instance->worker);
|
||||
|
||||
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");
|
||||
break;
|
||||
}
|
||||
|
||||
music_player_worker_start(music_player->worker);
|
||||
music_worker_start(music_player->worker);
|
||||
|
||||
InputEvent input;
|
||||
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) {
|
||||
if(music_player->model->volume < COUNT_OF(MUSIC_PLAYER_VOLUMES) - 1)
|
||||
music_player->model->volume++;
|
||||
music_player_worker_set_volume(
|
||||
music_worker_set_volume(
|
||||
music_player->worker, MUSIC_PLAYER_VOLUMES[music_player->model->volume]);
|
||||
} else if(input.key == InputKeyDown) {
|
||||
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]);
|
||||
}
|
||||
|
||||
|
@ -361,7 +360,7 @@ int32_t music_player_app(void* p) {
|
|||
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
|
||||
music_player_clear(music_player);
|
||||
} 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
|
||||
Version,+,31.2,,
|
||||
Version,+,31.3,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/cli/cli.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-tuple.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/one_wire_host.h,,
|
||||
Header,+,lib/one_wire/one_wire_slave.h,,
|
||||
|
@ -1519,6 +1520,18 @@ Function,-,mkstemps,int,"char*, int"
|
|||
Function,-,mktemp,char*,char*
|
||||
Function,-,mktime,time_t,tm*
|
||||
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_block,void,"NotificationApp*, const NotificationSequence*"
|
||||
Function,+,notification_message,void,"NotificationApp*, const NotificationSequence*"
|
||||
|
|
|
|
@ -25,6 +25,7 @@
|
|||
"appframe",
|
||||
"assets",
|
||||
"one_wire",
|
||||
"music_worker",
|
||||
"misc",
|
||||
"flipper_application",
|
||||
"flipperformat",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
entry,status,name,type,params
|
||||
Version,+,31.2,,
|
||||
Version,+,31.3,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/cli/cli.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-tuple.h,,
|
||||
Header,+,lib/mlib/m-variant.h,,
|
||||
Header,+,lib/music_worker/music_worker.h,,
|
||||
Header,+,lib/nfc/nfc_device.h,,
|
||||
Header,+,lib/nfc/protocols/nfc_util.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_read_only,void,"FuriHalMpuRegion, uint32_t, FuriHalMPURegionSize"
|
||||
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_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_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_on,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_start,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_stop,void,
|
||||
Function,+,furi_hal_rfid_field_is_present,_Bool,uint32_t*
|
||||
Function,-,furi_hal_rfid_init,void,
|
||||
Function,+,furi_hal_rfid_pin_pull_pulldown,void,
|
||||
Function,+,furi_hal_rfid_pin_pull_release,void,
|
||||
|
@ -2063,6 +2064,18 @@ Function,-,modf,double,"double, double*"
|
|||
Function,-,modff,float,"float, float*"
|
||||
Function,-,modfl,long double,"long double, long double*"
|
||||
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,-,nanf,float,const char*
|
||||
Function,-,nanl,long double,const char*
|
||||
|
|
|
|
@ -38,6 +38,7 @@
|
|||
"assets",
|
||||
"one_wire",
|
||||
"ibutton",
|
||||
"music_worker",
|
||||
"misc",
|
||||
"mbedtls",
|
||||
"lfrfid",
|
||||
|
|
|
@ -15,6 +15,7 @@ env.Append(
|
|||
Dir("u8g2"),
|
||||
Dir("update_util"),
|
||||
Dir("print"),
|
||||
Dir("music_worker"),
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -100,6 +101,7 @@ libs = env.BuildModules(
|
|||
"misc",
|
||||
"lfrfid",
|
||||
"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.h>
|
||||
|
@ -9,7 +9,7 @@
|
|||
#include <math.h>
|
||||
#include <m-array.h>
|
||||
|
||||
#define TAG "MusicPlayerWorker"
|
||||
#define TAG "MusicWorker"
|
||||
|
||||
#define MUSIC_PLAYER_FILETYPE "Flipper Music Format"
|
||||
#define MUSIC_PLAYER_VERSION 0
|
||||
|
@ -28,11 +28,11 @@ typedef struct {
|
|||
|
||||
ARRAY_DEF(NoteBlockArray, NoteBlock, M_POD_OPLIST);
|
||||
|
||||
struct MusicPlayerWorker {
|
||||
struct MusicWorker {
|
||||
FuriThread* thread;
|
||||
bool should_work;
|
||||
|
||||
MusicPlayerWorkerCallback callback;
|
||||
MusicWorkerCallback callback;
|
||||
void* callback_context;
|
||||
|
||||
float volume;
|
||||
|
@ -42,9 +42,9 @@ struct MusicPlayerWorker {
|
|||
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);
|
||||
MusicPlayerWorker* instance = context;
|
||||
MusicWorker* instance = context;
|
||||
|
||||
NoteBlockArray_it_t it;
|
||||
NoteBlockArray_it(it, instance->notes);
|
||||
|
@ -97,24 +97,24 @@ static int32_t music_player_worker_thread_callback(void* context) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
MusicPlayerWorker* music_player_worker_alloc() {
|
||||
MusicPlayerWorker* instance = malloc(sizeof(MusicPlayerWorker));
|
||||
MusicWorker* music_worker_alloc() {
|
||||
MusicWorker* instance = malloc(sizeof(MusicWorker));
|
||||
|
||||
NoteBlockArray_init(instance->notes);
|
||||
|
||||
instance->thread = furi_thread_alloc_ex(
|
||||
"MusicPlayerWorker", 1024, music_player_worker_thread_callback, instance);
|
||||
instance->thread =
|
||||
furi_thread_alloc_ex("MusicWorker", 1024, music_worker_thread_callback, instance);
|
||||
|
||||
instance->volume = 1.0f;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void music_player_worker_clear(MusicPlayerWorker* instance) {
|
||||
void music_worker_clear(MusicWorker* instance) {
|
||||
NoteBlockArray_reset(instance->notes);
|
||||
}
|
||||
|
||||
void music_player_worker_free(MusicPlayerWorker* instance) {
|
||||
void music_worker_free(MusicWorker* instance) {
|
||||
furi_assert(instance);
|
||||
furi_thread_free(instance->thread);
|
||||
NoteBlockArray_clear(instance->notes);
|
||||
|
@ -186,11 +186,8 @@ static size_t skip_till(const char* string, const char symbol) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool music_player_worker_add_note(
|
||||
MusicPlayerWorker* instance,
|
||||
uint8_t semitone,
|
||||
uint8_t duration,
|
||||
uint8_t dots) {
|
||||
static bool
|
||||
music_worker_add_note(MusicWorker* instance, uint8_t semitone, uint8_t duration, uint8_t dots) {
|
||||
NoteBlock note_block;
|
||||
|
||||
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;
|
||||
bool result = true;
|
||||
|
||||
|
@ -286,7 +283,7 @@ static bool music_player_worker_parse_notes(MusicPlayerWorker* instance, const c
|
|||
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(
|
||||
TAG,
|
||||
"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;
|
||||
}
|
||||
|
||||
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(file_path);
|
||||
|
||||
bool ret = false;
|
||||
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 {
|
||||
ret = music_player_worker_load_rtttl_from_file(instance, file_path);
|
||||
ret = music_worker_load_rtttl_from_file(instance, file_path);
|
||||
}
|
||||
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(file_path);
|
||||
|
||||
|
@ -369,7 +366,7 @@ bool music_player_worker_load_fmf_from_file(MusicPlayerWorker* instance, const c
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -383,7 +380,7 @@ bool music_player_worker_load_fmf_from_file(MusicPlayerWorker* instance, const c
|
|||
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(file_path);
|
||||
|
||||
|
@ -414,7 +411,7 @@ bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const
|
|||
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");
|
||||
break;
|
||||
}
|
||||
|
@ -429,7 +426,7 @@ bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const
|
|||
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);
|
||||
|
||||
const char* cursor = string;
|
||||
|
@ -470,28 +467,25 @@ bool music_player_worker_load_rtttl_from_string(MusicPlayerWorker* instance, con
|
|||
return false;
|
||||
}
|
||||
cursor++;
|
||||
if(!music_player_worker_parse_notes(instance, cursor)) {
|
||||
if(!music_worker_parse_notes(instance, cursor)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void music_player_worker_set_callback(
|
||||
MusicPlayerWorker* instance,
|
||||
MusicPlayerWorkerCallback callback,
|
||||
void* context) {
|
||||
void music_worker_set_callback(MusicWorker* instance, MusicWorkerCallback callback, void* context) {
|
||||
furi_assert(instance);
|
||||
instance->callback = callback;
|
||||
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);
|
||||
instance->volume = volume;
|
||||
}
|
||||
|
||||
void music_player_worker_start(MusicPlayerWorker* instance) {
|
||||
void music_worker_start(MusicWorker* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->should_work == false);
|
||||
|
||||
|
@ -499,10 +493,15 @@ void music_player_worker_start(MusicPlayerWorker* instance) {
|
|||
furi_thread_start(instance->thread);
|
||||
}
|
||||
|
||||
void music_player_worker_stop(MusicPlayerWorker* instance) {
|
||||
void music_worker_stop(MusicWorker* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->should_work == true);
|
||||
|
||||
instance->should_work = false;
|
||||
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…
Reference in a new issue