Integration with PanaCast 50

The following section outlines the basic steps to expose Jabra PanaCast 50 features using the C# wrapper from the Jabra SDK for Windows. You will learn how to:

  • Initialize the SDK using ServiceFactory
  • Get access to a DeviceService instance
  • Handle device arrival and removal notifications
  • Filter out a video device
  • Obtain an IDevice instance

Using the IDevice interface, you can call various APIs to get people count, set room capacity limits, control camera pan, tilt and zoom settings, set camera presets, and dynamically change video modes.

The code snippets in the following section demonstrate how you can build a simple WinForms application and use a TreeView control to show the Jabra devices connected to USB.

Initializing the library

The C# wrapper exposes a few core interfaces such as IServiceFactory, IDeviceService, IDevice, and ISettings to use with Jabra audio and video devices.

To use the Jabra library in your managed .NET application, you must add a reference to JabraSDK.dll providing access to all core interfaces and data types.

The following code snippet shows how you can instantiate ServiceFactory, register your client, and get an instance of DeviceService. Using DeviceService, you can register for a few callbacks to handle device arrival and removal events, as well as device logging events.

// Class members to keep track of Jabra core interfaces
using JabraSDK;

IServiceFactory m_serviceFactory = null;
IDeviceService m_deviceService = null;
IDevice m_currentDevice = null;
// Jabra SDK init
m_serviceFactory = new ServiceFactory();

//Replace with your Partner Key from  https://developer.jabra.com/
m_serviceFactory.SetClientId("xxxxx");
m_deviceService = m_serviceFactory.CreateDeviceService();

// Device arrival and removal event handlers for when a Jabra device is attached or
// removed from USB port. This event is also triggered for all the Jabra USB 
// device that are already attached to the USB port
m_deviceService.DeviceAdded += M_deviceService_DeviceAdded;
m_deviceService.DeviceRemoved += M_deviceService_DeviceRemoved;

// Device Logging event handler
m_deviceService.DeviceLoggingInput += M_deviceService_DeviceLoggingInput;

Handling Device Arrival and Removal Notifications

When you have registered for the DeviceAdded, DeviceRemoved, and the DeviceLoggingInput events by specifying callback methods, the callback methods will be asynchronous and called from different threads.

One of the typical actions you can take on these callback methods is to update Windows UI elements (TreeView) already created on the main thread. Because you cannot update Windows UI elements from a secondary thread directly, you must marshal and post them to the main thread via Control.Invoke as shown in the UpdateMainThreadUI function.

On a DeviceRemoved event, you can update the WinForm TreeView control and remove the device from the TreeView as shown in the RemoveDeviceFromTreeView function code sample that follows.

When a DeviceAdded event is received, you can add the device information to the TreeView, and do some initialization for Jabra PanaCast 50, as shown in the AddDeviceToTreeView and InitVideoDevice methods.

//Event handlers for device removal, arrival and device logging events
private void M_deviceService_DeviceRemoved(object sender, DeviceRemovedEventArgs e)
{
    UpdateMainThreadUI(UIAction.eDeviceRemoved, e.Device);

}

private void M_deviceService_DeviceAdded(object sender, DeviceAddedEventArgs e)
{
     UpdateMainThreadUI(UIAction.eDeviceAdded, e.Device);

     //Initialize Video device and set required properties
     InitVideoDevice(e.Device);
}

private void M_deviceService_DeviceLoggingInput(object sender, DeviceLoggingEventArgs e)
{               
    UpdateMainThreadUI(UIAction.eDeviceLog, e);
}



//Helper methods to marshal device arrival, removal and device logging events 
//to main thread to update Windows UI control created in the main thread
internal enum UIAction
{
    eDeviceAdded,
    eDeviceRemoved,
    eDeviceLog
}

private delegate void MarshalToMainForm(UIAction action, object obj);

private void UpdateMainThreadUI(UIAction action, object e)
{
     object[] args = new object[] { action, e };

     MarshalToMainForm MarshalToFormDelegate = new MarshalToMainForm(AccessMainForm);

     base.Invoke(MarshalToFormDelegate, args);

}


