ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
router_speaker.h
Go to the documentation of this file.
1#pragma once
2
3#ifdef USE_ESP32
4
8
9#include <freertos/FreeRTOS.h>
10
11#include <atomic>
12
13namespace esphome::router {
14
15class Router final : public Component, public speaker::Speaker {
16 public:
17 float get_setup_priority() const override { return setup_priority::DATA; }
18
19 void setup() override;
20 void loop() override;
21 void dump_config() override;
22
23 size_t play(const uint8_t *data, size_t length) override { return this->play(data, length, 0); }
24 size_t play(const uint8_t *data, size_t length, TickType_t ticks_to_wait) override;
25
26 void start() override;
27 void stop() override;
28 void finish() override;
29
30 bool has_buffered_data() const override;
31
32 void set_pause_state(bool pause_state) override;
33 bool get_pause_state() const override { return this->cached_pause_; }
34
35 void set_volume(float volume) override;
36 float get_volume() override { return this->volume_; }
37
38 void set_mute_state(bool mute_state) override;
39 bool get_mute_state() override { return this->mute_state_; }
40
41 // Allocate the output list to its final size. Must be called before add_output().
42 void set_output_count(size_t count) { this->outputs_.init(count); }
43 void add_output(speaker::Speaker *spk) { this->outputs_.push_back(spk); }
44
48
49 // Always valid: active_output_idx_ stays within [0, outputs_.size()) and at least
50 // two outputs are required (validated in Python), so this never returns null.
52 return this->outputs_[this->active_output_idx_.load(std::memory_order_relaxed)];
53 }
54
55 protected:
56 // Frames written to the active output but not yet played: incremented in play() and decremented
57 // (clamped at zero) by the active output's audio_output_callback. Mirrors mixer_speaker's
58 // frames_in_pipeline_.
59 std::atomic<uint32_t> frames_in_pipeline_{0};
60
61 // Set when entering STATE_STARTING; used to time out a start the output never acts on
63
64 bool cached_pause_{false};
65
67
68 // Index of the previously-active output we're waiting on to fully stop before
69 // starting the new one. -1 means no pending start. Set by switch_to_output()
70 // when switching mid-playback; cleared by loop() once the old output reports
71 // is_stopped(). Required because shared-bus drivers (e.g. two i2s_audio
72 // speakers on one i2s_bus) reject start() until the previous user releases.
73 std::atomic<int8_t> pending_start_prev_idx_{-1};
74
75 private:
77 // Index into outputs_, always within [0, outputs_.size()). Defaults to the first
78 // configured output; updated by switch_to_output().
79 std::atomic<int8_t> active_output_idx_{0};
80};
81
82} // namespace esphome::router
83
84#endif // USE_ESP32
Fixed-capacity vector - sized once through init() or try_init(); push_back never reallocates This avo...
Definition helpers.h:616
void set_mute_state(bool mute_state) override
size_t play(const uint8_t *data, size_t length) override
void set_output_count(size_t count)
speaker::Speaker * get_active_output() const
float get_setup_priority() const override
bool get_mute_state() override
bool get_pause_state() const override
void set_pause_state(bool pause_state) override
void set_volume(float volume) override
void add_output(speaker::Speaker *spk)
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.
float get_volume() override
std::atomic< int8_t > pending_start_prev_idx_
unsigned count
Definition gif.cpp:51
constexpr float DATA
For components that import data from directly connected sensors like DHT.
Definition component.h:45
static void uint32_t