Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get_microphone(), get_speaker(): Improved comparison between the call parameter "id" and existing device names #147

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 4 additions & 25 deletions soundcard/coreaudio.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import threading
import warnings

from soundcard.utils import match_device

_ffi = cffi.FFI()
_package_dir, _ = os.path.split(__file__)
with open(os.path.join(_package_dir, 'coreaudio.py.h'), 'rt') as f:
Expand Down Expand Up @@ -60,7 +62,7 @@ def get_speaker(id):
fuzzy-matched pattern for the speaker name.

"""
return _match_device(id, all_speakers())
return match_device(id, all_speakers())


def default_microphone():
Expand All @@ -79,30 +81,7 @@ def get_microphone(id, include_loopback=False):
fuzzy-matched pattern for the microphone name.

"""
return _match_device(id, all_microphones(include_loopback))


def _match_device(id, devices):
"""Find id in a list of devices.

id can be a CoreAudio id, a substring of the device name, or a
fuzzy-matched pattern for the microphone name.

"""
devices_by_id = {device.id: device for device in devices}
devices_by_name = {device.name: device for device in devices}
if id in devices_by_id:
return devices_by_id[id]
# try substring match:
for name, device in devices_by_name.items():
if id in name:
return device
# try fuzzy match:
pattern = '.*'.join(id)
for name, device in devices_by_name.items():
if re.match(pattern, name):
return device
raise IndexError('no device with id {}'.format(id))
return match_device(id, all_microphones(include_loopback))


def get_name():
Expand Down
28 changes: 4 additions & 24 deletions soundcard/mediafoundation.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

import numpy

from soundcard.utils import match_device

_ffi = cffi.FFI()
_package_dir, _ = os.path.split(__file__)
with open(os.path.join(_package_dir, 'mediafoundation.py.h'), 'rt') as f:
Expand Down Expand Up @@ -123,7 +125,7 @@ def get_speaker(id):
fuzzy-matched pattern for the speaker name.

"""
return _match_device(id, all_speakers())
return match_device(id, all_speakers())

def all_microphones(include_loopback=False):
"""A list of all connected microphones.
Expand Down Expand Up @@ -151,29 +153,7 @@ def get_microphone(id, include_loopback=False):
fuzzy-matched pattern for the microphone name.

"""
return _match_device(id, all_microphones(include_loopback))

def _match_device(id, devices):
"""Find id in a list of devices.

id can be a WASAPI id, a substring of the device name, or a
fuzzy-matched pattern for the microphone name.

"""
devices_by_id = {device.id: device for device in devices}
devices_by_name = {device.name: device for device in devices}
if id in devices_by_id:
return devices_by_id[id]
# try substring match:
for name, device in devices_by_name.items():
if id in name:
return device
# try fuzzy match:
pattern = '.*'.join(id)
for name, device in devices_by_name.items():
if re.match(pattern, name):
return device
raise IndexError('no device with id {}'.format(id))
return match_device(id, all_microphones(include_loopback))

def _str2wstr(string):
"""Converts a Python str to a Windows WSTR_T."""
Expand Down
41 changes: 4 additions & 37 deletions soundcard/pulseaudio.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import numpy
import cffi

from soundcard.utils import match_device

_ffi = cffi.FFI()
_package_dir, _ = os.path.split(__file__)
with open(os.path.join(_package_dir, 'pulseaudio.py.h'), 'rt') as f:
Expand Down Expand Up @@ -302,8 +304,7 @@ def get_speaker(id):
speaker : _Speaker

"""
speakers = _pulse.sink_list
return _Speaker(id=_match_soundcard(id, speakers)['id'])
return match_device(id, all_speakers())


def all_microphones(include_loopback=False, exclude_monitors=True):
Expand Down Expand Up @@ -367,41 +368,7 @@ def get_microphone(id, include_loopback=False, exclude_monitors=True):
-------
microphone : _Microphone
"""

if not exclude_monitors:
warnings.warn("The exclude_monitors flag is being replaced by the include_loopback flag", DeprecationWarning)
include_loopback = not exclude_monitors

microphones = _pulse.source_list
return _Microphone(id=_match_soundcard(id, microphones, include_loopback)['id'])


def _match_soundcard(id, soundcards, include_loopback=False):
"""Find id in a list of soundcards.

id can be a pulseaudio id, a substring of the microphone name, or
a fuzzy-matched pattern for the microphone name.
"""
if not include_loopback:
soundcards_by_id = {soundcard['id']: soundcard for soundcard in soundcards
if not 'monitor' in soundcard['id']}
soundcards_by_name = {soundcard['name']: soundcard for soundcard in soundcards
if not 'monitor' in soundcard['id']}
else:
soundcards_by_id = {soundcard['id']: soundcard for soundcard in soundcards}
soundcards_by_name = {soundcard['name']: soundcard for soundcard in soundcards}
if id in soundcards_by_id:
return soundcards_by_id[id]
# try substring match:
for name, soundcard in soundcards_by_name.items():
if id in name:
return soundcard
# try fuzzy match:
pattern = '.*'.join(id)
for name, soundcard in soundcards_by_name.items():
if re.match(pattern, name):
return soundcard
raise IndexError('no soundcard with id {}'.format(id))
return match_device(id, all_microphones(include_loopback))


def get_name():
Expand Down
21 changes: 21 additions & 0 deletions soundcard/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
def match_device(id, devices):
"""Find id in a list of devices.

id can be a platfom-specific id, a substring of the device name, or a
fuzzy-matched pattern for the microphone name.

"""
devices_by_id = {device.id: device for device in devices}
devices_by_name = {device.name: device for device in devices}
if id in devices_by_id:
return devices_by_id[id]
# try substring match:
for name, device in devices_by_name.items():
if id in name:
bastibe marked this conversation as resolved.
Show resolved Hide resolved
return device
# try fuzzy match:
pattern = '.*'.join(id)
for name, device in devices_by_name.items():
if re.match(pattern, name):
return device
raise IndexError('no device with id {}'.format(id))