Re: [python-win32] Control Volume on Windows [SEC=UNCLASSIFIED]
Andrew MacIntyre wrote: Trevor Haba wrote: I'm looking for a way to use python to change the volume on windows. After some googling the best I could come up with was this script I got from a relatively ancient entry on this mailing list (I think it was from 2005 or something). I'm using windows 7, and I would like it to work on windows 8 if possible, though its not necessary. I don't need to support any previous versions of windows. To which Tim Roberts replied: Alas, the news is not good. I think that comtypes (https://pypi.python.org/pypi/comtypes) can deal with early binding interfaces? You are quite right, and the attached script does it. NOTE! that I have not correctly defined all of the IMM interfaces for the general case; I've only created enough of them to make this particular example work. On my Win 7 machine, this is able to fetch the default endpoint, display the volume range (from -65.25 to 0 in steps of 0.75) and change the setting. I'm glad you brought this up. I've never played with comtypes before, and this was a revealing exercise. -- Tim Roberts, t...@probo.com Providenza Boekelheide, Inc. import win32com from comtypes import * import comtypes.client from ctypes import POINTER from ctypes.wintypes import DWORD, BOOL MMDeviceApiLib = \ GUID('{2FDAAFA3-7523-4F66-9957-9D5E7FE698F6}') IID_IMMDevice = \ GUID('{D666063F-1587-4E43-81F1-B948E807363F}') IID_IMMDeviceEnumerator = \ GUID('{A95664D2-9614-4F35-A746-DE8DB63617E6}') CLSID_MMDeviceEnumerator = \ GUID('{BCDE0395-E52F-467C-8E3D-C4579291692E}') IID_IMMDeviceCollection = \ GUID('{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}') IID_IAudioEndpointVolume = \ GUID('{5CDF2C82-841E-4546-9722-0CF74078229A}') class IMMDeviceCollection(IUnknown): _iid_ = GUID('{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}') pass class IAudioEndpointVolume(IUnknown): _iid_ = GUID('{5CDF2C82-841E-4546-9722-0CF74078229A}') _methods_ = [ STDMETHOD(HRESULT, 'RegisterControlChangeNotify', []), STDMETHOD(HRESULT, 'UnregisterControlChangeNotify', []), STDMETHOD(HRESULT, 'GetChannelCount', []), COMMETHOD([], HRESULT, 'SetMasterVolumeLevel', (['in'], c_float, 'fLevelDB'), (['in'], POINTER(GUID), 'pguidEventContext') ), COMMETHOD([], HRESULT, 'SetMasterVolumeLevelScalar', (['in'], c_float, 'fLevelDB'), (['in'], POINTER(GUID), 'pguidEventContext') ), COMMETHOD([], HRESULT, 'GetMasterVolumeLevel', (['out','retval'], POINTER(c_float), 'pfLevelDB') ), COMMETHOD([], HRESULT, 'GetMasterVolumeLevelScalar', (['out','retval'], POINTER(c_float), 'pfLevelDB') ), COMMETHOD([], HRESULT, 'SetChannelVolumeLevel', (['in'], DWORD, 'nChannel'), (['in'], c_float, 'fLevelDB'), (['in'], POINTER(GUID), 'pguidEventContext') ), COMMETHOD([], HRESULT, 'SetChannelVolumeLevelScalar', (['in'], DWORD, 'nChannel'), (['in'], c_float, 'fLevelDB'), (['in'], POINTER(GUID), 'pguidEventContext') ), COMMETHOD([], HRESULT, 'GetChannelVolumeLevel', (['in'], DWORD, 'nChannel'), (['out','retval'], POINTER(c_float), 'pfLevelDB') ), COMMETHOD([], HRESULT, 'GetChannelVolumeLevelScalar', (['in'], DWORD, 'nChannel'), (['out','retval'], POINTER(c_float), 'pfLevelDB') ), COMMETHOD([], HRESULT, 'SetMute', (['in'], BOOL, 'bMute'), (['in'], POINTER(GUID), 'pguidEventContext') ), COMMETHOD([], HRESULT, 'GetMute', (['out','retval'], POINTER(BOOL), 'pbMute') ), COMMETHOD([], HRESULT, 'GetVolumeStepInfo', (['out','retval'], POINTER(c_float), 'pnStep'), (['out','retval'], POINTER(c_float), 'pnStepCount'), ), COMMETHOD([], HRESULT, 'VolumeStepUp', (['in'], POINTER(GUID), 'pguidEventContext') ), COMMETHOD([], HRESULT, 'VolumeStepDown', (['in'], POINTER(GUID), 'pguidEventContext') ), COMMETHOD([], HRESULT, 'QueryHardwareSupport', (['out','retval'], POINTER(DWORD), 'pdwHardwareSupportMask') ), COMMETHOD([], HRESULT, 'GetVolumeRange', (['out','retval'], POINTER(c_float), 'pfMin'), (['out','retval'], POINTER(c_float), 'pfMax'), (['out','retval'], POINTER(c_float), 'pfIncr') ), ] class IMMDevice(IUnknown): _iid_ = GUID('{D666063F-1587-4E43-81F1-B948E807363F}') _methods_ = [ COMMETHOD([], HRESULT, 'Activate', (['in'], POINTER(GUID), 'iid'), (['in'], DWORD, 'dwClsCtx'), (['in'], POINTER(DWORD), 'pActivationParans'), (['out','retval'], POINTER(POINTER(IAudioEndpointVolume)), 'ppInterface') ), STDMETHOD(HRESULT,
[python-win32] Control Volume on Windows
I'm looking for a way to use python to change the volume on windows. After some googling the best I could come up with was this script I got from a relatively ancient entry on this mailing list (I think it was from 2005 or something). I'm using windows 7, and I would like it to work on windows 8 if possible, though its not necessary. I don't need to support any previous versions of windows. Here is the code: #!/usr/bin/env python #Boa:PyApp:main modules = {} import ctypes mixerSetControlDetails = ( ctypes.windll.winmm.mixerSetControlDetails) mixerGetControlDetails = ( ctypes.windll.winmm.mixerGetControlDetailsA) # Some constants MIXER_OBJECTF_MIXER = 0 # mmsystem.h VOLUME_CONTROL_ID = 1 # Same on all machines? SPEAKER_LINE_FADER_ID = 1 # Identifier identifier in OID value does not resolve to a positive integer MINIMUM_VOLUME = 0 # fader control (MSDN Library) MAXIMUM_VOLUME = 65535 # fader control (MSDN Library) class MIXERCONTROLDETAILS(ctypes.Structure): _pack_ = 1 _fields_ = [('cbStruct', ctypes.c_ulong), ('dwControlID', ctypes.c_ulong), ('cChannels', ctypes.c_ulong), ('cMultipleItems', ctypes.c_ulong), ('cbDetails', ctypes.c_ulong), ('paDetails', ctypes.POINTER(ctypes.c_ulong))] def setVolume(volume): Set the speaker volume on the 'Volume Control' mixer if not (MINIMUM_VOLUME = volume = MAXIMUM_VOLUME): raise ValueError, Volume out of range cd = MIXERCONTROLDETAILS(ctypes.sizeof(MIXERCONTROLDETAILS), SPEAKER_LINE_FADER_ID, 1, 0, ctypes.sizeof(ctypes.c_ulong), ctypes.pointer(ctypes.c_ulong(volume))) ret = mixerSetControlDetails(VOLUME_CONTROL_ID, ctypes.byref(cd), MIXER_OBJECTF_MIXER) if ret != 0: print WindowsError, Error %d while setting volume % ret ret = mixerGetControlDetails(VOLUME_CONTROL_ID, ctypes.byref(cd), MIXER_OBJECTF_MIXER) if ret != 0: print WindowsError, Error %d while setting volume % ret else: print 'cbStruct', cd.cbStruct print 'dwControlID', cd.dwControlID print 'cChannels', cd.cChannels print 'cMultipleItems', cd.cMultipleItems print 'cbDetails', cd.cbDetails print 'paDetails', cd.paDetails.contents return #setVolume((2**16-1)/2) setVolume(0) ## added by me, neither value does anything If I run this, the ret value is 0 and it prints out all the data from the cd struct. But it doesn't change the volume at all. If I change the SPEAKER_LINE_FADER_ID to 0 the program crashes with: windows error 1025 - error setting the volume. I've tried googling that error, winmm, ctypes.windll, and a bunch of other things but I seem unable to find any resources with any information at all. The original poster of this script said the constants might need to be changed, and that finding the right constants could take some work but never elaborated on how to actually do it. I've looked at the relevant MSDN C++ docs that windows provides, and while they are somewhat informative I would really like to keep this project to python only. I have been unable to find much of any documentation on pywin32 itself. Is it hidden somewhere? Anyone have any ideas? ___ python-win32 mailing list python-win32@python.org https://mail.python.org/mailman/listinfo/python-win32
Re: [python-win32] Control Volume on Windows
Trevor Haba wrote: I'm looking for a way to use python to change the volume on windows. After some googling the best I could come up with was this script I got from a relatively ancient entry on this mailing list (I think it was from 2005 or something). I'm using windows 7, and I would like it to work on windows 8 if possible, though its not necessary. I don't need to support any previous versions of windows. Alas, the news is not good. The simple and easy-to-use winmm APIs are no longer supported. They still work in many cases, but the mapping from the winmm device numbering to the new audio API device numbering is mysterious, as you have learned, and there is no good recipe to find them that works on every system. The blessed method of adjusting the volume in the Vista-and-beyond audio world requires the use of COM. You fetch an IMMDeviceEnumerator interface, use that to fetch an IMMDevice for your device, then fetch an IAudioEndpoint interface and call SetMasterVolumeLevel to adjust the volume. That's not really very much code in C++ terms, BUT none of those interfaces have late-binding support, which means Python cannot use them. So, your only real choice is to write a Python extension in C++. Fortunately, using boost/python.hpp, that's not as hard as it used to be. -- Tim Roberts, t...@probo.com Providenza Boekelheide, Inc. ___ python-win32 mailing list python-win32@python.org https://mail.python.org/mailman/listinfo/python-win32
Re: [python-win32] Control Volume on Windows [SEC=UNCLASSIFIED]
Trevor Haba wrote: I'm looking for a way to use python to change the volume on windows. After some googling the best I could come up with was this script I got from a relatively ancient entry on this mailing list (I think it was from 2005 or something). I'm using windows 7, and I would like it to work on windows 8 if possible, though its not necessary. I don't need to support any previous versions of windows. To which Tim Roberts replied: Alas, the news is not good. The simple and easy-to-use winmm APIs are no longer supported. They still work in many cases, but the mapping from the winmm device numbering to the new audio API device numbering is mysterious, as you have learned, and there is no good recipe to find them that works on every system. The blessed method of adjusting the volume in the Vista-and-beyond audio world requires the use of COM. You fetch an IMMDeviceEnumerator interface, use that to fetch an IMMDevice for your device, then fetch an IAudioEndpoint interface and call SetMasterVolumeLevel to adjust the volume. That's not really very much code in C++ terms, BUT none of those interfaces have late-binding support, which means Python cannot use them. I think that comtypes (https://pypi.python.org/pypi/comtypes) can deal with early binding interfaces? - These thoughts are mine alone! - Andrew MacIntyre Operations and Services Branch tel: +61 2 6219 5356 Communications Infrastructure Division fax: +61 2 6219 5347 Australian Communications Media Authority email: andrew.macint...@acma.gov.auhttp://www.acma.gov.au/ NOTICE: This email message is for the sole use of the intended recipient(s) and may contain confidential and privileged information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message. ___ python-win32 mailing list python-win32@python.org https://mail.python.org/mailman/listinfo/python-win32