-
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
Thanks a lot! But i need some examples... #4
Comments
first I want to start off with letting you know that the code works with python 2.7 only. I stumbled across some kind of a hole where I am able to get notifications when other applications start and stop playing. This is not something that is supposed to happen and every time I port he code to python 3 that feature stops functioning. First I have to explain the structure to you so you understand how things are put together. You have a device and that device has endpoints. This is where it can get a bit confusing. An endpoint is either an input or an output, i can be a single jack or it can be multiple jacks or it might not be a jack at all (i know right). so when you open up your sound manager in windows you see things like headphones, speakers, spdif those kinds of things. Those would be endpoints. You need to know if you want to change the volume level on a global level or do you want to change the volume for only the headphones or the speakers.
yes
no, application controls are called "sessions" and only the owning process of that session (or windows sound manager) is able to do that. could you imagine what it would be like if one application could change another applications sound settings. Microsoft did not release the API for changing the default sound device for this same reason. At some point some developer for Microsoft did leak that API to the public and that is the reason why we are able to do it. We are able to get events when a session starts and stops playing, this is not something that is supposed to happen but for some reason it does.
TY for letting me know this, I am going to have pypi pull it down as there is no credit given to me and I am the original author. And to make matters worse, it is an improper conversion and it is going to have issues. The Windows data types are not properly set up for a 64bit python for starters, they didn't change the singleton metaclass to work properly with Python 3 and there are other things as well. It looks like the person that made the change did update the code in attempt to be able to change session volumes of other applications but that is only going to work if the session events continue to work and every time I have made the conversion they stop functioning. I was never able to set the session volume levels so the code they added might not work. Mostly what the person that added that to pypi did was change the print statements and change the import statements. I personally find it exceedingly rude that the person did not ask if they could post it on pypi and that they provide no link on how to get support for their modified version. give me a day to hammer out an example for you an I will once again screw with getting it ported to Python 3. |
@kdschlosser
Sorry. Ofc i mean sessions. But I did not understand your answer unequivocally. In sum we can't did it?
Global level - its master volume for all or separately sessions. Did I understand correctly? P.S. I hope you are not very upset about the situation with pypi. |
It's cool about the pypi thing. It has been removed. My gripe with it was mostly the fact that the person did not provide information on where to get support for their version. It also appears that the name of the author is not who made the modifications. the name of the author is a female and the person that did the work is a guy.. kinds strange deal if you ask me. I am working on the python 3 port of it, we will see how it goes. I am writing a lot of it over again as my knowledge on how to write bindings to the windows API has improved since I wrote this library. IDK if you looked at pyWinAPI at all but it includes about 1,000,000 lines of code. Its not something that run it is used to save time. It is a direct port of the windows 10 SDK. or 1,000,000 lines of the 6,000,000 in the SDK. |
OK wanted to let you know that I didn't leave you hangin. I am working on the Python 3 port and it is coming along pretty good. I am writing about 80% of the thing over. I want to expose more of the low level bits to the users. The Python 2.7 version also had a wicked memory leak in it that I never managed to locate. It also had an issue with unicode characters (non English languages) I am hoping that these are sorted out now. I have to test the sessions and getting notifications when different things change, like new sessions getting started and new devices being added or when the volume changes. I am also going to expose some of the KS end of things to allow for altering pieces like bass boost and being able to set the channel configuration. I still have to test the volume controls as well and I have to get the interfaces to work for AGC, Bass, Treble, Mid , etc.. Here is a test I just finish up doing. I wanted t make sure that I enumerate the devices properly and the endpoints for a device. I also made sure that the various properties and attributes of the devices and the endpoints all worked.
|
OK sessions are working. The volume for an endpoint is working, volume for a session is working, volume for endpoint channels is working, volume for session channels is working and the peak meter for an endpoint and it's channels are working. I have to test the notifications and get the equalizer interfaces working. |
@kdschlosser Thanks for you answer! |
don't get too used to using the API in the python 2 version. It is going to work completely different. It will be a whole hell of a lot easier. In the version you are using you have to jump through hoops to handle notifications. You won't have to do that anymore. It is going to work like this. from pyWinCoreAudio import (
IMMDeviceEnumerator,
ON_DEVICE_ADDED,
ON_DEVICE_REMOVED,
ON_ENDPOINT_VOLUME_CHANGED
)
def on_device_added(signal, device):
print('device added:', device.name)
def on_device_removed(signal, name):
print('device removed:', name)
def on_endpoint_volume_changed(signal, device, endpoint, is_muted, master_volume, channel_volumes):
print('endpoint volume changed:', device.name + '.' + endpoint.name, 'mute:', is_muted, 'volume:', master_volume)
for i, channel in enumerate(channel_volumes):
print('channel:', i, 'volume:', channel.level)
_on_device_added = ON_DEVICE_ADDED.register(on_device_added)
_on_device_removed = ON_DEVICE_REMOVED.register(on_device_removed)
device_enum = IMMDeviceEnumerator()
volume_registrations = []
# registers to get notifications from all devices and all endpoints
_on_endpoint_volume = ON_ENDPOINT_VOLUME_CHANGED.register(on_endpoint_volume_changed)
volume_registrations.append(_on_endpoint_volume)
for device in device_enum:
print(device.name)
# registers to get notifications for all endpoints for a specific device
_on_endpoint_volume = ON_ENDPOINT_VOLUME_CHANGED.register(on_endpoint_volume_changed, device=device)
volume_registrations.append(_on_endpoint_volume)
for endpoint in device:
print(' ', endpoint.name)
# registers to get notifications for a specific endpoint
_on_endpoint_volume = ON_ENDPOINT_VOLUME_CHANGED.register(on_endpoint_volume_changed, device=device, endpoint=endpoint)
volume_registrations.append(_on_endpoint_volume)
for session in endpoint:
print(' ', session.name) You can also do a dynamic setup for getting notifications by using the callbacks. def on_device_added(signal, device):
print('device added:', device.name)
if device.name == 'some device name':
for endpoint in device:
if endpoint.name == 'Speakers':
_on_endpoint_volume = ON_ENDPOINT_VOLUME_CHANGED.register(on_endpoint_volume_changed, device=device, endpoint=endpoint)
_on_device_added = ON_DEVICE_ADDED.register(on_device_added) |
I have the convenience interfaces all done tho most audio cards will not use those interfaces. Instead they use a different mechanism that I am going to expose. The things you will be able to adjust if the device supports it is listed below.
|
It's won't be too much longer until I am am ready to have the code tested. |
you can view the changes I have made so far on the develop branch |
OK I have a version that is functional. it is in the develop branch. You can install it using
There is an example.py file in the develop branch that you can use as a guide. when you make the call to It is extremely important that you follow the example.py file. If you do anything with the library at the root level of your module you MUST make sure that you delete each object that is created. Even when something is done in a for loop or a while loop a reference to the object will exist in I am still working on getting the KS properties working and also all of the notifications. The default endpoint notification, session volume and endpoint volume notifications are functional. YOU MUST USE the exact same parameter names seen in the example for the callbacks. If you do not it will not function. The callback system holds a weak reference to the callbacks and also a weak reference to any devices, endpoint, sessions or interfaces passed when registering a callback. so you can delete the callback function and this will cause it to get unregistered. if a device, endpoint, session or interface that has been passed no longer exists the callback will get removed and you will need to register the callback again once the device, endpoint, session or interface becomes available again. rule of thumb with registering callbacks. If the signal has "DEVICE" in the name then you can pass a device object when registering if you want only notifications for that device. There are 2 signals where this doesn't hold true, the signals are You can use the signals in a dynamic nature by using the ON_DEVICE_ADDED and ON_DEVICE_REMOVED signals and registering and unregistering callbacks inside of the functions you pass to those 2 signals. For some bat shit crazy reason the notification API for core audio likes to send multiple notifications for the same thing. I have filter this out in the 3 tested signals. I have not done this with any of the other signals. The callback system uses a threadworker to make the call to the callback you provide. This is done so the core audio notification system doesn't get held up if you need to do some lengthy processing. It is also done to handle unhandled exceptions that might be in your code. The threadworker will catch any exceptions that are unhandled and it will print out the exception and the threadworker will continue along it merry way. The threadworker is a daemon thread so when the thread that imports pyWinCoreAudio terminates so does the threadworker. My recommendation is to only import pyWinCoreAudio from the main thread. The threadworker thread also exits after a period of activity. This is done to release resources. While I know it is not a lot of resources it holds in the first place I am just a stickler for giving back when it is not being used. Once a notification comes in the thread will restart and if a lot of notifications come in back to back it will process all of the notifications and then terminate after the timeout period has expired. The API is a whole lot easier to use with this new version. The majority of the objects that you use from the library are the ctypes objects. I did this to allow a user to add onto the library if they want. Here is the link to the development branch once again. |
Answering my own question, you must call the method 'set_default' of the desired endpoint, with the argument being the role, as described here: https://docs.microsoft.com/en-us/windows/win32/api/mmdeviceapi/ne-mmdeviceapi-erole Something like this: if endpoint.guid == '{6315A238-B914-4369-B086-7FCD1654E714}':
endpoint.set_default(0) Hope this will be helpful for someone. |
You can use the GUID for comparison or you can also use the name. The GUID can and will change if the sound device is a USB device and you plug the device into a different USB port. The GUID can also change if you update the drivers. The GUID is a little harder to locate and using the device name and the endpoint name to target a specific endpoint is easiest. The ERole and EDataFlow enumerations are available in the library, from pyWinCoreAudio.mmdeviceapi import ERole, EDataFlow
ERole.eConsole
ERole.eMultimedia
ERole.eCommunications
EDataFlow.eRender
EDataFlow.eCapture The file structure of the library matches the Windows SDK. How this helps is when you are reading documentation like the link you posted. If you scroll down the page near the bottom is the section "Requirements" If you look at the field labeled "Header" it is going to tell you the Windows SDK file where that piece of API is located. In the case of the link you posted the header file is "mmdeviceapi.h" Microsoft has the use of roles for defining the default endpoint and for the most part they really do not get used. It is common when setting the default endpoint to set the endpoint as the default for eConsole and eMultimedia to the same endpoint. The Windows Core Audio API is a rather tangled interwoven mess and I have done my best to untangle it and organize the various parts so they make sense. Endpoints are grouped together by device and sessions are grouped together by endpoint. It is easiest to think of an endpoint as a jack or a group of jacks. it is what the sound gets output to or where sound is captured from. Sessions are opened up by programs/apps to play or record. If you open up the Volume Mixer in Windows you will be given a volume control for each session that exists. You also have the ability to alter the volume of sessions from the library as well. With some creativity you can do some pretty wild things. An example is detecting when there is sound heard on a microphone or when sound starts and stops playing. You use the peak meter to accomplish those things. Because you can get notifications for plugging and unplugging from different jacks you can use the library to detect when you plug in your headphones and then start your favorite music application. Another is when you unplug your headphones have the library turn the volume down and or close the music application. |
Hello! Thanks a lot for you'r lib, it's fantastic!
You have done a great job and made the most powerful lib for Windows Core Audio API! Thanks a lot yet!
But can u make some 'quik start' or some little examples for each "ability". I mean just little example how change 'Volume Level' or 'mute' e.t.c
I'm just started programmon on python and some things is hard for me yet.
Can anyone give some suggest or couple-string-example how:
P.S. I can't understand some thing. In other issue author says he don't update this lib for python 3.7+ but in pypi.org i found this lib for python 3.7-3.9 and without descriprion and other links and by other author. It's mean good news for us and you finally updated for python 3 or it's some other people did it?
The text was updated successfully, but these errors were encountered: