I am building an app that starts a screen recorder application (like OBS) automatically (to record a zoom meeting).
I don't want any other application's audio to play during the recording, but I can't find a working code.
I used the example in this site with some code from here just to check the API
public enum MMRESULT : uint
{
// Source: https://www.pinvoke.net/default.aspx/winmm/MMRESULT.html?diff=y
MMSYSERR_NOERROR = 0,
MMSYSERR_ERROR = 1,
MMSYSERR_BADDEVICEID = 2,
MMSYSERR_NOTENABLED = 3,
MMSYSERR_ALLOCATED = 4,
MMSYSERR_INVALHANDLE = 5,
MMSYSERR_NODRIVER = 6,
MMSYSERR_NOMEM = 7,
MMSYSERR_NOTSUPPORTED = 8,
MMSYSERR_BADERRNUM = 9,
MMSYSERR_INVALFLAG = 10,
MMSYSERR_INVALPARAM = 11,
MMSYSERR_HANDLEBUSY = 12,
MMSYSERR_INVALIDALIAS = 13,
MMSYSERR_BADDB = 14,
MMSYSERR_KEYNOTFOUND = 15,
MMSYSERR_READERROR = 16,
MMSYSERR_WRITEERROR = 17,
MMSYSERR_DELETEERROR = 18,
MMSYSERR_VALNOTFOUND = 19,
MMSYSERR_NODRIVERCB = 20,
WAVERR_BADFORMAT = 32,
WAVERR_STILLPLAYING = 33,
WAVERR_UNPREPARED = 34
}
[DllImport("winmm.dll")]
public static extern MMRESULT waveOutGetVolume(IntPtr hwo, out uint dwVolume);
[DllImport("winmm.dll")]
public static extern MMRESULT waveOutSetVolume(IntPtr hwo, uint dwVolume);
public static void Main(string[] args)
{
foreach (Process process in Process.GetProcesses())
{
if (process.MainWindowHandle != IntPtr.Zero)
{
// Source: https://sites.google.com/site/lalitpundir/s-1
try
{
uint CurrVol = 0;
// At this point, CurrVol gets assigned the volume
MMRESULT res = waveOutGetVolume(process.Handle, out CurrVol);
// Calculate the volume
ushort CalcVol = (ushort)(CurrVol & 0x0000ffff);
// Get the volume on a scale of 1 to 10 (to fit the trackbar)
Console.WriteLine($"The volume of {process.ProcessName} is {CalcVol / (ushort.MaxValue / 10)}");
// Try muting chrome
if (process.ProcessName.Equals("chrome"))
{
Console.WriteLine("Muting chrome");
int NewVolume = 0;
uint NewVolumeAllChannels = (((uint)NewVolume & 0x0000ffff) | ((uint)NewVolume << 16));
res = waveOutSetVolume(process.Handle, NewVolumeAllChannels);
Console.WriteLine(res);
Thread.Sleep(5000);
}
}
catch (Win32Exception e)
{
Console.WriteLine($"Error with {process.ProcessName}");
}
}
}
}
The above code, always returns MMSYSERR_BADDEVICEID
for the waveOutGetVolume
and waveOutSetVolume
methods.
CodePudding user response:
Thanks you Make that 4 for the help.
The links you provided helped me find this answer,, which I modified a bit to fit my needs.
First of all, this answer requires the NuGet package CSCore.
This is an example code that I used (I am still learning the package):
public class MixerTest
{
static void Main(string[] args)
{
foreach (AudioSessionManager2 sessionManager in GetDefaultAudioSessionManager2(DataFlow.Render))
{
using (sessionManager)
{
using (var sessionEnumerator = sessionManager.GetSessionEnumerator())
{
foreach (var session in sessionEnumerator)
{
using var simpleVolume = session.QueryInterface<SimpleAudioVolume>();
using var sessionControl = session.QueryInterface<AudioSessionControl2>();
Console.WriteLine((sessionControl.Process.ProcessName, sessionControl.SessionIdentifier));
if (Process.GetProcessById(sessionControl.ProcessID).ProcessName.Equals("chrome"))
{
simpleVolume.IsMuted = true;
}
}
}
}
}
Console.ReadKey();
}
private static IEnumerable<AudioSessionManager2> GetDefaultAudioSessionManager2(DataFlow dataFlow)
{
using var enumerator = new MMDeviceEnumerator();
using var devices = enumerator.EnumAudioEndpoints(dataFlow, DeviceState.Active);
foreach (var device in devices)
{
Console.WriteLine("Device: " device.FriendlyName);
var sessionManager = AudioSessionManager2.FromMMDevice(device);
yield return sessionManager;
}
}
}