Skip to content
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

Open
askruga opened this issue Oct 10, 2021 · 14 comments
Open

Thanks a lot! But i need some examples... #4

askruga opened this issue Oct 10, 2021 · 14 comments

Comments

@askruga
Copy link

askruga commented Oct 10, 2021

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:

  • Switch default device, i mean "Speakers" to "Headphones" and how i can get event callbacks for it?
  • Can i switch Channel Volume Level? I mean change volume level just for "Chrome.exe" or "Skype.exe"

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?

@kdschlosser
Copy link
Owner

kdschlosser commented Oct 10, 2021

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.

Switch default device, i mean "Speakers" to "Headphones" and how i can get event callbacks for it?

yes

Can i switch Channel Volume Level? I mean change volume level just for "Chrome.exe" or "Skype.exe"

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.

but in pypi.org i found this lib for python 3.7-3.9 and without descriprion and other links and by other author.

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.

@askruga
Copy link
Author

askruga commented Oct 12, 2021

@kdschlosser
Thanks for you answer. Some thing become more understundable for me. Look forward to some examples. And adaptation for py3 ofcourse.

Can i switch Channel Volume Level? I mean change volume level just for "Chrome.exe" or "Skype.exe"

Sorry. Ofc i mean sessions. But I did not understand your answer unequivocally. In sum we can't did it?

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.

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.

@kdschlosser
Copy link
Owner

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.

@kdschlosser
Copy link
Owner

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.

AMD High Definition Audio Device
    endpoints:
        endpoint: 1 - Digital Display Audio (AMD High Definition Audio Device)
        description: 1 - Digital Display Audio
        type: Hdmi Interface
        data flow: Render
        form_factor: Digital Audio Display Device
        full_range_speakers: 0
        guid: {0D6DA6D5-450F-4A1C-ACA4-6A852D535C6A}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: 1 - Digital Display Audio
        connector_subtype: HDMI Interface
        connector_location: On separate chassis, HDMI
        connector_style: HDMI
        presence_detection: True
        connector_color: (0, 0, 0, 255)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: None


        endpoint: 2 - Digital Display Audio (AMD High Definition Audio Device)
        description: 2 - Digital Display Audio
        type: Hdmi Interface
        data flow: Render
        form_factor: Digital Audio Display Device
        full_range_speakers: 0
        guid: {41AE340C-C4EE-44A6-A388-61BE3AA3046C}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: 2 - Digital Display Audio
        connector_subtype: HDMI Interface
        connector_location: On separate chassis, HDMI
        connector_style: HDMI
        presence_detection: True
        connector_color: (0, 0, 0, 255)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: None


        endpoint: 3 - Digital Display Audio (AMD High Definition Audio Device)
        description: 3 - Digital Display Audio
        type: Hdmi Interface
        data flow: Render
        form_factor: Digital Audio Display Device
        full_range_speakers: 0
        guid: {75C5782C-D301-4C4C-80CC-80EEC7E07E2C}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: 3 - Digital Display Audio
        connector_subtype: HDMI Interface
        connector_location: On separate chassis, HDMI
        connector_style: HDMI
        presence_detection: True
        connector_color: (0, 0, 0, 255)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: None


        endpoint: 5 - Digital Display Audio (AMD High Definition Audio Device)
        description: 5 - Digital Display Audio
        type: Hdmi Interface
        data flow: Render
        form_factor: Digital Audio Display Device
        full_range_speakers: 0
        guid: {7F5F84C4-1BC3-4616-8F44-BDBE11173E1C}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: 5 - Digital Display Audio
        connector_subtype: HDMI Interface
        connector_location: On separate chassis, HDMI
        connector_style: HDMI
        presence_detection: True
        connector_color: (0, 0, 0, 255)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: None


        endpoint: 6 - Digital Display Audio (AMD High Definition Audio Device)
        description: 6 - Digital Display Audio
        type: Hdmi Interface
        data flow: Render
        form_factor: Digital Audio Display Device
        full_range_speakers: 0
        guid: {B4BB93B7-BD50-40E5-B268-3DDEE272FCDF}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: 6 - Digital Display Audio
        connector_subtype: HDMI Interface
        connector_location: On separate chassis, HDMI
        connector_style: HDMI
        presence_detection: True
        connector_color: (0, 0, 0, 255)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: None


        endpoint: 4 - Digital Display Audio (AMD High Definition Audio Device)
        description: 4 - Digital Display Audio
        type: Hdmi Interface
        data flow: Render
        form_factor: Digital Audio Display Device
        full_range_speakers: 0
        guid: {C2828656-5AB2-4BF9-A723-622F3A3E767A}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: 4 - Digital Display Audio
        connector_subtype: HDMI Interface
        connector_location: On separate chassis, HDMI
        connector_style: HDMI
        presence_detection: True
        connector_color: (0, 0, 0, 255)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: None


        endpoint: Internal AUX Jack (AMD High Definition Audio Device)
        description: Internal AUX Jack
        type: Unknown
        data flow: Capture
        form_factor: Unknown
        full_range_speakers: 0
        guid: {1521C3EA-9909-4CD6-A11C-F1076AEBC405}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: 
        connector_subtype: 
        connector_location: Unknown
        connector_style: Unknown
        presence_detection: False
        connector_color: (0, 0, 0, 0)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: None


        endpoint: Internal AUX Jack (AMD High Definition Audio Device)
        description: Internal AUX Jack
        type: Unknown
        data flow: Capture
        form_factor: Unknown
        full_range_speakers: 0
        guid: {1E069735-CD50-4328-BE32-E5A93CAA2075}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: 
        connector_subtype: 
        connector_location: Unknown
        connector_style: Unknown
        presence_detection: False
        connector_color: (0, 0, 0, 0)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: None


        endpoint: Internal AUX Jack (AMD High Definition Audio Device)
        description: Internal AUX Jack
        type: Unknown
        data flow: Capture
        form_factor: Unknown
        full_range_speakers: 0
        guid: {725CD6F0-C930-4613-830D-74143ED2F85E}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: 
        connector_subtype: 
        connector_location: Unknown
        connector_style: Unknown
        presence_detection: False
        connector_color: (0, 0, 0, 0)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: None


        endpoint: Internal AUX Jack (AMD High Definition Audio Device)
        description: Internal AUX Jack
        type: Unknown
        data flow: Capture
        form_factor: Unknown
        full_range_speakers: 0
        guid: {7321A5DB-D9C1-44C5-A593-2A36C932D7C0}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: 
        connector_subtype: 
        connector_location: Unknown
        connector_style: Unknown
        presence_detection: False
        connector_color: (0, 0, 0, 0)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: None


        endpoint: Internal AUX Jack (AMD High Definition Audio Device)
        description: Internal AUX Jack
        type: Unknown
        data flow: Capture
        form_factor: Unknown
        full_range_speakers: 0
        guid: {AF31A520-3C90-48C4-B67B-82BF42001B0E}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: 
        connector_subtype: 
        connector_location: Unknown
        connector_style: Unknown
        presence_detection: False
        connector_color: (0, 0, 0, 0)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: None


        endpoint: Internal AUX Jack (AMD High Definition Audio Device)
        description: Internal AUX Jack
        type: Unknown
        data flow: Capture
        form_factor: Unknown
        full_range_speakers: 0
        guid: {CC532439-97B7-467F-9E7F-31DBF5553779}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: 
        connector_subtype: 
        connector_location: Unknown
        connector_style: Unknown
        presence_detection: False
        connector_color: (0, 0, 0, 0)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: None


    connectors:
        name: 
        data flow: In
        type: Physical Internal
        connected: True
        connector type: Connector
        connector sub type: 

        name: 1 - Digital Display Audio
        data flow: Out
        type: Physical Internal
        connected: True
        connector type: Connector
        connector sub type: HDMI Interface

    subunits:
        name: Master Mute
        type: Subunit
        sub type: Mute

