-
Notifications
You must be signed in to change notification settings - Fork 9
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
Allow selecting devices by device name substrings #41
Comments
Substrings and/or globs by default seems a bit magical .. having an two functions - one that can lookup by exact string, and another that iterates through the names is enough that people can build any kind of matching they like on top. |
We could provide different selection methods, like
would that be un-magical enough? |
Makes sense.. I guess, glob, regex and match by string are common enough it could be a useful API. The usecases here are probably: GUIs (substring match), commandline: regex / glob. |
I think having to call a separate function for this doesn't really simplify anything. s = Stream(device="system") I don't think the suggested options ( For me, the main motivation for this feature is convenience. All this can be done in arbitrary ways in user code already, but I would like to have one convenient built-in way to select a device by string. As @bastibe and I discussed offline, the string to compare against should also include the name of the host API. We should probably collect a list of examples here, in order to be able to choose which selection method is best for our goal. When using JACK, it would be useful to specify Another example would be to use ALSA device numbers like this: Another possibility to select the same example device, would be Please add more examples! |
Fuzzy matching means that any search string |
Fuzzy matching sounds best indeed ... kind of coming round to this since, commandline and gui apps pysoundcard apps would be using the same kind of matching. |
I implemented something like this using the python module 'fuzzywuzzy':
import collections
from pysoundcard import devices
from fuzzywuzzy import fuzz
def fuzzydevices(match=''):
device_ratios = []
for device in devices():
ratio = fuzz.partial_ratio(device['name'], match)
if ratio > 30:
device_ratios.append((ratio, device))
for ratio, device in sorted(device_ratios, key=lambda ratio_device: (-ratio_device[0])):
yield device
>>> for device in fuzzydevices('loop pc'):
>>> print device['name']
Loopback: PCM (hw:1,0)
Loopback: PCM (hw:1,1) It works quite well, I tried some pretty tenuous input and it seems pretty sane - give it a try.. |
Updated this slightly for some code I'm using so there is an API to get one device, no matter what def fuzzydevices(match='', min_ratio=30):
device_ratios = []
for device in devices():
ratio = fuzz.partial_ratio(device['name'], match)
if ratio > min_ratio:
device_ratios.append((ratio, device))
for ratio, device in sorted(device_ratios, key=lambda ratio_device: (-ratio_device[0])):
yield device
def firstfuzzydevice(match=''):
devices = list(fuzzy_devices(match, 0))
return devices[0] |
I guess this API should allow matching other device parameters too, I'll have a look into this when I get some time .. |
That's cool! I'll have a look at fuzzywuzzy! |
I'm still not convinced that fuzzy matching provides an actual advantage compared to a plain substring match. @stuaxo: can you please provide a few concrete examples for search expressions and device strings that you would use? The only example so far was devices = [...] # iterable of strings
expression = "mic co"
matches = []
for d in devices:
if all(s.lower() in d.lower() for s in expression.split()):
matches.append(d)
if len(matches) == 1:
print("I found", repr(matches[0]))
elif len(matches) == 0:
print("I didn't find anything matching", repr(expression))
else:
print("I found multiple matches:", matches) |
I've only used "loop" so far, to grab a loopback device, I guess this should work with substring matching too.. in the future I'll probably be using line-in, but can't check that as I don't have it on this laptop. Once my current project is further along I should have more of an idea about this. I guess being able to select a single device is the useful part of this - additional filtering is something that should live in whatever GUI project is using pysoundcard ? |
In addition to numeric device IDs, it should also be possible to select devices by strings, e.g.
device="hdmi"
.I think it would be practical to use case-insensitive search, probably a space separated list of substring would also be useful, e.g.
device="hdmi 1"
.We could allow glob patterns and/or regular expressions, but I think that might be overkill.
If a string fits to several devices, an error should be raised.
The text was updated successfully, but these errors were encountered: