Is there a way in Java (+- JNA) to set the master system volume reliably in XP+Vista+Windows 7?

后端 未结 2 1150
深忆病人
深忆病人 2020-12-11 13:11

Appears that java\'s sound API\'s work well for single streams, and even for setting the input from the microphone, but not for setting the master volume level in Vista/Wind

相关标签:
2条回答
  • 2020-12-11 13:50

    Have done my share of JNI and steer clear where I can. As long as you have to go native to accomplish something, and assuming the task is simple and performance isn't a major issue, I've found it a lot easier to launch a separate process than deal with JNI or any of its cousins. Here is some C++ code adapted from this article that will set the master volume based on a single command line parameter:

    #include <WinSDKVer.h>
    #define _WIN32_WINNT _WIN32_WINNT_VISTA
    #include <SDKDDKVer.h>
    
    #define WIN32_LEAN_AND_MEAN
    // Windows Header Files:
    #include <windows.h>
    #include <tchar.h>
    
    #include <mmdeviceapi.h>
    #include <endpointvolume.h> 
    
    int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
    {
    double newVolume = _ttof(lpCmdLine);
    
    CoInitialize(NULL);
    
    IMMDeviceEnumerator* deviceEnumerator = NULL;
    if(CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator) == S_OK) {
        IMMDevice* defaultDevice = NULL;
        if(deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice) == S_OK) {
            IAudioEndpointVolume* endpointVolume = NULL;
            if(defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume) == S_OK) {
                endpointVolume->SetMasterVolumeLevelScalar((float)newVolume, NULL);
                endpointVolume->Release();
            }
            defaultDevice->Release();
        }
        deviceEnumerator->Release();
    }
    
    CoUninitialize();
    
    return 0;
    }
    

    Hope this helps.

    0 讨论(0)
  • 2020-12-11 14:01

    seeing as there appears to be no native solution, my current method is to use jna to send keyboard strokes for "keyboard volume up and down":

    https://superuser.com/questions/82229/how-to-control-master-volume-in-windows-7/86227#86227

    You might be able to create a dll then hook into it that is "vista volume aware" and could actually control it right, and call methods on that, using jna.

    ffi/jna/jnr/jacob (to access IAudioEndpointVolume etc.) might work. (appears jna doesn't really support COM?) ffi looks scary too, in that regard.

    Could possibly use a java COM bridge to do the same. So next thought is to try either bridj or jacob

    0 讨论(0)
提交回复
热议问题