// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
// Copyright (c) (2018-2022) Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Software License Agreement, located here: https://www.magicleap.com/software-license-agreement-ml2
// Terms and conditions applicable to third-party materials accompanying this distribution may also be found in the top-level NOTICE file appearing herein.
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
namespace UnityEngine.XR.MagicLeap
{
using System;
using System.Runtime.InteropServices;
using UnityEngine.XR.MagicLeap.Native;
///
/// Manages Audio.
///
public sealed partial class MLAudioInput : MLAutoAPISingleton
{
///
/// The mute state of the microphone.
///
private bool isMicrophoneMuted;
///
/// The delegate for the microphone mute changed event.
///
/// The new mute state of the microphone.
public delegate void OnMicrophoneMuteChangedDelegate(bool muted);
///
/// Raised whenever the global microphone mute gets changed.
///
public static event OnMicrophoneMuteChangedDelegate OnMicrophoneMuteChanged = delegate { };
///
/// Gets or sets a value indicating whether the microphone is muted.
///
public static bool MicrophoneMuted
{
get
{
return Instance.isMicrophoneMuted;
}
set
{
Instance.InternalSetMicMute(value);
}
}
///
/// Gets the result string for a MLResult.Code.
///
/// The MLResult.Code to be requested.
/// A pointer to the result string.
internal static IntPtr GetResultString(MLResult.Code result)
{
nativeGetResultStringPerfMarker.Begin();
IntPtr ptr = NativeBindings.MLAudioGetResultString(result);
nativeGetResultStringPerfMarker.End();
return ptr;
}
#if !DOXYGEN_SHOULD_SKIP_THIS
///
/// Called by MLAutoAPISingleton to start the API
///
///
/// MLResult.Result will be MLResult.Code.Ok if successful.
/// MLResult.Result will be MLResult.Code.UnspecifiedFailure if failed due to internal error.
/// MLResult.Result will be MLResult.Code.InvalidParam if a parameter is invalid.
/// MLResult.Result will be MLResult.Code.PermissionDenied if AudioCaptureMic permission is denied.
/// MLResult.Result will be MLResult.Code.AudioNotImplemented if the function is not implemented.
///
protected override MLResult.Code StartAPI()
{
startAPIPerfMarker.Begin();
MLResult.Code resultCode;
// Microphone Muted Callback
resultCode = this.RegisterOnMicrophoneMuteCallback();
if (resultCode != MLResult.Code.Ok)
{
startAPIPerfMarker.End();
return resultCode;
}
// Get the initial IsMicrophoneMuted value.
resultCode = Instance.GetMicrophoneMuted(out this.isMicrophoneMuted);
if (resultCode != MLResult.Code.Ok)
{
startAPIPerfMarker.End();
return resultCode;
}
startAPIPerfMarker.End();
return resultCode;
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
///
/// Called by MLAutoAPISingleton on destruction
///
protected override MLResult.Code StopAPI() => this.UnregisterOnMicrophoneMuteCallback();
///
/// Called every device frame
///
protected override void Update()
{
}
///
/// Handles the callback for MLAudioSetMicMute.
///
/// The mute state of the microphone.
/// A pointer to the callback.
[AOT.MonoPInvokeCallback(typeof(NativeBindings.MLAudioMicMuteCallback))]
private static void HandleOnMLAudioSetMicMuteCallback([MarshalAs(UnmanagedType.I1)] bool isMuted, IntPtr callback)
{
Instance.isMicrophoneMuted = isMuted;
MLThreadDispatch.Call(isMuted, OnMicrophoneMuteChanged);
}
///
/// Returns the mute state of the microphone.
///
/// The mute state of the microphone.
///
/// MLResult.Result will be MLResult.Code.Ok if successful.
/// MLResult.Result will be MLResult.Code.UnspecifiedFailure if failed due to internal error.
/// MLResult.Result will be MLResult.Code.InvalidParam if a parameter is invalid.
/// MLResult.Result will be MLResult.Code.PermissionDenied if AudioCaptureMic permission is denied.
/// MLResult.Result will be MLResult.Code.AudioNotImplemented if the function is not implemented.
///
private MLResult.Code GetMicrophoneMuted(out bool isMuted)
{
MLResult.Code result;
try
{
nativeIsMicMutedPerfMarker.Begin();
result = NativeBindings.MLAudioGetMicMute(out isMuted);
MLResult.DidNativeCallSucceed(result, nameof(NativeBindings.MLAudioGetMicMute));
nativeIsMicMutedPerfMarker.End();
if (result != MLResult.Code.Ok)
{
MLPluginLog.ErrorFormat("MLAudioInput.GetMicrophoneMuted failed to get the value. Reason: {0}", result);
}
}
catch (System.DllNotFoundException)
{
// Exception is caught in the Singleton BaseStart().
throw;
}
return result;
}
///
/// Registers a callback for the device microphone mute change event.
///
///
/// MLResult.Result will be MLResult.Code.Ok if successful.
/// MLResult.Result will be MLResult.Code.UnspecifiedFailure if failed due to internal error.
/// MLResult.Result will be MLResult.Code.InvalidParam if a parameter is invalid.
/// MLResult.Result will be MLResult.Code.PermissionDenied if AudioCaptureMic permission is denied.
/// MLResult.Result will be MLResult.Code.AudioNotImplemented if the function is not implemented.
///
private MLResult.Code RegisterOnMicrophoneMuteCallback()
{
MLResult.Code result;
try
{
nativeSetMicMuteCallbackPerfMarker.Begin();
// Attempt to register the native callback for the volume change event.
result = NativeBindings.MLAudioSetMicMuteCallback(HandleOnMLAudioSetMicMuteCallback, IntPtr.Zero);
nativeSetMicMuteCallbackPerfMarker.End();
if (result != MLResult.Code.Ok)
{
MLPluginLog.ErrorFormat("MLAudioInput.RegisterOnAudioSetMicMuteCallback failed to register callback. Reason: {0}", result);
}
}
catch (System.DllNotFoundException)
{
// Exception is caught in the Singleton BaseStart().
throw;
}
return result;
}
///
/// Unregisters a previously registered callback for the device microphone mute change event.
///
///
/// MLResult.Result will be MLResult.Code.Ok if successful.
/// MLResult.Result will be MLResult.Code.UnspecifiedFailure if failed due to internal error.
/// MLResult.Result will be MLResult.Code.InvalidParam if a parameter is invalid.
/// MLResult.Result will be MLResult.Code.PermissionDenied if AudioCaptureMic permission is denied.
/// MLResult.Result will be MLResult.Code.AudioNotImplemented if the function is not implemented.
///
private MLResult.Code UnregisterOnMicrophoneMuteCallback()
{
MLResult.Code result;
try
{
nativeSetMicMuteCallbackPerfMarker.Begin();
// Unregister the native callback for the microphone mute change event.
result = NativeBindings.MLAudioSetMicMuteCallback(null, IntPtr.Zero);
nativeSetMicMuteCallbackPerfMarker.End();
if (result != MLResult.Code.Ok)
{
MLPluginLog.ErrorFormat("MLAudioInput.UnregisterOnMicrophoneMuteCallback failed to register callback. Reason: {0}", result);
}
}
catch (System.DllNotFoundException)
{
MLPluginLog.Error(MLResult.Code.APIDLLNotFound);
throw;
}
return result;
}
///
/// Sets the mute state of the microphone.
///
/// The microphone mute state.
private void InternalSetMicMute(bool mute)
{
try
{
nativeSetMicMutePerfMarker.Begin();
MLResult.Code result = NativeBindings.MLAudioSetMicMute(mute);
nativeSetMicMutePerfMarker.End();
if (result != MLResult.Code.Ok)
{
MLPluginLog.ErrorFormat("MLAudioInput.InternalSetMicMute failed to set the value. Reason: {0}", result);
}
this.isMicrophoneMuted = mute;
}
catch (System.DllNotFoundException)
{
MLPluginLog.Error(MLResult.Code.APIDLLNotFound);
throw;
}
}
}
}