2021-04-16 23:21:06 +08:00
|
|
|
from abc import ABCMeta, abstractmethod
|
2023-06-27 01:05:51 +08:00
|
|
|
from enum import Enum, auto
|
|
|
|
from typing import Dict, Optional
|
2021-04-16 23:21:06 +08:00
|
|
|
|
|
|
|
from pyglet import event
|
|
|
|
from pyglet.util import with_metaclass
|
|
|
|
|
|
|
|
|
2023-06-27 01:05:51 +08:00
|
|
|
class DeviceState(Enum):
|
|
|
|
ACTIVE = auto()
|
|
|
|
DISABLED = auto()
|
|
|
|
MISSING = auto()
|
|
|
|
UNPLUGGED = auto()
|
2021-04-16 23:21:06 +08:00
|
|
|
|
|
|
|
|
2023-06-27 01:05:51 +08:00
|
|
|
class DeviceFlow(Enum):
|
|
|
|
OUTPUT = auto()
|
|
|
|
INPUT = auto()
|
|
|
|
INPUT_OUTPUT = auto()
|
2021-04-16 23:21:06 +08:00
|
|
|
|
|
|
|
|
|
|
|
class AudioDevice:
|
|
|
|
"""Base class for a platform independent audio device.
|
|
|
|
_platform_state and _platform_flow is used to make device state numbers."""
|
2023-06-27 01:05:51 +08:00
|
|
|
platform_state: Dict[int, DeviceState] = {} # Must be defined by the parent.
|
|
|
|
platform_flow: Dict[int, DeviceFlow] = {} # Must be defined by the parent.
|
2021-04-16 23:21:06 +08:00
|
|
|
|
2023-06-27 01:05:51 +08:00
|
|
|
def __init__(self, dev_id: str, name: str, description: str, flow: int, state: int):
|
2021-04-16 23:21:06 +08:00
|
|
|
self.id = dev_id
|
2023-06-27 01:05:51 +08:00
|
|
|
self.flow = flow # platform value
|
|
|
|
self.state = state # platform value
|
2021-04-16 23:21:06 +08:00
|
|
|
self.name = name
|
|
|
|
self.description = description
|
|
|
|
|
|
|
|
def __repr__(self):
|
2023-06-27 01:05:51 +08:00
|
|
|
return "{}(name='{}', state={}, flow={})".format(
|
|
|
|
self.__class__.__name__, self.name, self.platform_state[self.state].name, self.platform_flow[self.flow].name)
|
2021-04-16 23:21:06 +08:00
|
|
|
|
|
|
|
|
|
|
|
class AbstractAudioDeviceManager(with_metaclass(ABCMeta, event.EventDispatcher, object)):
|
|
|
|
|
|
|
|
def __del__(self):
|
|
|
|
"""Required to remove handlers before exit, as it can cause problems with the event system's weakrefs."""
|
|
|
|
self.remove_handlers(self)
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def get_default_output(self):
|
|
|
|
"""Returns a default active output device or None if none available."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def get_default_input(self):
|
|
|
|
"""Returns a default active input device or None if none available."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def get_output_devices(self):
|
|
|
|
"""Returns a list of all active output devices."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def get_input_devices(self):
|
|
|
|
"""Returns a list of all active input devices."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def get_all_devices(self):
|
|
|
|
"""Returns a list of all audio devices, no matter what state they are in."""
|
|
|
|
pass
|
|
|
|
|
2023-06-27 01:05:51 +08:00
|
|
|
def on_device_state_changed(self, device: AudioDevice, old_state: DeviceState, new_state: DeviceState):
|
|
|
|
"""Event, occurs when the state of a device changes, provides the old state and new state."""
|
2021-04-16 23:21:06 +08:00
|
|
|
pass
|
|
|
|
|
2023-06-27 01:05:51 +08:00
|
|
|
def on_device_added(self, device: AudioDevice):
|
2021-04-16 23:21:06 +08:00
|
|
|
"""Event, occurs when a new device is added to the system."""
|
|
|
|
pass
|
|
|
|
|
2023-06-27 01:05:51 +08:00
|
|
|
def on_device_removed(self, device: AudioDevice):
|
2021-04-16 23:21:06 +08:00
|
|
|
"""Event, occurs when an existing device is removed from the system."""
|
|
|
|
pass
|
|
|
|
|
2023-06-27 01:05:51 +08:00
|
|
|
def on_default_changed(self, device: Optional[AudioDevice], flow: DeviceFlow):
|
|
|
|
"""Event, occurs when the default audio device changes.
|
|
|
|
If there is no device that can be the default on the system, can be None.
|
|
|
|
The flow determines whether an input or output device became it's respective default.
|
|
|
|
"""
|
2021-04-16 23:21:06 +08:00
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
AbstractAudioDeviceManager.register_event_type('on_device_state_changed')
|
|
|
|
AbstractAudioDeviceManager.register_event_type('on_device_added')
|
|
|
|
AbstractAudioDeviceManager.register_event_type('on_device_removed')
|
|
|
|
AbstractAudioDeviceManager.register_event_type('on_default_changed')
|