// License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2017 Intel Corporation. All Rights Reserved. namespace Intel.RealSense { using System; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; using System.Runtime.ConstrainedExecution; using System.Security.Permissions; [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)] public sealed class ContextHandle : SafeHandleZeroOrMinusOneIsInvalid { public ContextHandle() : base(true) { } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] override protected bool ReleaseHandle() { if (!IsClosed) { NativeMethods.rs2_delete_context(this); } return true; } } /// /// default librealsense context class /// public class Context : IDisposable { private ContextHandle handle; static Context() { object error; ApiVersion = NativeMethods.rs2_get_api_version(out error); } /// /// Initializes a new instance of the class. /// public Context() { object error; handle = NativeMethods.rs2_create_context(ApiVersion, out error); onDevicesChangedCallback = new rs2_devices_changed_callback(OnDevicesChangedInternal); } /// /// Gets the safe handle /// /// Thrown when public ContextHandle Handle { get { if (handle.IsInvalid) { throw new ObjectDisposedException(GetType().Name); } return handle; } } /// /// the version API encoded into integer value "1.9.3" -> 10903 /// public static readonly int ApiVersion; /// /// Gets the API version /// public string Version { get { if (ApiVersion / 10000 == 0) { return ApiVersion.ToString(); } return $"{ApiVersion / 10000}.{(ApiVersion % 10000) / 100}.{ApiVersion % 100}"; } } // Keeps the delegate alive, if we were to assign onDevicesChanged directly, there'll be // no managed reference it, it will be collected and cause a native exception. private readonly rs2_devices_changed_callback onDevicesChangedCallback; /// /// Delegate to register as per-notifications callback /// /// list of removed devices /// list of added devices public delegate void OnDevicesChangedDelegate(DeviceList removed, DeviceList added); private event OnDevicesChangedDelegate OnDevicesChangedEvent; private readonly object deviceChangedEventLock = new object(); /// /// these events will be raised by the context whenever new RealSense device is connected or existing device gets disconnected /// public event OnDevicesChangedDelegate OnDevicesChanged { add { lock (deviceChangedEventLock) { if (OnDevicesChangedEvent == null) { object error; NativeMethods.rs2_set_devices_changed_callback(handle, onDevicesChangedCallback, IntPtr.Zero, out error); } OnDevicesChangedEvent += value; } } remove { lock (deviceChangedEventLock) { OnDevicesChangedEvent -= value; } } } /// /// Create a static snapshot of all connected devices at the time of the call /// /// Controls what kind of devices will be returned /// the list of devices /// devices in the collection should be disposed public DeviceList QueryDevices(bool include_platform_camera = false) { object error; var ptr = NativeMethods.rs2_query_devices_ex(handle, include_platform_camera ? 0xff : 0xfe, out error); return new DeviceList(ptr); } /// /// Gets a static snapshot of all connected devices at the time of the call /// /// the list of devices public DeviceList Devices { get { return QueryDevices(); } } /// Create a new device and add it to the context /// The file from which the device should be created /// a device that plays data from the file public PlaybackDevice AddDevice(string file) { object error; var ptr = NativeMethods.rs2_context_add_device(handle, file, out error); return Device.Create(ptr); } /// Removes a playback device from the context, if exists /// The file name that was used to add the device public void RemoveDevice(string file) { object error; NativeMethods.rs2_context_remove_device(handle, file, out error); } private void OnDevicesChangedInternal(IntPtr removedList, IntPtr addedList, IntPtr userData) { var e = OnDevicesChangedEvent; if (e != null) { using (var removed = new DeviceList(removedList)) using (var added = new DeviceList(addedList)) { e(removed, added); } } } public void Dispose() { handle.Dispose(); } } }