Realtek High Definition Audio
    endpoints:
        endpoint: Speakers (Realtek High Definition Audio)
        description: Speakers
        type: Speaker
        data flow: Render
        form_factor: Speakers
        full_range_speakers: 0
        guid: {2AA36ADF-25F2-4B1E-8C43-D15D464FF44E}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical External
        connector_name: Realtek HDA Primary output
        connector_subtype: Speaker
        connector_location: On primary chassis, Rear-mounted panel
        connector_style: 1/8"
        presence_detection: True
        connector_color: (0, 255, 0, 255)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: 66.89499616622925


        endpoint: Realtek Digital Output (Realtek High Definition Audio)
        description: Realtek Digital Output
        type: Spdif Interface
        data flow: Render
        form_factor: SPDIF
        full_range_speakers: 0
        guid: {44993944-1A71-45E5-960F-00B90D134431}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical External
        connector_name: Realtek Digital Output
        connector_subtype: SPDIF Interface
        connector_location: On primary chassis, ATAPI
        connector_style: ATAPI Internal
        presence_detection: False
        connector_color: (0, 0, 0, 255)
        is_connected: True
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: 42.9999977350235


        endpoint: Realtek Digital Output(Optical) (Realtek High Definition Audio)
        description: Realtek Digital Output(Optical)
        type: Spdif Interface
        data flow: Render
        form_factor: SPDIF
        full_range_speakers: 0
        guid: {633AADA6-C313-4300-9315-0393D2FAFC93}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical External
        connector_name: Realtek Digital Output(Optical)
        connector_subtype: SPDIF Interface
        connector_location: On primary chassis, Rear-mounted panel
        connector_style: Optical
        presence_detection: False
        connector_color: (255, 128, 0, 255)
        is_connected: True
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: 100.0


        endpoint: Realtek HD Audio 2nd output (Realtek High Definition Audio)
        description: Realtek HD Audio 2nd output
        type: Headphones
        data flow: Render
        form_factor: Headphones
        full_range_speakers: 0
        guid: {B7A2A829-AFAC-4CB9-B6B8-17ABC6F75925}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical External
        connector_name: Realtek HD Audio 2nd output
        connector_subtype: Headphones
        connector_location: On primary chassis, Front-mounted panel
        connector_style: 1/8"
        presence_detection: True
        connector_color: (0, 255, 0, 255)
        is_connected: True
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: 87.00000047683716


        endpoint: Mic in at front panel (Pink) (Realtek High Definition Audio)
        description: Mic in at front panel (Pink)
        type: Microphone
        data flow: Capture
        form_factor: Microphone
        full_range_speakers: 0
        guid: {0D69CB84-3520-4D0A-A5D0-A1D901FF09D2}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical External
        connector_name: Mic in at front panel (Pink)
        connector_subtype: Microphone
        connector_location: On primary chassis, Front-mounted panel
        connector_style: 1/8"
        presence_detection: True
        connector_color: (255, 128, 192, 255)
        is_connected: True
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: 6.769580394029617


        endpoint: Line In (Realtek High Definition Audio)
        description: Line In
        type: Line Connector
        data flow: Capture
        form_factor: Line Level
        full_range_speakers: 0
        guid: {22F7266B-FFC0-4653-A165-76DCDF8359D1}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical External
        connector_name: Line In
        connector_subtype: Line Connector
        connector_location: Unknown
        connector_style: Unknown
        presence_detection: False
        connector_color: (0, 0, 0, 0)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: 100.0


        endpoint: Subwoofer (Realtek High Definition Audio)
        description: Subwoofer
        type: Analog Connector
        data flow: Capture
        form_factor: Unknown
        full_range_speakers: 0
        guid: {3447F788-A092-4A04-9C67-B294068EB874}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: Subwoofer
        connector_subtype: Analog Connector
        connector_location: Unknown
        connector_style: Unknown
        presence_detection: False
        connector_color: (0, 0, 0, 0)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: 100.0


        endpoint: Center (Realtek High Definition Audio)
        description: Center
        type: Analog Connector
        data flow: Capture
        form_factor: Unknown
        full_range_speakers: 0
        guid: {371BF61D-28E3-4F6A-8A59-B36E1D9E3C55}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: Center
        connector_subtype: Analog Connector
        connector_location: Unknown
        connector_style: Unknown
        presence_detection: False
        connector_color: (0, 0, 0, 0)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: 100.0


        endpoint: Microphone (Realtek High Definition Audio)
        description: Microphone
        type: Microphone
        data flow: Capture
        form_factor: Microphone
        full_range_speakers: 0
        guid: {4AD4464D-204C-4C6F-AAEA-6C1E159E54C6}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical External
        connector_name: Microphone
        connector_subtype: Microphone
        connector_location: Unknown
        connector_style: Unknown
        presence_detection: False
        connector_color: (0, 0, 0, 0)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: 100.0


        endpoint: Line in at rear panel (Blue) (Realtek High Definition Audio)
        description: Line in at rear panel (Blue)
        type: Line Connector
        data flow: Capture
        form_factor: Line Level
        full_range_speakers: 0
        guid: {4DC4A388-4F21-4B8E-9789-A061E95181BA}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical External
        connector_name: Line in at rear panel (Blue)
        connector_subtype: Line Connector
        connector_location: On primary chassis, Rear-mounted panel
        connector_style: 1/8"
        presence_detection: True
        connector_color: (0, 0, 255, 255)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: 22.01419025659561


        endpoint: Front Pink In (Realtek High Definition Audio)
        description: Front Pink In
        type: Analog Connector
        data flow: Capture
        form_factor: Unknown
        full_range_speakers: 0
        guid: {5B997D39-E938-4DE2-A432-CC8A4028D153}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: Front Pink In
        connector_subtype: Analog Connector
        connector_location: Unknown
        connector_style: Unknown
        presence_detection: False
        connector_color: (255, 128, 192, 255)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: 100.0


        endpoint: Line in at front panel (Green) (Realtek High Definition Audio)
        description: Line in at front panel (Green)
        type: Line Connector
        data flow: Capture
        form_factor: Line Level
        full_range_speakers: 0
        guid: {7D9EE5B7-134F-4B04-B15D-181C8C10C2E1}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical External
        connector_name: Line in at front panel (Green)
        connector_subtype: Line Connector
        connector_location: On primary chassis, Front-mounted panel
        connector_style: 1/8"
        presence_detection: True
        connector_color: (0, 255, 0, 255)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: 22.01419025659561


        endpoint: Mic in at rear panel (Pink) (Realtek High Definition Audio)
        description: Mic in at rear panel (Pink)
        type: Microphone
        data flow: Capture
        form_factor: Microphone
        full_range_speakers: 0
        guid: {A59B0AAB-CEA8-4FFF-B1B6-C62666202850}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical External
        connector_name: Mic in at rear panel (Pink)
        connector_subtype: Microphone
        connector_location: On primary chassis, Rear-mounted panel
        connector_style: 1/8"
        presence_detection: True
        connector_color: (255, 128, 192, 255)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: 6.769580394029617


        endpoint: Front Green In (Realtek High Definition Audio)
        description: Front Green In
        type: Analog Connector
        data flow: Capture
        form_factor: Unknown
        full_range_speakers: 0
        guid: {AFE8A438-E24E-45D9-8CDE-C3B459E6CC5A}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: Front Green In
        connector_subtype: Analog Connector
        connector_location: Unknown
        connector_style: Unknown
        presence_detection: False
        connector_color: (0, 255, 0, 255)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: 100.0


        endpoint: Rear (Realtek High Definition Audio)
        description: Rear
        type: Analog Connector
        data flow: Capture
        form_factor: Unknown
        full_range_speakers: 0
        guid: {BB68BA88-2E93-4867-AB8B-8C69AD036E7D}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: Rear
        connector_subtype: Analog Connector
        connector_location: Unknown
        connector_style: Unknown
        presence_detection: False
        connector_color: (0, 0, 0, 0)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: 100.0


        endpoint: Front (Realtek High Definition Audio)
        description: Front
        type: Analog Connector
        data flow: Capture
        form_factor: Unknown
        full_range_speakers: 0
        guid: {D121F5F6-DA5C-4D78-9FF0-BDA29FFD9280}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: Front
        connector_subtype: Analog Connector
        connector_location: Unknown
        connector_style: Unknown
        presence_detection: False
        connector_color: (0, 0, 0, 0)
        is_connected: False
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: 100.0


        endpoint: Stereo Mix (Realtek High Definition Audio)
        description: Stereo Mix
        type: Analog Connector
        data flow: Capture
        form_factor: Unknown
        full_range_speakers: 0
        guid: {F88AEA7C-4ABC-4E08-8F78-BB22D19EB59C}
        physical_speakers: 0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical Internal
        connector_name: Stereo Mix
        connector_subtype: Analog Connector
        connector_location: On primary chassis
        connector_style: Unknown
        presence_detection: False
        connector_color: (0, 0, 0, 255)
        is_connected: True
        auto_gain_control: None
        bass: None
        channel_config: None
        input: None
        loudness: None
        midrange: None
        output: None
        treble: None
        volume: 22.01419025659561


    connectors:
        name: 
        data flow: In
        type: Software Fixed
        connected: True
        connector type: Connector
        connector sub type: 

        name: Realtek HDA Primary output
        data flow: Out
        type: Physical External
        connected: True
        connector type: Connector
        connector sub type: Speaker

        name: Microphone
        data flow: In
        type: Physical External
        connected: True
        connector type: Connector
        connector sub type: Microphone

        name: Front Pink In
        data flow: In
        type: Physical Internal
        connected: True
        connector type: Connector
        connector sub type: Analog Connector

        name: Line In
        data flow: In
        type: Physical External
        connected: True
        connector type: Connector
        connector sub type: Line Connector

        name: Front Green In
        data flow: In
        type: Physical Internal
        connected: True
        connector type: Connector
        connector sub type: Analog Connector

        name: Center
        data flow: In
        type: Physical Internal
        connected: True
        connector type: Connector
        connector sub type: Analog Connector

        name: Subwoofer
        data flow: In
        type: Physical Internal
        connected: True
        connector type: Connector
        connector sub type: Analog Connector

        name: Rear
        data flow: In
        type: Physical Internal
        connected: True
        connector type: Connector
        connector sub type: Analog Connector

        name: Front
        data flow: In
        type: Physical Internal
        connected: True
        connector type: Connector
        connector sub type: Analog Connector

    subunits:
        name: Speakers
        type: Subunit
        sub type: Volume

        name: Master Mute
        type: Subunit
        sub type: Mute

        name: Sum
        type: Subunit
        sub type: Sum

        name: Mute
        type: Subunit
        sub type: Mute

        name: Microphone
        type: Subunit
        sub type: Volume

        name: Mute
        type: Subunit
        sub type: Mute

        name: Front Pink In
        type: Subunit
        sub type: Volume

        name: Mute
        type: Subunit
        sub type: Mute

        name: Line In
        type: Subunit
        sub type: Volume

        name: Mute
        type: Subunit
        sub type: Mute

        name: Front Green In
        type: Subunit
        sub type: Volume

        name: Center
        type: Subunit
        sub type: Volume

        name: Subwoofer
        type: Subunit
        sub type: Volume

        name: Rear
        type: Subunit
        sub type: Volume

        name: Front
        type: Subunit
        sub type: Volume

@kdschlosser
Copy link
Owner

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.

@askruga
Copy link
Author

askruga commented Oct 26, 2021

@kdschlosser
So cool!! Thanks for u lib again!
I've been see into your library for 2 weeks now and have some progress. Now i can take all active(i mean sate) capture and render endpoints, switch it, set volume e.c.t. And i can set volume/mute for each session :)

Thanks for you answer!
I'm really looking forward to adaptation for py3

@kdschlosser
Copy link
Owner

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)

@kdschlosser
Copy link
Owner

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.

KSPROPERTY_AUDIO_LATENCY
KSPROPERTY_AUDIO_COPY_PROTECTION
KSPROPERTY_AUDIO_CHANNEL_CONFIG
KSPROPERTY_AUDIO_VOLUMELEVEL
KSPROPERTY_AUDIO_POSITION
KSPROPERTY_AUDIO_DYNAMIC_RANGE
KSPROPERTY_AUDIO_QUALITY
KSPROPERTY_AUDIO_SAMPLING_RATE
KSPROPERTY_AUDIO_DYNAMIC_SAMPLING_RATE
KSPROPERTY_AUDIO_MIX_LEVEL_TABLE
KSPROPERTY_AUDIO_MIX_LEVEL_CAPS
KSPROPERTY_AUDIO_MUX_SOURCE
KSPROPERTY_AUDIO_MUTE
KSPROPERTY_AUDIO_BASS
KSPROPERTY_AUDIO_MID
KSPROPERTY_AUDIO_TREBLE
KSPROPERTY_AUDIO_BASS_BOOST
KSPROPERTY_AUDIO_EQ_LEVEL
KSPROPERTY_AUDIO_NUM_EQ_BANDS
KSPROPERTY_AUDIO_EQ_BANDS
KSPROPERTY_AUDIO_AGC
KSPROPERTY_AUDIO_DELAY
KSPROPERTY_AUDIO_LOUDNESS
KSPROPERTY_AUDIO_WIDE_MODE
KSPROPERTY_AUDIO_WIDENESS
KSPROPERTY_AUDIO_REVERB_LEVEL
KSPROPERTY_AUDIO_CHORUS_LEVEL
KSPROPERTY_AUDIO_DEV_SPECIFIC
KSPROPERTY_AUDIO_DEMUX_DEST
KSPROPERTY_AUDIO_STEREO_ENHANCE
KSPROPERTY_AUDIO_MANUFACTURE_GUID
KSPROPERTY_AUDIO_PRODUCT_GUID
KSPROPERTY_AUDIO_CPU_RESOURCES
KSPROPERTY_AUDIO_STEREO_SPEAKER_GEOMETRY
KSPROPERTY_AUDIO_SURROUND_ENCODE
KSPROPERTY_AUDIO_3D_INTERFACE


if >= WINXP:
    KSPROPERTY_AUDIO_PEAKMETER
    KSPROPERTY_AUDIO_ALGORITHM_INSTANCE
    KSPROPERTY_AUDIO_FILTER_STATE
    KSPROPERTY_AUDIO_PREFERRED_STATUS

if >= VISTA:
    KSPROPERTY_AUDIO_PEQ_MAX_BANDS
    KSPROPERTY_AUDIO_PEQ_NUM_BANDS
    KSPROPERTY_AUDIO_PEQ_BAND_CENTER_FREQ
    KSPROPERTY_AUDIO_PEQ_BAND_Q_FACTOR
    KSPROPERTY_AUDIO_PEQ_BAND_LEVEL
    KSPROPERTY_AUDIO_CHORUS_MODULATION_RATE
    KSPROPERTY_AUDIO_CHORUS_MODULATION_DEPTH
    KSPROPERTY_AUDIO_REVERB_TIME
    KSPROPERTY_AUDIO_REVERB_DELAY_FEEDBACK
    KSPROPERTY_AUDIO_POSITIONEX
    KSPROPERTY_AUDIO_MIC_ARRAY_GEOMETRY

if >= WIN8:
    KSPROPERTY_AUDIO_PRESENTATION_POSITION
    KSPROPERTY_AUDIO_WAVERT_CURRENT_WRITE_POSITION
    KSPROPERTY_AUDIO_LINEAR_BUFFER_POSITION
    KSPROPERTY_AUDIO_PEAKMETER2

