How to programmatically set the system volume?
I'm a bit late to the party but if you are looking now there's a nuget package available (AudioSwitcher.AudioApi.CoreAudio) that simplifies audio interactions. Install it then it’s as simple as:
CoreAudioDevice defaultPlaybackDevice = new CoreAudioController().DefaultPlaybackDevice;
Debug.WriteLine("Current Volume:" + defaultPlaybackDevice.Volume);
defaultPlaybackDevice.Volume = 80;
How to Get and Set System Volume in Windows
This requires a plugin. Since this question is for Windows, you can use IAudioEndpointVolume
to build a C++ plugin then call it from C#. This post has a working C++ example of how to change volume with IAudioEndpointVolume
and you can use it as the base source to create the C++ plugin.
I've gone ahead and cleaned that code up then converted into a dll plugin and placed the DLL at Assets/Plugins folder. You can see how to build the C++ plugin here.
The C++ code:
#include "stdafx.h"
#include <windows.h>
#include <mmdeviceapi.h>
#include <endpointvolume.h>
#define DLLExport __declspec(dllexport)
extern "C"
{
enum class VolumeUnit {
Decibel,
Scalar
};
//Gets volume
DLLExport float GetSystemVolume(VolumeUnit vUnit) {
HRESULT hr;
// -------------------------
CoInitialize(NULL);
IMMDeviceEnumerator *deviceEnumerator = NULL;
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator);
IMMDevice *defaultDevice = NULL;
hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice);
deviceEnumerator->Release();
deviceEnumerator = NULL;
IAudioEndpointVolume *endpointVolume = NULL;
hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume);
defaultDevice->Release();
defaultDevice = NULL;
float currentVolume = 0;
if (vUnit == VolumeUnit::Decibel) {
//Current volume in dB
hr = endpointVolume->GetMasterVolumeLevel(¤tVolume);
}
else if (vUnit == VolumeUnit::Scalar) {
//Current volume as a scalar
hr = endpointVolume->GetMasterVolumeLevelScalar(¤tVolume);
}
endpointVolume->Release();
CoUninitialize();
return currentVolume;
}
//Sets volume
DLLExport void SetSystemVolume(double newVolume, VolumeUnit vUnit) {
HRESULT hr;
// -------------------------
CoInitialize(NULL);
IMMDeviceEnumerator *deviceEnumerator = NULL;
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator);
IMMDevice *defaultDevice = NULL;
hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice);
deviceEnumerator->Release();
deviceEnumerator = NULL;
IAudioEndpointVolume *endpointVolume = NULL;
hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume);
defaultDevice->Release();
defaultDevice = NULL;
if (vUnit == VolumeUnit::Decibel)
hr = endpointVolume->SetMasterVolumeLevel((float)newVolume, NULL);
else if (vUnit == VolumeUnit::Scalar)
hr = endpointVolume->SetMasterVolumeLevelScalar((float)newVolume, NULL);
endpointVolume->Release();
CoUninitialize();
}
}
The C# code:
using System.Runtime.InteropServices;
using UnityEngine;
public class VolumeManager : MonoBehaviour
{
//The Unit to use when getting and setting the volume
public enum VolumeUnit
{
//Perform volume action in decibels</param>
Decibel,
//Perform volume action in scalar
Scalar
}
/// <summary>
/// Gets the current volume
/// </summary>
/// <param name="vUnit">The unit to report the current volume in</param>
[DllImport("ChangeVolumeWindows")]
public static extern float GetSystemVolume(VolumeUnit vUnit);
/// <summary>
/// sets the current volume
/// </summary>
/// <param name="newVolume">The new volume to set</param>
/// <param name="vUnit">The unit to set the current volume in</param>
[DllImport("ChangeVolumeWindows")]
public static extern void SetSystemVolume(double newVolume, VolumeUnit vUnit);
// Use this for initialization
void Start()
{
//Get volume in Decibel
float volumeDecibel = GetSystemVolume(VolumeUnit.Decibel);
Debug.Log("Volume in Decibel: " + volumeDecibel);
//Get volume in Scalar
float volumeScalar = GetSystemVolume(VolumeUnit.Scalar);
Debug.Log("Volume in Scalar: " + volumeScalar);
//Set volume in Decibel
SetSystemVolume(-16f, VolumeUnit.Decibel);
//Set volume in Scalar
SetSystemVolume(0.70f, VolumeUnit.Scalar);
}
}
The GetSystemVolume
function is used to get the current volume and SetSystemVolume
is used to set it. This question is for Windows but you can do a similar thing with the API for other platforms.
To set it to 70%
when A key is pressed:
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
//Set Windows Volume 70%
SetSystemVolume(0.70f, VolumeUnit.Scalar);
}
}
How to programmatically set the system volume?
I'm a bit late to the party but if you are looking now there's a nuget package available (AudioSwitcher.AudioApi.CoreAudio) that simplifies audio interactions. Install it then it’s as simple as:
CoreAudioDevice defaultPlaybackDevice = new CoreAudioController().DefaultPlaybackDevice;
Debug.WriteLine("Current Volume:" + defaultPlaybackDevice.Volume);
defaultPlaybackDevice.Volume = 80;
How to change the System Volume programmatically
You're getting an error because this.Handle
isn't defined in a plain vanilla class like that VolumeChange
class you have there.
It comes from a system.windows.forms
form
class.
It needs to, because the SendMessageW
method requires a window handle
Since you didn't define it in your new class, you can't use it.
Try passing a valid window handle in the constructor for VolumeChange
, and using that to call SendMessageW
public class VolumeChange
{
private const int APPCOMMAND_VOLUME_MUTE = 0x80000;
private const int APPCOMMAND_VOLUME_UP = 0xA0000;
private const int APPCOMMAND_VOLUME_DOWN = 0x90000;
private const int WM_APPCOMMAND = 0x319;
private IntPtr windowHandle;
public VolumeChange(IntPtr hwnd)
{
windowHandle = hwnd;
}
[DllImport("user32.dll")]
public static extern IntPtr SendMessageW(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
private void btnMute_Click(object sender, EventArgs e)
{
SendMessageW(windowHandle, WM_APPCOMMAND, windowHandle,(IntPtr)APPCOMMAND_VOLUME_MUTE);
}
private void btnDecVol_Click(object sender, EventArgs e)
{
SendMessageW(windowHandle, WM_APPCOMMAND, windowHandle,(IntPtr)APPCOMMAND_VOLUME_DOWN);
}
private void btnIncVol_Click(object sender, EventArgs e)
{
SendMessageW(windowHandle, WM_APPCOMMAND,windowHandle,(IntPtr)APPCOMMAND_VOLUME_UP);
}
}
If passing a window handle in the contructor isn't an option, (if you want to make VolumeChange
static for instance)
Take a look at GetActiveWindow (MSDN)
Windows change system volume programmatically with Java or CMD
Take a look at a form post on oracles website https://forums.oracle.com/thread/2390172 you can see it is not possible from inside java using native libraries.
Quote from the oracle post: "Because Java is cross-platform, it cannot do platform-specific stuff like changing the volume or whatever you want to do to control the OS. You need to use the operating system's unique API layer to do it."
For command line I found this utility that seems to have what you are looking for http://www.nirsoft.net/utils/nircmd.html
If you don't want to rely on 3rd party executables you could either make your own exe or make a dll and look into using JNI.
Set System Volume Windows 10 in C#
class VolumeChanger
{
private const byte VK_VOLUME_MUTE = 0xAD;
private const byte VK_VOLUME_DOWN = 0xAE;
private const byte VK_VOLUME_UP = 0xAF;
private const UInt32 KEYEVENTF_EXTENDEDKEY = 0x0001;
private const UInt32 KEYEVENTF_KEYUP = 0x0002;
[DllImport("user32.dll")]
static extern void keybd_event(byte bVk, byte bScan, UInt32 dwFlags, UInt32 dwExtraInfo);
[DllImport("user32.dll")]
static extern Byte MapVirtualKey(UInt32 uCode, UInt32 uMapType);
public static void VolumeUp()
{
keybd_event(VK_VOLUME_UP, MapVirtualKey(VK_VOLUME_UP, 0), KEYEVENTF_EXTENDEDKEY, 0);
keybd_event(VK_VOLUME_UP, MapVirtualKey(VK_VOLUME_UP, 0), KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}
public static void VolumeDown()
{
keybd_event(VK_VOLUME_DOWN, MapVirtualKey(VK_VOLUME_DOWN, 0), KEYEVENTF_EXTENDEDKEY, 0);
keybd_event(VK_VOLUME_DOWN, MapVirtualKey(VK_VOLUME_DOWN, 0), KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}
public static void Mute()
{
keybd_event(VK_VOLUME_MUTE, MapVirtualKey(VK_VOLUME_MUTE, 0), KEYEVENTF_EXTENDEDKEY, 0);
keybd_event(VK_VOLUME_MUTE, MapVirtualKey(VK_VOLUME_MUTE, 0), KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}
}
Using this, you can mute, and increase or decrease Systemvolume by 2 degree.
I still searching a way to get the current Systemvolume.
Related Topics
How to Generate Database Tables from C# Classes
C# Json.Net How to Ignore a Property in Deserialization But Not in Serialization
How to Validate a Datetime in C#
How to Properly Make a Http Web Get Request
Deserialize Json String in to Multiple C# Objects
Convert Time-Formatted Column in Excel to C# Datetime
Count() a Specfic Attribute Within a List C#
How to Refresh or Show Immediately in Datagridview After Inserting
Formatting Date in Linq-To-Entities Query Causes Exception
How to Provide Success Messages ASP.NET MVC
Check If a File Is Real or a Symbolic Link
Decrypt M3U8 Playlist Encrypted With Aes-128 Without Iv
Post Json Array to MVC Controller
How to Rename Keys Within a Json File
What Is the Correct Way to Compare Char Ignoring Case