From d8aef1a0dad0211611a4b48630a054b15918d7a9 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 12 Nov 2021 22:07:11 -0700 Subject: [PATCH] feat(essentials): #865 More updates Adds ability to disable auto dialing behavior of selected directory contact. Adds XSig to send contact method info across bridge Adds XSig to send call history data across bridge and also joins to manipulate --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 125 +++++++++++++ .../Codec/iHasCallHistory.cs | 6 +- .../VideoCodec/VideoCodecBase.cs | 172 ++++++++++++++++-- 3 files changed, 287 insertions(+), 16 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index a0729352..a32dcc88 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -496,6 +496,19 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("DirectoryDisableAutoDialSelectedLine")] + public JoinDataComplete DirectoryDisableAutoDialSelectedLine = new JoinDataComplete( + new JoinData + { + JoinNumber = 107, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Set high to disable automatic dialing of a contact when selected", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); [JoinName("CameraTiltUp")] public JoinDataComplete CameraTiltUp = new JoinDataComplete( @@ -903,6 +916,20 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("RemoveSelectedRecentCallItem")] + public JoinDataComplete RemoveSelectedRecentCallItem = new JoinDataComplete( + new JoinData + { + JoinNumber = 181, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Removes the selected recent call item", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("SourceShareStart")] public JoinDataComplete SourceShareStart = new JoinDataComplete( new JoinData @@ -1219,6 +1246,34 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Analog }); + [JoinName("SelectRecentCallItem")] + public JoinDataComplete SelectRecentCallItem = new JoinDataComplete( + new JoinData + { + JoinNumber = 180, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Select/FB for Recent Call Item. Valid values 1 - 10", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("RecentCallOccurrenceType")] + public JoinDataComplete RecentCallOccurrenceType = new JoinDataComplete( + new JoinData + { + JoinNumber = 181, + JoinSpan = 10 + }, + new JoinMetadata + { + Description = "Recent Call Occurrence Type. [0-3] 0 = Unknown, 1 = Placed, 2 = Received, 3 = NoAnswer", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + #endregion @@ -1352,6 +1407,20 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Serial }); + [JoinName("ContactMethods")] + public JoinDataComplete ContactMethods = new JoinDataComplete( + new JoinData + { + JoinNumber = 103, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Contact Methods - XSig, 10 entries", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + [JoinName("CameraPresetNames")] public JoinDataComplete CameraPresetNames = new JoinDataComplete( new JoinData @@ -1408,6 +1477,62 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Serial }); + [JoinName("SelectedRecentCallName")] + public JoinDataComplete SelectedRecentCallName = new JoinDataComplete( + new JoinData + { + JoinNumber = 171, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Recent Call Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SelectedRecentCallNumber")] + public JoinDataComplete SelectedRecentCallNumber = new JoinDataComplete( + new JoinData + { + JoinNumber = 172, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Recent Call Number", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("RecentCallNamesStart")] + public JoinDataComplete RecentCallNamesStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 181, + JoinSpan = 10 + }, + new JoinMetadata + { + Description = "Recent Call Names", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("RecentCallTimesStart")] + public JoinDataComplete RecentCallTimesStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 191, + JoinSpan = 10 + }, + new JoinMetadata + { + Description = "Recent Calls Times", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + [JoinName("CurrentSource")] public JoinDataComplete CurrentSource = new JoinDataComplete( new JoinData diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasCallHistory.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasCallHistory.cs index 256938d1..83a74022 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasCallHistory.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasCallHistory.cs @@ -23,9 +23,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec public enum eCodecOccurrenceType { Unknown = 0, - Placed, - Received, - NoAnswer + Placed = 1, + Received = 2, + NoAnswer = 3, } /// 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 b87e47f6..114c1cf7 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 @@ -390,6 +390,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec LinkVideoCodecPhoneToApi(codec as IHasPhoneDialing, trilist, joinMap); } + if (codec is IHasCallHistory) + { + LinkVideoCodecCallHistoryToApi(codec as IHasCallHistory, trilist, joinMap); + } + trilist.OnlineStatusChange += (device, args) => { if (!args.DeviceOnLine) return; @@ -436,6 +441,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec (codec as IHasPhoneDialing).PhoneOffHookFeedback.FireUpdate(); } + if (codec is IHasCallHistory) + { + UpdateCallHistory((codec as IHasCallHistory), trilist, joinMap); + } + SharingContentIsOnFeedback.FireUpdate(); trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); @@ -901,7 +911,9 @@ ScreenIndexIsPinnedTo: {8} (a{17}) trilist.SetStringSigAction(joinMap.DirectorySearchString.JoinNumber, codec.SearchDirectory); - trilist.SetUShortSigAction(joinMap.DirectorySelectRow.JoinNumber, (i) => SelectDirectoryEntry(codec, i)); + trilist.SetUShortSigAction(joinMap.DirectorySelectRow.JoinNumber, (i) => SelectDirectoryEntry(codec, i, trilist, joinMap)); + + // Report feedback for number of contact methods for selected contact trilist.SetSigFalseAction(joinMap.DirectoryRoot.JoinNumber, codec.SetCurrentDirectoryToRoot); @@ -921,7 +933,7 @@ ScreenIndexIsPinnedTo: {8} (a{17}) }; } - private void SelectDirectoryEntry(IHasDirectory codec, ushort i) + private void SelectDirectoryEntry(IHasDirectory codec, ushort i, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { var entry = codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1]; @@ -931,21 +943,87 @@ ScreenIndexIsPinnedTo: {8} (a{17}) return; } - var dialableEntry = entry as IInvitableContact; + // Allow auto dial of selected line + if (!trilist.GetBool(joinMap.DirectoryDisableAutoDialSelectedLine.JoinNumber)) + { + var dialableEntry = entry as IInvitableContact; - if (dialableEntry != null) - { - Dial(dialableEntry); - return; - } + if (dialableEntry != null) + { + Dial(dialableEntry); + return; + } - var entryToDial = entry as DirectoryContact; + var entryToDial = entry as DirectoryContact; - if (entryToDial == null) return; + if (entryToDial == null) return; + + Dial(entryToDial.ContactMethods[0].Number); + return; + } + else + { + // If auto dial is disabled... + var entryToDial = entry as DirectoryContact; + + if (entryToDial == null) return; + + trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedLine.JoinNumber, () => Dial(entryToDial.ContactMethods[0].Number)); + + var clearBytes = XSigHelpers.ClearOutputs(); + + trilist.SetString(joinMap.ContactMethods.JoinNumber, + Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); + var contactMethodsXSig = UpdateContactMethodsXSig(entryToDial); + + trilist.SetString(joinMap.ContactMethods.JoinNumber, contactMethodsXSig); + } - Dial(entryToDial.ContactMethods[0].Number); } + /// + /// Generates the XSig data representing the available contact methods for the selected DirectoryContact + /// + /// + /// + private string UpdateContactMethodsXSig(DirectoryContact contact) + { + const int maxMethods = 10; + const int maxStrings = 3; + const int offset = maxStrings; + var stringIndex = 0; + var arrayIndex = 0; + var tokenArray = new XSigToken[contact.ContactMethods.Count]; + + // TODO: Add code to generate XSig data + + foreach (var method in contact.ContactMethods) + { + if (arrayIndex >= maxMethods * offset) + break; + + //serials + tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, method.Number); + tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, method.ContactMethodId.ToString()); + tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, method.Device.ToString()); + + arrayIndex += offset; + stringIndex += maxStrings; + } + + while (arrayIndex < maxMethods) + { + tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, String.Empty); + tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, String.Empty); + tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, String.Empty); + + arrayIndex += offset; + stringIndex += maxStrings; + } + + return GetXSigString(tokenArray); + } + private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot) { var contactIndex = 1; @@ -1079,7 +1157,7 @@ ScreenIndexIsPinnedTo: {8} (a{17}) private string UpdateCallStatusXSig() { const int maxCalls = 8; - const int maxStrings = 5; + const int maxStrings = 6; const int offset = 6; var stringIndex = 0; var digitalIndex = maxStrings * maxCalls; @@ -1457,7 +1535,75 @@ ScreenIndexIsPinnedTo: {8} (a{17}) }); } - private string SetCameraPresetNames(IEnumerable presets) + // Following fields only used for Bridging + private int _selectedRecentCallItemIndex; + private CodecCallHistory.CallHistoryEntry _selectedRecentCallItem; + + private void LinkVideoCodecCallHistoryToApi(IHasCallHistory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + codec.CallHistory.RecentCallsListHasChanged += (o, a) => + { + UpdateCallHistory(codec, trilist, joinMap); + }; + + // Selected item action and feedback + trilist.SetUShortSigAction(joinMap.SelectRecentCallItem.JoinNumber, (u) => + { + _selectedRecentCallItemIndex = (int)(u - 1); + trilist.SetUshort(joinMap.SelectRecentCallItem.JoinNumber, u); + + var _selectedRecentCallItem = codec.CallHistory.RecentCalls[_selectedRecentCallItemIndex]; + + if (_selectedRecentCallItem != null) + { + trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, _selectedRecentCallItem.Name); + trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, _selectedRecentCallItem.Number); + trilist.SetSigFalseAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber, () => codec.RemoveCallHistoryEntry(_selectedRecentCallItem)); + } + else + { + trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, string.Empty); + trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, string.Empty); + trilist.ClearBoolSigAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber); + } + }); + } + + + + private void UpdateCallHistory(IHasCallHistory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + // Clear out selected item + _selectedRecentCallItemIndex = 0; + _selectedRecentCallItem = null; + trilist.SetUshort(joinMap.SelectRecentCallItem.JoinNumber, 0); + trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, string.Empty); + trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, string.Empty); + trilist.ClearBoolSigAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber); + // + + + // Update the call history joins + var maxItems = joinMap.RecentCallNamesStart.JoinSpan; + + uint i = 0; + foreach(var item in codec.CallHistory.RecentCalls) + { + trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + i, item.Name); + trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + i, item.StartTime.ToShortTimeString()); + trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + i, (ushort)item.OccurrenceType); + i++; + } + + for (uint index = i; i < maxItems; index++) + { + trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + index, string.Empty); + trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + index, string.Empty); + trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + index, 0); + } + } + + private string SetCameraPresetNames(IEnumerable presets) { return SetCameraPresetNames(presets.Select(p => p.Description).ToList()); }