diff --git a/CODEOWNERS b/CODEOWNERS index e72b164761..88f62c3194 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -244,7 +244,6 @@ esphome/components/hyt271/* @Philippe12 esphome/components/i2c/* @esphome/core esphome/components/i2c_device/* @gabest11 esphome/components/i2s_audio/* @jesserockz -esphome/components/i2s_audio/media_player/* @jesserockz esphome/components/i2s_audio/microphone/* @jesserockz esphome/components/i2s_audio/speaker/* @jesserockz @kahrendt esphome/components/iaqcore/* @yozik04 diff --git a/esphome/components/i2s_audio/__init__.py b/esphome/components/i2s_audio/__init__.py index 977a239497..ffa63f5ee8 100644 --- a/esphome/components/i2s_audio/__init__.py +++ b/esphome/components/i2s_audio/__init__.py @@ -53,8 +53,6 @@ CONF_RIGHT = "right" CONF_STEREO = "stereo" CONF_BOTH = "both" -CONF_USE_LEGACY = "use_legacy" - i2s_audio_ns = cg.esphome_ns.namespace("i2s_audio") I2SAudioComponent = i2s_audio_ns.class_("I2SAudioComponent", cg.Component) I2SAudioBase = i2s_audio_ns.class_( @@ -154,20 +152,6 @@ def validate_mclk_divisible_by_3(config): return config -# Key for storing legacy driver setting in CORE.data -I2S_USE_LEGACY_DRIVER_KEY = "i2s_use_legacy_driver" - - -def _get_use_legacy_driver(): - """Get the legacy driver setting from CORE.data.""" - return CORE.data.get(I2S_USE_LEGACY_DRIVER_KEY) - - -def _set_use_legacy_driver(value: bool) -> None: - """Set the legacy driver setting in CORE.data.""" - CORE.data[I2S_USE_LEGACY_DRIVER_KEY] = value - - def i2s_audio_component_schema( class_: MockObjClass, *, @@ -192,10 +176,6 @@ def i2s_audio_component_schema( *I2S_MODE_OPTIONS, lower=True ), cv.Optional(CONF_USE_APLL, default=False): cv.boolean, - cv.Optional(CONF_BITS_PER_CHANNEL, default="default"): cv.All( - cv.Any(cv.float_with_unit("bits", "bit"), "default"), - cv.one_of(*I2S_BITS_PER_CHANNEL), - ), cv.Optional(CONF_MCLK_MULTIPLE, default=256): cv.one_of(*I2S_MCLK_MULTIPLE), } ) @@ -203,59 +183,28 @@ def i2s_audio_component_schema( async def register_i2s_audio_component(var, config): await cg.register_parented(var, config[CONF_I2S_AUDIO_ID]) - if use_legacy(): - cg.add(var.set_i2s_mode(I2S_MODE_OPTIONS[config[CONF_I2S_MODE]])) - cg.add(var.set_channel(I2S_CHANNELS[config[CONF_CHANNEL]])) - cg.add( - var.set_bits_per_sample(I2S_BITS_PER_SAMPLE[config[CONF_BITS_PER_SAMPLE]]) - ) - cg.add( - var.set_bits_per_channel( - I2S_BITS_PER_CHANNEL[config[CONF_BITS_PER_CHANNEL]] - ) - ) - else: - cg.add(var.set_i2s_role(I2S_ROLE_OPTIONS[config[CONF_I2S_MODE]])) - slot_mode = config[CONF_CHANNEL] - if slot_mode != CONF_STEREO: - slot_mode = CONF_MONO - slot_mask = config[CONF_CHANNEL] - if slot_mask not in [CONF_LEFT, CONF_RIGHT]: - slot_mask = CONF_BOTH - cg.add(var.set_slot_mode(I2S_SLOT_MODE[slot_mode])) - cg.add(var.set_std_slot_mask(I2S_STD_SLOT_MASK[slot_mask])) - cg.add(var.set_slot_bit_width(I2S_SLOT_BIT_WIDTH[config[CONF_BITS_PER_SAMPLE]])) + cg.add(var.set_i2s_role(I2S_ROLE_OPTIONS[config[CONF_I2S_MODE]])) + slot_mode = config[CONF_CHANNEL] + if slot_mode != CONF_STEREO: + slot_mode = CONF_MONO + slot_mask = config[CONF_CHANNEL] + if slot_mask not in [CONF_LEFT, CONF_RIGHT]: + slot_mask = CONF_BOTH + cg.add(var.set_slot_mode(I2S_SLOT_MODE[slot_mode])) + cg.add(var.set_std_slot_mask(I2S_STD_SLOT_MASK[slot_mask])) + cg.add(var.set_slot_bit_width(I2S_SLOT_BIT_WIDTH[config[CONF_BITS_PER_SAMPLE]])) cg.add(var.set_sample_rate(config[CONF_SAMPLE_RATE])) cg.add(var.set_use_apll(config[CONF_USE_APLL])) cg.add(var.set_mclk_multiple(I2S_MCLK_MULTIPLE[config[CONF_MCLK_MULTIPLE]])) -def validate_use_legacy(value): - if CONF_USE_LEGACY in value: - existing_value = _get_use_legacy_driver() - if (existing_value is not None) and (existing_value != value[CONF_USE_LEGACY]): - raise cv.Invalid( - f"All i2s_audio components must set {CONF_USE_LEGACY} to the same value." - ) - if (not value[CONF_USE_LEGACY]) and (CORE.using_arduino): - raise cv.Invalid("Arduino supports only the legacy i2s driver") - _set_use_legacy_driver(value[CONF_USE_LEGACY]) - elif CORE.using_arduino: - _set_use_legacy_driver(True) - return value - - -CONFIG_SCHEMA = cv.All( - cv.Schema( - { - cv.GenerateID(): cv.declare_id(I2SAudioComponent), - cv.Required(CONF_I2S_LRCLK_PIN): pins.internal_gpio_output_pin_number, - cv.Optional(CONF_I2S_BCLK_PIN): pins.internal_gpio_output_pin_number, - cv.Optional(CONF_I2S_MCLK_PIN): pins.internal_gpio_output_pin_number, - cv.Optional(CONF_USE_LEGACY): cv.boolean, - }, - ), - validate_use_legacy, +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(I2SAudioComponent), + cv.Required(CONF_I2S_LRCLK_PIN): pins.internal_gpio_output_pin_number, + cv.Optional(CONF_I2S_BCLK_PIN): pins.internal_gpio_output_pin_number, + cv.Optional(CONF_I2S_MCLK_PIN): pins.internal_gpio_output_pin_number, + }, ) @@ -311,13 +260,6 @@ def _assign_ports() -> None: def _final_validate(_): - from esphome.components.esp32 import idf_version - - if use_legacy() and idf_version() >= cv.Version(6, 0, 0): - raise cv.Invalid( - "The legacy I2S driver is not available in ESP-IDF 6.0+. " - "Set 'use_legacy: false' in i2s_audio configuration." - ) i2s_audio_configs = fv.full_config.get()[CONF_I2S_AUDIO] variant = get_esp32_variant() if variant not in I2S_PORTS: @@ -329,10 +271,6 @@ def _final_validate(_): _assign_ports() -def use_legacy(): - return _get_use_legacy_driver() - - FINAL_VALIDATE_SCHEMA = _final_validate @@ -349,11 +287,6 @@ async def to_code(config): # Re-enable ESP-IDF's I2S driver (excluded by default to save compile time) include_builtin_idf_component("esp_driver_i2s") - if use_legacy(): - cg.add_define("USE_I2S_LEGACY") - # Legacy I2S API lives in the "driver" shim component (driver/i2s.h) - include_builtin_idf_component("driver") - # Helps avoid callbacks being skipped due to processor load add_idf_sdkconfig_option("CONFIG_I2S_ISR_IRAM_SAFE", True) diff --git a/esphome/components/i2s_audio/i2s_audio.h b/esphome/components/i2s_audio/i2s_audio.h index f26ffddd46..5b260fa7ed 100644 --- a/esphome/components/i2s_audio/i2s_audio.h +++ b/esphome/components/i2s_audio/i2s_audio.h @@ -6,11 +6,7 @@ #include "esphome/core/defines.h" #include "esphome/core/helpers.h" #include -#ifdef USE_I2S_LEGACY -#include -#else #include -#endif namespace esphome { namespace i2s_audio { @@ -19,33 +15,19 @@ class I2SAudioComponent; class I2SAudioBase : public Parented { public: -#ifdef USE_I2S_LEGACY - void set_i2s_mode(i2s_mode_t mode) { this->i2s_mode_ = mode; } - void set_channel(i2s_channel_fmt_t channel) { this->channel_ = channel; } - void set_bits_per_sample(i2s_bits_per_sample_t bits_per_sample) { this->bits_per_sample_ = bits_per_sample; } - void set_bits_per_channel(i2s_bits_per_chan_t bits_per_channel) { this->bits_per_channel_ = bits_per_channel; } -#else void set_i2s_role(i2s_role_t role) { this->i2s_role_ = role; } void set_slot_mode(i2s_slot_mode_t slot_mode) { this->slot_mode_ = slot_mode; } void set_std_slot_mask(i2s_std_slot_mask_t std_slot_mask) { this->std_slot_mask_ = std_slot_mask; } void set_slot_bit_width(i2s_slot_bit_width_t slot_bit_width) { this->slot_bit_width_ = slot_bit_width; } -#endif void set_sample_rate(uint32_t sample_rate) { this->sample_rate_ = sample_rate; } void set_use_apll(uint32_t use_apll) { this->use_apll_ = use_apll; } void set_mclk_multiple(i2s_mclk_multiple_t mclk_multiple) { this->mclk_multiple_ = mclk_multiple; } protected: -#ifdef USE_I2S_LEGACY - i2s_mode_t i2s_mode_{}; - i2s_channel_fmt_t channel_; - i2s_bits_per_sample_t bits_per_sample_; - i2s_bits_per_chan_t bits_per_channel_; -#else i2s_role_t i2s_role_{}; i2s_slot_mode_t slot_mode_; i2s_std_slot_mask_t std_slot_mask_; i2s_slot_bit_width_t slot_bit_width_; -#endif uint32_t sample_rate_; bool use_apll_; i2s_mclk_multiple_t mclk_multiple_; @@ -57,17 +39,6 @@ class I2SAudioOut : public I2SAudioBase {}; class I2SAudioComponent : public Component { public: -#ifdef USE_I2S_LEGACY - i2s_pin_config_t get_pin_config() const { - return { - .mck_io_num = this->mclk_pin_, - .bck_io_num = this->bclk_pin_, - .ws_io_num = this->lrclk_pin_, - .data_out_num = I2S_PIN_NO_CHANGE, - .data_in_num = I2S_PIN_NO_CHANGE, - }; - } -#else i2s_std_gpio_config_t get_pin_config() const { return {.mclk = (gpio_num_t) this->mclk_pin_, .bclk = (gpio_num_t) this->bclk_pin_, @@ -80,7 +51,6 @@ class I2SAudioComponent : public Component { .ws_inv = false, }}; } -#endif void set_mclk_pin(int pin) { this->mclk_pin_ = pin; } void set_bclk_pin(int pin) { this->bclk_pin_ = pin; } @@ -101,13 +71,8 @@ class I2SAudioComponent : public Component { I2SAudioIn *audio_in_{nullptr}; I2SAudioOut *audio_out_{nullptr}; -#ifdef USE_I2S_LEGACY - int mclk_pin_{I2S_PIN_NO_CHANGE}; - int bclk_pin_{I2S_PIN_NO_CHANGE}; -#else int mclk_pin_{I2S_GPIO_UNUSED}; int bclk_pin_{I2S_GPIO_UNUSED}; -#endif int lrclk_pin_; int port_{}; }; diff --git a/esphome/components/i2s_audio/media_player/__init__.py b/esphome/components/i2s_audio/media_player/__init__.py index 426b211f47..b366d4fb05 100644 --- a/esphome/components/i2s_audio/media_player/__init__.py +++ b/esphome/components/i2s_audio/media_player/__init__.py @@ -1,121 +1,7 @@ -from esphome import pins -import esphome.codegen as cg -from esphome.components import esp32, media_player import esphome.config_validation as cv -from esphome.const import CONF_MODE -from .. import ( - CONF_I2S_AUDIO_ID, - CONF_I2S_DOUT_PIN, - CONF_LEFT, - CONF_MONO, - CONF_RIGHT, - CONF_STEREO, - I2SAudioComponent, - I2SAudioOut, - i2s_audio_ns, - use_legacy, +CONFIG_SCHEMA = cv.invalid( + "The I2S audio media player has been removed. " + "Use the speaker media player component instead. " + "See https://esphome.io/components/media_player/speaker.html for details." ) - -CODEOWNERS = ["@jesserockz"] -DEPENDENCIES = ["i2s_audio"] - -I2SAudioMediaPlayer = i2s_audio_ns.class_( - "I2SAudioMediaPlayer", cg.Component, media_player.MediaPlayer, I2SAudioOut -) - -i2s_dac_mode_t = cg.global_ns.enum("i2s_dac_mode_t") - - -CONF_MUTE_PIN = "mute_pin" -CONF_AUDIO_ID = "audio_id" -CONF_DAC_TYPE = "dac_type" -CONF_I2S_COMM_FMT = "i2s_comm_fmt" - -INTERNAL_DAC_OPTIONS = { - CONF_LEFT: i2s_dac_mode_t.I2S_DAC_CHANNEL_LEFT_EN, - CONF_RIGHT: i2s_dac_mode_t.I2S_DAC_CHANNEL_RIGHT_EN, - CONF_STEREO: i2s_dac_mode_t.I2S_DAC_CHANNEL_BOTH_EN, -} - -EXTERNAL_DAC_OPTIONS = [CONF_MONO, CONF_STEREO] - -NO_INTERNAL_DAC_VARIANTS = [esp32.VARIANT_ESP32S2] - -I2C_COMM_FMT_OPTIONS = ["lsb", "msb"] - - -def validate_esp32_variant(config): - if config[CONF_DAC_TYPE] != "internal": - return config - variant = esp32.get_esp32_variant() - if variant in NO_INTERNAL_DAC_VARIANTS: - raise cv.Invalid(f"{variant} does not have an internal DAC") - return config - - -CONFIG_SCHEMA = cv.All( - cv.typed_schema( - { - "internal": media_player.media_player_schema(I2SAudioMediaPlayer) - .extend( - { - cv.GenerateID(CONF_I2S_AUDIO_ID): cv.use_id(I2SAudioComponent), - cv.Required(CONF_MODE): cv.enum(INTERNAL_DAC_OPTIONS, lower=True), - } - ) - .extend(cv.COMPONENT_SCHEMA), - "external": media_player.media_player_schema(I2SAudioMediaPlayer) - .extend( - { - cv.GenerateID(CONF_I2S_AUDIO_ID): cv.use_id(I2SAudioComponent), - cv.Required( - CONF_I2S_DOUT_PIN - ): pins.internal_gpio_output_pin_number, - cv.Optional(CONF_MUTE_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_MODE, default="mono"): cv.one_of( - *EXTERNAL_DAC_OPTIONS, lower=True - ), - cv.Optional(CONF_I2S_COMM_FMT, default="msb"): cv.one_of( - *I2C_COMM_FMT_OPTIONS, lower=True - ), - } - ) - .extend(cv.COMPONENT_SCHEMA), - }, - key=CONF_DAC_TYPE, - ), - cv.only_with_arduino, - validate_esp32_variant, -) - - -def _final_validate(_): - if not use_legacy(): - raise cv.Invalid("I2S media player is only compatible with legacy i2s driver") - - -FINAL_VALIDATE_SCHEMA = _final_validate - - -async def to_code(config): - var = await media_player.new_media_player(config) - await cg.register_component(var, config) - - await cg.register_parented(var, config[CONF_I2S_AUDIO_ID]) - - if config[CONF_DAC_TYPE] == "internal": - cg.add(var.set_internal_dac_mode(config[CONF_MODE])) - else: - cg.add(var.set_dout_pin(config[CONF_I2S_DOUT_PIN])) - if CONF_MUTE_PIN in config: - pin = await cg.gpio_pin_expression(config[CONF_MUTE_PIN]) - cg.add(var.set_mute_pin(pin)) - cg.add(var.set_external_dac_channels(2 if config[CONF_MODE] == "stereo" else 1)) - cg.add(var.set_i2s_comm_fmt_lsb(config[CONF_I2S_COMM_FMT] == "lsb")) - - cg.add_library("WiFi", None) - cg.add_library("NetworkClientSecure", None) - cg.add_library("HTTPClient", None) - cg.add_library("esphome/ESP32-audioI2S", "2.3.0") - cg.add_build_flag("-DAUDIO_NO_SD_FS") diff --git a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp deleted file mode 100644 index 369c964a85..0000000000 --- a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp +++ /dev/null @@ -1,260 +0,0 @@ -#include "i2s_audio_media_player.h" - -#ifdef USE_ESP32_FRAMEWORK_ARDUINO - -#include "esphome/core/log.h" - -namespace esphome { -namespace i2s_audio { - -static const char *const TAG = "audio"; - -void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) { - media_player::MediaPlayerState play_state = media_player::MEDIA_PLAYER_STATE_PLAYING; - auto announcement = call.get_announcement(); - if (announcement.has_value()) { - play_state = *announcement ? media_player::MEDIA_PLAYER_STATE_ANNOUNCING : media_player::MEDIA_PLAYER_STATE_PLAYING; - } - auto media_url = call.get_media_url(); - if (media_url.has_value()) { - this->current_url_ = media_url; - if (this->i2s_state_ != I2S_STATE_STOPPED && this->audio_ != nullptr) { - if (this->audio_->isRunning()) { - this->audio_->stopSong(); - } - this->audio_->connecttohost(media_url->c_str()); - this->state = play_state; - } else { - this->start(); - } - } - - if (play_state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING) { - this->is_announcement_ = true; - } - - auto vol = call.get_volume(); - if (vol.has_value()) { - this->volume = *vol; - this->set_volume_(volume); - this->unmute_(); - } - auto cmd = call.get_command(); - if (cmd.has_value()) { - switch (*cmd) { - case media_player::MEDIA_PLAYER_COMMAND_MUTE: - this->mute_(); - break; - case media_player::MEDIA_PLAYER_COMMAND_UNMUTE: - this->unmute_(); - break; - case media_player::MEDIA_PLAYER_COMMAND_VOLUME_UP: { - float new_volume = this->volume + 0.1f; - if (new_volume > 1.0f) - new_volume = 1.0f; - this->set_volume_(new_volume); - this->unmute_(); - break; - } - case media_player::MEDIA_PLAYER_COMMAND_VOLUME_DOWN: { - float new_volume = this->volume - 0.1f; - if (new_volume < 0.0f) - new_volume = 0.0f; - this->set_volume_(new_volume); - this->unmute_(); - break; - } - default: - break; - } - if (this->i2s_state_ != I2S_STATE_RUNNING) { - return; - } - switch (*cmd) { - case media_player::MEDIA_PLAYER_COMMAND_PLAY: - if (!this->audio_->isRunning()) - this->audio_->pauseResume(); - this->state = play_state; - break; - case media_player::MEDIA_PLAYER_COMMAND_PAUSE: - if (this->audio_->isRunning()) - this->audio_->pauseResume(); - this->state = media_player::MEDIA_PLAYER_STATE_PAUSED; - break; - case media_player::MEDIA_PLAYER_COMMAND_STOP: - this->stop(); - break; - case media_player::MEDIA_PLAYER_COMMAND_TOGGLE: - this->audio_->pauseResume(); - if (this->audio_->isRunning()) { - this->state = media_player::MEDIA_PLAYER_STATE_PLAYING; - } else { - this->state = media_player::MEDIA_PLAYER_STATE_PAUSED; - } - break; - default: - break; - } - } - this->publish_state(); -} - -void I2SAudioMediaPlayer::mute_() { - if (this->mute_pin_ != nullptr) { - this->mute_pin_->digital_write(true); - } else { - this->set_volume_(0.0f, false); - } - this->muted_ = true; -} -void I2SAudioMediaPlayer::unmute_() { - if (this->mute_pin_ != nullptr) { - this->mute_pin_->digital_write(false); - } else { - this->set_volume_(this->volume, false); - } - this->muted_ = false; -} -void I2SAudioMediaPlayer::set_volume_(float volume, bool publish) { - if (this->audio_ != nullptr) - this->audio_->setVolume(remap(volume, 0.0f, 1.0f, 0, 21)); - if (publish) - this->volume = volume; -} - -void I2SAudioMediaPlayer::setup() { this->state = media_player::MEDIA_PLAYER_STATE_IDLE; } - -void I2SAudioMediaPlayer::loop() { - switch (this->i2s_state_) { - case I2S_STATE_STARTING: - this->start_(); - break; - case I2S_STATE_RUNNING: - this->play_(); - break; - case I2S_STATE_STOPPING: - this->stop_(); - break; - case I2S_STATE_STOPPED: - break; - } -} - -void I2SAudioMediaPlayer::play_() { - this->audio_->loop(); - if ((this->state == media_player::MEDIA_PLAYER_STATE_PLAYING || - this->state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING) && - !this->audio_->isRunning()) { - this->stop(); - } -} - -void I2SAudioMediaPlayer::start() { this->i2s_state_ = I2S_STATE_STARTING; } -void I2SAudioMediaPlayer::start_() { - if (!this->parent_->try_lock()) { - return; // Waiting for another i2s to return lock - } - -#if SOC_I2S_SUPPORTS_DAC - if (this->internal_dac_mode_ != I2S_DAC_CHANNEL_DISABLE) { - this->audio_ = make_unique