From e4a39337434ed896f5dab3801187adb735e341e4 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 6 May 2021 16:54:41 -0600 Subject: [PATCH] Mostly coded. Needs join numbers for ZoomRoomJoinMap values --- .../Essentials Devices Common.csproj | 1 + .../VideoCodec/Interfaces/IHasCodecLayouts.cs | 24 +- .../VideoCodec/VideoCodecBase.cs | 273 ++++++++++-------- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 114 ++++---- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 258 +++++++++++++++-- .../VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs | 141 +++++++++ 6 files changed, 592 insertions(+), 219 deletions(-) create mode 100644 essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index 6586bd41..3d9e5d30 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj @@ -176,6 +176,7 @@ + diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs index 139935c0..8ba3d139 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs @@ -25,20 +25,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// public interface IHasZoomRoomLayouts : IHasCodecLayouts { - BoolFeedback LayoutViewIsOnFirstPage { get; } - BoolFeedback LayoutViewIsOnLastPage { get; } - BoolFeedback CanSwitchWallView { get; } - BoolFeedback CanSwitchSpeakerView { get; } - BoolFeedback CanSwitchShareOnAllScreens { get; } - BoolFeedback CanSwapContentWithThumbnail { get; } + event EventHandler AvailableLayoutsChanged; - List AvailableLayouts { get; } + BoolFeedback LayoutViewIsOnFirstPageFeedback { get; } // TODO: #697 Consider modifying to report button visibility in func + BoolFeedback LayoutViewIsOnLastPageFeedback { get; } // TODO: #697 Consider modifying to report button visibility in func + BoolFeedback CanSwapContentWithThumbnailFeedback { get; } + BoolFeedback ContentSwappedWithThumbnailFeedback { get; } - void GetLayouts(); // Mot sure this is necessary if we're already subscribed to zStatus Call Layout - void SetLayout(ZoomRoom.eZoomRoomLayoutStyle layoutStyle); + ZoomRoom.zConfiguration.eLayoutStyle LastSelectedLayout { get; } + ZoomRoom.zConfiguration.eLayoutStyle AvailableLayouts { get; } + + void GetAvailableLayouts(); // Mot sure this is necessary if we're already subscribed to zStatus Call Layout + void SetLayout(ZoomRoom.zConfiguration.eLayoutStyle layoutStyle); void SwapContentWithThumbnail(); void LayoutTurnNextPage(); void LayoutTurnPreviousPage(); } + + public class LayoutInfoChangedEventArgs : EventArgs + { + public ZoomRoom.zConfiguration.eLayoutStyle AvailableLayouts { get; set; } + } } \ No newline at end of file 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 1a755cef..7b2f7f42 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 @@ -271,6 +271,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge); + /// + /// Use this method when using a plain VideoCodecControllerJoinMap + /// + /// + /// + /// + /// + /// protected void LinkVideoCodecToApi(VideoCodecBase codec, BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { @@ -288,136 +296,145 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec bridge.AddJoinMap(Key, joinMap); } - Debug.Console(1, this, "Linking to Trilist {0}", trilist.ID.ToString("X")); - - - - LinkVideoCodecDtmfToApi(trilist, joinMap); - - LinkVideoCodecCallControlsToApi(trilist, joinMap); - - LinkVideoCodecContentSharingToApi(trilist, joinMap); - - LinkVideoCodecPrivacyToApi(trilist, joinMap); - - LinkVideoCodecVolumeToApi(trilist, joinMap); - - if (codec is ICommunicationMonitor) - { - LinkVideoCodecCommMonitorToApi(codec as ICommunicationMonitor, trilist, joinMap); - } - - if (codec is IHasCodecCameras) - { - LinkVideoCodecCameraToApi(codec as IHasCodecCameras, trilist, joinMap); - } - - if (codec is IHasCodecSelfView) - { - LinkVideoCodecSelfviewToApi(codec as IHasCodecSelfView, trilist, joinMap); - } - - if (codec is IHasCameraAutoMode) - { - trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, SupportsCameraAutoMode); - LinkVideoCodecCameraModeToApi(codec as IHasCameraAutoMode, trilist, joinMap); - } - - if (codec is IHasCameraOff) - { - trilist.SetBool(joinMap.CameraSupportsOffMode.JoinNumber, SupportsCameraOff); - LinkVideoCodecCameraOffToApi(codec as IHasCameraOff, trilist, joinMap); - } - - if (codec is IHasCodecLayouts) - { - LinkVideoCodecCameraLayoutsToApi(codec as IHasCodecLayouts, trilist, joinMap); - } - - if (codec is IHasSelfviewPosition) - { - LinkVideoCodecSelfviewPositionToApi(codec as IHasSelfviewPosition, trilist, joinMap); - } - - if (codec is IHasDirectory) - { - LinkVideoCodecDirectoryToApi(codec as IHasDirectory, trilist, joinMap); - } - - if (codec is IHasScheduleAwareness) - { - LinkVideoCodecScheduleToApi(codec as IHasScheduleAwareness, trilist, joinMap); - } - - if (codec is IHasParticipants) - { - LinkVideoCodecParticipantsToApi(codec as IHasParticipants, trilist, joinMap); - } - - if (codec is IHasFarEndContentStatus) - { - (codec as IHasFarEndContentStatus).ReceivingContent.LinkInputSig(trilist.BooleanInput[joinMap.RecievingContent.JoinNumber]); - } - - if (codec is IHasPhoneDialing) - { - LinkVideoCodecPhoneToApi(codec as IHasPhoneDialing, trilist, joinMap); - } - - trilist.OnlineStatusChange += (device, args) => - { - if (!args.DeviceOnLine) return; - - if (codec is IHasDirectory) - { - (codec as IHasDirectory).SetCurrentDirectoryToRoot(); - } - - if (codec is IHasScheduleAwareness) - { - (codec as IHasScheduleAwareness).GetSchedule(); - } - - if (codec is IHasParticipants) - { - UpdateParticipantsXSig((codec as IHasParticipants).Participants.CurrentParticipants); - } - - if (codec is IHasCameraAutoMode) - { - trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, true); - - (codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate(); - } - - if (codec is IHasCodecSelfView) - { - (codec as IHasCodecSelfView).SelfviewIsOnFeedback.FireUpdate(); - } - - if (codec is IHasCameraAutoMode) - { - (codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate(); - } - - if (codec is IHasCameraOff) - { - (codec as IHasCameraOff).CameraIsOffFeedback.FireUpdate(); - } - - if (codec is IHasPhoneDialing) - { - (codec as IHasPhoneDialing).PhoneOffHookFeedback.FireUpdate(); - } - - SharingContentIsOnFeedback.FireUpdate(); - - trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); - - trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig()); - }; + LinkVideoCodecToApi(codec, trilist, joinMap); } + /// + /// Use this method when you need to pass in a join map that extends VideoCodecControllerJoinMap + /// + /// + /// + /// + protected void LinkVideoCodecToApi(VideoCodecBase codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + Debug.Console(1, this, "Linking to Trilist {0}", trilist.ID.ToString("X")); + + LinkVideoCodecDtmfToApi(trilist, joinMap); + + LinkVideoCodecCallControlsToApi(trilist, joinMap); + + LinkVideoCodecContentSharingToApi(trilist, joinMap); + + LinkVideoCodecPrivacyToApi(trilist, joinMap); + + LinkVideoCodecVolumeToApi(trilist, joinMap); + + if (codec is ICommunicationMonitor) + { + LinkVideoCodecCommMonitorToApi(codec as ICommunicationMonitor, trilist, joinMap); + } + + if (codec is IHasCodecCameras) + { + LinkVideoCodecCameraToApi(codec as IHasCodecCameras, trilist, joinMap); + } + + if (codec is IHasCodecSelfView) + { + LinkVideoCodecSelfviewToApi(codec as IHasCodecSelfView, trilist, joinMap); + } + + if (codec is IHasCameraAutoMode) + { + trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, SupportsCameraAutoMode); + LinkVideoCodecCameraModeToApi(codec as IHasCameraAutoMode, trilist, joinMap); + } + + if (codec is IHasCameraOff) + { + trilist.SetBool(joinMap.CameraSupportsOffMode.JoinNumber, SupportsCameraOff); + LinkVideoCodecCameraOffToApi(codec as IHasCameraOff, trilist, joinMap); + } + + if (codec is IHasCodecLayouts) + { + LinkVideoCodecCameraLayoutsToApi(codec as IHasCodecLayouts, trilist, joinMap); + } + + if (codec is IHasSelfviewPosition) + { + LinkVideoCodecSelfviewPositionToApi(codec as IHasSelfviewPosition, trilist, joinMap); + } + + if (codec is IHasDirectory) + { + LinkVideoCodecDirectoryToApi(codec as IHasDirectory, trilist, joinMap); + } + + if (codec is IHasScheduleAwareness) + { + LinkVideoCodecScheduleToApi(codec as IHasScheduleAwareness, trilist, joinMap); + } + + if (codec is IHasParticipants) + { + LinkVideoCodecParticipantsToApi(codec as IHasParticipants, trilist, joinMap); + } + + if (codec is IHasFarEndContentStatus) + { + (codec as IHasFarEndContentStatus).ReceivingContent.LinkInputSig(trilist.BooleanInput[joinMap.RecievingContent.JoinNumber]); + } + + if (codec is IHasPhoneDialing) + { + LinkVideoCodecPhoneToApi(codec as IHasPhoneDialing, trilist, joinMap); + } + + trilist.OnlineStatusChange += (device, args) => + { + if (!args.DeviceOnLine) return; + + if (codec is IHasDirectory) + { + (codec as IHasDirectory).SetCurrentDirectoryToRoot(); + } + + if (codec is IHasScheduleAwareness) + { + (codec as IHasScheduleAwareness).GetSchedule(); + } + + if (codec is IHasParticipants) + { + UpdateParticipantsXSig((codec as IHasParticipants).Participants.CurrentParticipants); + } + + if (codec is IHasCameraAutoMode) + { + trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, true); + + (codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate(); + } + + if (codec is IHasCodecSelfView) + { + (codec as IHasCodecSelfView).SelfviewIsOnFeedback.FireUpdate(); + } + + if (codec is IHasCameraAutoMode) + { + (codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate(); + } + + if (codec is IHasCameraOff) + { + (codec as IHasCameraOff).CameraIsOffFeedback.FireUpdate(); + } + + if (codec is IHasPhoneDialing) + { + (codec as IHasPhoneDialing).PhoneOffHookFeedback.FireUpdate(); + } + + SharingContentIsOnFeedback.FireUpdate(); + + trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); + + trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig()); + }; + } + private void LinkVideoCodecPhoneToApi(IHasPhoneDialing codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { codec.PhoneOffHookFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PhoneHookState.JoinNumber]); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs index a3ad932c..6720d4fc 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs @@ -23,46 +23,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom zCommand } - /// - /// The available layout styles - /// - public enum eZoomRoomLayoutStyle - { - Gallery, - Speaker, - Strip, - ShareAll - } - - /// - /// The avaliable layout positions for the thumbnails - /// - public enum eZoomRoomLayoutPosition - { - Center, - Up, - Right, - UpRight, - Down, - DownRight, - Left, - UpLeft, - DownLeft - } - - /// - /// The available layout sizes - /// - public enum eZoomRoomLayoutSize - { - Off, - Size1, - Size2, - Size3, - Strip - } - - public abstract class NotifiableObject : INotifyPropertyChanged { #region INotifyPropertyChanged Members @@ -606,7 +566,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public bool can_Switch_Floating_Share_Content { get; set; } /// - /// [on/off] // Set to On if it is possible to switch to Speaker view by invoking zConfiguration Call Layout Style: Speaker. The active speaker is shown full screen, and other video streams, like self-view, are shown in thumbnails. + /// [on/off] // Set to On if it is possible to invoke zConfiguration Call Layout Style: ShareAll, to switch to the ShareAll mode, where the content sharing is shown full screen on all monitors. /// [JsonProperty("can_Switch_Share_On_All_Screens")] public bool can_Switch_Share_On_All_Screens @@ -993,12 +953,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } } + [Flags] public enum eLayoutStyle { - Gallery, - Speaker, - Strip, - ShareAll + None = 0, + Gallery = 1, + Speaker = 2, + Strip = 4, + ShareAll = 8, } public enum eLayoutSize @@ -1023,20 +985,64 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom DownLeft } - public class Layout:NotifiableObject + public class Layout : NotifiableObject { - public bool ShareThumb { get; set; } - public eLayoutStyle Style { get; set; } - public eLayoutSize Size { get; set; } - + private bool _shareThumb; + private eLayoutStyle _style; + private eLayoutSize _size; private eLayoutPosition _position; - public eLayoutPosition Position { + + public bool ShareThumb + { + get { return _shareThumb; } + set + { + if (value != _shareThumb) + { + _shareThumb = value; + NotifyPropertyChanged("ShareThumb"); + } + } + } + + public eLayoutStyle Style + { + get { return _style; } + set + { + if (value != _style) + { + _style = value; + NotifyPropertyChanged("Style"); + } + } + } + + public eLayoutSize Size + { + get { return _size; } + set + { + if (value != _size) + { + _size = value; + NotifyPropertyChanged("Size"); + } + } + } + + public eLayoutPosition Position + { get { return _position; } set { - _position = value; - NotifyPropertyChanged("Position"); - } } + if (value != _position) + { + _position = value; + NotifyPropertyChanged("Position"); + } + } + } } public class Lock 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 905957f2..da8f0d67 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 @@ -23,7 +23,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor, IRouting, IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode, - IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing + IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts { private const long MeetingRefreshTimer = 60000; private const uint DefaultMeetingDurationMin = 30; @@ -121,6 +121,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom PhoneOffHookFeedback = new BoolFeedback(PhoneOffHookFeedbackFunc); CallerIdNameFeedback = new StringFeedback(CallerIdNameFeedbackFunc); CallerIdNumberFeedback = new StringFeedback(CallerIdNumberFeedbackFunc); + + LocalLayoutFeedback = new StringFeedback(LocalLayoutFeedbackFunc); + + LayoutViewIsOnFirstPageFeedback = new BoolFeedback(LayoutViewIsOnFirstPageFeedbackFunc); + + LayoutViewIsOnLastPageFeedback = new BoolFeedback(LayoutViewIsOnLastPageFeedbackFunc); + + CanSwapContentWithThumbnailFeedback = new BoolFeedback(CanSwapContentWithThumbnailFeedbackFunc); + + ContentSwappedWithThumbnailFeedback = new BoolFeedback(ContentSwappedWithThumbnailFeedbackFunc); + } public CommunicationGather PortGather { get; private set; } @@ -216,11 +227,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } } - protected Func LocalLayoutFeedbackFunc - { - get { return () => ""; } - } - protected Func LocalLayoutIsProminentFeedbackFunc { get { return () => false; } @@ -484,11 +490,28 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Configuration.Call.Layout.PropertyChanged += (o, a) => { - if (a.PropertyName != "Position") return; + switch (a.PropertyName) + { + case "Position": + { + ComputeSelfviewPipStatus(); - ComputeSelfviewPipStatus(); + SelfviewPipPositionFeedback.FireUpdate(); - SelfviewPipPositionFeedback.FireUpdate(); + break; + } + case "ShareThumb": + { + ContentSwappedWithThumbnailFeedback.FireUpdate(); + break; + } + case "Style": + { + LocalLayoutFeedback.FireUpdate(); + break; + } + + } }; Status.Call.Sharing.PropertyChanged += (o, a) => @@ -548,37 +571,31 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom switch (a.PropertyName) { case "can_Switch_Speaker_View": - { - // TODO: #697 Fire appropriate feedback(s) - break; - } case "can_Switch_Wall_View": - { - // #697 TODO: Fire appropriate feedback(s) - break; - } case "can_Switch_Share_On_All_Screens": { - // #697 TODO: Fire appropriate feedback(s) + // #697 TODO: Calls the method to compute the available layouts and set the value of AvailableLayouts enum + ComputeAvailableLayouts(); break; } case "is_In_First_Page": { - // TODO: #697 Fire appropriate feedback(s) - // + // TODO: #697 Fires appropriate feedback + LayoutViewIsOnFirstPageFeedback.FireUpdate(); break; } case "is_In_Last_Page": { - // TODO: #697 Fire appropriate feedback(s) - break; - } - case "video_type": - { - // TODO: #697 Fire appropriate feedback(s) - // LocalLayoutFeedback.FireUpdate(); + // TODO: #697 Fires appropriate feedback + LayoutViewIsOnLastPageFeedback.FireUpdate(); break; } + //case "video_type": + // { + // // TODO: #697 It appears as though the actual value we want to watch is Configuration.Call.Layout.Style + // LocalLayoutFeedback.FireUpdate(); + // break; + // } } }; } @@ -1639,7 +1656,75 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { - LinkVideoCodecToApi(this, trilist, joinStart, joinMapKey, bridge); + var joinMap = new ZoomRoomJoinMap(joinStart); + + var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); + + if (customJoins != null) + { + joinMap.SetCustomJoinData(customJoins); + } + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + + LinkVideoCodecToApi(this, trilist, joinMap); + + LinkZoomRoomToApi(trilist, joinMap); + } + + /// + /// Links all the specific Zoom functionality to the API bridge + /// + /// + /// + public void LinkZoomRoomToApi(BasicTriList trilist, ZoomRoomJoinMap joinMap) + { + var codec = this as IHasZoomRoomLayouts; + + if (codec != null) + { + codec.AvailableLayoutsChanged += (o, a) => + { + trilist.SetBool(joinMap.LayoutGalleryIsAvailable.JoinNumber, a.AvailableLayouts + == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Gallery)); + trilist.SetBool(joinMap.LayoutSpeakerIsAvailable.JoinNumber, a.AvailableLayouts + == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Speaker)); + trilist.SetBool(joinMap.LayoutStripIsAvailable.JoinNumber, a.AvailableLayouts + == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Strip)); + trilist.SetBool(joinMap.LayoutShareAllIsAvailable.JoinNumber, a.AvailableLayouts + == (a.AvailableLayouts & zConfiguration.eLayoutStyle.ShareAll)); + }; + + codec.CanSwapContentWithThumbnailFeedback.LinkInputSig(trilist.BooleanInput[joinMap.CanSwapContentWithThumbnail.JoinNumber]); + trilist.SetSigFalseAction(joinMap.SwapContentWithThumbnail.JoinNumber, () => codec.SwapContentWithThumbnail()); + codec.ContentSwappedWithThumbnailFeedback.LinkInputSig(trilist.BooleanInput[joinMap.SwapContentWithThumbnail.JoinNumber]); + + codec.LayoutViewIsOnFirstPageFeedback.LinkInputSig(trilist.BooleanInput[joinMap.LayoutIsOnFirstPage.JoinNumber]); + codec.LayoutViewIsOnLastPageFeedback.LinkInputSig(trilist.BooleanInput[joinMap.LayoutIsOnLastPage.JoinNumber]); + trilist.SetSigFalseAction(joinMap.LayoutTurnToNextPage.JoinNumber, () => codec.LayoutTurnNextPage() ); + trilist.SetSigFalseAction(joinMap.LayoutTurnToPreviousPage.JoinNumber, () => codec.LayoutTurnPreviousPage()); + + + trilist.SetStringSigAction(joinMap.GetSetCurrentLayout.JoinNumber, (s) => + { + try + { + var style = (zConfiguration.eLayoutStyle)Enum.Parse(typeof(zConfiguration.eLayoutStyle), s, true); + SetLayout(style); + } + catch (Exception e) + { + Debug.Console(2, this, "Unable to parse '{0}' to zConfiguration.eLayoutStyle: {1}", s, e); + } + }); + + codec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetCurrentLayout.JoinNumber]); + + + } } public override void ExecuteSwitch(object selector) @@ -1938,6 +2023,123 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } #endregion + + #region IHasZoomRoomLayouts Members + + public event EventHandler AvailableLayoutsChanged; + + private Func LayoutViewIsOnFirstPageFeedbackFunc {get {return () => Status.Layout.is_In_First_Page; } } + private Func LayoutViewIsOnLastPageFeedbackFunc { get { return () => Status.Layout.is_In_Last_Page; } } + private Func CanSwapContentWithThumbnailFeedbackFunc { get { return () => Status.Layout.can_Switch_Floating_Share_Content; } } + private Func ContentSwappedWithThumbnailFeedbackFunc { get { return () => Configuration.Call.Layout.ShareThumb; } } + + public BoolFeedback LayoutViewIsOnFirstPageFeedback { get; private set; } + + public BoolFeedback LayoutViewIsOnLastPageFeedback { get; private set; } + + public BoolFeedback CanSwapContentWithThumbnailFeedback { get; private set; } + + public BoolFeedback ContentSwappedWithThumbnailFeedback { get; private set; } + + + public zConfiguration.eLayoutStyle LastSelectedLayout { get; private set; } + + public zConfiguration.eLayoutStyle AvailableLayouts { get; private set; } + + /// + /// Reads individual properties to determine if which layouts are avalailable + /// + private void ComputeAvailableLayouts() + { + zConfiguration.eLayoutStyle availableLayouts = zConfiguration.eLayoutStyle.None; + //TODO: #697 Compute the avaialble layouts and set the value of AvailableLayouts + if (Status.Layout.can_Switch_Wall_View) + { + availableLayouts |= zConfiguration.eLayoutStyle.Gallery; + } + + if (Status.Layout.can_Switch_Speaker_View) + { + availableLayouts |= zConfiguration.eLayoutStyle.Speaker; + } + + if (Status.Layout.can_Switch_Share_On_All_Screens) + { + availableLayouts |= zConfiguration.eLayoutStyle.ShareAll; + } + + // There is no property that directly reports if strip mode is valid, but API stipulates + // that strip mode is available if the number of screens is 1 + if (Status.NumberOfScreens.NumOfScreens == 1) + { + availableLayouts |= zConfiguration.eLayoutStyle.Strip; + } + + var handler = AvailableLayoutsChanged; + if (handler != null) + { + handler(this, new LayoutInfoChangedEventArgs() { AvailableLayouts = availableLayouts }); + } + + AvailableLayouts = availableLayouts; + } + + public void GetAvailableLayouts() + { + SendText("zStatus Call Layout"); + } + + public void SetLayout(zConfiguration.eLayoutStyle layoutStyle) + { + LastSelectedLayout = layoutStyle; + SendText(String.Format("zConfiguration Call Layout Style: {0}", layoutStyle.ToString())); + } + + public void SwapContentWithThumbnail() + { + if (CanSwapContentWithThumbnailFeedback.BoolValue) + { + var oppositeValue = ContentSwappedWithThumbnailFeedback.BoolValue ? "on" : "off"; // Get the value based on the opposite of the current state + // TODO: #697 Need to verify the ternary above and make sure that the correct on/off value is being send based on the true/false value of the feedback + // to toggle the state + SendText(String.Format("zConfiguration Call Layout ShareThumb: {0}", oppositeValue)); + } + } + + public void LayoutTurnNextPage() + { + SendText("zCommand Call Layout TurnPage Forward: On"); + } + + public void LayoutTurnPreviousPage() + { + SendText("zCommand Call Layout TurnPage Forward: Off"); + } + + #endregion + + #region IHasCodecLayouts Members + + private Func LocalLayoutFeedbackFunc { get { return () => Configuration.Call.Layout.Style.ToString(); } } + + public StringFeedback LocalLayoutFeedback { get; private set; } + + public void LocalLayoutToggle() + { + throw new NotImplementedException(); + } + + public void LocalLayoutToggleSingleProminent() + { + throw new NotImplementedException(); + } + + public void MinMaxLayoutToggle() + { + throw new NotImplementedException(); + } + + #endregion } /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs new file mode 100644 index 00000000..49b22ae4 --- /dev/null +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs @@ -0,0 +1,141 @@ +using System; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Bridges.JoinMaps; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom +{ + public class ZoomRoomJoinMap : VideoCodecControllerJoinMap + { + // TODO: #697 Set join numbers + + [JoinName("LayoutIsOnFirstPage")] + public JoinDataComplete LayoutIsOnFirstPage = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Indicates if layout is on first page", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("LayoutIsOnLastPage")] + public JoinDataComplete LayoutIsOnLastPage = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Indicates if layout is on first page", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("LayoutTurnToNextPage")] + public JoinDataComplete LayoutTurnToNextPage = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Turns layout view to next page", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("LayoutTurnToPreviousPage")] + public JoinDataComplete LayoutTurnToPreviousPage = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Turns layout view to previous page", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CanSwapContentWithThumbnail")] + public JoinDataComplete CanSwapContentWithThumbnail = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, + new JoinMetadata + { + Description = "FB Indicates if content can be swapped with thumbnail", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SwapContentWithThumbnail")] + public JoinDataComplete SwapContentWithThumbnail = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Pulse to swap content with thumbnail. FB reports current state", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("GetSetCurrentLayout")] + public JoinDataComplete GetSetCurrentLayout = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Sets and reports the current layout. Use the LayoutXXXXIsAvailable signals to determine valid layouts", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("GetAvailableLayouts")] + public JoinDataComplete GetAvailableLayouts = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Gets the available layouts. Will update the LayoutXXXXXIsAvailbale signals.", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("LayoutGalleryIsAvailable")] + public JoinDataComplete LayoutGalleryIsAvailable = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, + new JoinMetadata + { + Description = "FB Indicates if layout 'Gallery' is available", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("LayoutSpeakerIsAvailable")] + public JoinDataComplete LayoutSpeakerIsAvailable = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, + new JoinMetadata + { + Description = "FB Indicates if layout 'Speaker' is available", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("LayoutStripIsAvailable")] + public JoinDataComplete LayoutStripIsAvailable = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, + new JoinMetadata + { + Description = "FB Indicates if layout 'Strip' is available", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("LayoutShareAllIsAvailable")] + public JoinDataComplete LayoutShareAllIsAvailable = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, + new JoinMetadata + { + Description = "FB Indicates if layout 'ShareAll' is available", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + public ZoomRoomJoinMap(uint joinStart) + : base(joinStart, typeof(ZoomRoomJoinMap)) + { + } + + public ZoomRoomJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { + } + } +} \ No newline at end of file