private void AccessMainForm(UIAction action, object obj)
{
    switch (action)
    {
         case UIAction.eDeviceAdded:
              AddDeviceToTreeView((IDevice)obj);
              break;

         case UIAction.eDeviceRemoved:
              RemoveDeviceFromTreeView((IDevice)obj);
               break;

         case UIAction.eDeviceLog:
              HandleDeviceLogEvents((DeviceLoggingEventArgs)obj);
              break;

      }
}

//Add device to the TreeView root node: 
/Create a new TreeNode
//Use IDevice.DeviceId to uniquely identify the TreeNode in the TreeView.
//Use IDevice.Name and IDevice.ProductId to display device info 
//Add the TreeNode to the TreeView
private void AddDeviceToTreeView(IDevice dev)
{
    if (m_rootNode != null)
    {
       TreeNode tn = new TreeNode();
       tn.Tag = dev.DeviceId;
       tn.Text = String.Format(dev.DeviceId + ". " + dev.Name + "( PID = 0x" + dev.ProductId.ToString("x") + " )");

       m_rootNode.Nodes.Add(tn);
       m_rootNode.Expand();
   }
}

//Remove device from the TreeView:
//Iterate through all the Nodes in the TreeView to find the TreeNode to remove
//Use IDevice.DeviceId for identifying the TreeNode for the device that is removed
//Remove the TreeNode from the TreeView
private void RemoveDeviceFromTreeView(IDevice dev)
{
    if (m_rootNode != null)
    {
        TreeNode nodeToRemove = null;
        foreach (TreeNode tn in m_rootNode.Nodes)
        {
            if ((int)tn.Tag == dev.DeviceId)
            {
                 nodeToRemove = tn;
                 break;
              }
         }

  if (nodeToRemove != null)
         {
              m_rootNode.Nodes.Remove(nodeToRemove);
              m_rootNode.Expand();
         }
     }
 }

Setting Room Capacity and People Count

The device arrival and removal methods are called for all Jabra USB video and audio devices supported by the Jabra library.

In addition to updating the TreeView UI control, you must also check for the device type. If it is a video device, you must also set video device-specific properties.

To set room capacity limits and receive notifications when the capacity exceeds the limit, you can use the IDevice methods SetRoomCapacity and SetRoomCapacityNotificationEnabled. Moreover, the SetNotificationStyle and SetNotificationUsage methods specifies the method (LED, Tone, Voice) and frequency (Always or Only When Video Is Enabled) of notifications.

To get the current People Count in the room, you can use the GetPeopleCount method. Changes in People Count are reported as part of the device logging events, so you must enable device logging by calling DeviceLoggingConfiguration(true) on the IDevice instance.

In addition, you can set how frequently the People Count change event is reported by calling the SetPeopleCountReportInterval method. As the People Count changes, you must specify an argument with an interval in seconds, as shown in the following code snippet:

//Check for Video device and set properties for room capacity, device logging
//and people count reporting interval
private void InitVideoDevice(IDevice dev)
{ 
    //Check for Video device
    if (dev.IsFeatureSupported(DeviceFeature.Video))
    {
       try
       {
           //Set the current video device instance so you can access the IDevice
           //instance from other modules
           m_currentDevice = dev;

           //Set the Room Capacity to 3 people
           dev.SetRoomCapacity(3);
           dev.SetRoomCapacityNotificationEnabled(true);

           //Set Room capacity exceeded notification alerts
           dev.SetNotificationStyle(NotificationStyle.LedTonesAndVoice);
           dev.SetNotificationUsage(NotificationUsage.WhenVideoIsEnabled);

           //Get the current people count in the room
    short peopleCount = dev.GetPeopleCount();

           //Enable Device Logging as People count changes are reported as part of the
        //device logging events.
           dev.DeviceLoggingConfiguration(true);

           //Set interval (in seconds) for people count event reporting
           dev.SetPeopleCountReportInterval(10);

        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "Jabra SDK Exception");
        }
    }
}

Handling Device Logging Events: Parsing People Count

When the People Count changes, the DeviceLoggingInput event handler is called, and the DeviceLoggingEventArgs Data property presents the JSON representation of the device event payload.

For example, see "People_count": "1" in the following Device Log Event:

