Closed josephernest closed 3 years ago
I do not have a small C++ sample code. However, mediafoundation.py is calling C functions using CFFI, which translates C function calls to Python function calls in a very straight-forward manner.
For example, have a look at your search for loopback microphones using sc.all_microphones(include_loopback=True)
:
# stripped out anything not relevant for this example:
def all_microphones(include_loopback=False):
with _DeviceEnumerator() as enum:
return [_Microphone(dev, isloopback=True) for dev in enum.all_devices('speaker')]
So further detail must be in _DeviceEnumerator
:
class _DeviceEnumerator:
"""Wrapper class for an IMMDeviceEnumerator**.
Provides methods for retrieving _Devices and pointers to the
underlying IMMDevices.
"""
def __init__(self):
self._ptr = _ffi.new('IMMDeviceEnumerator **')
IID_MMDeviceEnumerator = _guidof("{BCDE0395-E52F-467C-8E3D-C4579291692E}")
IID_IMMDeviceEnumerator = _guidof("{A95664D2-9614-4F35-A746-DE8DB63617E6}")
# see shared/WTypesbase.h and um/combaseapi.h:
CLSCTX_ALL = 23
hr = _ole32.CoCreateInstance(IID_MMDeviceEnumerator, _ffi.NULL, CLSCTX_ALL,
IID_IMMDeviceEnumerator, _ffi.cast("void **", self._ptr))
_com.check_error(hr)
def all_devices(self, kind):
"""Yields all sound cards of a given kind.
Kind may be 'speaker' or 'microphone'.
Sound cards are returned as _Device objects.
"""
DEVICE_STATE_ACTIVE = 0x1
data_flow = 1 # record
ppDevices = _ffi.new('IMMDeviceCollection **')
hr = self._ptr[0][0].lpVtbl.EnumAudioEndpoints(self._ptr[0], data_flow, DEVICE_STATE_ACTIVE, ppDevices);
_com.check_error(hr)
for ppDevice in _DeviceCollection(ppDevices):
device = _Device(self._device_id(ppDevice))
_com.release(ppDevice)
yield device
Any call to _com
and _ole32
is a straight-up method call in C++. The only "weird" thing here is that we use _ffi.new
instead of new
and (regrettably) self._ptr[0][0].lpVtbl.EnumAudioEndpoints(self._ptr[0], ...)
instead of self._ptr.EnumAudioEndpoints
. The latter is because we are calling a C++ method from C, which does not support classes.
Have a look at mediafoundation.py.h for a copied-together summary of all the C++ header files used in SoundCard/mediafoundation.
Thanks for your answer, I will study this!
Congrats @bastibe for this great project!
I've used in a recent project, and I am now thinking about re-writing my entire code in pure C++.
Just out curiosity, because I think you have spent some time to write
mediafoundation.py
, and you probably know the use of MediaFoundation for loopback device well, would you have a small C++ sample code that does just this:Thanks in advance!