ESPHome  2024.4.1
i2s_audio_media_player.cpp
Go to the documentation of this file.
2 
3 #ifdef USE_ESP32_FRAMEWORK_ARDUINO
4 
5 #include "esphome/core/log.h"
6 
7 namespace esphome {
8 namespace i2s_audio {
9 
10 static const char *const TAG = "audio";
11 
13  if (call.get_media_url().has_value()) {
14  this->current_url_ = call.get_media_url();
15  if (this->i2s_state_ != I2S_STATE_STOPPED && this->audio_ != nullptr) {
16  if (this->audio_->isRunning()) {
17  this->audio_->stopSong();
18  }
19  this->audio_->connecttohost(this->current_url_.value().c_str());
21  } else {
22  this->start();
23  }
24  }
25  if (call.get_volume().has_value()) {
26  this->volume = call.get_volume().value();
27  this->set_volume_(volume);
28  this->unmute_();
29  }
30  if (this->i2s_state_ != I2S_STATE_RUNNING) {
31  return;
32  }
33  if (call.get_command().has_value()) {
34  switch (call.get_command().value()) {
36  if (!this->audio_->isRunning())
37  this->audio_->pauseResume();
39  break;
41  if (this->audio_->isRunning())
42  this->audio_->pauseResume();
44  break;
46  this->stop();
47  break;
49  this->mute_();
50  break;
52  this->unmute_();
53  break;
55  this->audio_->pauseResume();
56  if (this->audio_->isRunning()) {
58  } else {
60  }
61  break;
63  float new_volume = this->volume + 0.1f;
64  if (new_volume > 1.0f)
65  new_volume = 1.0f;
66  this->set_volume_(new_volume);
67  this->unmute_();
68  break;
69  }
71  float new_volume = this->volume - 0.1f;
72  if (new_volume < 0.0f)
73  new_volume = 0.0f;
74  this->set_volume_(new_volume);
75  this->unmute_();
76  break;
77  }
78  }
79  }
80  this->publish_state();
81 }
82 
84  if (this->mute_pin_ != nullptr) {
85  this->mute_pin_->digital_write(true);
86  } else {
87  this->set_volume_(0.0f, false);
88  }
89  this->muted_ = true;
90 }
92  if (this->mute_pin_ != nullptr) {
93  this->mute_pin_->digital_write(false);
94  } else {
95  this->set_volume_(this->volume, false);
96  }
97  this->muted_ = false;
98 }
99 void I2SAudioMediaPlayer::set_volume_(float volume, bool publish) {
100  if (this->audio_ != nullptr)
101  this->audio_->setVolume(remap<uint8_t, float>(volume, 0.0f, 1.0f, 0, 21));
102  if (publish)
103  this->volume = volume;
104 }
105 
107  ESP_LOGCONFIG(TAG, "Setting up Audio...");
109 }
110 
112  switch (this->i2s_state_) {
113  case I2S_STATE_STARTING:
114  this->start_();
115  break;
116  case I2S_STATE_RUNNING:
117  this->play_();
118  break;
119  case I2S_STATE_STOPPING:
120  this->stop_();
121  break;
122  case I2S_STATE_STOPPED:
123  break;
124  }
125 }
126 
128  this->audio_->loop();
129  if (this->state == media_player::MEDIA_PLAYER_STATE_PLAYING && !this->audio_->isRunning()) {
130  this->stop();
131  }
132 }
133 
136  if (!this->parent_->try_lock()) {
137  return; // Waiting for another i2s to return lock
138  }
139 
140 #if SOC_I2S_SUPPORTS_DAC
141  if (this->internal_dac_mode_ != I2S_DAC_CHANNEL_DISABLE) {
142  this->audio_ = make_unique<Audio>(true, this->internal_dac_mode_, this->parent_->get_port());
143  } else {
144 #endif
145  this->audio_ = make_unique<Audio>(false, 3, this->parent_->get_port());
146 
147  i2s_pin_config_t pin_config = this->parent_->get_pin_config();
148  pin_config.data_out_num = this->dout_pin_;
149  i2s_set_pin(this->parent_->get_port(), &pin_config);
150 
151  this->audio_->setI2SCommFMT_LSB(this->i2s_comm_fmt_lsb_);
152  this->audio_->forceMono(this->external_dac_channels_ == 1);
153  if (this->mute_pin_ != nullptr) {
154  this->mute_pin_->setup();
155  this->mute_pin_->digital_write(false);
156  }
157 #if SOC_I2S_SUPPORTS_DAC
158  }
159 #endif
160 
162  this->high_freq_.start();
163  this->audio_->setVolume(remap<uint8_t, float>(this->volume, 0.0f, 1.0f, 0, 21));
164  if (this->current_url_.has_value()) {
165  this->audio_->connecttohost(this->current_url_.value().c_str());
167  this->publish_state();
168  }
169 }
171  if (this->i2s_state_ == I2S_STATE_STOPPED) {
172  return;
173  }
174  if (this->i2s_state_ == I2S_STATE_STARTING) {
176  return;
177  }
179 }
181  if (this->audio_->isRunning()) {
182  this->audio_->stopSong();
183  return;
184  }
185 
186  this->audio_ = nullptr;
187  this->current_url_ = {};
188  this->parent_->unlock();
190 
191  this->high_freq_.stop();
193  this->publish_state();
194 }
195 
197  auto traits = media_player::MediaPlayerTraits();
198  traits.set_supports_pause(true);
199  return traits;
200 };
201 
203  ESP_LOGCONFIG(TAG, "Audio:");
204  if (this->is_failed()) {
205  ESP_LOGCONFIG(TAG, "Audio failed to initialize!");
206  return;
207  }
208 #if SOC_I2S_SUPPORTS_DAC
209  if (this->internal_dac_mode_ != I2S_DAC_CHANNEL_DISABLE) {
210  switch (this->internal_dac_mode_) {
211  case I2S_DAC_CHANNEL_LEFT_EN:
212  ESP_LOGCONFIG(TAG, " Internal DAC mode: Left");
213  break;
214  case I2S_DAC_CHANNEL_RIGHT_EN:
215  ESP_LOGCONFIG(TAG, " Internal DAC mode: Right");
216  break;
217  case I2S_DAC_CHANNEL_BOTH_EN:
218  ESP_LOGCONFIG(TAG, " Internal DAC mode: Left & Right");
219  break;
220  default:
221  break;
222  }
223  } else {
224 #endif
225  ESP_LOGCONFIG(TAG, " External DAC channels: %d", this->external_dac_channels_);
226  ESP_LOGCONFIG(TAG, " I2S DOUT Pin: %d", this->dout_pin_);
227  LOG_PIN(" Mute Pin: ", this->mute_pin_);
228 #if SOC_I2S_SUPPORTS_DAC
229  }
230 #endif
231 }
232 
233 } // namespace i2s_audio
234 } // namespace esphome
235 
236 #endif // USE_ESP32_FRAMEWORK_ARDUINO
virtual void digital_write(bool value)=0
value_type const & value() const
Definition: optional.h:89
void control(const media_player::MediaPlayerCall &call) override
media_player::MediaPlayerTraits get_traits() override
bool has_value() const
Definition: optional.h:87
virtual void setup()=0
const optional< float > & get_volume() const
Definition: media_player.h:59
void start()
Start running the loop continuously.
Definition: helpers.cpp:547
void stop()
Stop running the loop continuously.
Definition: helpers.cpp:553
const optional< MediaPlayerCommand > & get_command() const
Definition: media_player.h:57
const optional< std::string > & get_media_url() const
Definition: media_player.h:58
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
void set_volume_(float volume, bool publish=true)