Commit replay stuff before sync

This commit is contained in:
furrtek
2017-01-10 19:45:40 +00:00
parent 3ec725c172
commit 12aeae3a82
19 changed files with 1210 additions and 22 deletions
+3
View File
@@ -172,6 +172,7 @@ set(CPPSRC
ui_rds.cpp
ui_receiver.cpp
ui_record_view.cpp
ui_replay_view.cpp
ui_rssi.cpp
ui_sd_card_status_view.cpp
# ui_sd_card_debug.cpp
@@ -198,6 +199,7 @@ set(CPPSRC
ert_app.cpp
${COMMON}/ert_packet.cpp
capture_app.cpp
replay_app.cpp
sd_card.cpp
time.cpp
file.cpp
@@ -206,6 +208,7 @@ set(CPPSRC
log_file.cpp
${COMMON}/png_writer.cpp
capture_thread.cpp
replay_thread.cpp
${COMMON}/manchester.cpp
string_format.cpp
temperature_logger.cpp
+90
View File
@@ -3731,6 +3731,60 @@ recent_entries.cpp.s:
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/recent_entries.cpp.s
.PHONY : recent_entries.cpp.s
replay_app.obj: replay_app.cpp.obj
.PHONY : replay_app.obj
# target to build an object file
replay_app.cpp.obj:
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/replay_app.cpp.obj
.PHONY : replay_app.cpp.obj
replay_app.i: replay_app.cpp.i
.PHONY : replay_app.i
# target to preprocess a source file
replay_app.cpp.i:
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/replay_app.cpp.i
.PHONY : replay_app.cpp.i
replay_app.s: replay_app.cpp.s
.PHONY : replay_app.s
# target to generate assembly for a file
replay_app.cpp.s:
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/replay_app.cpp.s
.PHONY : replay_app.cpp.s
replay_thread.obj: replay_thread.cpp.obj
.PHONY : replay_thread.obj
# target to build an object file
replay_thread.cpp.obj:
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/replay_thread.cpp.obj
.PHONY : replay_thread.cpp.obj
replay_thread.i: replay_thread.cpp.i
.PHONY : replay_thread.i
# target to preprocess a source file
replay_thread.cpp.i:
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/replay_thread.cpp.i
.PHONY : replay_thread.cpp.i
replay_thread.s: replay_thread.cpp.s
.PHONY : replay_thread.s
# target to generate assembly for a file
replay_thread.cpp.s:
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/replay_thread.cpp.s
.PHONY : replay_thread.cpp.s
rf_path.obj: rf_path.cpp.obj
.PHONY : rf_path.obj
@@ -4784,6 +4838,33 @@ ui_record_view.cpp.s:
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_record_view.cpp.s
.PHONY : ui_record_view.cpp.s
ui_replay_view.obj: ui_replay_view.cpp.obj
.PHONY : ui_replay_view.obj
# target to build an object file
ui_replay_view.cpp.obj:
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_replay_view.cpp.obj
.PHONY : ui_replay_view.cpp.obj
ui_replay_view.i: ui_replay_view.cpp.i
.PHONY : ui_replay_view.i
# target to preprocess a source file
ui_replay_view.cpp.i:
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_replay_view.cpp.i
.PHONY : ui_replay_view.cpp.i
ui_replay_view.s: ui_replay_view.cpp.s
.PHONY : ui_replay_view.s
# target to generate assembly for a file
ui_replay_view.cpp.s:
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_replay_view.cpp.s
.PHONY : ui_replay_view.cpp.s
ui_rssi.obj: ui_rssi.cpp.obj
.PHONY : ui_rssi.obj
@@ -5463,6 +5544,12 @@ help:
@echo "... recent_entries.obj"
@echo "... recent_entries.i"
@echo "... recent_entries.s"
@echo "... replay_app.obj"
@echo "... replay_app.i"
@echo "... replay_app.s"
@echo "... replay_thread.obj"
@echo "... replay_thread.i"
@echo "... replay_thread.s"
@echo "... rf_path.obj"
@echo "... rf_path.i"
@echo "... rf_path.s"
@@ -5580,6 +5667,9 @@ help:
@echo "... ui_record_view.obj"
@echo "... ui_record_view.i"
@echo "... ui_record_view.s"
@echo "... ui_replay_view.obj"
@echo "... ui_replay_view.i"
@echo "... ui_replay_view.s"
@echo "... ui_rssi.obj"
@echo "... ui_rssi.i"
@echo "... ui_rssi.s"
+23
View File
@@ -512,6 +512,29 @@ static constexpr Bitmap bitmap_icon_remote {
{ 16, 16 }, bitmap_icon_remote_data
};
static constexpr uint8_t bitmap_icon_replay_data[] = {
0x00, 0x00,
0xC0, 0x07,
0xF0, 0x1F,
0x79, 0x3C,
0x1D, 0x70,
0x0F, 0x60,
0x07, 0xE0,
0x1F, 0xC0,
0x00, 0xC0,
0x00, 0xE0,
0x00, 0x60,
0x00, 0x70,
0x30, 0x3C,
0xE0, 0x0F,
0x80, 0x03,
0x00, 0x00,
};
static constexpr Bitmap bitmap_icon_replay {
{ 16, 16 }, bitmap_icon_replay_data
};
static constexpr uint8_t bitmap_icon_soundboard_data[] = {
0x00, 0x00,
0xDE, 0x7B,
+1 -1
View File
@@ -26,8 +26,8 @@
//TEST: Imperial in whipcalc
//TEST: Numbers
//TEST: Jammer
//TODO: Frequency manager auto-remove duplicates
//TODO: Frequency manager auto-remove duplicates
//TODO: "TX box" view or composite widget with frequency and bw settings, simple and advanced setup TX buttons...
//TODO: Morse coder for foxhunts
//TODO: Finish EPAR tx
+121
View File
@@ -0,0 +1,121 @@
/*
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "replay_app.hpp"
#include "baseband_api.hpp"
#include "portapack.hpp"
using namespace portapack;
#include "portapack_persistent_memory.hpp"
using namespace portapack;
namespace ui {
ReplayAppView::ReplayAppView(NavigationView& nav) {
baseband::run_image(portapack::spi_flash::image_tag_replay);
add_children({ {
&channel,
&field_frequency,
&field_frequency_step,
&field_rf_amp,
&field_lna,
&field_vga,
&replay_view,
&waterfall,
} });
field_frequency.set_value(target_frequency());
field_frequency.set_step(receiver_model.frequency_step());
field_frequency.on_change = [this](rf::Frequency f) {
this->on_target_frequency_changed(f);
};
field_frequency.on_edit = [this, &nav]() {
// TODO: Provide separate modal method/scheme?
auto new_view = nav.push<FrequencyKeypadView>(this->target_frequency());
new_view->on_changed = [this](rf::Frequency f) {
this->on_target_frequency_changed(f);
this->field_frequency.set_value(f);
};
};
field_frequency_step.set_by_value(receiver_model.frequency_step());
field_frequency_step.on_change = [this](size_t, OptionsField::value_t v) {
receiver_model.set_frequency_step(v);
this->field_frequency.set_step(v);
};
radio::enable({
target_frequency(),
sampling_rate,
baseband_bandwidth,
rf::Direction::Transmit,
receiver_model.rf_amp(),
static_cast<int8_t>(receiver_model.lna()),
static_cast<int8_t>(receiver_model.vga()),
1,
});
replay_view.set_sampling_rate(sampling_rate / 8);
replay_view.on_error = [&nav](std::string message) {
nav.display_modal("Error", message);
};
}
ReplayAppView::~ReplayAppView() {
radio::disable();
baseband::shutdown();
}
void ReplayAppView::on_hide() {
// TODO: Terrible kludge because widget system doesn't notify Waterfall that
// it's being shown or hidden.
waterfall.on_hide();
View::on_hide();
}
void ReplayAppView::set_parent_rect(const Rect new_parent_rect) {
View::set_parent_rect(new_parent_rect);
const ui::Rect waterfall_rect { 0, header_height, new_parent_rect.width(), static_cast<ui::Dim>(new_parent_rect.height() - header_height) };
waterfall.set_parent_rect(waterfall_rect);
}
void ReplayAppView::focus() {
field_frequency.focus();
}
void ReplayAppView::on_target_frequency_changed(rf::Frequency f) {
set_target_frequency(f);
}
void ReplayAppView::set_target_frequency(const rf::Frequency new_value) {
persistent_memory::set_tuned_frequency(new_value);;
}
rf::Frequency ReplayAppView::target_frequency() const {
return persistent_memory::tuned_frequency();
}
} /* namespace ui */
+95
View File
@@ -0,0 +1,95 @@
/*
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef __REPLAY_APP_HPP__
#define __REPLAY_APP_HPP__
#include "ui_widget.hpp"
#include "ui_navigation.hpp"
#include "ui_receiver.hpp"
#include "ui_replay_view.hpp"
#include "ui_spectrum.hpp"
#include <string>
#include <memory>
namespace ui {
class ReplayAppView : public View {
public:
ReplayAppView(NavigationView& nav);
~ReplayAppView();
void on_hide() override;
void set_parent_rect(const Rect new_parent_rect) override;
void focus() override;
std::string title() const override { return "Capture"; };
private:
static constexpr ui::Dim header_height = 2 * 16;
static constexpr uint32_t sampling_rate = 4000000;
static constexpr uint32_t baseband_bandwidth = 2500000;
void on_target_frequency_changed(rf::Frequency f);
rf::Frequency target_frequency() const;
void set_target_frequency(const rf::Frequency new_value);
Channel channel {
{ 24 * 8, 5, 6 * 8, 4 },
};
FrequencyField field_frequency {
{ 0 * 8, 0 * 16 },
};
FrequencyStepView field_frequency_step {
{ 10 * 8, 0 * 16 },
};
RFAmpField field_rf_amp {
{ 16 * 8, 0 * 16 }
};
LNAGainField field_lna {
{ 18 * 8, 0 * 16 }
};
VGAGainField field_vga {
{ 21 * 8, 0 * 16 }
};
ReplayView replay_view {
{ 0 * 8, 1 * 16, 30 * 8, 1 * 16 },
"BBD_????", ReplayView::FileType::RawS16, 16384, 3
};
spectrum::WaterfallWidget waterfall;
};
} /* namespace ui */
#endif/*__REPLAY_APP_HPP__*/
+143
View File
@@ -0,0 +1,143 @@
/*
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "replay_thread.hpp"
#include "baseband_api.hpp"
// StreamOutput ///////////////////////////////////////////////////////////
class StreamOutput {
public:
StreamOutput(CaptureConfig* const config);
~StreamOutput();
size_t available() {
return fifo_buffers_full->len();
}
StreamBuffer* get_buffer() {
StreamBuffer* p { nullptr };
fifo_buffers_full->out(p);
return p;
}
bool release_buffer(StreamBuffer* const p) {
p->empty();
return fifo_buffers_empty->in(p);
}
static FIFO<StreamBuffer*>* fifo_buffers_empty;
static FIFO<StreamBuffer*>* fifo_buffers_full;
private:
CaptureConfig* const config;
};
FIFO<StreamBuffer*>* StreamOutput::fifo_buffers_empty = nullptr;
FIFO<StreamBuffer*>* StreamOutput::fifo_buffers_full = nullptr;
StreamOutput::StreamOutput(
CaptureConfig* const config
) : config { config }
{
baseband::capture_start(config);
fifo_buffers_empty = config->fifo_buffers_empty;
fifo_buffers_full = config->fifo_buffers_full;
}
StreamOutput::~StreamOutput() {
fifo_buffers_full = nullptr;
fifo_buffers_empty = nullptr;
baseband::capture_stop();
}
// CaptureThread //////////////////////////////////////////////////////////
Thread* ReplayThread::thread = nullptr;
ReplayThread::ReplayThread(
std::unique_ptr<Reader> reader,
size_t read_size,
size_t buffer_count,
std::function<void()> success_callback,
std::function<void(File::Error)> error_callback
) : config { read_size, buffer_count },
reader { std::move(reader) },
success_callback { std::move(success_callback) },
error_callback { std::move(error_callback) }
{
// Need significant stack for FATFS
thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, ReplayThread::static_fn, this);
}
ReplayThread::~ReplayThread() {
if( thread ) {
chThdTerminate(thread);
chEvtSignal(thread, event_mask_loop_wake);
chThdWait(thread);
thread = nullptr;
}
}
void ReplayThread::check_fifo_isr() {
// TODO: Prevent over-signalling by transmitting a set of
// flags from the baseband core.
const auto fifo = StreamOutput::fifo_buffers_full;
if( fifo ) {
if( !fifo->is_empty() ) {
chEvtSignalI(thread, event_mask_loop_wake);
}
}
}
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();
}
}
return 0;
}
Optional<File::Error> ReplayThread::run() {
StreamOutput stream { &config };
while( !chThdShouldTerminate() ) {
if( stream.available() ) {
auto buffer = stream.get_buffer();
auto read_result = reader->reader(buffer->data(), buffer->size());
if( read_result.is_error() ) {
return read_result.error();
}
stream.release_buffer(buffer);
} else {
chEvtWaitAny(event_mask_loop_wake);
}
}
return { };
}
+74
View File
@@ -0,0 +1,74 @@
/*
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef __REPLAY_THREAD_H__
#define __REPLAY_THREAD_H__
#include "ch.h"
#include "event_m0.hpp"
#include "file.hpp"
#include "optional.hpp"
#include <cstdint>
#include <cstddef>
#include <utility>
class Reader {
public:
virtual File::Result<size_t> read(const void* const buffer, const size_t bytes) = 0;
virtual ~Reader() = default;
};
class ReplayThread {
public:
ReplayThread(
std::unique_ptr<Reader> reader,
size_t read_size,
size_t buffer_count,
std::function<void()> success_callback,
std::function<void(File::Error)> error_callback
);
~ReplayThread();
const ReplayConfig& state() const {
return config;
}
static void check_fifo_isr();
private:
static constexpr auto event_mask_loop_wake = EVENT_MASK(0);
ReplayConfig config;
std::unique_ptr<Reader> reader;
std::function<void()> success_callback;
std::function<void(File::Error)> error_callback;
static Thread* thread;
static msg_t static_fn(void* arg);
Optional<File::Error> run();
};
#endif/*__REPLAY_THREAD_H__*/
+3 -2
View File
@@ -55,6 +55,7 @@
#include "tpms_app.hpp"
#include "pocsag_app.hpp"
#include "capture_app.hpp"
#include "replay_app.hpp"
#include "core_control.hpp"
@@ -338,16 +339,16 @@ void SystemMenuView::hackrf_mode(NavigationView& nav) {
}
SystemMenuView::SystemMenuView(NavigationView& nav) {
add_items<11>({ {
add_items<12>({ {
{ "Play dead", ui::Color::red(), &bitmap_icon_playdead, [&nav](){ nav.push<PlayDeadView>(); } },
{ "Receivers", ui::Color::cyan(), &bitmap_icon_receiver, [&nav](){ nav.push<ReceiverMenuView>(); } },
{ "Capture", ui::Color::cyan(), &bitmap_icon_capture, [&nav](){ nav.push<CaptureAppView>(); } },
{ "Replay", ui::Color::blue(), &bitmap_icon_replay, [&nav](){ nav.push<ReplayAppView>(); } },
{ "Code transmitters", ui::Color::green(), &bitmap_icon_codetx, [&nav](){ nav.push<TransmitterCodedMenuView>(); } },
{ "Audio transmitters", ui::Color::green(), &bitmap_icon_audiotx, [&nav](){ nav.push<TransmitterAudioMenuView>(); } },
{ "Close Call", ui::Color::orange(),&bitmap_icon_closecall, [&nav](){ nav.push<CloseCallView>(); } },
{ "Jammer", ui::Color::orange(),&bitmap_icon_jammer, [&nav](){ nav.push<JammerView>(); } },
{ "Utilities", ui::Color::purple(),nullptr, [&nav](){ nav.push<UtilitiesView>(); } },
//{ "Analyze", ui::Color::white(), [&nav](){ nav.push<NotImplementedView>(); } },
{ "Setup", ui::Color::white(), nullptr, [&nav](){ nav.push<SetupMenuView>(); } },
//{ "Debug", ui::Color::white(), nullptr, [&nav](){ nav.push<DebugMenuView>(); } },
{ "HackRF mode", ui::Color::white(), &bitmap_icon_hackrf, [this, &nav](){ hackrf_mode(nav); } },
+191
View File
@@ -0,0 +1,191 @@
/*
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "ui_replay_view.hpp"
#include "portapack.hpp"
#include "message.hpp"
#include "portapack_shared_memory.hpp"
using namespace portapack;
#include "time.hpp"
#include "string_format.hpp"
#include "utility.hpp"
#include <cstdint>
namespace ui {
ReplayView::ReplayView(
const Rect parent_rect,
std::string filename_stem_pattern,
const FileType file_type,
const size_t read_size,
const size_t buffer_count
) : View { parent_rect },
filename_stem_pattern { filename_stem_pattern },
file_type { file_type },
read_size { read_size },
buffer_count { buffer_count }
{
add_children({ {
&rect_background,
&button_record,
&text_replay_filename,
&text_time_seek,
} });
rect_background.set_parent_rect({ { 0, 0 }, size() });
button_record.on_select = [this](ImageButton&) {
this->toggle();
};
signal_token_tick_second = time::signal_tick_second += [this]() {
this->on_tick_second();
};
}
ReplayView::~ReplayView() {
time::signal_tick_second -= signal_token_tick_second;
}
void ReplayView::focus() {
button_record.focus();
}
void ReplayView::set_sampling_rate(const size_t new_sampling_rate) {
if( new_sampling_rate != sampling_rate ) {
stop();
sampling_rate = new_sampling_rate;
button_record.hidden(sampling_rate == 0);
text_replay_filename.hidden(sampling_rate == 0);
text_time_seek.hidden(sampling_rate == 0);
rect_background.hidden(sampling_rate != 0);
update_status_display();
}
}
bool ReplayView::is_active() const {
return (bool)replay_thread;
}
void ReplayView::toggle() {
if( is_active() ) {
stop();
} else {
start();
}
}
void ReplayView::start() {
stop();
text_replay_filename.set("");
if( sampling_rate == 0 ) {
return;
}
const auto filename_stem = next_filename_stem_matching_pattern(filename_stem_pattern);
if( filename_stem.empty() ) {
return;
}
std::unique_ptr<Reader> reader;
auto p = std::make_unique<FileReader>();
auto create_error = p->create(
filename_stem + ".C16"
);
if( create_error.is_valid() ) {
handle_error(create_error.value());
} else {
reader = std::move(p);
}
if( reader ) {
text_replay_filename.set(filename_stem);
button_record.set_bitmap(&bitmap_stop);
replay_thread = std::make_unique<ReplayThread>(
std::move(reader),
read_size, buffer_count,
[]() {
ReplayThreadDoneMessage message { };
EventDispatcher::send_message(message);
},
[](File::Error error) {
ReplayThreadDoneMessage message { error.code() };
EventDispatcher::send_message(message);
}
);
}
update_status_display();
}
void ReplayView::stop() {
if( is_active() ) {
replay_thread.reset();
button_record.set_bitmap(&bitmap_record);
}
update_status_display();
}
void ReplayView::on_tick_second() {
update_status_display();
}
void ReplayView::update_status_display() {
/*if( sampling_rate ) {
const auto space_info = std::filesystem::space("");
const uint32_t bytes_per_second = file_type == FileType::WAV ? (sampling_rate * 2) : (sampling_rate * 4);
const uint32_t available_seconds = space_info.free / bytes_per_second;
const uint32_t seconds = available_seconds % 60;
const uint32_t available_minutes = available_seconds / 60;
const uint32_t minutes = available_minutes % 60;
const uint32_t hours = available_minutes / 60;
const std::string available_time =
to_string_dec_uint(hours, 3, ' ') + ":" +
to_string_dec_uint(minutes, 2, '0') + ":" +
to_string_dec_uint(seconds, 2, '0');
text_time_available.set(available_time);
}*/
}
void ReplayView::handle_replay_thread_done(const File::Error error) {
stop();
if( error.code() ) {
handle_error(error);
}
}
void ReplayView::handle_error(const File::Error error) {
if( on_error ) {
on_error(error.what());
}
}
} /* namespace ui */
+116
View File
@@ -0,0 +1,116 @@
/*
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef __UI_REPLAY_VIEW_H__
#define __UI_REPLAY_VIEW_H__
#include "ui_widget.hpp"
#include "replay_thread.hpp"
#include "signal.hpp"
#include "bitmap.hpp"
#include <cstddef>
#include <string>
#include <memory>
namespace ui {
class ReplayView : public View {
public:
std::function<void(std::string)> on_error;
enum FileType {
RawS16 = 2,
WAV = 3,
};
ReplayView(
const Rect parent_rect,
std::string filename_stem_pattern,
FileType file_type,
const size_t read_size,
const size_t buffer_count
);
~ReplayView();
void focus() override;
void set_sampling_rate(const size_t new_sampling_rate);
void start();
void stop();
bool is_active() const;
private:
void toggle();
void on_tick_second();
void update_status_display();
void handle_replay_thread_done(const File::Error error);
void handle_error(const File::Error error);
bool pwmrssi_enabled = false;
const std::string filename_stem_pattern;
const FileType file_type;
const size_t read_size;
const size_t buffer_count;
size_t sampling_rate { 0 };
SignalToken signal_token_tick_second;
Rectangle rect_background {
Color::black()
};
ImageButton button_record {
{ 4 * 8, 0 * 16, 2 * 8, 1 * 16 },
&bitmap_record,
Color::red(),
Color::black()
};
Text text_replay_filename {
{ 7 * 8, 0 * 16, 8 * 8, 16 },
"",
};
Text text_time_seek {
{ 21 * 8, 0 * 16, 9 * 8, 16 },
"",
};
std::unique_ptr<ReplayThread> replay_thread;
MessageHandlerRegistration message_handler_capture_thread_error {
Message::ID::CaptureThreadDone,
[this](const Message* const p) {
const auto message = *reinterpret_cast<const ReplayThreadDoneMessage*>(p);
this->handle_replay_thread_done(message.error);
}
};
};
} /* namespace ui */
#endif/*__UI_REPLAY_VIEW_H__*/