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

Control Microphone / Inputs, too? #50

Open
McNugget6750 opened this issue Nov 10, 2021 · 7 comments
Open

Control Microphone / Inputs, too? #50

McNugget6750 opened this issue Nov 10, 2021 · 7 comments

Comments

@McNugget6750
Copy link

Is there a way to control the input volumes for microphone (and line) as well as mute these?
So far I have only found tools for setting the output volumes of things.

@drp0
Copy link

drp0 commented Nov 28, 2021

Try this:

from __future__ import print_function
from ctypes import POINTER, cast
import comtypes
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume, CLSID_MMDeviceEnumerator, IMMDeviceEnumerator, EDataFlow, ERole, DEVICE_STATE

# audioVol4
# D.R.Patterson, 28/11/2021
# Get and set the volume of any audio device
# Specify device type using "in" / "out"
# Specify device state using DEVICE_STATE enumeration
# Volume expressed in percentages.

# For the basis of this code: akaufman1, https://github.com/AndreMiras/pycaw/issues/8
# For pointing the way with SetMasterVolumeLevelScalar: Roy Joseph Argumido, https://github.com/AndreMiras/pycaw/issues/13

class MyAudioUtilities(AudioUtilities):
    @staticmethod
    def GetDevice(id=None, default=0):
        device_enumerator = comtypes.CoCreateInstance(
            CLSID_MMDeviceEnumerator,
            IMMDeviceEnumerator,
            comtypes.CLSCTX_INPROC_SERVER)
        if id is not None:
            thisDevice = device_enumerator.GetDevice(id)
        else:
            if default == 0:
                # output
                thisDevice = device_enumerator.GetDefaultAudioEndpoint(EDataFlow.eRender.value, ERole.eMultimedia.value)
            else:
                # input
                thisDevice = device_enumerator.GetDefaultAudioEndpoint(EDataFlow.eCapture.value, ERole.eMultimedia.value)
        return thisDevice

    @staticmethod
    def MyGetAudioDevices(direction="in", State = DEVICE_STATE.ACTIVE.value):
        devices = []
        # for all use EDataFlow.eAll.value
        if direction == "in":
            Flow = EDataFlow.eCapture.value     # 1
        else:
            Flow = EDataFlow.eRender.value      # 0
        
        deviceEnumerator = comtypes.CoCreateInstance(
            CLSID_MMDeviceEnumerator,
            IMMDeviceEnumerator,
            comtypes.CLSCTX_INPROC_SERVER)
        if deviceEnumerator is None:
            return devices
        

        collection = deviceEnumerator.EnumAudioEndpoints(Flow, State)
        if collection is None:
            return devices

        count = collection.GetCount()
        for i in range(count):
            dev = collection.Item(i)
            if dev is not None:
                if not ": None" in str(AudioUtilities.CreateDevice(dev)):
                    devices.append(AudioUtilities.CreateDevice(dev))
        return devices
    
def main():
    direction = input("Input or output devices (in / out) ")
    direction = direction.lower()
    if direction != "in" and direction != "out": direction = "in"
    # DEVICE_STATE pycaw library defines:
    #   ACTIVE = 0x00000001
    #   DISABLED = 0x00000002
    #   NOTPRESENT = 0x00000004
    #   UNPLUGGED = 0x00000008
    #   MASK_ALL = 0x0000000F
    states = []                                 # Copy states
    names = []                                  # copy state names
    state = 0
    I = 0
    for val in DEVICE_STATE:
        print("Ref " + str(I) + ": " + val.name)
        states.append(val.value)
        names.append(val.name)
        I += 1
    ref = -1
    while (ref < 0) or (ref >= I):
        ref = int(input("Enter Ref 0 to " + str(I-1) +" for required state "))
    state = states[ref]
    print("Selected " + names[ref] + ", mask value: " + str(state))
    print()
    
    mixer_output = None
    tmp = None
    #devicelist = MyAudioUtilities.GetAllDevices()
    devicelist = MyAudioUtilities.MyGetAudioDevices(direction, state)
    i = 0
    for device in devicelist:
        print(i, device)
        i += 1

    if direction == "in":
        print(i, "Default Input")
    else:
        print(i, "Default Output")
    i += 1

    deviceSel = i
    
    while (deviceSel >= i) or (deviceSel < 0):
        print()
        search = input("Which device 0 to " + str(i-1) + ": ")
        deviceSel = int(search)
    
    if deviceSel < i-1:                         # use specific audio device
        mixer_output = devicelist[int(search)]
        print(mixer_output)
        tmp = mixer_output.id
        devices = MyAudioUtilities.GetDevice(tmp)

    else:

        if direction == "in":                   # use default audio device
            print("Default Input")
            devices = MyAudioUtilities.GetDevice(tmp, 1)   # default input
        else:    
            print("Default Output")
            devices = MyAudioUtilities.GetDevice(tmp, 0)   # default output

    print()

    # NB if names[ref] = "DISABLED" or "NOTPRESENT" 0r "UNPLUGGED"
    # Setting the volume will not work!
    try:
        interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
        volume = cast(interface, POINTER(IAudioEndpointVolume))
        
        print("GetMute(): ", volume.GetMute())      # set using volume.SetMute(1, None)
        print("GetMasterVolumeLevelScalar(): %s" % int(0.5 + 100.0 * volume.GetMasterVolumeLevelScalar()))
        print("GetVolumeRange(): (%s, %s, %s)" % volume.GetVolumeRange())

        newLevel = input("Enter new level (Ctrl C to quit): ")

        intnewLevel = int(newLevel.replace('%', ''))
        if intnewLevel < 0:  intnewLevel = 0.0
        if intnewLevel > 100: intnewLevel = 100.0
        print("SetMasterVolumeLevelScalar", intnewLevel / 100.0)
        volume.SetMasterVolumeLevelScalar(intnewLevel / 100.0, None)
        print("GetMasterVolumeLevelScalar(): %s" % int(0.5 + 100.0 * volume.GetMasterVolumeLevelScalar()))
    except:
        print("Error selecting interface volume.: device: " + names[ref])

