@@ -498,26 +498,31 @@ def get_status():
498498 raise RuntimeError ("play()/rec()/playrec() was not called yet" )
499499
500500
501- def query_devices (index = None ):
501+ def query_devices (device = None , kind = None ):
502502 """Return information about available devices.
503503
504504 Information and capabilities of PortAudio devices.
505505 Devices may support input, output or both input and output.
506506
507- To find the default device, use :attr:`default.device`.
507+ To find the default input/output device, use :attr:`default.device`.
508508
509509 Parameters
510510 ----------
511- index : int, optional
512- If specified, information about only the given device `index` is
511+ device : int or str, optional
512+ Numeric device ID or device name substring(s).
513+ If specified, information about only the given `device` is
513514 returned in a single dictionary.
515+ kind : {'input', 'output'}, optional
516+ If `device` is not specified and `kind` is ``'input'`` or
517+ ``'output'``, a single dictionary is returned with information
518+ about the default input or output device, respectively.
514519
515520 Returns
516521 -------
517522 dict or DeviceList
518- A dictionary with information about the given device `index` or
519- -- if no `index ` was specified -- a :class:`DeviceList`
520- containing one dictionary for each available device.
523+ A dictionary with information about the given ` device` or -- if
524+ no `device ` was specified -- a :class:`DeviceList` containing
525+ one dictionary for each available device.
521526 The dictionaries have the following keys:
522527
523528 ``'name'``
@@ -602,18 +607,21 @@ def query_devices(index=None):
602607 4 Built-in Digital Output, Core Audio (0 in, 2 out)
603608
604609 """
605- if index is None :
610+ if kind not in ('input' , 'output' , None ):
611+ raise ValueError ("Invalid kind: {0!r}" .format (kind ))
612+ if device is None and kind is None :
606613 return DeviceList (query_devices (i )
607614 for i in range (_check (_lib .Pa_GetDeviceCount ())))
608- info = _lib .Pa_GetDeviceInfo (index )
615+ device = _get_device_id (device , kind , raise_on_error = True )
616+ info = _lib .Pa_GetDeviceInfo (device )
609617 if not info :
610- raise PortAudioError ("Error querying device {0}" .format (index ))
618+ raise PortAudioError ("Error querying device {0}" .format (device ))
611619 assert info .structVersion == 2
612620 if info .hostApi == _lib .Pa_HostApiTypeIdToHostApiIndex (_lib .paDirectSound ):
613621 encoding = 'mbcs'
614622 else :
615623 encoding = 'utf-8'
616- return {
624+ device_dict = {
617625 'name' : _ffi .string (info .name ).decode (encoding , 'replace' ),
618626 'hostapi' : info .hostApi ,
619627 'max_input_channels' : info .maxInputChannels ,
@@ -624,6 +632,10 @@ def query_devices(index=None):
624632 'default_high_output_latency' : info .defaultHighOutputLatency ,
625633 'default_samplerate' : info .defaultSampleRate ,
626634 }
635+ if kind and device_dict ['max_' + kind + '_channels' ] < 1 :
636+ raise ValueError (
637+ "Not an {0} device: {1!r}" .format (kind , device_dict ['name' ]))
638+ return device_dict
627639
628640
629641def query_hostapis (index = None ):
@@ -1778,7 +1790,7 @@ class DeviceList(tuple):
17781790
17791791 def __repr__ (self ):
17801792 idev , odev = [
1781- dev if isinstance (dev , int ) else _find_device_id ( kind , dev )
1793+ dev if isinstance (dev , int ) else _get_device_id ( dev , kind )
17821794 for kind , dev in zip (('input' , 'output' ), default .device )
17831795 ]
17841796 digits = len (str (_lib .Pa_GetDeviceCount () - 1 ))
@@ -2319,8 +2331,7 @@ def _get_stream_parameters(kind, device, channels, dtype, latency, samplerate):
23192331 if samplerate is None :
23202332 samplerate = default .samplerate
23212333
2322- if not isinstance (device , int ):
2323- device = _find_device_id (kind , device , raise_on_error = True )
2334+ device = _get_device_id (device , kind , raise_on_error = True )
23242335 info = query_devices (device )
23252336 if channels is None :
23262337 channels = info ['max_' + kind + '_channels' ]
@@ -2398,15 +2409,34 @@ def _check(err, msg=""):
23982409 return err
23992410
24002411
2401- def _find_device_id ( kind , query_string , raise_on_error = False ):
2412+ def _get_device_id ( id_or_query_string , kind , raise_on_error = False ):
24022413 """Return device ID given space-separated substrings."""
2414+ assert kind in ('input' , 'output' , None )
2415+
2416+ if id_or_query_string is None :
2417+ id_or_query_string = default .device
2418+
2419+ idev , odev = _split (id_or_query_string )
2420+ if kind == 'input' :
2421+ id_or_query_string = idev
2422+ elif kind == 'output' :
2423+ id_or_query_string = odev
2424+ else :
2425+ if idev == odev :
2426+ id_or_query_string = idev
2427+ else :
2428+ raise ValueError ("Input and output device are different: {0!r}"
2429+ .format (id_or_query_string ))
2430+
2431+ if isinstance (id_or_query_string , int ):
2432+ return id_or_query_string
24032433 device_list = []
24042434 for id , info in enumerate (query_devices ()):
2405- if info ['max_' + kind + '_channels' ] > 0 :
2435+ if not kind or info ['max_' + kind + '_channels' ] > 0 :
24062436 hostapi_info = query_hostapis (info ['hostapi' ])
24072437 device_list .append ((id , info ['name' ], hostapi_info ['name' ]))
24082438
2409- query_string = query_string .lower ()
2439+ query_string = id_or_query_string .lower ()
24102440 substrings = query_string .split ()
24112441 matches = []
24122442 exact_device_matches = []
@@ -2423,19 +2453,22 @@ def _find_device_id(kind, query_string, raise_on_error=False):
24232453 if device_string .lower () == query_string :
24242454 exact_device_matches .append (id )
24252455
2456+ if kind is None :
2457+ kind = 'input/output' # Just used for error messages
2458+
24262459 if not matches :
24272460 if raise_on_error :
24282461 raise ValueError (
2429- "No " + kind + " device matching " + repr (query_string ))
2462+ "No " + kind + " device matching " + repr (id_or_query_string ))
24302463 else :
24312464 return - 1
24322465 if len (matches ) > 1 :
24332466 if len (exact_device_matches ) == 1 :
24342467 return exact_device_matches [0 ]
24352468 if raise_on_error :
24362469 raise ValueError ("Multiple " + kind + " devices found for " +
2437- repr (query_string ) + ": " +
2438- '; ' .join ('[{0}] {1}' .format (id , name )
2470+ repr (id_or_query_string ) + ":\n " +
2471+ '\n ' .join ('[{0}] {1}' .format (id , name )
24392472 for id , name in matches ))
24402473 else :
24412474 return - 1
0 commit comments