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",
|
"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…
Reference in a new issue