if __name__ == "__main__":
    try:
        while True:
            main()
            print()
    except KeyboardInterrupt:
        print()

David

@gitagogaming
Copy link

Try this:

from __future__ import print_function
from ctypes import POINTER, cast
import comtypes
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume, CLSID_MMDeviceEnumerator, IMMDeviceEnumerator, EDataFlow, ERole, DEVICE_STATE

# audioVol4
# D.R.Patterson, 28/11/2021
# Get and set the volume of any audio device
# Specify device type using "in" / "out"
# Specify device state using DEVICE_STATE enumeration
# Volume expressed in percentages.

# For the basis of this code: akaufman1, https://github.com/AndreMiras/pycaw/issues/8
# For pointing the way with SetMasterVolumeLevelScalar: Roy Joseph Argumido, https://github.com/AndreMiras/pycaw/issues/13

class MyAudioUtilities(AudioUtilities):
    @staticmethod
    def GetDevice(id=None, default=0):
        device_enumerator = comtypes.CoCreateInstance(
            CLSID_MMDeviceEnumerator,
            IMMDeviceEnumerator,
            comtypes.CLSCTX_INPROC_SERVER)
        if id is not None:
            thisDevice = device_enumerator.GetDevice(id)
        else:
            if default == 0:
                # output
                thisDevice = device_enumerator.GetDefaultAudioEndpoint(EDataFlow.eRender.value, ERole.eMultimedia.value)
            else:
                # input
                thisDevice = device_enumerator.GetDefaultAudioEndpoint(EDataFlow.eCapture.value, ERole.eMultimedia.value)
        return thisDevice

    @staticmethod
    def MyGetAudioDevices(direction="in", State = DEVICE_STATE.ACTIVE.value):
        devices = []
        # for all use EDataFlow.eAll.value
        if direction == "in":
            Flow = EDataFlow.eCapture.value     # 1
        else:
            Flow = EDataFlow.eRender.value      # 0
        
        deviceEnumerator = comtypes.CoCreateInstance(
            CLSID_MMDeviceEnumerator,
            IMMDeviceEnumerator,
            comtypes.CLSCTX_INPROC_SERVER)
        if deviceEnumerator is None:
            return devices
        

        collection = deviceEnumerator.EnumAudioEndpoints(Flow, State)
        if collection is None:
            return devices

        count = collection.GetCount()
        for i in range(count):
            dev = collection.Item(i)
            if dev is not None:
                if not ": None" in str(AudioUtilities.CreateDevice(dev)):
                    devices.append(AudioUtilities.CreateDevice(dev))
        return devices
    
def main():
    direction = input("Input or output devices (in / out) ")
    direction = direction.lower()
    if direction != "in" and direction != "out": direction = "in"
    # DEVICE_STATE pycaw library defines:
    #   ACTIVE = 0x00000001
    #   DISABLED = 0x00000002
    #   NOTPRESENT = 0x00000004
    #   UNPLUGGED = 0x00000008
    #   MASK_ALL = 0x0000000F
    states = []                                 # Copy states
    names = []                                  # copy state names
    state = 0
    I = 0
    for val in DEVICE_STATE:
        print("Ref " + str(I) + ": " + val.name)
        states.append(val.value)
        names.append(val.name)
        I += 1
    ref = -1
    while (ref < 0) or (ref >= I):
        ref = int(input("Enter Ref 0 to " + str(I-1) +" for required state "))
    state = states[ref]
    print("Selected " + names[ref] + ", mask value: " + str(state))
    print()
    
    mixer_output = None
    tmp = None
    #devicelist = MyAudioUtilities.GetAllDevices()
    devicelist = MyAudioUtilities.MyGetAudioDevices(direction, state)
    i = 0
    for device in devicelist:
        print(i, device)
        i += 1

    if direction == "in":
        print(i, "Default Input")
    else:
        print(i, "Default Output")
    i += 1

    deviceSel = i
    
    while (deviceSel >= i) or (deviceSel < 0):
        print()
        search = input("Which device 0 to " + str(i-1) + ": ")
        deviceSel = int(search)
    
    if deviceSel < i-1:                         # use specific audio device
        mixer_output = devicelist[int(search)]
        print(mixer_output)
        tmp = mixer_output.id
        devices = MyAudioUtilities.GetDevice(tmp)

    else:

        if direction == "in":                   # use default audio device
            print("Default Input")
            devices = MyAudioUtilities.GetDevice(tmp, 1)   # default input
        else:    
            print("Default Output")
            devices = MyAudioUtilities.GetDevice(tmp, 0)   # default output

    print()

    # NB if names[ref] = "DISABLED" or "NOTPRESENT" 0r "UNPLUGGED"
    # Setting the volume will not work!
    try:
        interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
        volume = cast(interface, POINTER(IAudioEndpointVolume))
        
        print("GetMute(): ", volume.GetMute())      # set using volume.SetMute(1, None)
        print("GetMasterVolumeLevelScalar(): %s" % int(0.5 + 100.0 * volume.GetMasterVolumeLevelScalar()))
        print("GetVolumeRange(): (%s, %s, %s)" % volume.GetVolumeRange())

        newLevel = input("Enter new level (Ctrl C to quit): ")

        intnewLevel = int(newLevel.replace('%', ''))
        if intnewLevel < 0:  intnewLevel = 0.0
        if intnewLevel > 100: intnewLevel = 100.0
        print("SetMasterVolumeLevelScalar", intnewLevel / 100.0)
        volume.SetMasterVolumeLevelScalar(intnewLevel / 100.0, None)
        print("GetMasterVolumeLevelScalar(): %s" % int(0.5 + 100.0 * volume.GetMasterVolumeLevelScalar()))
    except:
        print("Error selecting interface volume.: device: " + names[ref])

if __name__ == "__main__":
    try:
        while True:
            main()
            print()
    except KeyboardInterrupt:
        print()

David

Was trying to get microphone mute state today and came across this but also had an error when trying

ImportError: cannot import name 'CLSID_MMDeviceEnumerator' from 'pycaw.pycaw' - was wondering how i might resolve this as I have the mostrecent version of the module

@drp0
Copy link

drp0 commented Feb 25, 2022

Hi gitagogaming,
I have just re-tested my code without issue.
pip list gives my pycaw version as 20181226
David

@drp0
Copy link

drp0 commented Feb 25, 2022

gitagogaming,
I am using python 3.91
If you get past the import issue I suggest looking at the pycaw.py edit detailed at #53
You might want to try the amendment.
David

@cdwcgt
Copy link

cdwcgt commented Mar 20, 2023

- from pycaw.pycaw import CLSID_MMDeviceEnumerator
+ from pycaw.constants import CLSID_MMDeviceEnumerator

@Gloryness
Copy link

This is so helpful because windows 11 keeps auto adjusting my microphone's input volume and I've already followed tutorials to stop it from happening but none work. So now I'm just gonna have a python script running 24/7 to keep setting my microphone to the volume I want it to be on.

@hilmiguner
Copy link

Try this:

from __future__ import print_function
from ctypes import POINTER, cast
import comtypes
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume, CLSID_MMDeviceEnumerator, IMMDeviceEnumerator, EDataFlow, ERole, DEVICE_STATE

# audioVol4
# D.R.Patterson, 28/11/2021
# Get and set the volume of any audio device
# Specify device type using "in" / "out"
# Specify device state using DEVICE_STATE enumeration
# Volume expressed in percentages.

# For the basis of this code: akaufman1, https://github.com/AndreMiras/pycaw/issues/8
# For pointing the way with SetMasterVolumeLevelScalar: Roy Joseph Argumido, https://github.com/AndreMiras/pycaw/issues/13

class MyAudioUtilities(AudioUtilities):
    @staticmethod
    def GetDevice(id=None, default=0):
        device_enumerator = comtypes.CoCreateInstance(
            CLSID_MMDeviceEnumerator,
            IMMDeviceEnumerator,
            comtypes.CLSCTX_INPROC_SERVER)
        if id is not None:
            thisDevice = device_enumerator.GetDevice(id)
        else:
            if default == 0:
                # output
                thisDevice = device_enumerator.GetDefaultAudioEndpoint(EDataFlow.eRender.value, ERole.eMultimedia.value)
            else:
                # input
                thisDevice = device_enumerator.GetDefaultAudioEndpoint(EDataFlow.eCapture.value, ERole.eMultimedia.value)
        return thisDevice

    @staticmethod
    def MyGetAudioDevices(direction="in", State = DEVICE_STATE.ACTIVE.value):
        devices = []
        # for all use EDataFlow.eAll.value
        if direction == "in":
            Flow = EDataFlow.eCapture.value     # 1
        else:
            Flow = EDataFlow.eRender.value      # 0
        
        deviceEnumerator = comtypes.CoCreateInstance(
            CLSID_MMDeviceEnumerator,
            IMMDeviceEnumerator,
            comtypes.CLSCTX_INPROC_SERVER)
        if deviceEnumerator is None:
            return devices
        

        collection = deviceEnumerator.EnumAudioEndpoints(Flow, State)
        if collection is None:
            return devices

        count = collection.GetCount()
        for i in range(count):
            dev = collection.Item(i)
            if dev is not None:
                if not ": None" in str(AudioUtilities.CreateDevice(dev)):
                    devices.append(AudioUtilities.CreateDevice(dev))
        return devices
    
def main():
    direction = input("Input or output devices (in / out) ")
    direction = direction.lower()
    if direction != "in" and direction != "out": direction = "in"
    # DEVICE_STATE pycaw library defines:
    #   ACTIVE = 0x00000001
    #   DISABLED = 0x00000002
    #   NOTPRESENT = 0x00000004
    #   UNPLUGGED = 0x00000008
    #   MASK_ALL = 0x0000000F
    states = []                                 # Copy states
    names = []                                  # copy state names
    state = 0
    I = 0
    for val in DEVICE_STATE:
        print("Ref " + str(I) + ": " + val.name)
        states.append(val.value)
        names.append(val.name)
        I += 1
    ref = -1
    while (ref < 0) or (ref >= I):
        ref = int(input("Enter Ref 0 to " + str(I-1) +" for required state "))
    state = states[ref]
    print("Selected " + names[ref] + ", mask value: " + str(state))
    print()
    
    mixer_output = None
    tmp = None
    #devicelist = MyAudioUtilities.GetAllDevices()
    devicelist = MyAudioUtilities.MyGetAudioDevices(direction, state)
    i = 0
    for device in devicelist:
        print(i, device)
        i += 1

    if direction == "in":
        print(i, "Default Input")
    else:
        print(i, "Default Output")
    i += 1

    deviceSel = i
    
    while (deviceSel >= i) or (deviceSel < 0):
        print()
        search = input("Which device 0 to " + str(i-1) + ": ")
        deviceSel = int(search)
    
    if deviceSel < i-1:                         # use specific audio device
        mixer_output = devicelist[int(search)]
        print(mixer_output)
        tmp = mixer_output.id
        devices = MyAudioUtilities.GetDevice(tmp)

    else:

        if direction == "in":                   # use default audio device
            print("Default Input")
            devices = MyAudioUtilities.GetDevice(tmp, 1)   # default input
        else:    
            print("Default Output")
            devices = MyAudioUtilities.GetDevice(tmp, 0)   # default output

    print()

    # NB if names[ref] = "DISABLED" or "NOTPRESENT" 0r "UNPLUGGED"
    # Setting the volume will not work!
    try:
        interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
        volume = cast(interface, POINTER(IAudioEndpointVolume))
        
        print("GetMute(): ", volume.GetMute())      # set using volume.SetMute(1, None)
        print("GetMasterVolumeLevelScalar(): %s" % int(0.5 + 100.0 * volume.GetMasterVolumeLevelScalar()))
        print("GetVolumeRange(): (%s, %s, %s)" % volume.GetVolumeRange())

        newLevel = input("Enter new level (Ctrl C to quit): ")

        intnewLevel = int(newLevel.replace('%', ''))
        if intnewLevel < 0:  intnewLevel = 0.0
        if intnewLevel > 100: intnewLevel = 100.0
        print("SetMasterVolumeLevelScalar", intnewLevel / 100.0)
        volume.SetMasterVolumeLevelScalar(intnewLevel / 100.0, None)
        print("GetMasterVolumeLevelScalar(): %s" % int(0.5 + 100.0 * volume.GetMasterVolumeLevelScalar()))
    except:
        print("Error selecting interface volume.: device: " + names[ref])

if __name__ == "__main__":
    try:
        while True:
            main()
            print()
    except KeyboardInterrupt:
        print()

David

You are the best man!!! I want to learn more about Windows Core Audio API for Python but in a more basic way than the original docs if its possible. Can you suggest me any source? If you can I will be very grateful!!

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

6 participants