mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-10-01 01:26:06 -04:00
Added loop option in Replay app
Updated binary
This commit is contained in:
parent
70c7646743
commit
c9381f1418
@ -44,18 +44,15 @@ void ReplayAppView::on_file_changed(std::filesystem::path new_file_path) {
|
||||
|
||||
file_path = new_file_path;
|
||||
|
||||
text_filename.set(new_file_path.string().substr(0, 18));
|
||||
text_filename.set(new_file_path.string().substr(0, 19));
|
||||
|
||||
bbd_file.open("/" + new_file_path.string());
|
||||
auto file_size = bbd_file.size();
|
||||
auto duration = file_size / (2 * 2 * sampling_rate / 8);
|
||||
auto duration = (file_size * 1000) / (2 * 2 * sampling_rate / 8);
|
||||
|
||||
progressbar.set_max(file_size);
|
||||
|
||||
if (duration >= 60)
|
||||
str_duration = to_string_dec_uint(duration / 60) + "m";
|
||||
|
||||
text_duration.set(str_duration + to_string_dec_uint(duration % 60) + "s");
|
||||
text_duration.set(to_string_time_ms(duration));
|
||||
|
||||
button_play.focus();
|
||||
}
|
||||
@ -68,27 +65,31 @@ void ReplayAppView::focus() {
|
||||
button_open.focus();
|
||||
}
|
||||
|
||||
void ReplayAppView::file_error() {
|
||||
nav_.display_modal("Error", "File read error.");
|
||||
}
|
||||
|
||||
bool ReplayAppView::is_active() const {
|
||||
return (bool)replay_thread;
|
||||
}
|
||||
|
||||
void ReplayAppView::toggle() {
|
||||
if( is_active() ) {
|
||||
stop();
|
||||
stop(false);
|
||||
} else {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
void ReplayAppView::start() {
|
||||
stop();
|
||||
stop(false);
|
||||
|
||||
std::unique_ptr<stream::Reader> reader;
|
||||
|
||||
auto p = std::make_unique<FileReader>();
|
||||
auto open_error = p->open(file_path);
|
||||
if( open_error.is_valid() ) {
|
||||
handle_error(open_error.value());
|
||||
file_error();
|
||||
} else {
|
||||
reader = std::move(p);
|
||||
}
|
||||
@ -99,12 +100,8 @@ void ReplayAppView::start() {
|
||||
std::move(reader),
|
||||
read_size, buffer_count,
|
||||
&ready_signal,
|
||||
[]() {
|
||||
ReplayThreadDoneMessage message { };
|
||||
EventDispatcher::send_message(message);
|
||||
},
|
||||
[](File::Error error) {
|
||||
ReplayThreadDoneMessage message { error.code() };
|
||||
[](uint32_t return_code) {
|
||||
ReplayThreadDoneMessage message { return_code };
|
||||
EventDispatcher::send_message(message);
|
||||
}
|
||||
);
|
||||
@ -121,25 +118,27 @@ void ReplayAppView::start() {
|
||||
});
|
||||
}
|
||||
|
||||
void ReplayAppView::stop() {
|
||||
void ReplayAppView::stop(const bool do_loop) {
|
||||
if( is_active() )
|
||||
replay_thread.reset();
|
||||
|
||||
progressbar.set_value(0);
|
||||
|
||||
radio::disable();
|
||||
button_play.set_bitmap(&bitmap_play);
|
||||
}
|
||||
|
||||
void ReplayAppView::handle_replay_thread_done(const File::Error error) {
|
||||
stop();
|
||||
if( error.code() ) {
|
||||
handle_error(error);
|
||||
if (do_loop && check_loop.value()) {
|
||||
start();
|
||||
} else {
|
||||
radio::disable();
|
||||
button_play.set_bitmap(&bitmap_play);
|
||||
}
|
||||
}
|
||||
|
||||
void ReplayAppView::handle_error(const File::Error error) {
|
||||
nav_.display_modal("Error", error.what());
|
||||
void ReplayAppView::handle_replay_thread_done(const uint32_t return_code) {
|
||||
if (return_code == ReplayThread::END_OF_FILE) {
|
||||
stop(true);
|
||||
} else if (return_code == ReplayThread::READ_ERROR) {
|
||||
stop(false);
|
||||
file_error();
|
||||
}
|
||||
|
||||
progressbar.set_value(0);
|
||||
}
|
||||
|
||||
ReplayAppView::ReplayAppView(
|
||||
@ -150,14 +149,15 @@ ReplayAppView::ReplayAppView(
|
||||
|
||||
add_children({
|
||||
&labels,
|
||||
&field_frequency,
|
||||
&field_lna,
|
||||
&field_rf_amp,
|
||||
&button_play,
|
||||
&button_open,
|
||||
&text_filename,
|
||||
&text_duration,
|
||||
&progressbar,
|
||||
&button_open,
|
||||
&field_frequency,
|
||||
&field_lna,
|
||||
&field_rf_amp,
|
||||
&check_loop,
|
||||
&button_play,
|
||||
&waterfall,
|
||||
});
|
||||
|
||||
|
@ -45,10 +45,6 @@ public:
|
||||
|
||||
std::string title() const override { return "Replay"; };
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
bool is_active() const;
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
|
||||
@ -67,53 +63,59 @@ private:
|
||||
rf::Frequency target_frequency() const;
|
||||
|
||||
void toggle();
|
||||
void start();
|
||||
void stop(const bool do_loop);
|
||||
bool is_active() const;
|
||||
void set_ready();
|
||||
void handle_replay_thread_done(const File::Error error);
|
||||
void handle_error(const File::Error error);
|
||||
void handle_replay_thread_done(const uint32_t return_code);
|
||||
void file_error();
|
||||
|
||||
std::filesystem::path file_path { };
|
||||
std::unique_ptr<ReplayThread> replay_thread { };
|
||||
bool ready_signal { false };
|
||||
|
||||
Labels labels {
|
||||
{ { 10 * 8, 0 * 8 }, "LNA: AMP:", Color::light_grey() }
|
||||
};
|
||||
|
||||
FrequencyField field_frequency {
|
||||
{ 0 * 8, 0 * 16 },
|
||||
};
|
||||
|
||||
LNAGainField field_lna {
|
||||
{ 14 * 8, 0 * 16 }
|
||||
};
|
||||
|
||||
RFAmpField field_rf_amp {
|
||||
{ 21 * 8, 0 * 16 }
|
||||
};
|
||||
|
||||
ImageButton button_play {
|
||||
{ 0 * 8, 1 * 16 + 8, 2 * 8, 1 * 16 },
|
||||
&bitmap_play,
|
||||
Color::green(),
|
||||
Color::black()
|
||||
};
|
||||
|
||||
Text text_filename {
|
||||
{ 2 * 8, 1 * 16, 18 * 8, 16 },
|
||||
"-"
|
||||
};
|
||||
Text text_duration {
|
||||
{ 2 * 8, 2 * 16, 6 * 8, 16 },
|
||||
"-"
|
||||
};
|
||||
ProgressBar progressbar {
|
||||
{ 9 * 8, 2 * 16, 10 * 8, 16 }
|
||||
{ { 10 * 8, 2 * 16 }, "LNA: A:", Color::light_grey() }
|
||||
};
|
||||
|
||||
Button button_open {
|
||||
{ 20 * 8, 1 * 16, 10 * 8, 2 * 16 },
|
||||
{ 0 * 8, 0 * 16, 10 * 8, 2 * 16 },
|
||||
"Open file"
|
||||
};
|
||||
|
||||
Text text_filename {
|
||||
{ 11 * 8, 0 * 16, 19 * 8, 16 },
|
||||
"-"
|
||||
};
|
||||
Text text_duration {
|
||||
{ 11 * 8, 1 * 16, 6 * 8, 16 },
|
||||
"-"
|
||||
};
|
||||
ProgressBar progressbar {
|
||||
{ 18 * 8, 1 * 16, 12 * 8, 16 }
|
||||
};
|
||||
|
||||
FrequencyField field_frequency {
|
||||
{ 0 * 8, 2 * 16 },
|
||||
};
|
||||
LNAGainField field_lna {
|
||||
{ 14 * 8, 2 * 16 }
|
||||
};
|
||||
RFAmpField field_rf_amp {
|
||||
{ 19 * 8, 2 * 16 }
|
||||
};
|
||||
Checkbox check_loop {
|
||||
{ 21 * 8, 2 * 16 },
|
||||
4,
|
||||
"Loop",
|
||||
true
|
||||
};
|
||||
ImageButton button_play {
|
||||
{ 28 * 8, 2 * 16, 2 * 8, 1 * 16 },
|
||||
&bitmap_play,
|
||||
Color::green(),
|
||||
Color::black()
|
||||
};
|
||||
|
||||
spectrum::WaterfallWidget waterfall { };
|
||||
|
||||
@ -121,7 +123,7 @@ private:
|
||||
Message::ID::ReplayThreadDone,
|
||||
[this](const Message* const p) {
|
||||
const auto message = *reinterpret_cast<const ReplayThreadDoneMessage*>(p);
|
||||
this->handle_replay_thread_done(message.error);
|
||||
this->handle_replay_thread_done(message.return_code);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -42,13 +42,11 @@ ReplayThread::ReplayThread(
|
||||
size_t read_size,
|
||||
size_t buffer_count,
|
||||
bool* ready_signal,
|
||||
std::function<void()> success_callback,
|
||||
std::function<void(File::Error)> error_callback
|
||||
std::function<void(uint32_t return_code)> terminate_callback
|
||||
) : config { read_size, buffer_count },
|
||||
reader { std::move(reader) },
|
||||
ready_sig { ready_signal },
|
||||
success_callback { std::move(success_callback) },
|
||||
error_callback { std::move(error_callback) }
|
||||
terminate_callback { std::move(terminate_callback) }
|
||||
{
|
||||
// Need significant stack for FATFS
|
||||
thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, ReplayThread::static_fn, this);
|
||||
@ -64,18 +62,14 @@ ReplayThread::~ReplayThread() {
|
||||
|
||||
msg_t ReplayThread::static_fn(void* arg) {
|
||||
auto obj = static_cast<ReplayThread*>(arg);
|
||||
const auto error = obj->run();
|
||||
if( error.is_valid() && obj->error_callback ) {
|
||||
obj->error_callback(error.value());
|
||||
} else {
|
||||
if( obj->success_callback ) {
|
||||
obj->success_callback();
|
||||
}
|
||||
const auto return_code = obj->run();
|
||||
if( obj->terminate_callback ) {
|
||||
obj->terminate_callback(return_code);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Optional<File::Error> ReplayThread::run() {
|
||||
uint32_t ReplayThread::run() {
|
||||
BasebandReplay replay { &config };
|
||||
BufferExchange buffers { &config };
|
||||
|
||||
@ -99,7 +93,7 @@ Optional<File::Error> ReplayThread::run() {
|
||||
for (size_t c = 0; c < blocks; c++) {
|
||||
auto read_result = reader->read(&((uint8_t*)prefill_buffer->data())[c * 512], 512);
|
||||
if( read_result.is_error() ) {
|
||||
return read_result.error();
|
||||
return READ_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,10 +110,10 @@ Optional<File::Error> ReplayThread::run() {
|
||||
|
||||
auto read_result = reader->read(buffer->data(), buffer->capacity());
|
||||
if( read_result.is_error() ) {
|
||||
return read_result.error();
|
||||
return READ_ERROR;
|
||||
} else {
|
||||
if (read_result.value() == 0) {
|
||||
return { };
|
||||
return END_OF_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,5 +122,5 @@ Optional<File::Error> ReplayThread::run() {
|
||||
buffers.put(buffer);
|
||||
}
|
||||
|
||||
return { };
|
||||
return TERMINATED;
|
||||
}
|
||||
|
@ -41,8 +41,7 @@ public:
|
||||
size_t read_size,
|
||||
size_t buffer_count,
|
||||
bool* ready_signal,
|
||||
std::function<void()> success_callback,
|
||||
std::function<void(File::Error)> error_callback
|
||||
std::function<void(uint32_t return_code)> terminate_callback
|
||||
);
|
||||
~ReplayThread();
|
||||
|
||||
@ -53,19 +52,24 @@ public:
|
||||
|
||||
const ReplayConfig& state() const {
|
||||
return config;
|
||||
}
|
||||
};
|
||||
|
||||
enum replaythread_return {
|
||||
READ_ERROR = 0,
|
||||
END_OF_FILE,
|
||||
TERMINATED
|
||||
};
|
||||
|
||||
private:
|
||||
ReplayConfig config;
|
||||
std::unique_ptr<stream::Reader> reader;
|
||||
bool* ready_sig;
|
||||
std::function<void()> success_callback;
|
||||
std::function<void(File::Error)> error_callback;
|
||||
std::function<void(uint32_t return_code)> terminate_callback;
|
||||
Thread* thread { nullptr };
|
||||
|
||||
static msg_t static_fn(void* arg);
|
||||
|
||||
Optional<File::Error> run();
|
||||
uint32_t run();
|
||||
};
|
||||
|
||||
#endif/*__REPLAY_THREAD_H__*/
|
||||
|
@ -117,6 +117,23 @@ std::string to_string_short_freq(const uint64_t f) {
|
||||
return final_str;
|
||||
}
|
||||
|
||||
std::string to_string_time_ms(const uint32_t ms) {
|
||||
std::string final_str { "" };
|
||||
|
||||
if (ms < 1000) {
|
||||
final_str = to_string_dec_uint(ms) + "ms";
|
||||
} else {
|
||||
auto seconds = ms / 1000;
|
||||
|
||||
if (seconds >= 60)
|
||||
final_str = to_string_dec_uint(seconds / 60) + "m";
|
||||
|
||||
return final_str + to_string_dec_uint(seconds % 60) + "s";
|
||||
}
|
||||
|
||||
return final_str;
|
||||
}
|
||||
|
||||
static void to_string_hex_internal(char* p, const uint64_t n, const int32_t l) {
|
||||
const uint32_t d = n & 0xf;
|
||||
p[l] = (d > 9) ? (d + 55) : (d + 48);
|
||||
|
@ -45,6 +45,7 @@ std::string to_string_hex(const uint64_t n, const int32_t l = 0);
|
||||
std::string to_string_hex_array(uint8_t * const array, const int32_t l = 0);
|
||||
|
||||
std::string to_string_short_freq(const uint64_t f);
|
||||
std::string to_string_time_ms(const uint32_t ms);
|
||||
|
||||
std::string to_string_datetime(const rtc::RTC& value, const TimeFormat format = YMDHMS);
|
||||
std::string to_string_timestamp(const rtc::RTC& value);
|
||||
|
@ -133,9 +133,7 @@ void SoundBoardView::play_sound(uint16_t id) {
|
||||
}
|
||||
|
||||
void SoundBoardView::show_infos(uint16_t id) {
|
||||
uint32_t duration = sounds[id].ms_duration;
|
||||
|
||||
text_duration.set(to_string_dec_uint(duration / 1000) + "." + to_string_dec_uint((duration / 100) % 10) + "s");
|
||||
text_duration.set(to_string_time_ms(sounds[id].ms_duration));
|
||||
|
||||
text_title.set(sounds[id].title);
|
||||
}
|
||||
|
@ -997,13 +997,13 @@ public:
|
||||
class ReplayThreadDoneMessage : public Message {
|
||||
public:
|
||||
constexpr ReplayThreadDoneMessage(
|
||||
uint32_t error = 0
|
||||
uint32_t return_code = 0
|
||||
) : Message { ID::ReplayThreadDone },
|
||||
error { error }
|
||||
return_code { return_code }
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t error;
|
||||
uint32_t return_code;
|
||||
};
|
||||
|
||||
#endif/*__MESSAGE_H__*/
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user