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

pycaw.py fails at line 704: value = store.GetValue(pk) #53

Open
drp0 opened this issue Nov 25, 2021 · 0 comments
Open

pycaw.py fails at line 704: value = store.GetValue(pk) #53

drp0 opened this issue Nov 25, 2021 · 0 comments

Comments

@drp0
Copy link

drp0 commented Nov 25, 2021

I modified and adapted code from issues to produce a program to set / get any device volume.
I wrote it on my laptop, where it worked flawlessly. I tested it on my PC- with many audio devices- and it failed with the call to devicelist = MyAudioUtilities.GetAllDevices().
The error message clearly identifies a problem with line 704: value = store.GetValue(pk). This is the same error as detailed in this closed issue
I edited pycaw.py as recommended by Michael Farrell (micolous) in issue 15.
This work round allowed the program to reveal 67 audio devices and a bunch of other devices which had been causing issues with GetAllDevices().
It would be useful to make this change to the pycaw library!
I would recommend missing out the print statements in the except processing, unless people have nothing better to stare at.

Both machines have:
windows 11
Python 3.9.1
pycaw 20181226
comtypes 1.1.10
cmake 3.18.4.post1 (from python install)
enum34 1.1.10

My code:

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

# audioVol3
# D.R.Patterson, 23/11/2021
# Get and set the volume of any audio device
# Using 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


def main():
    mixer_output = None
    tmp = None
    devicelist = MyAudioUtilities.GetAllDevices()
    i = 0
    for device in devicelist:
        print(i, device)
        i += 1
    print(i, "Default Output")
    i += 1
    print(i, "Default Input")
    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-2:
        mixer_output = devicelist[int(search)]
        print(mixer_output)
        tmp = mixer_output.id
        devices = MyAudioUtilities.GetDevice(tmp)
    else:
        if deviceSel == i-2:
            print("Default Output")
            devices = MyAudioUtilities.GetDevice(tmp, 0)   # default output
        else:
            print("Default Input")
            devices = MyAudioUtilities.GetDevice(tmp, 1)   # default input
    print()
    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()))

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

pycaw.py solution from micolous:

           for j in range(propCount):
                pk = store.GetAt(j)
                try:
                    value = store.GetValue(pk)
                    v = value.GetValue()
                except:
                    # error getting property
                    print(f'Error getting device {id} property {pk}')
                    print('other properties:')
                    print(properties)
                    continue
                # TODO
                # PropVariantClear(byref(value))
                name = str(pk)
                properties[name] = v
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

1 participant