@@ -818,7 +818,7 @@ def query_hostapis(index=None):
818
818
The dictionaries have the following keys:
819
819
820
820
``'name'``
821
- The name of the host API.
821
+ The name of the host API and suitable for user display .
822
822
``'devices'``
823
823
A list of device IDs belonging to the host API.
824
824
Use `query_devices()` to get information about a device.
@@ -831,6 +831,16 @@ def query_hostapis(index=None):
831
831
overwritten by assigning to `default.device` -- take(s)
832
832
precedence over `default.hostapi` and the information in
833
833
the abovementioned dictionaries.
834
+ ``'apiname'``
835
+ *apiname* is a string that is suitable for use as a Python
836
+ identifier. Unlike *name*, *apiname* does not contain
837
+ spaces or any other characters that are not suitable as a
838
+ Python identifier. These strings are derived from
839
+ PortAudio's PaHostApiTypeId enumeration and thus correspond
840
+ on a one-to-one basis with that enumeration. These strings
841
+ shall never be eubject to locale settings such as LANG,
842
+ LC_ALL, or LC_MESSAGES. In short, these strings are safer
843
+ than *name* for hard coding into an application.
834
844
``'api'``
835
845
A namedtuple containing the platform-specific API from
836
846
PortAudio. If a platform-specific API is unavailable, this
@@ -858,6 +868,7 @@ def query_hostapis(index=None):
858
868
for i in range (info .deviceCount )],
859
869
'default_input_device' : info .defaultInputDevice ,
860
870
'default_output_device' : info .defaultOutputDevice ,
871
+ 'apiname' : _get_host_apiname (info .type ),
861
872
'api' : api ,
862
873
}
863
874
@@ -2353,6 +2364,48 @@ class CallbackAbort(Exception):
2353
2364
# Host-API:
2354
2365
2355
2366
2367
+ # Is there a way to query the names used in "enum PaHostApiTypeId"?
2368
+ # If so, then I wouldn't bother with this dict, _typeid_to_apiname.
2369
+ #
2370
+ # Q: Should _typeid_to_apiname be brought out to global scope, with
2371
+ # the leading underscore? I'm averse to relying upon converting the
2372
+ # current .name field as an api identifier, since those strings are
2373
+ # intended for user consumption. (For example, will Port Audio one
2374
+ # day provide language translations of those names? If they did,
2375
+ # these names could differ for each user purely based on locale
2376
+ # settings, such as LANG, LC_ALL, or LC_MESSAGES!)
2377
+ _typeid_to_apiname = {
2378
+ _lib .paInDevelopment : str .lower ('InDevelopment' ),
2379
+ _lib .paDirectSound : str .lower ('DirectSound' ),
2380
+ _lib .paMME : str .lower ('MME' ),
2381
+ _lib .paASIO : str .lower ('ASIO' ),
2382
+ _lib .paSoundManager : str .lower ('SoundManager' ),
2383
+ _lib .paCoreAudio : str .lower ('CoreAudio' ),
2384
+ _lib .paOSS : str .lower ('OSS' ),
2385
+ _lib .paALSA : str .lower ('ALSA' ),
2386
+ _lib .paAL : str .lower ('AL' ),
2387
+ _lib .paBeOS : str .lower ('BeOS' ),
2388
+ _lib .paWDMKS : str .lower ('WDMKS' ),
2389
+ _lib .paJACK : str .lower ('JACK' ),
2390
+ _lib .paWASAPI : str .lower ('WASAPI' ),
2391
+ _lib .paAudioScienceHPI : str .lower ('AudioScienceHPI' ),
2392
+ }
2393
+ def _get_host_apiname (hostapi_typeid ):
2394
+ # Assume int for building '_hostapi###' strings.
2395
+ assert isinstance (hostapi_typeid , int )
2396
+ try :
2397
+ # Pre-assigned name:
2398
+ return _typeid_to_apiname [hostapi_typeid ]
2399
+ except KeyError :
2400
+ # Make up new names on the fly:
2401
+ if hostapi_typeid >= 0 :
2402
+ # 42 -> '_hostapi42'
2403
+ return '_hostapi' + str (hostapi_typeid )
2404
+ else :
2405
+ # -37 -> '_hostapi_37'
2406
+ return '_hostapi_' + str (- hostapi_typeid )
2407
+
2408
+
2356
2409
_api_dicts = {}
2357
2410
def _get_host_api (hostapi_typeid ):
2358
2411
"""Lookup hostapi_typeid and return the results as a namedtuple.
@@ -2376,11 +2429,34 @@ def _get_host_api(hostapi_typeid):
2376
2429
2377
2430
"""
2378
2431
api_dict = _api_dicts [hostapi_typeid ]
2379
- API = _namedtuple ('_API_' + str (hostapi_typeid ), api_dict .keys ())
2432
+ # Using .upper() to distinguish that we're using _get_host_apiname
2433
+ # to name a type:
2434
+ API = _namedtuple (_get_host_apiname (hostapi_typeid ).upper (),
2435
+ api_dict .keys ())
2380
2436
api = API (** api_dict )
2381
2437
return api
2382
2438
2383
2439
2440
+ # hostapis is an alternative interface to query_hostapis and populated during _initialize().
2441
+ hostapis = None
2442
+
2443
+
2444
+ def _populate_hostapis ():
2445
+ global hostapis
2446
+ # For now, just invoke query_hostapis() to get the list. Later if
2447
+ # we deprecate query_hostapis, we can move its guts into here.
2448
+ hostapi_list = query_hostapis ()
2449
+ # There is one _HostAPI for each field in _HostAPIs:
2450
+ _HostAPI = _namedtuple ('_HostAPI' , ('name' , 'devices' ,
2451
+ 'default_input_device' ,
2452
+ 'default_output_device' ,
2453
+ 'apiname' , 'api' ))
2454
+ class HostAPIs (_namedtuple ('HostAPIs' , (h ['apiname' ] for h in hostapi_list ))):
2455
+ """Access to PortAudio Host API's"""
2456
+ __slots__ = ()
2457
+ hostapis = HostAPIs (* (_HostAPI (** h ) for h in hostapi_list ))
2458
+
2459
+
2384
2460
# Host-API: ASIO
2385
2461
2386
2462
@@ -3176,6 +3252,7 @@ def _initialize():
3176
3252
global _initialized
3177
3253
_check (_lib .Pa_Initialize (), 'Error initializing PortAudio' )
3178
3254
_initialized += 1
3255
+ _populate_hostapis ()
3179
3256
3180
3257
3181
3258
def _terminate ():
0 commit comments