Decouple play/pause from output on/off
I think this was the cause of toggling play/pause making audio go away. Or at least I can't repro that bug anymore, anyway.
This commit is contained in:
@@ -81,6 +81,7 @@ void AudioState::react(const OutputModeChanged& ev) {
|
||||
// TODO: handle SetInUse
|
||||
ESP_LOGI(kTag, "output mode changed");
|
||||
auto new_mode = sServices->nvs().OutputMode();
|
||||
sOutput->SetMode(IAudioOutput::Modes::kOff);
|
||||
switch (new_mode) {
|
||||
case drivers::NvsStorage::Output::kBluetooth:
|
||||
sOutput = sBtOutput;
|
||||
@@ -89,6 +90,7 @@ void AudioState::react(const OutputModeChanged& ev) {
|
||||
sOutput = sI2SOutput;
|
||||
break;
|
||||
}
|
||||
sOutput->SetMode(IAudioOutput::Modes::kOnPaused);
|
||||
}
|
||||
|
||||
namespace states {
|
||||
@@ -125,6 +127,7 @@ void Uninitialised::react(const system_fsm::BootComplete& ev) {
|
||||
} else {
|
||||
sOutput = sBtOutput;
|
||||
}
|
||||
sOutput->SetMode(IAudioOutput::Modes::kOnPaused);
|
||||
|
||||
sSampleConverter.reset(new SampleConverter());
|
||||
sSampleConverter->SetOutput(sOutput);
|
||||
@@ -170,7 +173,7 @@ void Standby::react(const TogglePlayPause& ev) {
|
||||
|
||||
void Playback::entry() {
|
||||
ESP_LOGI(kTag, "beginning playback");
|
||||
sOutput->SetInUse(true);
|
||||
sOutput->SetMode(IAudioOutput::Modes::kOnPlaying);
|
||||
|
||||
events::System().Dispatch(PlaybackStarted{});
|
||||
events::Ui().Dispatch(PlaybackStarted{});
|
||||
@@ -181,7 +184,7 @@ void Playback::exit() {
|
||||
// TODO(jacqueline): Second case where it's useful to wait for the i2s buffer
|
||||
// to drain.
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
sOutput->SetInUse(false);
|
||||
sOutput->SetMode(IAudioOutput::Modes::kOnPaused);
|
||||
|
||||
events::System().Dispatch(PlaybackFinished{});
|
||||
events::Ui().Dispatch(PlaybackFinished{});
|
||||
|
||||
@@ -33,8 +33,8 @@ BluetoothAudioOutput::BluetoothAudioOutput(StreamBufferHandle_t s,
|
||||
|
||||
BluetoothAudioOutput::~BluetoothAudioOutput() {}
|
||||
|
||||
auto BluetoothAudioOutput::SetInUse(bool in_use) -> void {
|
||||
if (in_use) {
|
||||
auto BluetoothAudioOutput::SetMode(Modes mode) -> void {
|
||||
if (mode == Modes::kOnPlaying) {
|
||||
bluetooth_.SetSource(stream());
|
||||
} else {
|
||||
bluetooth_.SetSource(nullptr);
|
||||
|
||||
@@ -48,6 +48,7 @@ I2SAudioOutput::I2SAudioOutput(StreamBufferHandle_t s,
|
||||
: IAudioOutput(s),
|
||||
expander_(expander),
|
||||
dac_(std::move(dac)),
|
||||
current_mode_(Modes::kOff),
|
||||
current_config_(),
|
||||
left_difference_(0),
|
||||
current_volume_(0),
|
||||
@@ -60,12 +61,18 @@ I2SAudioOutput::~I2SAudioOutput() {
|
||||
dac_->SetSource(nullptr);
|
||||
}
|
||||
|
||||
auto I2SAudioOutput::SetInUse(bool in_use) -> void {
|
||||
if (in_use) {
|
||||
dac_->Start();
|
||||
} else {
|
||||
dac_->Stop();
|
||||
auto I2SAudioOutput::SetMode(Modes mode) -> void {
|
||||
if (mode == current_mode_) {
|
||||
return;
|
||||
}
|
||||
if (mode == Modes::kOff) {
|
||||
dac_->Stop();
|
||||
return;
|
||||
} else if (current_mode_ == Modes::kOff) {
|
||||
dac_->Start();
|
||||
}
|
||||
current_mode_ = mode;
|
||||
dac_->SetPaused(mode == Modes::kOnPaused);
|
||||
}
|
||||
|
||||
auto I2SAudioOutput::SetVolumeImbalance(int_fast8_t balance) -> void {
|
||||
|
||||
@@ -31,11 +31,17 @@ class IAudioOutput {
|
||||
|
||||
virtual ~IAudioOutput() {}
|
||||
|
||||
enum class Modes {
|
||||
kOff,
|
||||
kOnPaused,
|
||||
kOnPlaying,
|
||||
};
|
||||
|
||||
/*
|
||||
* Indicates whether this output is currently being sent samples. If this is
|
||||
* false, the output should place itself into a low power state.
|
||||
*/
|
||||
virtual auto SetInUse(bool) -> void = 0;
|
||||
virtual auto SetMode(Modes) -> void = 0;
|
||||
|
||||
virtual auto SetVolumeImbalance(int_fast8_t balance) -> void = 0;
|
||||
virtual auto SetVolume(uint_fast8_t percent) -> void = 0;
|
||||
|
||||
@@ -24,7 +24,7 @@ class BluetoothAudioOutput : public IAudioOutput {
|
||||
BluetoothAudioOutput(StreamBufferHandle_t, drivers::Bluetooth& bt);
|
||||
~BluetoothAudioOutput();
|
||||
|
||||
auto SetInUse(bool) -> void override;
|
||||
auto SetMode(Modes) -> void override;
|
||||
|
||||
auto SetVolumeImbalance(int_fast8_t balance) -> void override;
|
||||
auto SetVolume(uint_fast8_t percent) -> void override;
|
||||
|
||||
@@ -25,7 +25,7 @@ class I2SAudioOutput : public IAudioOutput {
|
||||
std::unique_ptr<drivers::I2SDac> dac);
|
||||
~I2SAudioOutput();
|
||||
|
||||
auto SetInUse(bool) -> void override;
|
||||
auto SetMode(Modes) -> void override;
|
||||
|
||||
auto SetMaxVolume(uint16_t) -> void;
|
||||
auto SetVolumeDb(uint16_t) -> void;
|
||||
@@ -46,6 +46,7 @@ class I2SAudioOutput : public IAudioOutput {
|
||||
drivers::IGpios& expander_;
|
||||
std::unique_ptr<drivers::I2SDac> dac_;
|
||||
|
||||
Modes current_mode_;
|
||||
std::optional<Format> current_config_;
|
||||
int_fast8_t left_difference_;
|
||||
uint16_t current_volume_;
|
||||
|
||||
+22
-25
@@ -111,38 +111,23 @@ I2SDac::~I2SDac() {
|
||||
|
||||
auto I2SDac::Start() -> void {
|
||||
std::lock_guard<std::mutex> lock(configure_mutex_);
|
||||
|
||||
gpio_.WriteSync(IGpios::Pin::kAmplifierUnmute, false);
|
||||
|
||||
// Ensure the DAC powers up to a muted state.
|
||||
wm8523::WriteRegister(wm8523::Register::kPsCtrl, 0b10);
|
||||
|
||||
// Enable MCLK; this has the side effect of triggering the DAC's startup
|
||||
// sequence.
|
||||
i2s_channel_enable(i2s_handle_);
|
||||
i2s_active_ = true;
|
||||
|
||||
wm8523::WriteRegister(wm8523::Register::kPsCtrl, 0b11);
|
||||
gpio_.WriteSync(IGpios::Pin::kAmplifierUnmute, true);
|
||||
}
|
||||
|
||||
auto I2SDac::Stop() -> void {
|
||||
std::lock_guard<std::mutex> lock(configure_mutex_);
|
||||
|
||||
// Mute the DAC.
|
||||
wm8523::WriteRegister(wm8523::Register::kPsCtrl, 0b10);
|
||||
vTaskDelay(pdMS_TO_TICKS(5));
|
||||
// Silence the output.
|
||||
gpio_.WriteSync(IGpios::Pin::kAmplifierUnmute, false);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(5));
|
||||
|
||||
// Turn everything off.
|
||||
set_channel(false);
|
||||
wm8523::WriteRegister(wm8523::Register::kPsCtrl, 0b0);
|
||||
i2s_channel_disable(i2s_handle_);
|
||||
i2s_active_ = false;
|
||||
}
|
||||
|
||||
gpio_.WriteSync(IGpios::Pin::kAmplifierEnable, false);
|
||||
auto I2SDac::SetPaused(bool paused) -> void {
|
||||
if (paused) {
|
||||
gpio_.WriteSync(IGpios::Pin::kAmplifierUnmute, false);
|
||||
set_channel(false);
|
||||
} else {
|
||||
set_channel(true);
|
||||
gpio_.WriteSync(IGpios::Pin::kAmplifierUnmute, true);
|
||||
}
|
||||
}
|
||||
|
||||
auto I2SDac::Reconfigure(Channels ch, BitsPerSample bps, SampleRate rate)
|
||||
@@ -261,4 +246,16 @@ auto I2SDac::SetSource(StreamBufferHandle_t buffer) -> void {
|
||||
}
|
||||
}
|
||||
|
||||
auto I2SDac::set_channel(bool enabled) -> void {
|
||||
if (i2s_active_ == enabled) {
|
||||
return;
|
||||
}
|
||||
i2s_active_ = enabled;
|
||||
if (enabled) {
|
||||
i2s_channel_enable(i2s_handle_);
|
||||
} else {
|
||||
i2s_channel_disable(i2s_handle_);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace drivers
|
||||
|
||||
@@ -46,6 +46,7 @@ class I2SDac {
|
||||
|
||||
auto Start() -> void;
|
||||
auto Stop() -> void;
|
||||
auto SetPaused(bool) -> void;
|
||||
|
||||
enum Channels {
|
||||
CHANNELS_MONO,
|
||||
@@ -75,6 +76,8 @@ class I2SDac {
|
||||
I2SDac& operator=(const I2SDac&) = delete;
|
||||
|
||||
private:
|
||||
auto set_channel(bool) -> void;
|
||||
|
||||
IGpios& gpio_;
|
||||
i2s_chan_handle_t i2s_handle_;
|
||||
bool i2s_active_;
|
||||
|
||||
Reference in New Issue
Block a user