diff --git a/FSharp.FlashCap/FSharp.FlashCap.fsproj b/FSharp.FlashCap/FSharp.FlashCap.fsproj index b337f3d..d4ee34f 100644 --- a/FSharp.FlashCap/FSharp.FlashCap.fsproj +++ b/FSharp.FlashCap/FSharp.FlashCap.fsproj @@ -1,7 +1,7 @@ - net48;netstandard2.0;netstandard2.1;net5.0;net6.0;net7.0;net8.0;net9.0 + net48;netstandard2.0;netstandard2.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 true diff --git a/FlashCap.Core/FlashCap.Core.csproj b/FlashCap.Core/FlashCap.Core.csproj index c59cbb8..36d91d6 100644 --- a/FlashCap.Core/FlashCap.Core.csproj +++ b/FlashCap.Core/FlashCap.Core.csproj @@ -1,7 +1,7 @@ - net35;net40;net45;net461;net48;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0 + net35;net40;net45;net461;net48;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 True $(NoWarn);CS0649 true diff --git a/FlashCap.Core/Internal/AVFoundation/AVCaptureSession.cs b/FlashCap.Core/Internal/AVFoundation/AVCaptureSession.cs index f248612..3492a24 100644 --- a/FlashCap.Core/Internal/AVFoundation/AVCaptureSession.cs +++ b/FlashCap.Core/Internal/AVFoundation/AVCaptureSession.cs @@ -23,6 +23,14 @@ public AVCaptureSession() : base(IntPtr.Zero, false) Init(); } + private void ValidateHandle(string method) + { + if (Handle == IntPtr.Zero) + { + throw new NullReferenceException($"{nameof(AVCaptureSession)} handle is NULL in '{method}'."); + } + } + private void Init() { var sessionClass = LibObjC.SendAndGetHandle( @@ -34,50 +42,61 @@ private void Init() LibObjC.GetSelector("init")); Handle = sessionObj; + ValidateHandle(nameof(Init)); - LibCoreFoundation.CFRetain(this.Handle); + LibCoreFoundation.CFRetain(this.Handle); } - public void AddInput(AVCaptureInput input) => - LibObjC.SendNoResult( - Handle, - LibObjC.GetSelector("addInput:"), - input.Handle); - + public void AddInput(AVCaptureInput input) + { + ValidateHandle(nameof(AddInput)); + + LibObjC.SendNoResult( + Handle, + LibObjC.GetSelector("addInput:"), + input.Handle); + } + public void AddOutput(AVCaptureOutput output) { IntPtr allocSel = LibObjC.GetSelector("alloc"); IntPtr initSel = LibObjC.GetSelector("init"); - var videoDataOutputObj = output as AVCaptureVideoDataOutput ; - - if (videoDataOutputObj == null) - { - throw new Exception("Failed to get video data output"); - } - - var videoDataOutput = videoDataOutputObj.Handle; - + var videoDataOutputObj = output as AVCaptureVideoDataOutput + ?? throw new Exception("Failed to get video data output") ; + + var videoDataOutput = videoDataOutputObj.Handle; + + ValidateHandle(nameof(AddOutput)); LibObjC.SendNoResult( Handle, LibObjC.GetSelector("addOutput:"), videoDataOutput); } - public bool CanAddOutput(AVCaptureOutput output) => - LibObjC.SendAndGetBool( + public bool CanAddOutput(AVCaptureOutput output) + { + ValidateHandle(nameof(CanAddOutput)); + return LibObjC.SendAndGetBool( Handle, LibObjC.GetSelector("canAddOutput:"), - output.Handle); - - public void StartRunning() => + output.Handle); + } + + public void StartRunning() + { + ValidateHandle(nameof(StartRunning)); LibObjC.SendNoResult( Handle, - LibObjC.GetSelector("startRunning")); - - public void StopRunning() => + LibObjC.GetSelector("startRunning")); + } + + public void StopRunning() + { + ValidateHandle(nameof(StopRunning)); LibObjC.SendNoResult( Handle, - LibObjC.GetSelector("stopRunning")); + LibObjC.GetSelector("stopRunning")); + } } } diff --git a/FlashCap.Core/Internal/AVFoundation/LibAVFoundation.cs b/FlashCap.Core/Internal/AVFoundation/LibAVFoundation.cs index 4690e56..e23130c 100644 --- a/FlashCap.Core/Internal/AVFoundation/LibAVFoundation.cs +++ b/FlashCap.Core/Internal/AVFoundation/LibAVFoundation.cs @@ -9,7 +9,6 @@ //////////////////////////////////////////////////////////////////////////// using System; -using System.Diagnostics; using System.Runtime.InteropServices; using System.Linq; using static FlashCap.Internal.NativeMethods_AVFoundation; @@ -24,6 +23,14 @@ internal static partial class LibAVFoundation public delegate void AVRequestAccessStatus(bool accessGranted); + private static void ValidateHandle(string method) + { + if (Handle == IntPtr.Zero) + { + throw new NullReferenceException($"{nameof(LibAVFoundation)} handle is NULL in '{method}'."); + } + } + public sealed class AVFrameRateRange : LibObjC.NSObject { public AVFrameRateRange(IntPtr handle, bool retain) : @@ -226,6 +233,7 @@ public static AVAuthorizationStatus GetAuthorizationStatus(IntPtr mediaType) public static unsafe void RequestAccessForMediaType(IntPtr mediaType, AVRequestAccessStatus completion) { + ValidateHandle(nameof(RequestAccessForMediaType)); RequestAccessForMediaTypeBlockFactory ??= LibObjC.BlockLiteralFactory.CreateFactory( signature: "v@?^vC", delegate (IntPtr block, byte accessGranted) @@ -260,6 +268,7 @@ public AVCaptureDeviceDiscoverySession(IntPtr handle, bool retain) : public static AVCaptureDeviceDiscoverySession DiscoverySessionWithVideoDevices() { + ValidateHandle(nameof(DiscoverySessionWithVideoDevices)); var deviceTypes = new[] { AVCaptureDeviceType.BuiltInWideAngleCamera, @@ -369,7 +378,7 @@ private static unsafe IntPtr FromDevice(AVCaptureDevice device) public abstract class AVCaptureVideoDataOutputSampleBuffer : LibObjC.NSObject { private const string HandleVariableName = nameof(GCHandle); - private static IntPtr HandleVariableDescriptor; + private static readonly IntPtr HandleVariableDescriptor; static AVCaptureVideoDataOutputSampleBuffer() { diff --git a/FlashCap/FlashCap.csproj b/FlashCap/FlashCap.csproj index 2294f6f..4be0d32 100644 --- a/FlashCap/FlashCap.csproj +++ b/FlashCap/FlashCap.csproj @@ -1,7 +1,7 @@ - net35;net40;net45;net461;net48;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0 + net35;net40;net45;net461;net48;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 $(NoWarn);CS0649 true diff --git a/samples/FlashCap.Avalonia/FlashCap.Avalonia/FlashCap.Avalonia.csproj b/samples/FlashCap.Avalonia/FlashCap.Avalonia/FlashCap.Avalonia.csproj index 63e5bf8..59d0390 100644 --- a/samples/FlashCap.Avalonia/FlashCap.Avalonia/FlashCap.Avalonia.csproj +++ b/samples/FlashCap.Avalonia/FlashCap.Avalonia/FlashCap.Avalonia.csproj @@ -2,7 +2,7 @@ WinExe - net48;net8.0 + net48;net8.0;net9.0;net10.0 true