15static const char *
const TAG =
"router.speaker";
18static const uint32_t STATE_TRANSITION_TIMEOUT_MS = 5000;
20static inline uint32_t atomic_subtract_clamped(std::atomic<uint32_t> &var,
uint32_t amount) {
21 uint32_t current = var.load(std::memory_order_acquire);
26 subtracted = std::min(amount, current);
27 new_value = current - subtracted;
28 }
while (!var.compare_exchange_weak(current, new_value, std::memory_order_release, std::memory_order_acquire));
37 for (
size_t i = 0; i < this->outputs_.size(); i++) {
38 this->outputs_[i]->add_audio_output_callback([
this, i](
uint32_t frames, int64_t timestamp_us) {
45 if (this->active_output_idx_.load(std::memory_order_relaxed) !=
static_cast<int8_t
>(i)) {
63 if (pending_prev_idx >= 0) {
101 ESP_LOGW(TAG,
"Active output did not start; giving up");
113 static_cast<unsigned>(this->outputs_.size()));
123 vTaskDelay(ticks_to_wait);
133 vTaskDelay(ticks_to_wait);
185 if (target ==
nullptr) {
190 for (
size_t i = 0; i < this->outputs_.size(); i++) {
191 if (this->outputs_[i] == target) {
192 new_idx =
static_cast<int8_t
>(i);
197 ESP_LOGW(TAG,
"Switch target is not a configured output");
200 if (new_idx == this->active_output_idx_.load(std::memory_order_relaxed)) {
211 this->active_output_idx_.store(new_idx, std::memory_order_relaxed);
216 const int8_t old_idx = this->active_output_idx_.load(std::memory_order_relaxed);
219 this->outputs_[old_idx]->stop();
222 this->active_output_idx_.store(new_idx, std::memory_order_relaxed);
uint32_t IRAM_ATTR HOT get_loop_component_start_time() const
Get the cached time in milliseconds from when the current component started its loop execution.
uint32_t bytes_to_frames(size_t bytes) const
Convert bytes to frames.
void set_mute_state(bool mute_state) override
size_t play(const uint8_t *data, size_t length) override
speaker::Speaker * get_active_output() const
void apply_cached_state_to_active_()
void set_pause_state(bool pause_state) override
void dump_config() override
void set_volume(float volume) override
bool has_buffered_data() const override
std::atomic< uint32_t > frames_in_pipeline_
bool switch_to_output(speaker::Speaker *target)
Switch the active output to the given speaker.
std::atomic< int8_t > pending_start_prev_idx_
virtual size_t play(const uint8_t *data, size_t length)=0
Plays the provided audio data.
virtual void set_volume(float volume)
virtual void set_pause_state(bool pause_state)
CallbackManager< void(uint32_t, int64_t)> audio_output_callback_
void set_audio_stream_info(const audio::AudioStreamInfo &audio_stream_info)
virtual void set_mute_state(bool mute_state)
virtual bool has_buffered_data() const =0
audio::AudioStreamInfo audio_stream_info_
uint32_t IRAM_ATTR HOT millis()
Application App
Global storage of Application pointer - only one Application can exist.
int64_t esp_timer_get_time(void)