Add async_get_supported_voices to tts.Provider ()

* Add async_get_supported_voices to tts.Provider

* Update WS API
pull/91679/head
Erik Montnemery 2023-04-19 13:47:49 +02:00 committed by GitHub
parent 85d57a046c
commit f3e6d6dfc0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 65 additions and 22 deletions
homeassistant/components
tests/components

View File

@ -10,6 +10,7 @@ from homeassistant.components.tts import (
PLATFORM_SCHEMA, PLATFORM_SCHEMA,
Provider, Provider,
) )
from homeassistant.core import callback
from .const import DOMAIN from .const import DOMAIN
@ -95,6 +96,11 @@ class CloudProvider(Provider):
"""Return list of supported options like voice, emotion.""" """Return list of supported options like voice, emotion."""
return [ATTR_GENDER, ATTR_VOICE, ATTR_AUDIO_OUTPUT] return [ATTR_GENDER, ATTR_VOICE, ATTR_AUDIO_OUTPUT]
@callback
def async_get_supported_voices(self, language: str) -> list[str] | None:
"""Return a list of supported voices for a language."""
return TTS_VOICES.get(language)
@property @property
def default_options(self): def default_options(self):
"""Return a dict include default options.""" """Return a dict include default options."""

View File

@ -739,18 +739,20 @@ def websocket_list_engine_voices(
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict
) -> None: ) -> None:
"""List voices for a given language.""" """List voices for a given language."""
voices = { engine_id = msg["engine_id"]
"voices": [ language = msg["language"]
# placeholder until TTS refactoring
{ manager: SpeechManager = hass.data[DOMAIN]
"voice_id": "voice_1", engine = manager.providers.get(engine_id)
"name": "James Earl Jones",
}, if not engine:
{ connection.send_error(
"voice_id": "voice_2", msg["id"],
"name": "Fran Drescher", websocket_api.const.ERR_NOT_FOUND,
}, f"tts engine {engine_id} not found",
] )
} return
voices = {"voices": engine.async_get_supported_voices(language)}
connection.send_message(websocket_api.result_message(msg["id"], voices)) connection.send_message(websocket_api.result_message(msg["id"], voices))

View File

@ -25,7 +25,7 @@ from homeassistant.const import (
CONF_NAME, CONF_NAME,
CONF_PLATFORM, CONF_PLATFORM,
) )
from homeassistant.core import HomeAssistant, ServiceCall from homeassistant.core import HomeAssistant, ServiceCall, callback
from homeassistant.helpers import config_per_platform, discovery from homeassistant.helpers import config_per_platform, discovery
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.service import async_set_service_schema from homeassistant.helpers.service import async_set_service_schema
@ -227,6 +227,11 @@ class Provider:
"""Return a list of supported options like voice, emotions.""" """Return a list of supported options like voice, emotions."""
return None return None
@callback
def async_get_supported_voices(self, language: str) -> list[str] | None:
"""Return a list of supported voices for a language."""
return None
@property @property
def default_options(self) -> Mapping[str, Any] | None: def default_options(self) -> Mapping[str, Any] | None:
"""Return a mapping with the default options.""" """Return a mapping with the default options."""

View File

@ -78,6 +78,7 @@ async def test_provider_properties(cloud_with_prefs) -> None:
) )
assert provider.supported_options == ["gender", "voice", "audio_output"] assert provider.supported_options == ["gender", "voice", "audio_output"]
assert "nl-NL" in provider.supported_languages assert "nl-NL" in provider.supported_languages
assert "ColetteNeural" in provider.async_get_supported_voices("nl-NL")
async def test_get_tts_audio(cloud_with_prefs) -> None: async def test_get_tts_audio(cloud_with_prefs) -> None:

View File

@ -11,7 +11,7 @@ from homeassistant.components.tts import (
Provider, Provider,
TtsAudioType, TtsAudioType,
) )
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from tests.common import MockPlatform from tests.common import MockPlatform
@ -40,6 +40,13 @@ class MockProvider(Provider):
"""Return list of supported languages.""" """Return list of supported languages."""
return SUPPORT_LANGUAGES return SUPPORT_LANGUAGES
@callback
def async_get_supported_voices(self, language: str) -> list[str] | None:
"""Return list of supported languages."""
if language == "en-US":
return ["James Earl Jones", "Fran Drescher"]
return None
@property @property
def supported_options(self) -> list[str]: def supported_options(self) -> list[str]:
"""Return list of supported options like voice, emotions.""" """Return list of supported options like voice, emotions."""

View File

@ -1077,16 +1077,38 @@ async def test_ws_list_voices(
await client.send_json_auto_id( await client.send_json_auto_id(
{ {
"type": "tts/engine/voices", "type": "tts/engine/voices",
"engine_id": "smurf", "engine_id": "smurf_tts",
"language": "smurfish",
}
)
msg = await client.receive_json()
assert not msg["success"]
assert msg["error"] == {
"code": "not_found",
"message": "tts engine smurf_tts not found",
}
await client.send_json_auto_id(
{
"type": "tts/engine/voices",
"engine_id": "test",
"language": "smurfish", "language": "smurfish",
} }
) )
msg = await client.receive_json() msg = await client.receive_json()
assert msg["success"] assert msg["success"]
assert msg["result"] == { assert msg["result"] == {"voices": None}
"voices": [
{"voice_id": "voice_1", "name": "James Earl Jones"}, await client.send_json_auto_id(
{"voice_id": "voice_2", "name": "Fran Drescher"}, {
] "type": "tts/engine/voices",
"engine_id": "test",
"language": "en-US",
} }
)
msg = await client.receive_json()
assert msg["success"]
assert msg["result"] == {"voices": ["James Earl Jones", "Fran Drescher"]}