1
0
mirror of https://github.com/esphome/esphome.git synced 2026-02-08 00:31:58 +00:00

[speaker] Replace set_retry with set_interval to avoid heap allocation

set_retry internally does a std::make_shared<RetryArgs>() heap allocation
on every invocation. Replace with set_interval + countdown counter which
avoids this entirely. All 3 call sites used fixed-interval polling
(no backoff), making set_interval a direct fit.
This commit is contained in:
J. Nick Koston
2026-02-07 14:17:55 -06:00
parent 9de91539e6
commit 6a3da67a1e
2 changed files with 26 additions and 21 deletions

View File

@@ -103,6 +103,20 @@ void SpeakerMediaPlayer::set_playlist_delay_ms(AudioPipelineType pipeline_type,
} }
} }
void SpeakerMediaPlayer::stop_and_unpause_media_() {
this->media_pipeline_->stop();
this->unpause_media_remaining_ = 3;
this->set_interval("unpause_med", 50, [this]() {
if (this->media_pipeline_state_ == AudioPipelineState::STOPPED) {
this->cancel_interval("unpause_med");
this->media_pipeline_->set_pause_state(false);
this->is_paused_ = false;
} else if (--this->unpause_media_remaining_ == 0) {
this->cancel_interval("unpause_med");
}
});
}
void SpeakerMediaPlayer::watch_media_commands_() { void SpeakerMediaPlayer::watch_media_commands_() {
if (!this->is_ready()) { if (!this->is_ready()) {
return; return;
@@ -144,15 +158,7 @@ void SpeakerMediaPlayer::watch_media_commands_() {
if (this->is_paused_) { if (this->is_paused_) {
// If paused, stop the media pipeline and unpause it after confirming its stopped. This avoids playing a // If paused, stop the media pipeline and unpause it after confirming its stopped. This avoids playing a
// short segment of the paused file before starting the new one. // short segment of the paused file before starting the new one.
this->media_pipeline_->stop(); this->stop_and_unpause_media_();
this->set_retry("unpause_med", 50, 3, [this](const uint8_t remaining_attempts) {
if (this->media_pipeline_state_ == AudioPipelineState::STOPPED) {
this->media_pipeline_->set_pause_state(false);
this->is_paused_ = false;
return RetryResult::DONE;
}
return RetryResult::RETRY;
});
} else { } else {
// Not paused, just directly start the file // Not paused, just directly start the file
if (media_command.file.has_value()) { if (media_command.file.has_value()) {
@@ -197,27 +203,21 @@ void SpeakerMediaPlayer::watch_media_commands_() {
this->cancel_timeout("next_ann"); this->cancel_timeout("next_ann");
this->announcement_playlist_.clear(); this->announcement_playlist_.clear();
this->announcement_pipeline_->stop(); this->announcement_pipeline_->stop();
this->set_retry("unpause_ann", 50, 3, [this](const uint8_t remaining_attempts) { this->unpause_announcement_remaining_ = 3;
this->set_interval("unpause_ann", 50, [this]() {
if (this->announcement_pipeline_state_ == AudioPipelineState::STOPPED) { if (this->announcement_pipeline_state_ == AudioPipelineState::STOPPED) {
this->cancel_interval("unpause_ann");
this->announcement_pipeline_->set_pause_state(false); this->announcement_pipeline_->set_pause_state(false);
return RetryResult::DONE; } else if (--this->unpause_announcement_remaining_ == 0) {
this->cancel_interval("unpause_ann");
} }
return RetryResult::RETRY;
}); });
} }
} else { } else {
if (this->media_pipeline_ != nullptr) { if (this->media_pipeline_ != nullptr) {
this->cancel_timeout("next_media"); this->cancel_timeout("next_media");
this->media_playlist_.clear(); this->media_playlist_.clear();
this->media_pipeline_->stop(); this->stop_and_unpause_media_();
this->set_retry("unpause_med", 50, 3, [this](const uint8_t remaining_attempts) {
if (this->media_pipeline_state_ == AudioPipelineState::STOPPED) {
this->media_pipeline_->set_pause_state(false);
this->is_paused_ = false;
return RetryResult::DONE;
}
return RetryResult::RETRY;
});
} }
} }

View File

@@ -112,6 +112,9 @@ class SpeakerMediaPlayer : public Component,
/// media pipelines are defined. /// media pipelines are defined.
inline bool single_pipeline_() { return (this->media_speaker_ == nullptr); } inline bool single_pipeline_() { return (this->media_speaker_ == nullptr); }
/// Stops the media pipeline and polls until stopped to unpause it, avoiding an audible glitch.
void stop_and_unpause_media_();
// Processes commands from media_control_command_queue_. // Processes commands from media_control_command_queue_.
void watch_media_commands_(); void watch_media_commands_();
@@ -141,6 +144,8 @@ class SpeakerMediaPlayer : public Component,
bool is_paused_{false}; bool is_paused_{false};
bool is_muted_{false}; bool is_muted_{false};
uint8_t unpause_media_remaining_{0};
uint8_t unpause_announcement_remaining_{0};
// The amount to change the volume on volume up/down commands // The amount to change the volume on volume up/down commands
float volume_increment_; float volume_increment_;