/// <summary> /// Create an audio track from a local audio capture device (microphone). /// This does not add the track to any peer connection. Instead, the track must be added manually to /// an audio transceiver to be attached to a peer connection and transmitted to a remote peer. /// </summary> /// <param name="settings">Settings to initialize the local audio track.</param> /// <returns>Asynchronous task completed once the device is capturing and the track is created.</returns> /// <remarks> /// On UWP this requires the "microphone" capability. /// See <see href="https://docs.microsoft.com/en-us/windows/uwp/packaging/app-capability-declarations"/> /// for more details. /// </remarks> public static Task <LocalAudioTrack> CreateFromDeviceAsync(LocalAudioTrackSettings settings = null) { return(Task.Run(() => { // On UWP this cannot be called from the main UI thread, so always call it from // a background worker thread. string trackName = settings?.trackName; if (string.IsNullOrEmpty(trackName)) { trackName = Guid.NewGuid().ToString(); } // Create interop wrappers var track = new LocalAudioTrack(trackName); // Parse settings var config = new PeerConnectionInterop.LocalAudioTrackInteropInitConfig(track, settings); // Create native implementation objects uint res = LocalAudioTrackInterop.LocalAudioTrack_CreateFromDevice(config, trackName, out LocalAudioTrackHandle trackHandle); Utils.ThrowOnErrorCode(res); track.SetHandle(trackHandle); return track; })); }
/// <inheritdoc/> public void Dispose() { if (_nativeHandle.IsClosed) { return; } // Remove the track from the peer connection, if any if (Transceiver != null) { Debug.Assert(PeerConnection != null); Debug.Assert(Transceiver.LocalTrack == this); Transceiver.LocalAudioTrack = null; } Debug.Assert(PeerConnection == null); Debug.Assert(Transceiver == null); // Unregister interop callbacks if (_selfHandle != IntPtr.Zero) { LocalAudioTrackInterop.LocalAudioTrack_RegisterFrameCallback(_nativeHandle, null, IntPtr.Zero); Utils.ReleaseWrapperRef(_selfHandle); _selfHandle = IntPtr.Zero; _interopCallbackArgs = null; } // Destroy the native object. This may be delayed if a P/Invoke callback is underway, // but will be handled at some point anyway, even if the managed instance is gone. _nativeHandle.Dispose(); }
private void RegisterInteropCallbacks() { _interopCallbackArgs = new LocalAudioTrackInterop.InteropCallbackArgs() { Track = this, FrameCallback = LocalAudioTrackInterop.FrameCallback, }; _selfHandle = Utils.MakeWrapperRef(this); LocalAudioTrackInterop.LocalAudioTrack_RegisterFrameCallback( _nativeHandle, _interopCallbackArgs.FrameCallback, _selfHandle); }