if >= WINBLUE:
    KSPROPERTY_AUDIO_WAVERT_CURRENT_WRITE_LASTBUFFER_POSITION
    KSPROPERTY_AUDIO_VOLUMELIMIT_ENGAGED

if >= WIN10_RS1:
    KSPROPERTY_AUDIO_MIC_SENSITIVITY
    KSPROPERTY_AUDIO_MIC_SNR

if >= WIN10_RS4:
    KSPROPERTY_AUDIO_MIC_SENSITIVITY2

@kdschlosser
Copy link
Owner

It's won't be too much longer until I am am ready to have the code tested.

@kdschlosser
Copy link
Owner

you can view the changes I have made so far on the develop branch
https://github.com/kdschlosser/pyWinCoreAudio/tree/develop

@kdschlosser
Copy link
Owner

OK I have a version that is functional. it is in the develop branch. You can install it using

pip install https://github.com/kdschlosser/pyWinCoreAudio/tarball/develop

There is an example.py file in the develop branch that you can use as a guide.

when you make the call to pyWinCoreAudio.devices() here is going to be a notice that gets printed out. This notice is extremely important so please read it. It will keep your program stable by following the directions in it. If you do not follow the directions you can potentially have a memory leak or end up with an app crash. If you do not want the notice to appear pass False in the call to pyWinCoreAudio.devices()

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 globals() so you have to make sure that it gets deleted at the end of each iteration.

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 ON_DEVICE_ADDED and ON_DEVICE_REMOVED. You cannot pass a device object when registering a callback for those 2 signals. If the signal name has "ENDPOINT" in the name you can pass a device object when registering. This will enable getting notifications for all endpoints attached to that device. You can also target a specific endpoint by passing both the device object and an endpoint that belongs to that device. If you do that you will get notifications only for that endpoint. If "SESSION" is in the name for the signal you can pass device, device and endpoint or device, endpoint and session. If "INTERFACE" is in the same you can pass device, device and endpoint or device, endpoint and interface.

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.
https://github.com/kdschlosser/pyWinCoreAudio/tree/develop

@danielbibit
Copy link

danielbibit commented Mar 30, 2022

Hi, sorry if I missed something, but I'm running the example code from your develop branch, and I still can't figure out how to achive this:

Can anyone give some suggest or couple-string-example how:

  • Switch default device, i mean "Speakers" to "Headphones" and how i can get event callbacks for it?

I've managed to filter the devices and endpoints that I'm interested in:

