add audio config service (not tested yet)
This commit is contained in:
parent
adc3ea0211
commit
258ea2b9b6
@ -9,3 +9,4 @@ SERVICE_START_COMPUTER_TO_WINDOWS = "start_computer_to_windows"
|
|||||||
SERVICE_RESTART_COMPUTER = "restart_computer"
|
SERVICE_RESTART_COMPUTER = "restart_computer"
|
||||||
SERVICE_CHANGE_MONITORS_CONFIG = "change_monitors_config"
|
SERVICE_CHANGE_MONITORS_CONFIG = "change_monitors_config"
|
||||||
SERVICE_STEAM_BIG_PICTURE = "steam_big_picture"
|
SERVICE_STEAM_BIG_PICTURE = "steam_big_picture"
|
||||||
|
SERVICE_CHANGE_AUDIO_CONFIG = "change_audio_config"
|
||||||
|
@ -97,3 +97,37 @@ steam_big_picture:
|
|||||||
value: stop
|
value: stop
|
||||||
- label: Exit and go back to the desktop Steam UI
|
- label: Exit and go back to the desktop Steam UI
|
||||||
value: exit
|
value: exit
|
||||||
|
change_audio_config:
|
||||||
|
name: Change audio config
|
||||||
|
description: Change audio config (volume, mute, input, output).
|
||||||
|
target:
|
||||||
|
entity:
|
||||||
|
integration: easy_computer_manager
|
||||||
|
domain: switch
|
||||||
|
fields:
|
||||||
|
volume:
|
||||||
|
name: Volume
|
||||||
|
description: The volume to set.
|
||||||
|
example: 50
|
||||||
|
selector:
|
||||||
|
number:
|
||||||
|
min: 0
|
||||||
|
max: 100
|
||||||
|
mute:
|
||||||
|
name: Mute
|
||||||
|
description: Mute the audio.
|
||||||
|
example: true
|
||||||
|
selector:
|
||||||
|
boolean:
|
||||||
|
input_device:
|
||||||
|
name: Input device
|
||||||
|
description: The ID/name/description of the input device.
|
||||||
|
example: "Kraken 7.1 Chroma Stéréo analogique"
|
||||||
|
selector:
|
||||||
|
text:
|
||||||
|
output_output:
|
||||||
|
name: Output device
|
||||||
|
description: The ID/name/description of the output device.
|
||||||
|
example: "Starship/Matisse HD Audio Controller Stéréo analogique"
|
||||||
|
selector:
|
||||||
|
text:
|
@ -37,7 +37,7 @@ from paramiko.ssh_exception import AuthenticationException
|
|||||||
from . import utils
|
from . import utils
|
||||||
from .const import SERVICE_RESTART_TO_WINDOWS_FROM_LINUX, SERVICE_PUT_COMPUTER_TO_SLEEP, \
|
from .const import SERVICE_RESTART_TO_WINDOWS_FROM_LINUX, SERVICE_PUT_COMPUTER_TO_SLEEP, \
|
||||||
SERVICE_START_COMPUTER_TO_WINDOWS, SERVICE_RESTART_COMPUTER, SERVICE_RESTART_TO_LINUX_FROM_WINDOWS, \
|
SERVICE_START_COMPUTER_TO_WINDOWS, SERVICE_RESTART_COMPUTER, SERVICE_RESTART_TO_LINUX_FROM_WINDOWS, \
|
||||||
SERVICE_CHANGE_MONITORS_CONFIG, SERVICE_STEAM_BIG_PICTURE
|
SERVICE_CHANGE_MONITORS_CONFIG, SERVICE_STEAM_BIG_PICTURE, SERVICE_CHANGE_AUDIO_CONFIG
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -96,19 +96,20 @@ async def async_setup_entry(
|
|||||||
|
|
||||||
platform = entity_platform.async_get_current_platform()
|
platform = entity_platform.async_get_current_platform()
|
||||||
|
|
||||||
services = [SERVICE_RESTART_TO_WINDOWS_FROM_LINUX,
|
basic_services = [SERVICE_RESTART_TO_WINDOWS_FROM_LINUX,
|
||||||
SERVICE_RESTART_TO_LINUX_FROM_WINDOWS,
|
SERVICE_RESTART_TO_LINUX_FROM_WINDOWS,
|
||||||
SERVICE_PUT_COMPUTER_TO_SLEEP,
|
SERVICE_PUT_COMPUTER_TO_SLEEP,
|
||||||
SERVICE_START_COMPUTER_TO_WINDOWS,
|
SERVICE_START_COMPUTER_TO_WINDOWS,
|
||||||
SERVICE_RESTART_COMPUTER]
|
SERVICE_RESTART_COMPUTER]
|
||||||
|
|
||||||
for service in services:
|
for service in basic_services:
|
||||||
platform.async_register_entity_service(
|
platform.async_register_entity_service(
|
||||||
service,
|
service,
|
||||||
{},
|
{},
|
||||||
service,
|
service,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Register the service to change the monitors configuration
|
||||||
platform.async_register_entity_service(
|
platform.async_register_entity_service(
|
||||||
SERVICE_CHANGE_MONITORS_CONFIG,
|
SERVICE_CHANGE_MONITORS_CONFIG,
|
||||||
make_entity_service_schema(
|
make_entity_service_schema(
|
||||||
@ -116,6 +117,8 @@ async def async_setup_entry(
|
|||||||
),
|
),
|
||||||
SERVICE_CHANGE_MONITORS_CONFIG,
|
SERVICE_CHANGE_MONITORS_CONFIG,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Register the service to control Steam Big Picture mode
|
||||||
platform.async_register_entity_service(
|
platform.async_register_entity_service(
|
||||||
SERVICE_STEAM_BIG_PICTURE,
|
SERVICE_STEAM_BIG_PICTURE,
|
||||||
make_entity_service_schema(
|
make_entity_service_schema(
|
||||||
@ -124,6 +127,18 @@ async def async_setup_entry(
|
|||||||
SERVICE_STEAM_BIG_PICTURE,
|
SERVICE_STEAM_BIG_PICTURE,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Register the service to change the audio configuration
|
||||||
|
platform.async_register_entity_service(
|
||||||
|
SERVICE_CHANGE_AUDIO_CONFIG,
|
||||||
|
make_entity_service_schema(
|
||||||
|
{vol.Optional("volume"): int,
|
||||||
|
vol.Optional("mute"): bool,
|
||||||
|
vol.Optional("input_device"): str,
|
||||||
|
vol.Optional("output_device"): str}
|
||||||
|
),
|
||||||
|
SERVICE_CHANGE_AUDIO_CONFIG,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ComputerSwitch(SwitchEntity):
|
class ComputerSwitch(SwitchEntity):
|
||||||
"""Representation of a computer switch."""
|
"""Representation of a computer switch."""
|
||||||
@ -269,6 +284,10 @@ class ComputerSwitch(SwitchEntity):
|
|||||||
else:
|
else:
|
||||||
raise HomeAssistantError("You must specify an action.")
|
raise HomeAssistantError("You must specify an action.")
|
||||||
|
|
||||||
|
def change_audio_config(self, volume: int, mute: bool, input_device: str, output_device: str) -> None:
|
||||||
|
"""Change the audio configuration using a YAML config file."""
|
||||||
|
utils.change_audio_config(self._connection, volume, mute, input_device, output_device)
|
||||||
|
|
||||||
def update(self) -> None:
|
def update(self) -> None:
|
||||||
"""Ping the computer to see if it is online and update the state."""
|
"""Ping the computer to see if it is online and update the state."""
|
||||||
ping_cmd = [
|
ping_cmd = [
|
||||||
|
@ -350,3 +350,91 @@ def steam_big_picture(connection: Connection, action: str):
|
|||||||
|
|
||||||
if result is None or result.return_code != 0:
|
if result is None or result.return_code != 0:
|
||||||
raise HomeAssistantError(f"Could not {action} Steam Big Picture on system running at {connection.host}.")
|
raise HomeAssistantError(f"Could not {action} Steam Big Picture on system running at {connection.host}.")
|
||||||
|
|
||||||
|
|
||||||
|
def get_audio_config(connection: Connection):
|
||||||
|
if is_unix_system(connection):
|
||||||
|
config = {'sinks': [], 'sources': []}
|
||||||
|
|
||||||
|
def parse_device_info(lines, device_type):
|
||||||
|
devices = []
|
||||||
|
current_device = {}
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
if line.startswith(f"{device_type} #"):
|
||||||
|
if current_device and "Monitor" not in current_device['description']:
|
||||||
|
devices.append(current_device)
|
||||||
|
current_device = {'id': int(re.search(r'#(\d+)', line).group(1))}
|
||||||
|
elif line.startswith(" Name:"):
|
||||||
|
current_device['name'] = line.split(":")[1].strip()
|
||||||
|
elif line.startswith(" State:"):
|
||||||
|
current_device['state'] = line.split(":")[1].strip()
|
||||||
|
elif line.startswith(" Description:"):
|
||||||
|
current_device['description'] = line.split(":")[1].strip()
|
||||||
|
|
||||||
|
if current_device:
|
||||||
|
devices.append(current_device)
|
||||||
|
|
||||||
|
return devices
|
||||||
|
|
||||||
|
# Get sinks
|
||||||
|
result = connection.run("LANG=en_US.UTF-8 pactl list sinks")
|
||||||
|
if result.return_code != 0:
|
||||||
|
raise HomeAssistantError(f"Could not get audio sinks on system running at {connection.host}.")
|
||||||
|
config['sinks'] = parse_device_info(result.stdout.split('\n'), 'Sink')
|
||||||
|
|
||||||
|
# Get sources
|
||||||
|
result = connection.run("LANG=en_US.UTF-8 pactl list sources")
|
||||||
|
if result.return_code != 0:
|
||||||
|
raise HomeAssistantError(f"Could not get audio sources on system running at {connection.host}.")
|
||||||
|
config['sources'] = parse_device_info(result.stdout.split('\n'), 'Source')
|
||||||
|
|
||||||
|
return config
|
||||||
|
else:
|
||||||
|
raise HomeAssistantError("Not implemented yet for Windows OS.")
|
||||||
|
|
||||||
|
|
||||||
|
def change_audio_config(connection: Connection, volume: int, mute: bool, input_device: str = "@DEFAULT_SOURCE@",
|
||||||
|
output_device: str = "@DEFAULT_SINK@"):
|
||||||
|
"""Change audio configuration on the host system."""
|
||||||
|
|
||||||
|
if is_unix_system(connection):
|
||||||
|
current_config = get_audio_config(connection)
|
||||||
|
executable = "pactl"
|
||||||
|
commands = []
|
||||||
|
|
||||||
|
def get_device_id(device_type, user_device):
|
||||||
|
for device in current_config[device_type]:
|
||||||
|
if device['description'] == user_device:
|
||||||
|
return device['name']
|
||||||
|
return user_device
|
||||||
|
|
||||||
|
# Set default sink if specified
|
||||||
|
if output_device and output_device != "@DEFAULT_SINK@":
|
||||||
|
output_device = get_device_id('sinks', output_device)
|
||||||
|
commands.append(f"{executable} set-default-sink {output_device}")
|
||||||
|
|
||||||
|
# Set default source if specified
|
||||||
|
if input_device and input_device != "@DEFAULT_SOURCE@":
|
||||||
|
input_device = get_device_id('sources', input_device)
|
||||||
|
commands.append(f"{executable} set-default-source {input_device}")
|
||||||
|
|
||||||
|
# Set sink volume if specified
|
||||||
|
if volume is not None:
|
||||||
|
commands.append(f"{executable} set-sink-volume {output_device} {volume}%")
|
||||||
|
|
||||||
|
# Set sink and source mute status if specified
|
||||||
|
if mute is not None:
|
||||||
|
commands.append(f"{executable} set-sink-mute {output_device} {'yes' if mute else 'no'}")
|
||||||
|
commands.append(f"{executable} set-source-mute {output_device} {'yes' if mute else 'no'}")
|
||||||
|
|
||||||
|
# Execute commands
|
||||||
|
for command in commands:
|
||||||
|
_LOGGER.debug("Running command: %s", command)
|
||||||
|
result = connection.run(command)
|
||||||
|
|
||||||
|
if result.return_code != 0:
|
||||||
|
raise HomeAssistantError("Could not change audio config on system running on %s, check logs with debug",
|
||||||
|
connection.host)
|
||||||
|
else:
|
||||||
|
raise HomeAssistantError("Not implemented yet for Windows OS.")
|
||||||
|
Loading…
Reference in New Issue
Block a user