DeviceID = 1,
Data = {
  "AppID": "0NcMNlux1F4w4lU+6AG7kAM8KpzBgFag2CmoDbSn5sQ=",
  "Device Name": "Jabra PanaCast 50",
  "ESN": "70BF92FEBD86",
  "FW": "1.15.0",
  "LocalTimeStamp": "05-01-2022 21:19:59",
  "People_count": "1",
  "Pid": "3012",
  "Raw data": "0x03 0x00 0x01 0x00",
  "Seq.No": 5,
  "Variant": "08-0A"
}

You can use a JSON parsing library such as Newtonsoft.Json to parse the payload and extract the "People_count" property as shown in the following code snippet:

private void HandleDeviceLogEvents(DeviceLoggingEventArgs e)
{
   //Parse People Count from JSON payload
   var parsed = JObject.Parse(e.Data);
   JToken pc = parsed["People_count"];
   if (pc != null)
   {
      String peopleCount = String.Format("People Count = {0}", pc);
      tsPeopleCount.Text = peopleCount;
   }
}

When People Count in the room exceeds capacity, a device logging event is reported.

For example, see "Room_exceeded": "TRUE" in the following Device Log Event:

DeviceID = 1,
Data = {
  "AppID": "0NcMNlux1F4w4lU+6AG7kAM8KpzBgFag2CmoDbSn5sQ=",
  "Device Name": "Jabra PanaCast 50",
  "ESN": "70BF92FEBD86",
  "FW": "1.15.0",
  "LocalTimeStamp": "05-01-2022 21:24:32",
  "Pid": "3012",
  "Raw data": "0x01 0x0a 0x01",
  "Room_exceeded": "TRUE",
  "Seq.No": 5,
  "Variant": "08-0A"
}

Based on the chosen notification method and frequency, you will receive LED, tone, or voice alerts on the Panacast 50.

Camera Control, Video Signal Settings, and Intelligent Zoom

Jabra PanaCast 50 supports camera control settings such as Zoom, Pan, Tilt, etc. and Video Signal settings such as Contrast, Brightness, Hue, etc. via standard UVC through Video Control Input and Output descriptors.

Therefore, any Windows video camera tool that supports UVC can access the supported settings and allow end-users to change them.

The following example shows video signal and camera control settings supported by PanaCast 50.

Jabra PanaCast controls 1

Jabra PanaCast controls 2

To change these video device settings, a Windows application developer can use tools like DirectShow or Media Foundation SDK. Moreover, the Jabra SDK library enables you to read, write, and get the range of each video device setting by providing simple APIs.

For example, using the IDevice instance, you can call the GetZoomLimits, GetPanTiltLimits methods to get metadata about the Zoom, Pan, and Tilt ranges or call the SetZoom, SetPanTilt methods to set them on the Jabra device.

PanaCast 50 also lets you store three camera presets for Pan, Tilt, and Zoom. You can apply them via the StorePTZPreset and ApplyPTZPreset methods as shown in the following code snippet.

//Get PTZ Limits from the device
ZoomLimits zl = dev.GetZoomLimits();
PanAndTiltLimits pl = dev.GetPanTiltLimits();

//Set PTZ Max and store in preset 1
dev.SetZoom(zl.Max);
dev.SetPanTilt(pl.PanLimits.Max, pl.TiltLimits.Max);
dev.StorePTZPreset(PTZPresetSlot.PTZPreset1);


//Set PTX min and store in preset 2
dev.SetZoom(zl.Min);
dev.SetPanTilt(pl.PanLimits.Min, pl.TiltLimits.Min);
dev.StorePTZPreset(PTZPresetSlot.PTZPreset2);

//Set PTX and store in preset 3
dev.SetZoom((ushort)(zl.Max/2));
dev.SetPanTilt(pl.PanLimits.Max /2, pl.TiltLimits.Max/2);
dev.StorePTZPreset(PTZPresetSlot.PTZPreset3);
//Apply Preset 1 to the device
dev.ApplyPTZPreset(PTZPresetSlot.PTZPreset1);

Using the Jabra SDK library, you can change Intelligent Zoom and Virtual Director AI features on the Jabra PanaCast 50. You can get the current video mode by calling the GetVideoMode method and switch between full-screen, Intelligent Zoom, and Virtual Director (Active speaker) modes by calling the SetVideoMode method, as shown in the following code sample.

//Get current Video Mode 
VideoMode vmode = dev.GetVideoMode();

//Set the Video mode to Virtual Director to track active speaker
dev.SetVideoMode(VideoMode.ActiveSpeaker);