from abc import ABCMeta, abstractmethod from enum import Enum, auto from typing import Dict, Optional from pyglet import event from pyglet.util import with_metaclass class DeviceState(Enum): ACTIVE = auto() DISABLED = auto() MISSING = auto() UNPLUGGED = auto() class DeviceFlow(Enum): OUTPUT = auto() INPUT = auto() INPUT_OUTPUT = auto() class AudioDevice: """Base class for a platform independent audio device. _platform_state and _platform_flow is used to make device state numbers.""" platform_state: Dict[int, DeviceState] = {} # Must be defined by the parent. platform_flow: Dict[int, DeviceFlow] = {} # Must be defined by the parent. def __init__(self, dev_id: str, name: str, description: str, flow: int, state: int): self.id = dev_id self.flow = flow # platform value self.state = state # platform value self.name = name self.description = description def __repr__(self): return "{}(name='{}', state={}, flow={})".format( self.__class__.__name__, self.name, self.platform_state[self.state].name, self.platform_flow[self.flow].name) 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 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.""" pass def on_device_added(self, device: AudioDevice): """Event, occurs when a new device is added to the system.""" pass def on_device_removed(self, device: AudioDevice): """Event, occurs when an existing device is removed from the system.""" pass 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. """ 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')