From 0cd3c1bdc509d5ec58ccfc42561b789d6077b728 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 29 Jul 2021 13:01:02 -0600 Subject: [PATCH 1/4] fix(ZoomRoom): #767 #768 Adds Output2 on ZoomRoom and updates to UI for VTC Updates EssentialsVideoCodecUiDriver and codec classes to better deal with dynamic use of IHasCallHistory and --- .../UI/JoinConstants/UIBoolJoin.cs | 7 ++++- .../VC/EssentialsVideoCodecUiDriver.cs | 26 ++++++++++++++----- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 3 ++- .../VideoCodec/CiscoCodec/xStatus.cs | 20 ++++++++++++-- .../VideoCodec/VideoCodecBase.cs | 4 +-- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 6 +++++ 6 files changed, 53 insertions(+), 13 deletions(-) diff --git a/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs b/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs index 293fddd5..f8685671 100644 --- a/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs +++ b/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs @@ -103,7 +103,7 @@ namespace PepperDash.Essentials /// /// 1202 /// - public const uint VCStagingInactivePopoverVisible = 1202; + public const uint VCStagingInactivePopoverWithRecentsVisible = 1202; /// /// /// @@ -121,6 +121,11 @@ namespace PepperDash.Essentials /// public const uint VCRecentsVisible = 1206; + /// + /// 1202 + /// + public const uint VCStagingInactivePopoverWithoutRecentsVisible = 1207; + /// /// 1208 /// diff --git a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs index 5642d757..6d5521a8 100644 --- a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs +++ b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs @@ -142,7 +142,10 @@ namespace PepperDash.Essentials.UIDrivers.VC VCControlsInterlock.SetButDontShow(UIBoolJoin.VCKeypadVisible); StagingBarsInterlock = new JoinedSigInterlock(triList); - StagingBarsInterlock.SetButDontShow(UIBoolJoin.VCStagingInactivePopoverVisible); + if(Codec is IHasCallHistory) + StagingBarsInterlock.SetButDontShow(UIBoolJoin.VCStagingInactivePopoverWithRecentsVisible); + else + StagingBarsInterlock.SetButDontShow(UIBoolJoin.VCStagingInactivePopoverWithoutRecentsVisible); StagingButtonsFeedbackInterlock = new JoinedSigInterlock(triList); StagingButtonsFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingKeypadPress); @@ -351,10 +354,15 @@ namespace PepperDash.Essentials.UIDrivers.VC TriList.UShortInput[UIUshortJoin.VCStagingConnectButtonMode].UShortValue = (ushort)(Codec.IsInCall ? 1 : 0); uint stageJoin; - if (Codec.IsInCall) - stageJoin = UIBoolJoin.VCStagingActivePopoverVisible; - else - stageJoin = UIBoolJoin.VCStagingInactivePopoverVisible; + if (Codec.IsInCall) + stageJoin = UIBoolJoin.VCStagingActivePopoverVisible; + else + { + if (Codec is IHasCallHistory) + stageJoin = UIBoolJoin.VCStagingInactivePopoverWithRecentsVisible; + else + stageJoin = UIBoolJoin.VCStagingInactivePopoverWithoutRecentsVisible; + } if (IsVisible) StagingBarsInterlock.ShowInterlocked(stageJoin); else @@ -513,9 +521,13 @@ namespace PepperDash.Essentials.UIDrivers.VC var codecOffCameras = Codec as IHasCameraOff; + var supportsCameraOffMode = Codec.SupportsCameraOff; + var codecAutoCameras = Codec as IHasCameraAutoMode; - if (codecAutoCameras != null) + var supportsAutoCameraMode = Codec.SupportsCameraAutoMode; + + if (codecAutoCameras != null && supportsAutoCameraMode) { CameraModeList.SetItemButtonAction(1,(b) => codecAutoCameras.CameraAutoModeOn()); TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 1 Visible"].BoolValue = true; @@ -554,7 +566,7 @@ namespace PepperDash.Essentials.UIDrivers.VC //TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanOutput["Item 2 Pressed"].SetSigFalseAction( // () => ShowCameraManualMode()); - if (codecOffCameras != null) + if (codecOffCameras != null && supportsCameraOffMode) { TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 3 Visible"].BoolValue = true; codecOffCameras.CameraIsOffFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 3 Selected"]); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index a7be2443..d31fbda1 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -314,7 +314,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco FarEndIsSharingContentFeedback = new BoolFeedback(FarEndIsSharingContentFeedbackFunc); CameraIsOffFeedback = new BoolFeedback(() => CodecStatus.Status.Video.Input.MainVideoMute.BoolValue); CameraIsMutedFeedback = CameraIsOffFeedback; - + SupportsCameraOff = true; PresentationViewMaximizedFeedback = new BoolFeedback(() => CurrentPresentationView == "Maximized"); @@ -417,6 +417,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco CodecStatus.Status.RoomAnalytics.PeoplePresence.ValueChangedAction = RoomIsOccupiedFeedback.FireUpdate; CodecStatus.Status.RoomAnalytics.PeopleCount.Current.ValueChangedAction = PeopleCountFeedback.FireUpdate; CodecStatus.Status.Cameras.SpeakerTrack.Status.ValueChangedAction = CameraAutoModeIsOnFeedback.FireUpdate; + CodecStatus.Status.Cameras.SpeakerTrack.Availability.ValueChangedAction = () => { SupportsCameraAutoMode = CodecStatus.Status.Cameras.SpeakerTrack.Availability.BoolValue; }; CodecStatus.Status.Video.Selfview.Mode.ValueChangedAction = SelfviewIsOnFeedback.FireUpdate; CodecStatus.Status.Video.Selfview.PIPPosition.ValueChangedAction = ComputeSelfviewPipStatus; CodecStatus.Status.Video.Layout.LayoutFamily.Local.ValueChangedAction = ComputeLocalLayout; diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs index 676737c4..8184289e 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs @@ -277,9 +277,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public SoftwareID SoftwareID { get; set; } } - public class Availability + public class Availability : ValueProperty { - public string Value { get; set; } + string _Value; + public bool BoolValue { get; private set; } + + public string Value + { + get + { + return _Value; + } + set + { + // If the incoming value is "Available" it sets the BoolValue true, otherwise sets it false + _Value = value; + BoolValue = value == "Available"; + OnValueChanged(); + } + } } public class Status2 : ValueProperty diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index fc38a647..c5cff74e 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -65,8 +65,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec public bool ShowSelfViewByDefault { get; protected set; } - protected bool SupportsCameraOff; - protected bool SupportsCameraAutoMode; + public bool SupportsCameraOff { get; protected set; } + public bool SupportsCameraAutoMode { get; protected set; } public bool IsReady { get; protected set; } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index f8d4bf47..9ac80c33 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -95,6 +95,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, null, this); + Output2 = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, + eRoutingSignalType.Video, + eRoutingPortConnectionType.DisplayPort, null, this); + SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc); CameraIsOffFeedback = new BoolFeedback(CameraIsOffFeedbackFunc); @@ -252,6 +256,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public RoutingInputPort CodecOsdIn { get; private set; } public RoutingOutputPort Output1 { get; private set; } + public RoutingOutputPort Output2 { get; private set; } #region ICommunicationMonitor Members @@ -685,6 +690,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // Set up output ports OutputPorts.Add(Output1); + OutputPorts.Add(Output2); } /// From 49c1c61a8830269ef3a1624a8336c24ecebf0679 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 29 Jul 2021 14:51:16 -0600 Subject: [PATCH 2/4] updates ZoomRoom to use GenericQueue --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 45 +++---------------- 1 file changed, 7 insertions(+), 38 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 9ac80c33..c2ec5c38 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -15,6 +15,7 @@ using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.DeviceTypeInterfaces; using PepperDash.Essentials.Core.Routing; +using PepperDash.Essentials.Core.Queues; using PepperDash.Essentials.Devices.Common.Cameras; using PepperDash.Essentials.Devices.Common.Codec; using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco; @@ -30,10 +31,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private const long MeetingRefreshTimer = 60000; private const uint DefaultMeetingDurationMin = 30; private const string Delimiter = "\x0D\x0A"; - private readonly CrestronQueue _receiveQueue; + + private readonly GenericQueue _receiveQueue; + //private readonly CrestronQueue _receiveQueue; - private readonly Thread _receiveThread; + //private readonly Thread _receiveThread; private readonly ZoomRoomSyncState _syncState; public bool CommDebuggingIsOn; @@ -51,11 +54,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { _props = JsonConvert.DeserializeObject(config.Properties.ToString()); - // The queue that will collect the repsonses in the order they are received - _receiveQueue = new CrestronQueue(1024); - - // The thread responsible for dequeuing and processing the messages - _receiveThread = new Thread(o => ProcessQueue(), null) { Priority = Thread.eThreadPriority.MediumPriority }; + _receiveQueue = new GenericQueue(Key + "-rxQueue", Thread.eThreadPriority.MediumPriority, 512); Communication = comm; @@ -787,37 +786,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom //if (CommDebuggingIsOn) // Debug.Console(1, this, "Gathered: '{0}'", args.Text); - _receiveQueue.Enqueue(args.Text); - - // If the receive thread has for some reason stopped, this will restart it - if (_receiveThread.ThreadState != Thread.eThreadStates.ThreadRunning) - { - _receiveThread.Start(); - } - } - - - /// - /// Runs in it's own thread to dequeue messages in the order they were received to be processed - /// - /// - private object ProcessQueue() - { - try - { - while (true) - { - var message = _receiveQueue.Dequeue(); - - ProcessMessage(message); - } - } - catch (Exception e) - { - Debug.Console(1, this, "Error Processing Queue: {0}", e); - } - - return null; + _receiveQueue.Enqueue(new ProcessStringMessage(args.Text, ProcessMessage)); } From 19cbe480a64cfa2d31d16254d58f3e3bda02311c Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 29 Jul 2021 16:39:34 -0600 Subject: [PATCH 3/4] reverts IMobileControl back to using EssentialsRoomBase instead of IEssentialsRoom for now --- PepperDashEssentials/ControlSystem.cs | 8 +- .../DeviceTypeInterfaces/IMobileControl.cs | 2 +- .../Factory/DeviceFactory.cs | 255 +++++++++--------- 3 files changed, 137 insertions(+), 128 deletions(-) diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index 033d82fe..2495340c 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -484,7 +484,7 @@ namespace PepperDash.Essentials Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge..."); - CreateMobileControlBridge(room); + CreateMobileControlBridge(room as EssentialsRoomBase); } else if (room is IEssentialsHuddleVtc1Room) { @@ -495,7 +495,7 @@ namespace PepperDash.Essentials Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge..."); - CreateMobileControlBridge(room); + CreateMobileControlBridge(room as EssentialsRoomBase); } else if (room is EssentialsTechRoom) { @@ -507,7 +507,7 @@ namespace PepperDash.Essentials Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge"); - CreateMobileControlBridge(room); + CreateMobileControlBridge(room as EssentialsRoomBase); } else { @@ -524,7 +524,7 @@ namespace PepperDash.Essentials } - private static void CreateMobileControlBridge(IEssentialsRoom room) + private static void CreateMobileControlBridge(EssentialsRoomBase room) { var mobileControl = GetMobileControlDevice(); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs index a2dda43a..c87e7865 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs @@ -8,7 +8,7 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces /// public interface IMobileControl : IKeyed { - void CreateMobileControlRoomBridge(IEssentialsRoom room, IMobileControl parent); + void CreateMobileControlRoomBridge(EssentialsRoomBase room, IMobileControl parent); void LinkSystemMonitorToAppServer(); } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs index ec041853..a17e0d91 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs @@ -1,90 +1,90 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; -using Crestron.SimplSharpPro.GeneralIO; -using Crestron.SimplSharp.Reflection; -using PepperDash.Core; -using Newtonsoft.Json.Linq; -using Newtonsoft.Json; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Config; -using PepperDash.Essentials.Core.CrestronIO; -using PepperDash.Essentials.Core.Touchpanels; - -namespace PepperDash.Essentials.Core -{ - public class DeviceFactoryWrapper - { - public CType CType { get; set; } - public string Description { get; set; } - public Func FactoryMethod { get; set; } - - public DeviceFactoryWrapper() - { - CType = null; - Description = "Not Available"; - } - } - - public class DeviceFactory - { - public DeviceFactory() - { - var assy = Assembly.GetExecutingAssembly(); - PluginLoader.SetEssentialsAssembly(assy.GetName().Name, assy); - - var types = assy.GetTypes().Where(ct => typeof(IDeviceFactory).IsAssignableFrom(ct) && !ct.IsInterface && !ct.IsAbstract); - - if (types != null) - { - foreach (var type in types) - { - try - { - var factory = (IDeviceFactory)Crestron.SimplSharp.Reflection.Activator.CreateInstance(type); - factory.LoadTypeFactories(); - } - catch (Exception e) - { - Debug.Console(0, Debug.ErrorLogLevel.Error, "Unable to load type: '{1}' DeviceFactory: {0}", e, type.Name); - } - } - } - } - - /// - /// A dictionary of factory methods, keyed by config types, added by plugins. - /// These methods are looked up and called by GetDevice in this class. - /// - static Dictionary FactoryMethods = - new Dictionary(StringComparer.OrdinalIgnoreCase); - - /// - /// Adds a plugin factory method - /// - /// - /// - public static void AddFactoryForType(string typeName, Func method) - { - Debug.Console(1, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName); - DeviceFactory.FactoryMethods.Add(typeName, new DeviceFactoryWrapper() { FactoryMethod = method}); - } - - public static void AddFactoryForType(string typeName, string description, CType cType, Func method) - { - Debug.Console(1, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName); - - if(FactoryMethods.ContainsKey(typeName)) - { - Debug.Console(0, Debug.ErrorLogLevel.Error, "Unable to add type: '{0}'. Already exists in DeviceFactory", typeName); - return; - } - - var wrapper = new DeviceFactoryWrapper() { CType = cType, Description = description, FactoryMethod = method }; - DeviceFactory.FactoryMethods.Add(typeName, wrapper); +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.GeneralIO; +using Crestron.SimplSharp.Reflection; +using PepperDash.Core; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Config; +using PepperDash.Essentials.Core.CrestronIO; +using PepperDash.Essentials.Core.Touchpanels; + +namespace PepperDash.Essentials.Core +{ + public class DeviceFactoryWrapper + { + public CType CType { get; set; } + public string Description { get; set; } + public Func FactoryMethod { get; set; } + + public DeviceFactoryWrapper() + { + CType = null; + Description = "Not Available"; + } + } + + public class DeviceFactory + { + public DeviceFactory() + { + var assy = Assembly.GetExecutingAssembly(); + PluginLoader.SetEssentialsAssembly(assy.GetName().Name, assy); + + var types = assy.GetTypes().Where(ct => typeof(IDeviceFactory).IsAssignableFrom(ct) && !ct.IsInterface && !ct.IsAbstract); + + if (types != null) + { + foreach (var type in types) + { + try + { + var factory = (IDeviceFactory)Crestron.SimplSharp.Reflection.Activator.CreateInstance(type); + factory.LoadTypeFactories(); + } + catch (Exception e) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "Unable to load type: '{1}' DeviceFactory: {0}", e, type.Name); + } + } + } + } + + /// + /// A dictionary of factory methods, keyed by config types, added by plugins. + /// These methods are looked up and called by GetDevice in this class. + /// + static Dictionary FactoryMethods = + new Dictionary(StringComparer.OrdinalIgnoreCase); + + /// + /// Adds a plugin factory method + /// + /// + /// + public static void AddFactoryForType(string typeName, Func method) + { + Debug.Console(1, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName); + DeviceFactory.FactoryMethods.Add(typeName, new DeviceFactoryWrapper() { FactoryMethod = method}); + } + + public static void AddFactoryForType(string typeName, string description, CType cType, Func method) + { + Debug.Console(1, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName); + + if(FactoryMethods.ContainsKey(typeName)) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "Unable to add type: '{0}'. Already exists in DeviceFactory", typeName); + return; + } + + var wrapper = new DeviceFactoryWrapper() { CType = cType, Description = description, FactoryMethod = method }; + DeviceFactory.FactoryMethods.Add(typeName, wrapper); } private static void CheckForSecrets(IEnumerable obj) @@ -156,44 +156,53 @@ namespace PepperDash.Essentials.Core Debug.Console(0, Debug.ErrorLogLevel.Error, "Exception occurred while creating device {0}: {1}", dc.Key, ex.Message); Debug.Console(2, "{0}", ex.StackTrace); + + if (ex.InnerException == null) + { + return null; + } + + Debug.Console(0, Debug.ErrorLogLevel.Error, "Inner exception while creating device {0}: {1}", dc.Key, + ex.InnerException.Message); + Debug.Console(2, "{0}", ex.InnerException.StackTrace); return null; } } - /// - /// Prints the type names and associated metadata from the FactoryMethods collection. - /// - /// - public static void GetDeviceFactoryTypes(string filter) - { - Dictionary types = new Dictionary(); - - if (!string.IsNullOrEmpty(filter)) - { - types = FactoryMethods.Where(k => k.Key.Contains(filter)).ToDictionary(k => k.Key, k => k.Value); - } - else - { - types = FactoryMethods; - } - - Debug.Console(0, "Device Types:"); - - foreach (var type in types.OrderBy(t => t.Key)) - { - var description = type.Value.Description; - var cType = "Not Specified by Plugin"; - - if(type.Value.CType != null) - { - cType = type.Value.CType.FullName; - } - - Debug.Console(0, - @"Type: '{0}' - CType: '{1}' - Description: {2}", type.Key, cType, description); - } - } - } + /// + /// Prints the type names and associated metadata from the FactoryMethods collection. + /// + /// + public static void GetDeviceFactoryTypes(string filter) + { + Dictionary types = new Dictionary(); + + if (!string.IsNullOrEmpty(filter)) + { + types = FactoryMethods.Where(k => k.Key.Contains(filter)).ToDictionary(k => k.Key, k => k.Value); + } + else + { + types = FactoryMethods; + } + + Debug.Console(0, "Device Types:"); + + foreach (var type in types.OrderBy(t => t.Key)) + { + var description = type.Value.Description; + var cType = "Not Specified by Plugin"; + + if(type.Value.CType != null) + { + cType = type.Value.CType.FullName; + } + + Debug.Console(0, + @"Type: '{0}' + CType: '{1}' + Description: {2}", type.Key, cType, description); + } + } + } } \ No newline at end of file From 1696ef3ac11fea37202e6ab0d0f89e2a4d7f7608 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 2 Aug 2021 16:58:32 -0600 Subject: [PATCH 4/4] Adds LocalLayoutToggle() implementation and minor updates to UI Driver --- .../UI/JoinConstants/UIBoolJoin.cs | 4 ++ .../VC/EssentialsVideoCodecUiDriver.cs | 28 ++++++++++- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 46 ++++++++++++++++++- 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs b/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs index f8685671..aaecb81a 100644 --- a/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs +++ b/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs @@ -248,6 +248,10 @@ namespace PepperDash.Essentials /// public const uint VCCameraSelectBarWithoutModeVisible = 1261; + /// + /// 1262 + /// + public const uint VCCameraAutoModeIsOnFb = 1262; /// /// 1271 diff --git a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs index 6d5521a8..e95ab5e5 100644 --- a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs +++ b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs @@ -532,6 +532,7 @@ namespace PepperDash.Essentials.UIDrivers.VC CameraModeList.SetItemButtonAction(1,(b) => codecAutoCameras.CameraAutoModeOn()); TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 1 Visible"].BoolValue = true; codecAutoCameras.CameraAutoModeIsOnFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 1 Selected"]); + codecAutoCameras.CameraAutoModeIsOnFeedback.LinkInputSig(TriList.BooleanInput[UIBoolJoin.VCCameraAutoModeIsOnFb]); //TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanOutput["Item 1 Pressed"].SetSigFalseAction( //() => codecAutoCameras.CameraAutoModeOn()); @@ -857,19 +858,32 @@ namespace PepperDash.Essentials.UIDrivers.VC // Determines if codec is in manual camera control mode and shows feedback void ShowCameraManualMode() { + Debug.Console(2, "ShowCameraManualMode"); + var inManualMode = true; var codecOffCameras = Codec as IHasCameraOff; var codecAutoCameras = Codec as IHasCameraAutoMode; + var supportsAutoCameras = codecAutoCameras != null && Codec.SupportsCameraAutoMode; + if (codecOffCameras != null && codecOffCameras.CameraIsOffFeedback.BoolValue) { inManualMode = false; + + var codecCameraMute = Codec as IHasCameraMute; + + if (codecCameraMute != null) + { + codecCameraMute.CameraMuteOff(); + inManualMode = true; + + } } // Clear auto mode - if (codecAutoCameras != null ) + if (supportsAutoCameras) { if (codecAutoCameras.CameraAutoModeIsOnFeedback.BoolValue) { @@ -1213,7 +1227,7 @@ namespace PepperDash.Essentials.UIDrivers.VC var lc = Codec as IHasCodecLayouts; if (lc != null) { - TriList.SetSigFalseAction(UIBoolJoin.VCLayoutTogglePress, lc.LocalLayoutToggleSingleProminent); + lc.LocalLayoutFeedback.LinkInputSig(TriList.StringInput[UIStringJoin.VCLayoutModeText]); lc.LocalLayoutFeedback.OutputChange += (o,a) => { @@ -1226,14 +1240,24 @@ namespace PepperDash.Essentials.UIDrivers.VC var cisco = Codec as PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.CiscoSparkCodec; if (cisco != null) { + TriList.SetSigFalseAction(UIBoolJoin.VCLayoutTogglePress, lc.LocalLayoutToggleSingleProminent); // Cisco has min/max buttons that need special sauce cisco.SharingContentIsOnFeedback.OutputChange += CiscoSharingAndPresentation_OutputChanges; //cisco.PresentationViewMaximizedFeedback.OutputChange += CiscoSharingAndPresentation_OutputChanges; TriList.SetSigFalseAction(UIBoolJoin.VCMinMaxPress, cisco.MinMaxLayoutToggle); } + + var zoomRoom = Codec as PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom.ZoomRoom; + if (zoomRoom != null) + { + TriList.BooleanInput[UIBoolJoin.VCLayoutToggleEnable].BoolValue = true; + TriList.SetSigFalseAction(UIBoolJoin.VCLayoutTogglePress, lc.LocalLayoutToggle); + } } + + } /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index c2ec5c38..eb55db9f 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -123,7 +123,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Participants = new CodecParticipants(); - SupportsCameraOff = _props.SupportsCameraOff; + SupportsCameraOff = true; // Always allow turning off the camera for zoom calls? SupportsCameraAutoMode = _props.SupportsCameraAutoMode; PhoneOffHookFeedback = new BoolFeedback(PhoneOffHookFeedbackFunc); @@ -2446,9 +2446,51 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void LocalLayoutToggle() { - throw new NotImplementedException(); + var currentLayout = LocalLayoutFeedback.StringValue; + + var eCurrentLayout = (int)Enum.Parse(typeof(zConfiguration.eLayoutStyle), currentLayout, true); + + var nextLayout = GetNextLayout(eCurrentLayout); + + if (nextLayout != zConfiguration.eLayoutStyle.None) + { + SetLayout(nextLayout); + } } + /// + /// Tries to get the next available layout + /// + /// + /// + private zConfiguration.eLayoutStyle GetNextLayout(int currentLayout) + { + if (AvailableLayouts == zConfiguration.eLayoutStyle.None) + { + return zConfiguration.eLayoutStyle.None; + } + + zConfiguration.eLayoutStyle nextLayout; + + if (((zConfiguration.eLayoutStyle)currentLayout & zConfiguration.eLayoutStyle.ShareAll) == zConfiguration.eLayoutStyle.ShareAll) + { + nextLayout = zConfiguration.eLayoutStyle.Gallery; + } + else + { + nextLayout = (zConfiguration.eLayoutStyle)(currentLayout << 1); + } + + if ((AvailableLayouts & nextLayout) == nextLayout) + { + return nextLayout; + } + else + { + return GetNextLayout((int)nextLayout); + } + } + public void LocalLayoutToggleSingleProminent() { throw new NotImplementedException();