AMD High Definition Audio Device
    endpoints:
        endpoint: 1 - DELL P2418HT (AMD High Definition Audio Device)
        description: 1 - DELL P2418HT
        type: Unknown
        data flow: Render
        form_factor: Digital Audio Display Device
        full_range_speakers: 0
        guid: {4EFCDC5E-1A0D-425B-A4C2-86C386D21970}
        physical_speakers: 2.0
        system_effects: False
        hdcp_capable: True
        ai_capable: False
        connector_type: Physical External
        connector_name:
        connector_subtype: HDMI Interface
        connector_location: On separate chassis, HDMI
        connector_style: HDMI
        presence_detection: True
        connector_color: (0, 0, 0, 255)
        is_connected: True
        channel_config: 2.0
        input: None
        output: None
        audio_channels: [<pyWinCoreAudio.mmdeviceapi.AudioChannel object at 0x000001D0571B17F0>, <pyWinCoreAudio.mmdeviceapi.AudioChannel object at 0x000001D0571B1310>]


        endpoint: 6 - LG TV (AMD High Definition Audio Device)
        description: 6 - LG TV
        type: Unknown
        data flow: Render
        form_factor: Digital Audio Display Device
        full_range_speakers: 0
        guid: {8A336AE5-279B-4DE1-803C-8F98D662A090}
        physical_speakers: 2.0
        system_effects: False
        hdcp_capable: True
        ai_capable: True
        connector_type: Physical External
        connector_name:
        connector_subtype: HDMI Interface
        connector_location: On separate chassis, HDMI
        connector_style: HDMI
        presence_detection: True
        connector_color: (0, 0, 0, 255)
        is_connected: True
        channel_config: 2.0
        input: None
        output: None
        audio_channels: [<pyWinCoreAudio.mmdeviceapi.AudioChannel object at 0x000001D0571B1B20>, <pyWinCoreAudio.mmdeviceapi.AudioChannel object at 0x000001D0571B10A0>]


Realtek High Definition Audio
    endpoints:
        endpoint: Speakers (Realtek High Definition Audio)
        description: Speakers
        type: Unknown
        data flow: Render
        form_factor: Speakers
        full_range_speakers: 2.0
        guid: {6315A238-B914-4369-B086-7FCD1654E714}
        physical_speakers: 2.0
        system_effects: False
        hdcp_capable: False
        ai_capable: False
        connector_type: Physical External
        connector_name: Realtek HD Audio output
        connector_subtype: Speaker
        connector_location: On primary chassis, Rear-mounted panel
        connector_style: 1/8"
        presence_detection: True
        connector_color: (0, 255, 0, 255)
        is_connected: True
        channel_config: 2.0
        input: None
        output: None
        audio_channels: [<pyWinCoreAudio.mmdeviceapi.AudioChannel object at 0x000001D0571B1F40>, <pyWinCoreAudio.mmdeviceapi.AudioChannel object at 0x000001D0571B1280>]

And I can get the events for what I'm looking for, no problems.

OnPropertyValueChanged
Default changed: AMD High Definition Audio Device.6 - LG TV (AMD High Definition Audio Device) role: Multimedia flow: Render
Default changed: AMD High Definition Audio Device.6 - LG TV (AMD High Definition Audio Device) role: Console flow: Render
Default changed: AMD High Definition Audio Device.6 - LG TV (AMD High Definition Audio Device) role: Communications flow: Render
OnPropertyValueChanged
Default changed: Realtek High Definition Audio.Speakers (Realtek High Definition Audio) role: Multimedia flow: Render
Default changed: Realtek High Definition Audio.Speakers (Realtek High Definition Audio) role: Console flow: Render
Default changed: Realtek High Definition Audio.Speakers (Realtek High Definition Audio) role: Communications flow: Render
OnPropertyValueChanged
Default changed: AMD High Definition Audio Device.1 - DELL P2418HT (AMD High Definition Audio Device) role: Multimedia flow: Render
Default changed: AMD High Definition Audio Device.1 - DELL P2418HT (AMD High Definition Audio Device) role: Console flow: Render
Default changed: AMD High Definition Audio Device.1 - DELL P2418HT (AMD High Definition Audio Device) role: Communications flow: Render

But my goal is to switch the default output device like so:
image

This is the first time that I'm messing with a windows API, so any pointers will be appreciated.

Also, thank you for your work!

@danielbibit
Copy link

But my goal is to switch the default output device like so:

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.

@kdschlosser
Copy link
Owner

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants