2015-08-21 48 views
5

Come posso modificare il volume principale sul mio laptop usando python? Conosco un metodo, in cui simulo pressioni dei tasti volume su/volume giù usando i tipi, ma senza conoscere il volume corrente dovrei avere il mio codice eseguire 50 pressioni dei tasti in sequenza consecutive ogni volta che ho avviato l'applicazione per calibrare a zero.Leggere e/o modificare il volume master di Windows 8 in Python

C'è un modo per me per ottenere il volume di sistema corrente, o meglio, impostare il volume principale su un valore specificato?

Sto utilizzando un sistema Windows 8 a 64 bit con Python 3.4.

+0

posso chiederle che cosa la vostra applicazione è? Le funzionalità audio integrate di Python sono molto scarse. – TigerhawkT3

+0

Chiama le API di Windows come [mixerOpen] (https://msdn.microsoft.com/en-us/library/windows/desktop/dd757308%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396) da Python . –

+0

@DavidChing, in Vista e in seguito l'API winmm.dll modifica le impostazioni audio per applicazione. L'impostazione del volume principale richiede l'uso dell'interfaccia COM 'IAudioEndpointVolume'. – eryksun

risposta

5

Tim Roberts ha pubblicato un esempio comtypes nell'elenco di discussione python-win32 relativo a Control Volume on Windows. Nell'esempio seguente, ho modificato il codice di Tim e aggiunto i metodi di classe che restituiscono l'endpoint audio predefinito e la sua interfaccia IAudioEndpointVolume.

L'intervallo di volume dB sui due sistemi che ho testato (Windows 7 e Windows 10) ha normalizzato il livello massimo a 0 dB, ma il livello minimo e l'incremento di volume differivano tra i sistemi. Raccomando invece di usare i metodi scalari e integrali. L'intervallo scalare è compreso tra 0,0 e 1,0.

import ctypes 
import comtypes 
from ctypes import wintypes 

MMDeviceApiLib = comtypes.GUID(
    '{2FDAAFA3-7523-4F66-9957-9D5E7FE698F6}') 
IID_IMMDevice = comtypes.GUID(
    '{D666063F-1587-4E43-81F1-B948E807363F}') 
IID_IMMDeviceCollection = comtypes.GUID(
    '{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}') 
IID_IMMDeviceEnumerator = comtypes.GUID(
    '{A95664D2-9614-4F35-A746-DE8DB63617E6}') 
IID_IAudioEndpointVolume = comtypes.GUID(
    '{5CDF2C82-841E-4546-9722-0CF74078229A}') 
CLSID_MMDeviceEnumerator = comtypes.GUID(
    '{BCDE0395-E52F-467C-8E3D-C4579291692E}') 

# EDataFlow 
eRender = 0 # audio rendering stream 
eCapture = 1 # audio capture stream 
eAll = 2 # audio rendering or capture stream 

# ERole 
eConsole = 0 # games, system sounds, and voice commands 
eMultimedia = 1 # music, movies, narration 
eCommunications = 2 # voice communications 

LPCGUID = REFIID = ctypes.POINTER(comtypes.GUID) 
LPFLOAT = ctypes.POINTER(ctypes.c_float) 
LPDWORD = ctypes.POINTER(wintypes.DWORD) 
LPUINT = ctypes.POINTER(wintypes.UINT) 
LPBOOL = ctypes.POINTER(wintypes.BOOL) 
PIUnknown = ctypes.POINTER(comtypes.IUnknown) 

class IMMDevice(comtypes.IUnknown): 
    _iid_ = IID_IMMDevice 
    _methods_ = (
     comtypes.COMMETHOD([], ctypes.HRESULT, 'Activate', 
      (['in'], REFIID, 'iid'), 
      (['in'], wintypes.DWORD, 'dwClsCtx'), 
      (['in'], LPDWORD, 'pActivationParams', None), 
      (['out','retval'], ctypes.POINTER(PIUnknown), 'ppInterface')), 
     comtypes.STDMETHOD(ctypes.HRESULT, 'OpenPropertyStore', []), 
     comtypes.STDMETHOD(ctypes.HRESULT, 'GetId', []), 
     comtypes.STDMETHOD(ctypes.HRESULT, 'GetState', [])) 

PIMMDevice = ctypes.POINTER(IMMDevice) 

class IMMDeviceCollection(comtypes.IUnknown): 
    _iid_ = IID_IMMDeviceCollection 

PIMMDeviceCollection = ctypes.POINTER(IMMDeviceCollection) 

class IMMDeviceEnumerator(comtypes.IUnknown): 
    _iid_ = IID_IMMDeviceEnumerator 
    _methods_ = (
     comtypes.COMMETHOD([], ctypes.HRESULT, 'EnumAudioEndpoints', 
      (['in'], wintypes.DWORD, 'dataFlow'), 
      (['in'], wintypes.DWORD, 'dwStateMask'), 
      (['out','retval'], ctypes.POINTER(PIMMDeviceCollection), 
      'ppDevices')), 
     comtypes.COMMETHOD([], ctypes.HRESULT, 'GetDefaultAudioEndpoint', 
      (['in'], wintypes.DWORD, 'dataFlow'), 
      (['in'], wintypes.DWORD, 'role'), 
      (['out','retval'], ctypes.POINTER(PIMMDevice), 'ppDevices'))) 
    @classmethod 
    def get_default(cls, dataFlow, role): 
     enumerator = comtypes.CoCreateInstance(
      CLSID_MMDeviceEnumerator, cls, comtypes.CLSCTX_INPROC_SERVER) 
     return enumerator.GetDefaultAudioEndpoint(dataFlow, role) 

class IAudioEndpointVolume(comtypes.IUnknown): 
    _iid_ = IID_IAudioEndpointVolume 
    _methods_ = (
     comtypes.STDMETHOD(ctypes.HRESULT, 'RegisterControlChangeNotify', []), 
     comtypes.STDMETHOD(ctypes.HRESULT, 'UnregisterControlChangeNotify', []), 
     comtypes.COMMETHOD([], ctypes.HRESULT, 'GetChannelCount', 
      (['out', 'retval'], LPUINT, 'pnChannelCount')), 
     comtypes.COMMETHOD([], ctypes.HRESULT, 'SetMasterVolumeLevel', 
      (['in'], ctypes.c_float, 'fLevelDB'), 
      (['in'], LPCGUID, 'pguidEventContext', None)), 
     comtypes.COMMETHOD([], ctypes.HRESULT, 'SetMasterVolumeLevelScalar', 
      (['in'], ctypes.c_float, 'fLevel'), 
      (['in'], LPCGUID, 'pguidEventContext', None)), 
     comtypes.COMMETHOD([], ctypes.HRESULT, 'GetMasterVolumeLevel', 
      (['out','retval'], LPFLOAT, 'pfLevelDB')), 
     comtypes.COMMETHOD([], ctypes.HRESULT, 'GetMasterVolumeLevelScalar', 
      (['out','retval'], LPFLOAT, 'pfLevel')), 
     comtypes.COMMETHOD([], ctypes.HRESULT, 'SetChannelVolumeLevel', 
      (['in'], wintypes.UINT, 'nChannel'), 
      (['in'], ctypes.c_float, 'fLevelDB'), 
      (['in'], LPCGUID, 'pguidEventContext', None)), 
     comtypes.COMMETHOD([], ctypes.HRESULT, 'SetChannelVolumeLevelScalar', 
      (['in'], wintypes.UINT, 'nChannel'), 
      (['in'], ctypes.c_float, 'fLevel'), 
      (['in'], LPCGUID, 'pguidEventContext', None)), 
     comtypes.COMMETHOD([], ctypes.HRESULT, 'GetChannelVolumeLevel', 
      (['in'], wintypes.UINT, 'nChannel'), 
      (['out','retval'], LPFLOAT, 'pfLevelDB')), 
     comtypes.COMMETHOD([], ctypes.HRESULT, 'GetChannelVolumeLevelScalar', 
      (['in'], wintypes.UINT, 'nChannel'), 
      (['out','retval'], LPFLOAT, 'pfLevel')), 
     comtypes.COMMETHOD([], ctypes.HRESULT, 'SetMute', 
      (['in'], wintypes.BOOL, 'bMute'), 
      (['in'], LPCGUID, 'pguidEventContext', None)), 
     comtypes.COMMETHOD([], ctypes.HRESULT, 'GetMute', 
      (['out','retval'], LPBOOL, 'pbMute')), 
     comtypes.COMMETHOD([], ctypes.HRESULT, 'GetVolumeStepInfo', 
      (['out','retval'], LPUINT, 'pnStep'), 
      (['out','retval'], LPUINT, 'pnStepCount')), 
     comtypes.COMMETHOD([], ctypes.HRESULT, 'VolumeStepUp', 
      (['in'], LPCGUID, 'pguidEventContext', None)), 
     comtypes.COMMETHOD([], ctypes.HRESULT, 'VolumeStepDown', 
      (['in'], LPCGUID, 'pguidEventContext', None)), 
     comtypes.COMMETHOD([], ctypes.HRESULT, 'QueryHardwareSupport', 
      (['out','retval'], LPDWORD, 'pdwHardwareSupportMask')), 
     comtypes.COMMETHOD([], ctypes.HRESULT, 'GetVolumeRange', 
      (['out','retval'], LPFLOAT, 'pfLevelMinDB'), 
      (['out','retval'], LPFLOAT, 'pfLevelMaxDB'), 
      (['out','retval'], LPFLOAT, 'pfVolumeIncrementDB'))) 
    @classmethod 
    def get_default(cls): 
     endpoint = IMMDeviceEnumerator.get_default(eRender, eMultimedia) 
     interface = endpoint.Activate(cls._iid_, comtypes.CLSCTX_INPROC_SERVER) 
     return ctypes.cast(interface, ctypes.POINTER(cls)) 

Ad esempio:

if __name__ == '__main__': 

    def show_vol(ev): 
     voldb = ev.GetMasterVolumeLevel() 
     volsc = ev.GetMasterVolumeLevelScalar() 
     volst, nstep = ev.GetVolumeStepInfo() 
     print('Master Volume (dB): %0.4f' % voldb) 
     print('Master Volume (scalar): %0.4f' % volsc) 
     print('Master Volume (step): %d/%d' % (volst, nstep)) 

    def test(): 
     ev = IAudioEndpointVolume.get_default() 
     vol = ev.GetMasterVolumeLevelScalar() 
     vmin, vmax, vinc = ev.GetVolumeRange() 
     print('Volume Range (min, max, step) (dB): ' 
       '%0.4f, %0.4f, %0.4f' % (vmin, vmax, vinc)) 
     show_vol(ev) 
     try: 
      print('\nIncrement the master volume') 
      ev.VolumeStepUp() 
      show_vol(ev) 
      print('\nDecrement the master volume twice') 
      ev.VolumeStepDown() 
      ev.VolumeStepDown() 
      show_vol(ev) 
      print('\nSet the master volume to 0.75 scalar') 
      ev.SetMasterVolumeLevelScalar(0.75) 
      show_vol(ev) 
      print('\nSet the master volume to 0.25 scalar') 
      ev.SetMasterVolumeLevelScalar(0.25) 
      show_vol(ev) 
     finally: 
      ev.SetMasterVolumeLevelScalar(vol) 

    comtypes.CoInitialize() 
    try: 
     test() 
    finally: 
     comtypes.CoUninitialize() 
+0

Grazie! Funziona alla grande! –