[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:
Sergey Gavrilov 2023-06-29 14:23:04 +03:00 committed by GitHub
parent e5ae3e22b3
commit 95c1585df6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 295 additions and 153 deletions

View file

@ -12,5 +12,6 @@ App(
"display_test", "display_test",
"text_box_test", "text_box_test",
"file_browser_test", "file_browser_test",
"speaker_debug",
], ],
) )

View 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"],
)

View 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;
}

View file

@ -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;

View file

@ -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,
) )

View file

@ -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);

View file

@ -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
}

View file

@ -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);

View file

@ -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*"

1 entry status name type params
2 Version + 31.2 31.3
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
128 Header + lib/mlib/m-rbtree.h
129 Header + lib/mlib/m-tuple.h
130 Header + lib/mlib/m-variant.h
131 Header + lib/music_worker/music_worker.h
132 Header + lib/one_wire/maxim_crc.h
133 Header + lib/one_wire/one_wire_host.h
134 Header + lib/one_wire/one_wire_slave.h
1520 Function - mktemp char* char*
1521 Function - mktime time_t tm*
1522 Function - mrand48 long
1523 Function - music_worker_alloc MusicWorker*
1524 Function - music_worker_clear void MusicWorker*
1525 Function - music_worker_free void MusicWorker*
1526 Function - music_worker_is_playing _Bool MusicWorker*
1527 Function - music_worker_load _Bool MusicWorker*, const char*
1528 Function - music_worker_load_fmf_from_file _Bool MusicWorker*, const char*
1529 Function - music_worker_load_rtttl_from_file _Bool MusicWorker*, const char*
1530 Function - music_worker_load_rtttl_from_string _Bool MusicWorker*, const char*
1531 Function - music_worker_set_callback void MusicWorker*, MusicWorkerCallback, void*
1532 Function - music_worker_set_volume void MusicWorker*, float
1533 Function - music_worker_start void MusicWorker*
1534 Function - music_worker_stop void MusicWorker*
1535 Function + notification_internal_message void NotificationApp*, const NotificationSequence*
1536 Function + notification_internal_message_block void NotificationApp*, const NotificationSequence*
1537 Function + notification_message void NotificationApp*, const NotificationSequence*

View file

@ -25,6 +25,7 @@
"appframe", "appframe",
"assets", "assets",
"one_wire", "one_wire",
"music_worker",
"misc", "misc",
"flipper_application", "flipper_application",
"flipperformat", "flipperformat",

View file

@ -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*

1 entry status name type params
2 Version + 31.2 31.3
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
146 Header + lib/mlib/m-rbtree.h
147 Header + lib/mlib/m-tuple.h
148 Header + lib/mlib/m-variant.h
149 Header + lib/music_worker/music_worker.h
150 Header + lib/nfc/nfc_device.h
151 Header + lib/nfc/protocols/nfc_util.h
152 Header + lib/one_wire/maxim_crc.h
1221 Function + furi_hal_mpu_protect_no_access void FuriHalMpuRegion, uint32_t, FuriHalMPURegionSize
1222 Function + furi_hal_mpu_protect_read_only void FuriHalMpuRegion, uint32_t, FuriHalMPURegionSize
1223 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
1224 Function - furi_hal_nfc_deinit void
1225 Function + furi_hal_nfc_detect _Bool FuriHalNfcDevData*, uint32_t
1226 Function + furi_hal_nfc_emulate_nfca _Bool uint8_t*, uint8_t, uint8_t*, uint8_t, FuriHalNfcEmulateCallback, void*, uint32_t
1227 Function + furi_hal_nfc_exit_sleep void
1228 Function + furi_hal_nfc_field_detect_start void
1229 Function + furi_hal_nfc_field_is_present _Bool
1230 Function + furi_hal_nfc_field_off void
1231 Function + furi_hal_nfc_field_on void
1232 Function - furi_hal_nfc_init void
1308 Function + furi_hal_rfid_comp_set_callback void FuriHalRfidCompCallback, void*
1309 Function + furi_hal_rfid_comp_start void
1310 Function + furi_hal_rfid_comp_stop void
Function + furi_hal_rfid_field_is_present _Bool uint32_t*
1311 Function + furi_hal_rfid_field_detect_start void
1312 Function + furi_hal_rfid_field_detect_stop void
1313 Function + furi_hal_rfid_field_is_present _Bool uint32_t*
1314 Function - furi_hal_rfid_init void
1315 Function + furi_hal_rfid_pin_pull_pulldown void
1316 Function + furi_hal_rfid_pin_pull_release void
2064 Function - modff float float, float*
2065 Function - modfl long double long double, long double*
2066 Function - mrand48 long
2067 Function - music_worker_alloc MusicWorker*
2068 Function - music_worker_clear void MusicWorker*
2069 Function - music_worker_free void MusicWorker*
2070 Function - music_worker_is_playing _Bool MusicWorker*
2071 Function - music_worker_load _Bool MusicWorker*, const char*
2072 Function - music_worker_load_fmf_from_file _Bool MusicWorker*, const char*
2073 Function - music_worker_load_rtttl_from_file _Bool MusicWorker*, const char*
2074 Function - music_worker_load_rtttl_from_string _Bool MusicWorker*, const char*
2075 Function - music_worker_set_callback void MusicWorker*, MusicWorkerCallback, void*
2076 Function - music_worker_set_volume void MusicWorker*, float
2077 Function - music_worker_start void MusicWorker*
2078 Function - music_worker_stop void MusicWorker*
2079 Function - nan double const char*
2080 Function - nanf float const char*
2081 Function - nanl long double const char*

View file

@ -38,6 +38,7 @@
"assets", "assets",
"one_wire", "one_wire",
"ibutton", "ibutton",
"music_worker",
"misc", "misc",
"mbedtls", "mbedtls",
"lfrfid", "lfrfid",

View file

@ -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",
], ],
) )

View 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")

View file

@ -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;
}

View 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);