Coder Social home page Coder Social logo

coreaudio's People

Contributors

bferdinandus avatar friendlyagent avatar morphx666 avatar pyroluk avatar uxsoft avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

coreaudio's Issues

Add license information and debug info to csproj

Hi,
This csproj has some nuget related information but no license info (and other nice to have properties).
it is good to add it so it will be shown in Visual Studio nuget management.

example:

	<PropertyGroup>
		<PublishRepositoryUrl>true</PublishRepositoryUrl>
		<IncludeSymbols>true</IncludeSymbols>
		<SymbolPackageFormat>snupkg</SymbolPackageFormat>
		<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
		<PackageLicenseExpression>MIT</PackageLicenseExpression>
		<RepositoryType>git</RepositoryType>
		<Nullable>enable</Nullable>
		<LangVersion>latest</LangVersion>
	</PropertyGroup>

NuGet Package?

Hi,
It would be useful to have this published as a NuGet package. Let me know if you want help setting up GitHub actions to auto-publish the NuGet package for every commit or something.

PlaybackStopped Event fire multiple times

I am using playbackStoped Event to use as Rewind. To make clear, If audio file is complete then I wan to call palybackStopped event and inside it, I want to call outputDevice.Play() method. OutputDevice is object of WaveOutEvent. After calling outputDevice.Play() , playbackStoped fired multiple times and not able to again play.

Can't adjust the volume of certain applications

Some of my users are reporting (radj307/volume-control#86, radj307/volume-control#128) a weird and difficult to reproduce problem where SimpleAudioVolume doesn't affect some specific applications:

  • Dota 2
  • Call of Duty: Modern Warfare III
  • Little Nightmares
  • Destiny 2

It works fine for everything else.

I believe the issue is due to this library because it affects Volume Control (which uses this library), but not EarTrumpet (which has its own C# implementation of the Core Audio APIs) or vccli (which uses the C++ APIs directly).
I wrote a simple C# clone of vccli using this library and had an affected user test it & that didn't work either (radj307/volume-control#160).

Especially weird is that if the affected user uses vccli to change the volume/mute at least once, the problem stops happening entirely.

Please let me know if there's anything else I can provide or do that might help.

[BUG] Exception on Enumerating NOTPRESENT devices

Enumerating Active, Disabled and Unplugged devices work just fine but enumerating Not present devices produces this exception (which means also DEVICE_STATEMASK_ALL will cause this exception) :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CoreAudio;
using static System.Console;

namespace MyTests
{
    class Program
    {
        static void Main(string[] args)
        {
            MMDeviceEnumerator DevEnum = new MMDeviceEnumerator();
            {
                MMDeviceCollection Devices = DevEnum.EnumerateAudioEndPoints(EDataFlow.eAll, DEVICE_STATE.DEVICE_STATE_NOTPRESENT);
                List<MMDevice> DevicesList = Devices.ToList();
                foreach (MMDevice Item in DevicesList)
                WriteLine(Item.DeviceFriendlyName);
                ReadLine();
            }
        }
    }
}

Exception trace:
image

System.Runtime.InteropServices.COMException: 'Exception from HRESULT: 0xE000020B'

Exception details:

System.Runtime.InteropServices.COMException
  HResult=0xE000020B
  Message=Exception from HRESULT: 0xE000020B
  Source=mscorlib
  StackTrace:
   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
   at CoreAudio.PropertyStore.get_Item(PROPERTYKEY testKey)
   at CoreAudio.MMDevice.get_DeviceFriendlyName()
   at MyTests.Program.Main(String[] args) in A:\source\repos\ClassLibrary1-.NET_Framework\Class1.cs:line 21

Mic peak volume

Hey @morphx666,

Maybe I've looked over it, but is there a way to get the peak volume of the default mic (input device)?

DisplayName and IconPath are sometimes empty string.

Hello,

Could you help me out?

I'm using these commands to be able to get the audio sessions for the active device

MMDeviceEnumerator deviceEnumerator = new MMDeviceEnumerator();
MMDevice device = deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
SessionCollection sessions = device.AudioSessionManager2.Sessions;
foreach (AudioSessionControl2 session in sessions)
{
    Console.WriteLine($"Session Identifier: {session.GetSessionIdentifier}");
    Console.WriteLine($"Session Name: {session.DisplayName}");
    Console.WriteLine($"Session IconPath: {session.IconPath}");
    Console.WriteLine("===================");
}

When the active device is my USB Headset then the DisplayName and IconPath are filled.

Session Identifier: {0.0.0.00000000}.{e4aa5a18-bf9b-470f-b5e2-f88a9d5c5998}|#%b{A9EF3FD9-4240-455E-A4D5-F2B3301887B2}
Session Name: @%SystemRoot%\System32\AudioSrv.Dll,-202
Session IconPath: @%SystemRoot%\System32\AudioSrv.Dll,-203
===================
Session Identifier: {0.0.0.00000000}.{e4aa5a18-bf9b-470f-b5e2-f88a9d5c5998}|\Device\HarddiskVolume4\Program Files\Mozilla Firefox\firefox.exe%b{00000000-0000-0000-0000-000000000000}
Session Name: Mozilla Firefox
Session IconPath: C:\Program Files\Mozilla Firefox\firefox.exe
===================
Session Identifier: {0.0.0.00000000}.{e4aa5a18-bf9b-470f-b5e2-f88a9d5c5998}|\Device\HarddiskVolume4\Program Files\VideoLAN\VLC\vlc.exe%b{4533F59D-59EE-00C6-ADB2-C68B501A6655}
Session Name: VLC media player
Session IconPath:
===================

But if I select my speakers as output then the DisplayName and IconPath are empty for some of the items.

Session Identifier: {0.0.0.00000000}.{e13e75ff-84a0-4dd6-bed0-ad11a8c3887b}|\Device\HarddiskVolume4\Program Files\VideoLAN\VLC\vlc.exe%b{4533F59D-59EE-00C6-ADB2-C68B501A6655}
Session Name: VLC media player
Session IconPath:
===================
Session Identifier: {0.0.0.00000000}.{e13e75ff-84a0-4dd6-bed0-ad11a8c3887b}|\Device\HarddiskVolume4\Program Files\Mozilla Firefox\firefox.exe%b{00000000-0000-0000-0000-000000000000}
Session Name:
Session IconPath:
===================
Session Identifier: {0.0.0.00000000}.{e13e75ff-84a0-4dd6-bed0-ad11a8c3887b}|#%b{A9EF3FD9-4240-455E-A4D5-F2B3301887B2}
Session Name: @%SystemRoot%\System32\AudioSrv.Dll,-202
Session IconPath: @%SystemRoot%\System32\AudioSrv.Dll,-203
===================

Maybe this is a specific problem for Mozilla Firefox? Why does the Name and IconPath of Mozilla disappear when I switch output devices?

With regards, Ben

Get AudioSessionControl2 object from OnSessionCreated event

Hi, first of all thanks for this piece of art!
I am writing simple VR mixer and i had been blocked in this part of code, where i need to take the AudioSessionControl2 object connected to a specific Process and insert it in a list.
My first idea was to modified the code, by changing the access modifier from internal to public. (But if was written as internal, is there a reason??)
Is there a way to get this object without modify the code?

Here the code

var list = new ObservableCollection<AudioSessionControl2>();

var changestate = new AudioSessionControl2.StateChangedDelegate(delegate (object o, AudioSessionState reason) {
    if (reason == AudioSessionState.AudioSessionStateExpired) 
        list.Remove((AudioSessionControl2) o);
});

var eventContext = Guid.NewGuid();
    MMDeviceEnumerator DevEnum = new MMDeviceEnumerator(eventContext);
    MMDevice device = DevEnum.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
    
    //evento per individuare nuove instance audio. Da effettuare dopo la scansione delle sessioni premilimari!
    device.AudioSessionManager2.OnSessionCreated += (sender, session) => {
        Console.WriteLine("Ho creato una nuova instanza Audio!");
        uint pid;
        session.GetProcessId(out pid);
        Console.WriteLine(Process.GetProcessById((int)pid).ProcessName);
        /*
          Here i Need the AudioSessionControl2 object.
        */
        // my first idea works, but required the change to access modifier "public"
        var audio = new AudioSessionControl2(session, typeof(IAudioSessionControl2).GUID);
        audio.OnStateChanged += changestate;
        list.Add(audio);
    };
    
    foreach (var endpoint in device.AudioSessionManager2.Sessions) {
        endpoint.OnStateChanged += changestate;
        list.Add(endpoint);
    }
    
    list.CollectionChanged += (sender, eventArgs) => {
        if(eventArgs.Action is not (NotifyCollectionChangedAction.Add or NotifyCollectionChangedAction.Remove)) return;
        UpdateGui();

        void UpdateGui() {
            Console.WriteLine("---------------inizio---------------");
            foreach (var VARIABLE in list) {
                Console.WriteLine(Process.GetProcessById((int)VARIABLE.ProcessID).ProcessName);
                Console.WriteLine("-------------------------------");
            }
            Console.WriteLine("---------------fine---------------");
        }
    };

foreach (var VARIABLE in list) {
    Console.WriteLine(Process.GetProcessById((int)VARIABLE.ProcessID).ProcessName);
    Console.WriteLine("-------------------------------");
} 

//stay open the process....
Console.ReadLine();

Part to Connector and AudioVolumeLevel in Part.cs

  1. Part to Connector
    https://learn.microsoft.com/en-us/windows/win32/coreaudio/device-topologies
    I could not port the 2nd code snippet above link to c# using CoreAudio. Because Connector could be converted to Part, but Part could not be Converted to Connector. So I modified Part.cs by referencing Connector.cs as below.
Connector? connector;
...
public Connector? Connector
{
    get
    {
        if (connector == null)
        {
            var pUnk = Marshal.GetIUnknownForObject(part);
            var res = Marshal.QueryInterface(pUnk, ref RefIId.IIdIConnector, out var ppv);
            if (ppv != IntPtr.Zero)
                connector = new Connector((IConnector)Marshal.GetObjectForIUnknown(ppv));
            else
                connector = null;
        }
        return connector;
    }
}

All connectors are parts, but not all parts are connectors, so I'm not sure this way, but anyway, I needed a way to make the sample code in the official document work.

  1. AudioVolumeLevel doesn't work.
    I think it's because of variable overriding.
    void GetAudioVolumeLevel(AudioVolumeLevel? audioVolumeLevel) {
    I modified it as below.
//private AudioVolumeLevel? GetAudioVolumeLevel() {
//    return audioVolumeLevel;
//}

void GetAudioVolumeLevel() {
    part.Activate(CLSCTX.ALL, ref RefIId.IIdIAudioVolumeLevel, out var result);
    if(result is IAudioVolumeLevel level) {
        audioVolumeLevel = new AudioVolumeLevel(level);
        _AudioVolumeLevelChangeNotification = new ControlChangeNotify(this);
        Marshal.ThrowExceptionForHR(part.RegisterControlChangeCallback(ref RefIId.IIdIAudioVolumeLevel,
            _AudioVolumeLevelChangeNotification));
    }
}

Hopefully these will be fixed in the next version.
Thanks

[Samples] Error running the samples

Hi,
There is an error when running the netcore CoreAudioForms.Core.Sample
System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'

in:
v = (int)(device.AudioMeterInformation.PeakValues[1] * 100);

Detect device change/disconnect

Hi

I'm probably just being an idiot, but I can't see a way to detect when a device is disconnected or changed.

For example, I would like to be able to get an event/notification when I turn on my Bluetooth headset. Normally I use my USB headset, but when I turn on my BT set then Windows will automatically switch to the BT set. I would like to be able to detect when the USB set is disconnected so I can react to it.

From what I can see on learn.microsoft.com, it should be possible with device events, but I can't see how to use these in this library.
https://learn.microsoft.com/en-us/windows/win32/coreaudio/device-events

Protected memory exception when changing master volume

Had this exception when using the Nuget package.

Downloaded the code from GitHub and ran the Forms.Framework sample and got the same error. Am running it in Framework 4.8.1, but read through another issue that just changing the targeting framework should work. Should mention that changing the selected device is working just fine. Only the volume has this problem.

image

System.AccessViolationException
HResult=0x80004003
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Source=
StackTrace:

Stack trace
at CoreAudio.Interfaces.IAudioEndpointVolume.SetMasterVolumeLevelScalar(Single fLevel, Guid pguidEventContext)
at CoreAudio.AudioEndpointVolume.set_MasterVolumeLevelScalar(Single value) in C:\Code\ExampleCode\CoreAudio-master\CoreAudio\AudioEndpointVolume.cs:line 60
at CoreAudioForms.Framework.Sample.FormMain.Master_Scroll(Object sender, EventArgs e) in C:\Code\ExampleCode\CoreAudio-master\samples\CoreAudioForms.Framework.Sample\FormMain.cs:line 35
at System.Windows.Forms.TrackBar.OnScroll(EventArgs e)
at System.Windows.Forms.TrackBar.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.SendMessage(HandleRef hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.Control.SendMessage(Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.Control.ReflectMessageInternal(IntPtr hWnd, Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WmVScroll(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
at System.Windows.Forms.Control.DefWndProc(Message& m)
at System.Windows.Forms.Control.WmMouseMove(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.TrackBar.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at CoreAudioForms.Framework.Sample.Program.Main() in C:\Code\ExampleCode\CoreAudio-master\samples\CoreAudioForms.Framework.Sample\Program.cs:line 13

Bug: possible memory leak

Hello,

I've been experimenting with various "CoreAudio" wrapper libraries and it looks like most of them, including this one, appear to be leaking memory - slowly but constantly (or it's me using the library wrong, not excluding that :D)

I have a memory dump created at the end of the tests however github allows attachments only up to 25MB - compressed dump is 30MB+. I can deliver it via preferred method if required.

Test project is a clean new one with CoreAudio installed via nuget.
Code used for testing (put directly into main function, please ignore the var name typo):

        var enumerator = new MMDeviceEnumerator(Guid.Empty);
        while (true)
        {
            foreach (var device in enumerator.EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active))
            {
                var termpVar = device.DeviceFriendlyName;
                device.Dispose();
            }
        }

Results:
oJeViP
OvLLpo
Yk0j7R
2SNesS

Unhandled exception when disposing AudioSessionManager2

hi @morphx666, I'm trying to use your (great!) library to continuously monitor volume level, sessions and default audio device.

It all works great, apart from when I want to dispose an AudioSessionManager2 because the default device changed. It then crashes here:

void UnregisterNotifications()
{
    _Sessions = null;

    if (_AudioSessionNotification != null)
        Marshal.ThrowExceptionForHR(_AudioSessionManager2.UnregisterSessionNotification(_AudioSessionNotification));
}

I'm simply calling Dispose() on my object. What am I doing wrong?

AudioSessionManager2.OnSessionCreated never gets fired

Event never seems to properly fire, I've tried getting Count of sessions as according to MS documentation notifications are suppressed until user gets sessions to prevent race conditions but it doesn't seem to help either.

Code reproducing issue:

using CoreAudio;

var deviceEnumerator = new MMDeviceEnumerator(Guid.NewGuid());

var sessionManager = deviceEnumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Communications).AudioSessionManager2;

sessionManager.RefreshSessions();

var test = sessionManager.Sessions.Count;

foreach (var session in sessionManager.Sessions)
{
    Console.WriteLine($"Existing session: {session.DisplayName}:{session.SessionIdentifier}");
}

sessionManager.OnSessionCreated += (sender, session) =>
{
    Console.WriteLine("Session created");
};

await Task.Delay(TimeSpan.FromMinutes(1));

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.