112 lines
4.6 KiB
Python
112 lines
4.6 KiB
Python
#!/usr/bin/env python3
|
|
import subprocess
|
|
import sys
|
|
|
|
CARD_INDEX = 2 # Можно изменить при необходимости
|
|
|
|
def _get_mixer_name(card_index, mixer_type=None):
|
|
"""
|
|
Вспомогательная функция: находит микшер указанного типа или первый из списка.
|
|
|
|
Args:
|
|
card_index: Индекс звуковой карты
|
|
mixer_type: Тип микшера ('Playback' или 'Capture'). Если None, вернет первый найденный.
|
|
"""
|
|
try:
|
|
result = subprocess.run(
|
|
['amixer', '-c', str(card_index), 'scontrols'],
|
|
capture_output=True, text=True, check=True
|
|
)
|
|
|
|
# Если указан конкретный тип микшера, ищем его
|
|
if mixer_type in ['Playback', 'Capture']:
|
|
for line in result.stdout.splitlines():
|
|
name = line.strip().replace("Simple mixer control '", "").replace("',0", "")
|
|
if name == mixer_type:
|
|
return name
|
|
print(f"Mixer type '{mixer_type}' not found for card {card_index}.", file=sys.stderr)
|
|
return None
|
|
|
|
# Если тип не указан, возвращаем первый подходящий
|
|
for line in result.stdout.splitlines():
|
|
name = line.strip().replace("Simple mixer control '", "").replace("',0", "")
|
|
if name in ['Playback', 'Capture']:
|
|
return name
|
|
|
|
print(f"No valid mixer (Playback/Capture) found for card {card_index}.", file=sys.stderr)
|
|
return None
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"Error listing mixers: {e}", file=sys.stderr)
|
|
return None
|
|
|
|
|
|
def get_volume(card_index, mixer_type=None):
|
|
"""
|
|
Получить текущую громкость для устройства (card_index).
|
|
|
|
Args:
|
|
card_index: Индекс звуковой карты
|
|
mixer_type: Тип микшера ('Playback' или 'Capture'). Если None, используется первый найденный.
|
|
|
|
Возвращает: int (0-100) или None при ошибке.
|
|
"""
|
|
mixer_name = _get_mixer_name(card_index, mixer_type)
|
|
if not mixer_name:
|
|
print(f"No valid mixer found for card {card_index} with type {mixer_type}.", file=sys.stderr)
|
|
return None
|
|
|
|
try:
|
|
result = subprocess.run(
|
|
['amixer', '-c', str(card_index), '-M', 'sget', mixer_name],
|
|
capture_output=True, text=True, check=True
|
|
)
|
|
for line in result.stdout.splitlines():
|
|
if '[' in line and ']' in line and '%' in line:
|
|
percentage = line.split('[')[1].split(']')[0].strip('%')
|
|
return int(percentage)
|
|
return None
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"Failed to get volume: {e}", file=sys.stderr)
|
|
return None
|
|
except ValueError:
|
|
print("Failed to parse volume percentage.", file=sys.stderr)
|
|
return None
|
|
|
|
|
|
def set_volume(card_index, volume, mixer_type=None):
|
|
"""
|
|
Установить громкость для устройства (card_index).
|
|
|
|
Args:
|
|
card_index: Индекс звуковой карты
|
|
volume: Громкость (int от 0 до 100)
|
|
mixer_type: Тип микшера ('Playback' или 'Capture'). Если None, используется первый найденный.
|
|
|
|
Возвращает: True при успехе, False при ошибке.
|
|
"""
|
|
if not (0 <= volume <= 100):
|
|
print("Volume must be between 0 and 100.", file=sys.stderr)
|
|
return False
|
|
|
|
mixer_name = _get_mixer_name(card_index, mixer_type)
|
|
if not mixer_name:
|
|
print(f"No valid mixer found for card {card_index} with type {mixer_type}.", file=sys.stderr)
|
|
return False
|
|
|
|
try:
|
|
subprocess.run(
|
|
['amixer', '-c', str(card_index), '-M', 'sset', mixer_name, f'{volume}%'],
|
|
check=True
|
|
)
|
|
print(f"Volume set to {volume}% for card {card_index}, mixer '{mixer_name}'")
|
|
return True
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"Failed to set volume: {e}", file=sys.stderr)
|
|
return False
|
|
|
|
|
|
# === Пример использования (раскомментировать для теста) ===
|
|
# if __name__ == "__main__":
|
|
# print("Current volume:", get_volume(CARD_INDEX))
|
|
# set_volume(CARD_INDEX, 75)
|
|
# print("New volume:", get_volume(CARD_INDEX)) |