Implement the finish() method and action. implement the is_stopped condition (#7255)

This commit is contained in:
NP v/d Spek 2024-08-14 05:42:43 +02:00 committed by GitHub
parent d6f130e35a
commit cf6ea7cb2c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 77 additions and 15 deletions

View file

@ -180,7 +180,11 @@ void I2SAudioSpeaker::player_task(void *params) {
}
}
void I2SAudioSpeaker::stop() {
void I2SAudioSpeaker::stop() { this->stop_(false); }
void I2SAudioSpeaker::finish() { this->stop_(true); }
void I2SAudioSpeaker::stop_(bool wait_on_empty) {
if (this->is_failed())
return;
if (this->state_ == speaker::STATE_STOPPED)
@ -192,7 +196,11 @@ void I2SAudioSpeaker::stop() {
this->state_ = speaker::STATE_STOPPING;
DataEvent data;
data.stop = true;
xQueueSendToFront(this->buffer_queue_, &data, portMAX_DELAY);
if (wait_on_empty) {
xQueueSend(this->buffer_queue_, &data, portMAX_DELAY);
} else {
xQueueSendToFront(this->buffer_queue_, &data, portMAX_DELAY);
}
}
void I2SAudioSpeaker::watch_() {

View file

@ -53,6 +53,7 @@ class I2SAudioSpeaker : public Component, public speaker::Speaker, public I2SAud
void start() override;
void stop() override;
void finish() override;
size_t play(const uint8_t *data, size_t length) override;
@ -60,6 +61,7 @@ class I2SAudioSpeaker : public Component, public speaker::Speaker, public I2SAud
protected:
void start_();
void stop_(bool wait_on_empty);
void watch_();
static void player_task(void *params);

View file

@ -1,13 +1,11 @@
from esphome import automation
import esphome.config_validation as cv
import esphome.codegen as cg
from esphome.automation import maybe_simple_id
from esphome.const import CONF_ID, CONF_DATA
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.const import CONF_DATA, CONF_ID
from esphome.core import CORE
from esphome.coroutine import coroutine_with_priority
CODEOWNERS = ["@jesserockz"]
IS_PLATFORM_COMPONENT = True
@ -22,8 +20,12 @@ PlayAction = speaker_ns.class_(
StopAction = speaker_ns.class_(
"StopAction", automation.Action, cg.Parented.template(Speaker)
)
FinishAction = speaker_ns.class_(
"FinishAction", automation.Action, cg.Parented.template(Speaker)
)
IsPlayingCondition = speaker_ns.class_("IsPlayingCondition", automation.Condition)
IsStoppedCondition = speaker_ns.class_("IsStoppedCondition", automation.Condition)
async def setup_speaker_core_(var, config):
@ -75,11 +77,18 @@ async def speaker_play_action(config, action_id, template_arg, args):
automation.register_action("speaker.stop", StopAction, SPEAKER_AUTOMATION_SCHEMA)(
speaker_action
)
automation.register_action("speaker.finish", FinishAction, SPEAKER_AUTOMATION_SCHEMA)(
speaker_action
)
automation.register_condition(
"speaker.is_playing", IsPlayingCondition, SPEAKER_AUTOMATION_SCHEMA
)(speaker_action)
automation.register_condition(
"speaker.is_stopped", IsStoppedCondition, SPEAKER_AUTOMATION_SCHEMA
)(speaker_action)
@coroutine_with_priority(100.0)
async def to_code(config):

View file

@ -39,10 +39,20 @@ template<typename... Ts> class StopAction : public Action<Ts...>, public Parente
void play(Ts... x) override { this->parent_->stop(); }
};
template<typename... Ts> class FinishAction : public Action<Ts...>, public Parented<Speaker> {
public:
void play(Ts... x) override { this->parent_->finish(); }
};
template<typename... Ts> class IsPlayingCondition : public Condition<Ts...>, public Parented<Speaker> {
public:
bool check(Ts... x) override { return this->parent_->is_running(); }
};
template<typename... Ts> class IsStoppedCondition : public Condition<Ts...>, public Parented<Speaker> {
public:
bool check(Ts... x) override { return this->parent_->is_stopped(); }
};
} // namespace speaker
} // namespace esphome

View file

@ -17,10 +17,15 @@ class Speaker {
virtual void start() = 0;
virtual void stop() = 0;
// In compare between *STOP()* and *FINISH()*; *FINISH()* will stop after emptying the play buffer,
// while *STOP()* will break directly.
// When finish() is not implemented on the plateform component it should just do a normal stop.
virtual void finish() { this->stop(); }
virtual bool has_buffered_data() const = 0;
bool is_running() const { return this->state_ == STATE_RUNNING; }
bool is_stopped() const { return this->state_ == STATE_STOPPED; }
protected:
State state_{STATE_STOPPED};

View file

@ -1,8 +1,15 @@
esphome:
on_boot:
then:
- speaker.play: [0, 1, 2, 3]
- speaker.stop
- if:
condition: speaker.is_stopped
then:
- speaker.play: [0, 1, 2, 3]
- if:
condition: speaker.is_playing
then:
- speaker.finish:
- speaker.stop:
i2s_audio:
i2s_lrclk_pin: 16

View file

@ -1,8 +1,15 @@
esphome:
on_boot:
then:
- speaker.play: [0, 1, 2, 3]
- speaker.stop
- if:
condition: speaker.is_stopped
then:
- speaker.play: [0, 1, 2, 3]
- if:
condition: speaker.is_playing
then:
- speaker.finish:
- speaker.stop:
i2s_audio:
i2s_lrclk_pin: 6

View file

@ -1,8 +1,15 @@
esphome:
on_boot:
then:
- speaker.play: [0, 1, 2, 3]
- speaker.stop
- if:
condition: speaker.is_stopped
then:
- speaker.play: [0, 1, 2, 3]
- if:
condition: speaker.is_playing
then:
- speaker.finish:
- speaker.stop:
i2s_audio:
i2s_lrclk_pin: 6

View file

@ -1,8 +1,15 @@
esphome:
on_boot:
then:
- speaker.play: [0, 1, 2, 3]
- speaker.stop
- if:
condition: speaker.is_stopped
then:
- speaker.play: [0, 1, 2, 3]
- if:
condition: speaker.is_playing
then:
- speaker.finish:
- speaker.stop:
i2s_audio:
i2s_lrclk_pin: 16