[Question] Get current ports of sink and source devices
Switch0621 opened this issue · 2 comments
Greetings!
Please advice me, how can i get actual info about current sink and source ports?
I want to my app is notifying user about connecting/disconnecting microphone and headphones. So, two state - no active sink/source port : active port is port name
P.S.: likely error, after set log callback, i open device (with empty name) and create context for this device and all is freezed.
Calling alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER)
(or alcGetString(NULL, ALC_DEVICE_SPECIFIER)
if ALC_ENUMERATE_ALL_EXT
isn't supported) will return a nul-separated list of available device names. Like this:
const char *names = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
while(names && *names)
{
printf("%s\n", names);
names += strlen(names)+1;
}
It shouldn't freeze creating a context. Even if there's no devices, opening the default devices (using an empty name) should fail if there's nothing to open. Or if there is a device but it's unusable, opening the device or creating the context should fail. Something's wrong if it freezes. Can you provide a backtrace from a debug build?
I think to compile a little CSharp project is more simple way.
There is a code of simple console application in dotnet8.0 on Linux:
`
using System.Runtime.InteropServices;
namespace ConsoleApp1;
class Program
{
private const string OpenAlLinux = "libopenal.so.1";
private static IntPtr _openalLinux = IntPtr.Zero;
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public delegate void LogDelegate(IntPtr user, char level, string message, int length);
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private delegate void LogCallbackSetter(LogDelegate callback, IntPtr user);
[DllImport(OpenAlLinux, EntryPoint = "alGetProcAddress", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern IntPtr GetProcAddress([In] string fname);
[DllImport(OpenAlLinux, EntryPoint = "alcOpenDevice", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern IntPtr OpenDevice([In] string devicename);
[DllImport(OpenAlLinux, EntryPoint = "alcCloseDevice", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
private static extern bool CloseDevice([In] IntPtr device);
[DllImport(OpenAlLinux, EntryPoint = "alcCreateContext", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr CreateContext([In] IntPtr device, [In] int[] attributeList);
private static IntPtr CreateContext(IntPtr device, OpenAlContextAttributes attributes) => CreateContext(device, attributes.CreateAttributeArray());
[DllImport(OpenAlLinux, EntryPoint = "alcDestroyContext", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
private static extern void DestroyContext(IntPtr context);
static void Main(string[] args)
{
// load openAl library
_openalLinux = NativeLibrary.Load(OpenAlLinux);
if (_openalLinux == IntPtr.Zero)
throw new Exception("Can't load library libopenal.so");
// set log callback
var sptr = GetProcAddress("alsoft_set_log_callback");
var logSetter = Marshal.GetDelegateForFunctionPointer<LogCallbackSetter>(sptr);
logSetter.Invoke(AlLogCallback, IntPtr.Zero);
// try to create context
var contextAttributes = new OpenAlContextAttributes();
var defaultPlayingDevice = OpenDevice(string.Empty);
var defaultPlayingDeviceContext = IntPtr.Zero;
if (defaultPlayingDevice != IntPtr.Zero)
defaultPlayingDeviceContext = CreateContext(defaultPlayingDevice, contextAttributes);
// wait
Console.ReadKey();
// dispose
if (defaultPlayingDeviceContext != IntPtr.Zero)
DestroyContext(defaultPlayingDeviceContext);
if (defaultPlayingDevice != IntPtr.Zero)
CloseDevice(defaultPlayingDevice);
}
private static void AlLogCallback(IntPtr user, char level, string message, int length) { }
}
`
The program is shutdown on context creation.
If i comment 'set log callback' code block - it's working fine.