Open dskrypa opened 1 year ago
the call from that function should read
IMMDeviceEnumerator.default_audio_endpoint(self.data_flow, self.role)
and not
IMMDeviceEnumerator.default_audio_endpoint(self.data_flow, self.data_flow)
so if you can do me a favor and run this code to see if the output ends up being correct we can get it all fixed up.
for df in (EDataFlow.eRender, EDataFlow.eCapture):
for role in (ERole.eConsole, ERole.eMultimedia, ERole.eCommunications):
ep = IMMDeviceEnumerator.default_audio_endpoint(df, role)
print(ep == IMMDeviceEnumerator.default_audio_endpoint(ep.data_flow, ep.role))
I want to make sure that the data_flow and the role as returned from the default device is going to be correct to be used in checking if it is the default or not.
Good catch on this.
If the result of running that test is all True
then go ahead and fix the code and submit a PR for it and I will get it merged. If you do not want to bother with making a PR let me know and I will get it done.
Otherwise if the library working for what you need it to? is there any functionality that needs to be added to it???
I would be happy to submit a PR, but it looks like IMMDevice
doesn't have a role
attribute/property:
AttributeError: 'POINTER(IMMDevice)' object has no attribute 'role'
I looked at the _methods_
in that class and in IMMEndpoint
since that is where the GetDataFlow
method that is used by the data_flow
property is defined, but didn't see anything that seemed like it would provide the endpoint's role. I'm not overly familiar with the underlying interfaces; I had the Microsoft documentation open yesterday, but haven't dived back in today.
Do you have local changes that haven't been pushed to GitHub, perhaps, that added that?
In terms of library functionality, I'm not entirely sure if what I want to do is actually possible. I have found conflicting suggestions in different threads/answers. My goal is almost exactly the same as what was stated in this thread - I want to toggle the Disable all enhancements
setting for a particular render endpoint. Normally, I keep them disabled, but some shows really need the loudness equalization for dialogue to be audible. The setting is buried far too deep in clicky menus...
It sounds like it may be possible to accomplish this by toggling the PKEY_AudioEndpoint_Disable_SysFx
property. I did not find an obvious way to do so yet, but I spent most of yesterday reading through different libraries and then getting more familiar with this one. I plan to try again likely either later today or tomorrow.
I will be pushing an update in about a day or so. I am checking into what you are wanting to do with enabling the effects. I have checking to see if they are disabled but nothing to enable them. I have to do some testing to find out if I am able to turn it on the way I would like to.
Sorry I am running behind. I recently upgraded to Windows 10 and then to Windows 11 and I have been messing about with the audio components and it not playing nice nice with anything Realtek which is the sound card I have is a USB kind of a sound card. It's funky. I just now managed to locate drivers for it that gave the option you are trying to enable and disable. So now I will be able to locate the property key for it and code up a method to turn it on and off.
On another note. I did add a cool feature. when I push an update you will be able to target a specific audio session and change the endpoint for that session. that will be pretty handy. I also came across a bunch of new interfaces that are in the latest windows SDK so I have to rummage through those and see what they offer.
No rush at all! Thank you very much for your help! That sounds cool :)
By the way, just to make sure it's clear, when toggling the Disable all enhancements
setting via the UI, Windows remembers the last settings that were checked for the specific enhancements that should be enabled. I only ever toggle Disable all enhancements
. Assuming toggling it via API would have the same behavior, it should hopefully be relatively straightforward.
OK I added the feature for enabling and disabling all enhancements. you access it using the audio_enhancements_enabled
method of an endpoint. you can read the current state and change it as well. The property takes a boolean value
print(endpoint.audio_enhancements_enabled)
endpoint.audio_enhancements_enabled = False
print(endpoint.audio_enhancements_enabled)
endpoint.audio_enhancements_enabled = True
print(endpoint.audio_enhancements_enabled)
The only crappy thing is the sound control panel was not coded to receive property change notifications. So if you have the sound control panel open and change the property using this library you will NOT see the switch move. You have to close the control panel and open it again and the switch will then be in the correct position.
There are 2 places that exist in Windows to change this setting. The first is under System -> Sound and then you click on the endpoint to see the properties. The setting is called "Enhance Audio"
The second place is when you are in the properties page for an endpoint and then you click on the "Advanced" link under "Enhance Audio" doing that will open up the dialog for changing settings to the endpoint. If you select the "Advanced" tab in that dialog the checkbox "Enable Audio Enhancements" is the same setting.
This dialog also does not receive property change notifications either.
new code is in the develop branch.
changing that setting in the library is going to function exactly like it does in the sound settings of Windows
Amazing, thank you! I'll test it out tomorrow.
I fixed the example and added better support for some of the properties. so a new commit has been pushed to the develop branch.
I don't know what brand of sound card you have, If you have a realtek card I stumbled upon a huge number of undocumented COM interfaces buried inside of the driver DLL files. They are all for changing settings on the cards. The fun settings like EQ and sound processors and settings for the processors.
It is going to take me a long while to hammer out what the different interfaces do. I just finished writing the COM interface binders in Python. all 6000+ lines worth.
I tried toggling the enhancements for a given endpoint, but it resulted in this error:
Traceback (most recent call last):
Cell In [1], line 3
ep.audio_enhancements_enabled = False
File ..\venv\lib\site-packages\pyWinCoreAudio\mmdeviceapi.py:3018 in audio_enhancements_enabled
self.set_property(PKEY_AudioEndpoint_Disable_SysFx, value, VT_UI4)
File ..\venv\lib\site-packages\pyWinCoreAudio\mmdeviceapi.py:2885 in set_property
return pStore.SetValue(key, value, vt)
File ..\venv\lib\site-packages\pyWinCoreAudio\propsys.py:119 in SetValue
self.__com_SetValue(key, ctypes.byref(prop_var))
ValueError: NULL COM pointer access
I am running Win 10 Pro, 22H2 (19045.2251), and tried this with Python 3.10.8 in an interactive ipython session. The test was on a device that I had not tried toggling that setting on before though - I just built a new PC, and the new sound card (Sound Blaster Z SE) apparently doesn't have the same options in the Windows Sound Control Panel as my old one (builtin to old motherboard - not sure which vendor/model) did. The above attempt was on the Speakers endpoint for my USB headset (Plantronics Savi 7xx). It was set as the default communications device.
Once I have had time to get settled in, I will definitely take a closer look and try again. Thank you again for your help on this! And I will definitely be playing around with this more later - the new additions sound very interesting.
Try running the script as an administrator.
I will also look and see if there is anything off with it.
First off, thank you for your work on this library!
In the develop branch, in
IMMDevice.is_default
, I noticed that the 2nd argument it uses when callingdefault_audio_endpoint
appears to be incorrect since that method expects the 2nd argument to be anERole
:It probably ends up providing a correct result for most use cases, but is not 100% accurate. Maybe a
is_default_for_role
method would be better here, and/or updatingis_default
to return True if it is the default for anyERole
?Example showing a case where the default communications output endpoint is not identified as being the default by
is_default
: