Events#

using Itala;
using Itala.GenApi;

/// <summary>
/// "Events" example shows how the client code can react to events sent by
///  a device. ItalaApiNET is responsible for detecting the incoming events, updating
///  the related values on the nodemap (if any) and notifying the user.
///  The natural way to handle events is via the functionality provided by GenApi 
///  shown in the NodeCallback example.
///  Additionally, ItalaApiNET provides a way to handle events coming directly
///  from the IDevice interface.
/// </summary>
internal class Program
{
  const int SLEEP = 1000;

  private static void Events_Sample()
  {
    Console.WriteLine("######## Events ########");
    ISystem system = SystemFactory.Create();
    List<DeviceInfo> deviceInfos = system.EnumerateDevices();

    if (deviceInfos.Count == 0)
      throw new ItalaRuntimeException("No devices found. Example canceled.");
    if (deviceInfos[0].AccessStatus != DeviceAccessStatus.AvailableReadWrite)
      throw new ItalaRuntimeException("Target device is unaccessible in RW mode. Example canceled.");
    IDevice device = system.CreateDevice(deviceInfos[0]);
    Console.WriteLine("First device initialized.");

    // Select the exposure end event..
    IEnumeration eventSelector = device.GetNodeMap().GetNode<IEnumeration>("EventSelector");
    if (!eventSelector.IsWritable)
      throw new ItalaRuntimeException("Unable to select the exposure end event. Aborting.");
    eventSelector.FromString("ExposureEnd");

    // ..and enable it on the device. The original value is also kept so 
    // that it can be restored at the end of the example.
    IEnumeration eventNotification = device.GetNodeMap().GetNode<IEnumeration>("EventNotification");
    if (!eventNotification.IsWritable)
      throw new ItalaRuntimeException("Unable to turn on notifications for exposure end event. Aborting.");
    Int64 originalEventNotification = eventNotification.IntValue;
    eventNotification.FromString("On");
    Console.WriteLine("Exposure end event enabled on the device.");

    // Start to listen for events on the host.
    device.EnableEvents();
    Console.WriteLine("Event listening enabled on the host.");

    // Get one of the exposure end event related nodes. In this case, the frame timestamp
    // is chosen. WARNING: the event node is not available until the event occurs, so no
    // availability check is performed here.
    INode eventExposureEndTimestamp = device.GetNodeMap().GetNode("EventExposureEndTimestamp");

    // The handler is registered to the EventExposureEndTimestamp node. Every time the
    // node value changes, the handler gets called and the new value can be read.
    NodeChangedEventHandler onNodeChanged = (INode node) =>
    {
      IInteger eventExposureEndTimestamp = node.TryGetAs<IInteger>();
      Console.WriteLine("\tExposureEndEventTimestamp value change detected by the handler, new value is " + eventExposureEndTimestamp.Value);
    };
    eventExposureEndTimestamp.NodeChanged += onNodeChanged;
    Console.WriteLine("Handler registered to the EventExposureEndTimestamp node...\n");

    // Additionally, a different handler can be registered to the IDevice interface
    // to handle the event coming from the device without the GenApi mechanism involved.
    // When the event occurs, the handler registered by the user is called.
    DeviceEventHandler onDeviceEvent = (IDevice device, ulong eventId) =>
    {
      IInteger eventExposureEnd = device.GetNodeMap().GetNode<IInteger>("EventExposureEnd");
      if (eventExposureEnd.Value == (Int64)eventId)
      {
        Console.WriteLine("Handler called on device event, occurred at "+ device.GetNodeMap().GetNode<IInteger>("EventExposureEndTimestamp").Value+"\n");
      }
    };
    device.DeviceEvent += onDeviceEvent;

    device.StartAcquisition();
    Thread.Sleep(SLEEP);
    device.StopAcquisition();

    // When the event functionality is no longer required, the function
    // must be unregistered from the node. The same is true for the device event handler.
    // The event listening must be disabled.
    eventExposureEndTimestamp.NodeChanged -= onNodeChanged;
    device.DisableEvents();
    device.DeviceEvent -= onDeviceEvent;

    //Set original value in camera
    eventNotification.IntValue = originalEventNotification;

    device.Dispose();
    Console.WriteLine("Device instance disposed.");
    system.Dispose();
    Console.WriteLine("System instance disposed.");
  }

  private static void Main(string[] args)
  {
    try
    {
      Events_Sample();
    }
    catch (Exception ex)
    {
      Console.WriteLine(ex.ToString());
    }
  }
}