use libtag duration where available
This commit is contained in:
@@ -112,17 +112,13 @@ int CmdPlayFile(int argc, char** argv) {
|
|||||||
database::TrackId id = std::atoi(argv[1]);
|
database::TrackId id = std::atoi(argv[1]);
|
||||||
AppConsole::sTrackQueue->AddLast(id);
|
AppConsole::sTrackQueue->AddLast(id);
|
||||||
} else {
|
} else {
|
||||||
// TODO.
|
|
||||||
/*
|
|
||||||
std::ostringstream path;
|
std::ostringstream path;
|
||||||
path << '/' << argv[1];
|
path << '/' << argv[1];
|
||||||
for (int i = 2; i < argc; i++) {
|
for (int i = 2; i < argc; i++) {
|
||||||
path << ' ' << argv[i];
|
path << ' ' << argv[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
events::Dispatch<audio::PlayFile, audio::AudioState>(
|
events::Audio().Dispatch(audio::PlayFile{.filename = path.str()});
|
||||||
audio::PlayFile{.filename = path.str()});
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -93,6 +93,10 @@ void Uninitialised::react(const system_fsm::BootComplete&) {
|
|||||||
transit<Standby>();
|
transit<Standby>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Standby::react(const PlayFile& ev) {
|
||||||
|
sFileSource->SetPath(ev.filename);
|
||||||
|
}
|
||||||
|
|
||||||
void Standby::react(const internal::InputFileOpened& ev) {
|
void Standby::react(const internal::InputFileOpened& ev) {
|
||||||
transit<Playback>();
|
transit<Playback>();
|
||||||
}
|
}
|
||||||
@@ -161,6 +165,9 @@ void Playback::react(const internal::InputFileClosed& ev) {}
|
|||||||
void Playback::react(const internal::InputFileFinished& ev) {
|
void Playback::react(const internal::InputFileFinished& ev) {
|
||||||
ESP_LOGI(kTag, "finished playing file");
|
ESP_LOGI(kTag, "finished playing file");
|
||||||
sTrackQueue->Next();
|
sTrackQueue->Next();
|
||||||
|
if (!sTrackQueue->GetCurrent()) {
|
||||||
|
transit<Standby>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Playback::react(const internal::AudioPipelineIdle& ev) {
|
void Playback::react(const internal::AudioPipelineIdle& ev) {
|
||||||
|
|||||||
@@ -61,10 +61,12 @@ Timer::Timer(StreamInfo::Pcm format)
|
|||||||
|
|
||||||
auto Timer::SetLengthSeconds(uint32_t len) -> void {
|
auto Timer::SetLengthSeconds(uint32_t len) -> void {
|
||||||
total_duration_seconds_ = len;
|
total_duration_seconds_ = len;
|
||||||
|
has_duration_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Timer::SetLengthBytes(uint32_t len) -> void {
|
auto Timer::SetLengthBytes(uint32_t len) -> void {
|
||||||
total_duration_seconds_ = bytes_to_samples(len) / format_.sample_rate;
|
total_duration_seconds_ = bytes_to_samples(len) / format_.sample_rate;
|
||||||
|
has_duration_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Timer::AddBytes(std::size_t bytes) -> void {
|
auto Timer::AddBytes(std::size_t bytes) -> void {
|
||||||
@@ -135,8 +137,14 @@ void AudioTask::Main() {
|
|||||||
if (ForwardPcmStream(*pcm, stream.data())) {
|
if (ForwardPcmStream(*pcm, stream.data())) {
|
||||||
stream.consume(stream.data().size_bytes());
|
stream.consume(stream.data().size_bytes());
|
||||||
}
|
}
|
||||||
|
if (!timer_->has_duration()) {
|
||||||
|
if (stream.info().total_length_seconds()) {
|
||||||
|
timer_->SetLengthSeconds(*stream.info().total_length_seconds());
|
||||||
|
} else {
|
||||||
timer_->SetLengthBytes(
|
timer_->SetLengthBytes(
|
||||||
stream.info().total_length_bytes().value_or(0));
|
stream.info().total_length_bytes().value_or(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,6 +241,8 @@ auto AudioTask::BeginDecoding(InputStream& stream) -> bool {
|
|||||||
|
|
||||||
if (format.duration_seconds) {
|
if (format.duration_seconds) {
|
||||||
timer_->SetLengthSeconds(*format.duration_seconds);
|
timer_->SetLengthSeconds(*format.duration_seconds);
|
||||||
|
} else if (stream.info().total_length_seconds()) {
|
||||||
|
timer_->SetLengthSeconds(*stream.info().total_length_seconds());
|
||||||
} else {
|
} else {
|
||||||
timer_->SetLengthBytes(stream.info().total_length_bytes().value_or(0));
|
timer_->SetLengthBytes(stream.info().total_length_bytes().value_or(0));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -283,6 +283,9 @@ auto FatfsAudioInput::OpenFile(const std::string& path) -> void {
|
|||||||
|
|
||||||
OutputStream writer{input_buffer_.get()};
|
OutputStream writer{input_buffer_.get()};
|
||||||
writer.prepare(format, info.fsize);
|
writer.prepare(format, info.fsize);
|
||||||
|
if (tags.duration) {
|
||||||
|
writer.info().total_length_seconds() = *tags.duration;
|
||||||
|
}
|
||||||
|
|
||||||
streamer_->Restart(std::move(file));
|
streamer_->Restart(std::move(file));
|
||||||
is_first_read_ = true;
|
is_first_read_ = true;
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ struct QueueUpdate : tinyfsm::Event {
|
|||||||
bool current_changed;
|
bool current_changed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PlayFile : tinyfsm::Event {
|
||||||
|
std::string filename;
|
||||||
|
};
|
||||||
|
|
||||||
struct VolumeChanged : tinyfsm::Event {};
|
struct VolumeChanged : tinyfsm::Event {};
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ class AudioState : public tinyfsm::Fsm<AudioState> {
|
|||||||
|
|
||||||
virtual void react(const system_fsm::BootComplete&) {}
|
virtual void react(const system_fsm::BootComplete&) {}
|
||||||
|
|
||||||
|
virtual void react(const PlayFile&) {}
|
||||||
virtual void react(const QueueUpdate&) {}
|
virtual void react(const QueueUpdate&) {}
|
||||||
virtual void react(const PlaybackUpdate&) {}
|
virtual void react(const PlaybackUpdate&) {}
|
||||||
|
|
||||||
@@ -82,6 +83,7 @@ class Uninitialised : public AudioState {
|
|||||||
|
|
||||||
class Standby : public AudioState {
|
class Standby : public AudioState {
|
||||||
public:
|
public:
|
||||||
|
void react(const PlayFile&) override;
|
||||||
void react(const internal::InputFileOpened&) override;
|
void react(const internal::InputFileOpened&) override;
|
||||||
void react(const QueueUpdate&) override;
|
void react(const QueueUpdate&) override;
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ class Timer {
|
|||||||
auto SetLengthBytes(uint32_t) -> void;
|
auto SetLengthBytes(uint32_t) -> void;
|
||||||
|
|
||||||
auto AddBytes(std::size_t) -> void;
|
auto AddBytes(std::size_t) -> void;
|
||||||
|
auto has_duration() const -> bool { return has_duration_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
auto bytes_to_samples(uint32_t) -> uint32_t;
|
auto bytes_to_samples(uint32_t) -> uint32_t;
|
||||||
@@ -35,6 +36,7 @@ class Timer {
|
|||||||
uint32_t current_seconds_;
|
uint32_t current_seconds_;
|
||||||
uint32_t current_sample_in_second_;
|
uint32_t current_sample_in_second_;
|
||||||
|
|
||||||
|
bool has_duration_;
|
||||||
uint32_t total_duration_seconds_;
|
uint32_t total_duration_seconds_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,13 @@ class StreamInfo {
|
|||||||
return total_length_bytes_;
|
return total_length_bytes_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto total_length_seconds() -> std::optional<std::uint32_t>& {
|
||||||
|
return total_length_seconds_;
|
||||||
|
}
|
||||||
|
auto total_length_seconds() const -> std::optional<std::uint32_t> {
|
||||||
|
return total_length_seconds_;
|
||||||
|
}
|
||||||
|
|
||||||
struct Encoded {
|
struct Encoded {
|
||||||
// The codec that this stream is associated with.
|
// The codec that this stream is associated with.
|
||||||
codecs::StreamType type;
|
codecs::StreamType type;
|
||||||
@@ -77,6 +84,7 @@ class StreamInfo {
|
|||||||
private:
|
private:
|
||||||
std::size_t bytes_in_stream_;
|
std::size_t bytes_in_stream_;
|
||||||
std::optional<std::uint32_t> total_length_bytes_;
|
std::optional<std::uint32_t> total_length_bytes_;
|
||||||
|
std::optional<std::uint32_t> total_length_seconds_;
|
||||||
Format format_{};
|
Format format_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user